Implement support for arbitrarily complex indexers

fixes #7566
This commit is contained in:
Gunnar Beutner 2014-11-04 15:19:33 +01:00
parent 58d5c42d9c
commit a6f20c7a22
11 changed files with 242 additions and 285 deletions

View File

@ -200,3 +200,37 @@ Array::Ptr Array::ShallowClone(void) const
CopyTo(clone); CopyTo(clone);
return clone; return clone;
} }
Array::Ptr icinga::MakeArray(const Value& val1)
{
Array::Ptr result = make_shared<Array>();
result->Add(val1);
return result;
}
Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2)
{
Array::Ptr result = make_shared<Array>();
result->Add(val1);
result->Add(val2);
return result;
}
Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2, const Value& val3)
{
Array::Ptr result = make_shared<Array>();
result->Add(val1);
result->Add(val2);
result->Add(val3);
return result;
}
Array::Ptr icinga::MakeArray(const Value& val1, const Value& val2, const Value& val3, const Value& val4)
{
Array::Ptr result = make_shared<Array>();
result->Add(val1);
result->Add(val2);
result->Add(val3);
result->Add(val4);
return result;
}

View File

@ -79,6 +79,11 @@ inline Array::Iterator range_end(Array::Ptr x)
return x->End(); return x->End();
} }
I2_BASE_API Array::Ptr MakeArray(const Value& val1);
I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2);
I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2, const Value& val3);
I2_BASE_API Array::Ptr MakeArray(const Value& val1, const Value& val2, const Value& val3, const Value& val4);
} }
namespace boost namespace boost

View File

@ -252,11 +252,11 @@ in { yylval->op = &Expression::OpIn; return T_IN; }
-?[0-9]+(\.[0-9]+)?m { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; } -?[0-9]+(\.[0-9]+)?m { yylval->num = strtod(yytext, NULL) * 60; return T_NUMBER; }
-?[0-9]+(\.[0-9]+)?s { yylval->num = strtod(yytext, NULL); return T_NUMBER; } -?[0-9]+(\.[0-9]+)?s { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
-?[0-9]+(\.[0-9]+)? { yylval->num = strtod(yytext, NULL); return T_NUMBER; } -?[0-9]+(\.[0-9]+)? { yylval->num = strtod(yytext, NULL); return T_NUMBER; }
= { yylval->op = &Expression::OpSet; return T_SET; } = { yylval->csop = OpSetLiteral; return T_SET; }
\+= { yylval->op = &Expression::OpSetPlus; return T_SET_PLUS; } \+= { yylval->csop = OpSetAdd; return T_SET_ADD; }
-= { yylval->op = &Expression::OpSetMinus; return T_SET_MINUS; } -= { yylval->csop = OpSetSubtract; return T_SET_SUBTRACT; }
\*= { yylval->op = &Expression::OpSetMultiply; return T_SET_MULTIPLY; } \*= { yylval->csop = OpSetMultiply; return T_SET_MULTIPLY; }
\/= { yylval->op = &Expression::OpSetDivide; return T_SET_DIVIDE; } \/= { yylval->csop = OpSetDivide; return T_SET_DIVIDE; }
\+ { yylval->op = &Expression::OpAdd; return T_PLUS; } \+ { yylval->op = &Expression::OpAdd; return T_PLUS; }
\- { yylval->op = &Expression::OpSubtract; return T_MINUS; } \- { yylval->op = &Expression::OpSubtract; return T_MINUS; }
\* { yylval->op = &Expression::OpMultiply; return T_MULTIPLY; } \* { yylval->op = &Expression::OpMultiply; return T_MULTIPLY; }

View File

@ -96,6 +96,7 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
double num; double num;
icinga::Value *variant; icinga::Value *variant;
icinga::Expression::OpCallback op; icinga::Expression::OpCallback op;
CombinedSetOp csop;
icinga::TypeSpecifier type; icinga::TypeSpecifier type;
std::vector<String> *slist; std::vector<String> *slist;
Array *array; Array *array;
@ -108,11 +109,11 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
%token T_NULL %token T_NULL
%token <text> T_IDENTIFIER %token <text> T_IDENTIFIER
%token <op> T_SET "= (T_SET)" %token <csop> T_SET "= (T_SET)"
%token <op> T_SET_PLUS "+= (T_SET_PLUS)" %token <csop> T_SET_ADD "+= (T_SET_ADD)"
%token <op> T_SET_MINUS "-= (T_SET_MINUS)" %token <csop> T_SET_SUBTRACT "-= (T_SET_SUBTRACT)"
%token <op> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)" %token <csop> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)"
%token <op> T_SET_DIVIDE "/= (T_SET_DIVIDE)" %token <csop> T_SET_DIVIDE "/= (T_SET_DIVIDE)"
%token <op> T_SHIFT_LEFT "<< (T_SHIFT_LEFT)" %token <op> T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token <op> T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)" %token <op> T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
@ -168,10 +169,13 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
%type <array> rterm_items_inner %type <array> rterm_items_inner
%type <array> identifier_items %type <array> identifier_items
%type <array> identifier_items_inner %type <array> identifier_items_inner
%type <array> indexer
%type <array> indexer_items
%type <variant> indexer_item
%type <array> lterm_items %type <array> lterm_items
%type <array> lterm_items_inner %type <array> lterm_items_inner
%type <variant> typerulelist %type <variant> typerulelist
%type <op> lbinary_op %type <csop> combined_set_op
%type <type> type %type <type> type
%type <variant> rterm %type <variant> rterm
%type <variant> rterm_array %type <variant> rterm_array
@ -436,8 +440,8 @@ object:
m_Abstract.push(false); m_Abstract.push(false);
m_ObjectAssign.push(true); m_ObjectAssign.push(true);
m_SeenAssign.push(false); m_SeenAssign.push(false);
m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo())); m_Assign.push(MakeLiteral(false));
m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo())); m_Ignore.push(MakeLiteral(false));
} }
object_declaration identifier rterm rterm_scope object_declaration identifier rterm rterm_scope
{ {
@ -516,9 +520,47 @@ identifier_items_inner: /* empty */
} }
; ;
lbinary_op: T_SET indexer: T_IDENTIFIER
| T_SET_PLUS {
| T_SET_MINUS $$ = new Array();
$$->Add(MakeLiteral($1));
free($1);
}
| T_IDENTIFIER indexer_items
{
$$ = $2;
$$->Insert(0, MakeLiteral($1));
}
;
indexer_items: indexer_item
{
$$ = new Array();
$$->Add(*$1);
delete $1;
}
| indexer_items indexer_item
{
$$ = $1;
$$->Add(*$2);
delete $2;
}
;
indexer_item: '.' T_IDENTIFIER
{
$$ = new Value(MakeLiteral($2));
free($2);
}
| '[' rterm ']'
{
$$ = $2;
}
;
combined_set_op: T_SET
| T_SET_ADD
| T_SET_SUBTRACT
| T_SET_MULTIPLY | T_SET_MULTIPLY
| T_SET_DIVIDE | T_SET_DIVIDE
{ {
@ -557,45 +599,11 @@ lterm_items_inner: lterm
} }
; ;
lterm: identifier lbinary_op rterm lterm: indexer combined_set_op rterm
{ {
Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $1, @1); $$ = new Value(make_shared<Expression>(&Expression::OpSet, MakeArray(Array::Ptr($1), $2), *$3, DebugInfoRange(@1, @3)));
free($1);
$$ = new Value(make_shared<Expression>($2, aindex, *$3, DebugInfoRange(@1, @3)));
delete $3; delete $3;
} }
| identifier '[' rterm ']' lbinary_op rterm
{
Expression::Ptr subexpr = make_shared<Expression>($5, *$3, *$6, DebugInfoRange(@1, @6));
delete $3;
delete $6;
Array::Ptr subexprl = make_shared<Array>();
subexprl->Add(subexpr);
Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $1, @1);
free($1);
Expression::Ptr expr = make_shared<Expression>(&Expression::OpDict, subexprl, DebugInfoRange(@1, @6));
$$ = new Value(make_shared<Expression>(&Expression::OpSetPlus, aindex, expr, DebugInfoRange(@1, @6)));
}
| identifier '.' T_IDENTIFIER lbinary_op rterm
{
Expression::Ptr aindex = make_shared<Expression>(&Expression::OpLiteral, $3, @3);
Expression::Ptr subexpr = make_shared<Expression>($4, aindex, *$5, DebugInfoRange(@1, @5));
free($3);
delete $5;
Array::Ptr subexprl = make_shared<Array>();
subexprl->Add(subexpr);
Expression::Ptr aindexl = make_shared<Expression>(&Expression::OpLiteral, $1, @1);
free($1);
Expression::Ptr expr = make_shared<Expression>(&Expression::OpDict, subexprl, DebugInfoRange(@1, @5));
$$ = new Value(make_shared<Expression>(&Expression::OpSetPlus, aindexl, expr, DebugInfoRange(@1, @5)));
}
| T_IMPORT rterm | T_IMPORT rterm
{ {
Expression::Ptr avar = make_shared<Expression>(&Expression::OpVariable, "type", DebugInfoRange(@1, @2)); Expression::Ptr avar = make_shared<Expression>(&Expression::OpVariable, "type", DebugInfoRange(@1, @2));
@ -612,7 +620,7 @@ lterm: identifier lbinary_op rterm
m_Assign.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Assign.top(), *$3, DebugInfoRange(@1, @3)); m_Assign.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Assign.top(), *$3, DebugInfoRange(@1, @3));
delete $3; delete $3;
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfoRange(@1, @3))); $$ = new Value(MakeLiteral());
} }
| T_IGNORE T_WHERE rterm | T_IGNORE T_WHERE rterm
{ {
@ -622,12 +630,12 @@ lterm: identifier lbinary_op rterm
m_Ignore.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Ignore.top(), *$3, DebugInfoRange(@1, @3)); m_Ignore.top() = make_shared<Expression>(&Expression::OpLogicalOr, m_Ignore.top(), *$3, DebugInfoRange(@1, @3));
delete $3; delete $3;
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfoRange(@1, @3))); $$ = new Value(MakeLiteral());
} }
| T_RETURN rterm | T_RETURN rterm
{ {
Expression::Ptr aname = make_shared<Expression>(&Expression::OpLiteral, "__result", @1); Expression::Ptr aname = MakeLiteral("__result");
$$ = new Value(make_shared<Expression>(&Expression::OpSet, aname, *$2, DebugInfoRange(@1, @2))); $$ = new Value(make_shared<Expression>(&Expression::OpSet, MakeArray(MakeArray(MakeLiteral(aname)), OpSetLiteral), *$2, DebugInfoRange(@1, @2)));
delete $2; delete $2;
} }
@ -711,27 +719,26 @@ rterm_scope: '{' newlines lterm_items newlines '}'
rterm: T_STRING rterm: T_STRING
{ {
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, $1, @1)); $$ = new Value(MakeLiteral($1));
free($1); free($1);
} }
| T_NUMBER | T_NUMBER
{ {
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, $1, @1)); $$ = new Value(MakeLiteral($1));
} }
| T_NULL | T_NULL
{ {
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, @1)); $$ = new Value(MakeLiteral());
} }
| rterm '.' T_IDENTIFIER | rterm '.' T_IDENTIFIER
{ {
$$ = new Value(make_shared<Expression>(&Expression::OpIndexer, *$1, make_shared<Expression>(&Expression::OpLiteral, $3, @3), DebugInfoRange(@1, @3))); $$ = new Value(make_shared<Expression>(&Expression::OpIndexer, *$1, MakeLiteral($3), DebugInfoRange(@1, @3)));
delete $1; delete $1;
free($3); free($3);
} }
| rterm '(' rterm_items ')' | rterm '(' rterm_items ')'
{ {
Array::Ptr arguments = Array::Ptr($3); $$ = new Value(make_shared<Expression>(&Expression::OpFunctionCall, *$1, MakeLiteral(Array::Ptr($3)), DebugInfoRange(@1, @4)));
$$ = new Value(make_shared<Expression>(&Expression::OpFunctionCall, *$1, make_shared<Expression>(&Expression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4)));
delete $1; delete $1;
} }
| T_IDENTIFIER | T_IDENTIFIER
@ -792,67 +799,43 @@ rterm: T_STRING
| rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); } | rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
| T_FUNCTION identifier '(' identifier_items ')' rterm_scope | T_FUNCTION identifier '(' identifier_items ')' rterm_scope
{ {
Array::Ptr arr = make_shared<Array>();
arr->Add($2);
free($2);
Expression::Ptr aexpr = *$6; Expression::Ptr aexpr = *$6;
delete $6; delete $6;
aexpr->MakeInline(); aexpr->MakeInline();
arr->Add(aexpr);
$$ = new Value(make_shared<Expression>(&Expression::OpFunction, arr, Array::Ptr($4), DebugInfoRange(@1, @6))); $$ = new Value(make_shared<Expression>(&Expression::OpFunction, MakeArray($2, aexpr), Array::Ptr($4), DebugInfoRange(@1, @6)));
free($2);
} }
| T_FUNCTION '(' identifier_items ')' rterm_scope | T_FUNCTION '(' identifier_items ')' rterm_scope
{ {
Array::Ptr arr = make_shared<Array>();
arr->Add(Empty);
Expression::Ptr aexpr = *$5; Expression::Ptr aexpr = *$5;
delete $5; delete $5;
aexpr->MakeInline(); aexpr->MakeInline();
arr->Add(aexpr);
$$ = new Value(make_shared<Expression>(&Expression::OpFunction, arr, Array::Ptr($3), DebugInfoRange(@1, @5))); $$ = new Value(make_shared<Expression>(&Expression::OpFunction, MakeArray(Empty, aexpr), Array::Ptr($3), DebugInfoRange(@1, @5)));
} }
| T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope | T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope
{ {
Array::Ptr arr = make_shared<Array>();
arr->Add($3);
free($3);
arr->Add($5);
free($5);
Expression::Ptr aexpr = *$7; Expression::Ptr aexpr = *$7;
delete $7; delete $7;
arr->Add(aexpr);
Expression::Ptr ascope = *$9; Expression::Ptr ascope = *$9;
delete $9; delete $9;
$$ = new Value(make_shared<Expression>(&Expression::OpFor, arr, ascope, DebugInfoRange(@1, @9))); $$ = new Value(make_shared<Expression>(&Expression::OpFor, MakeArray($3, $5, aexpr), ascope, DebugInfoRange(@1, @9)));
free($3);
free($5);
} }
| T_FOR '(' identifier T_IN rterm ')' rterm_scope | T_FOR '(' identifier T_IN rterm ')' rterm_scope
{ {
Array::Ptr arr = make_shared<Array>();
arr->Add($3);
free($3);
arr->Add(Empty);
Expression::Ptr aexpr = *$5; Expression::Ptr aexpr = *$5;
delete $5; delete $5;
arr->Add(aexpr);
Expression::Ptr ascope = *$7; Expression::Ptr ascope = *$7;
delete $7; delete $7;
$$ = new Value(make_shared<Expression>(&Expression::OpFor, arr, ascope, DebugInfoRange(@1, @7))); $$ = new Value(make_shared<Expression>(&Expression::OpFor, MakeArray($3, Empty, aexpr), ascope, DebugInfoRange(@1, @7)));
free($3);
} }
; ;
@ -892,7 +875,7 @@ apply_for_specifier: /* empty */
optional_rterm: /* empty */ optional_rterm: /* empty */
{ {
$$ = new Value(make_shared<Expression>(&Expression::OpLiteral, Empty, DebugInfo())); $$ = new Value(MakeLiteral(Empty));
} }
| rterm | rterm
{ {
@ -904,8 +887,8 @@ apply:
{ {
m_Apply.push(true); m_Apply.push(true);
m_SeenAssign.push(false); m_SeenAssign.push(false);
m_Assign.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo())); m_Assign.push(MakeLiteral(false));
m_Ignore.push(make_shared<Expression>(&Expression::OpLiteral, false, DebugInfo())); m_Ignore.push(MakeLiteral(false));
m_FKVar.push(""); m_FKVar.push("");
m_FVVar.push(""); m_FVVar.push("");
m_FTerm.push(Expression::Ptr()); m_FTerm.push(Expression::Ptr());

View File

@ -93,8 +93,8 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
Array::Ptr templateArray = make_shared<Array>(); Array::Ptr templateArray = make_shared<Array>();
templateArray->Add(m_Name); templateArray->Add(m_Name);
exprs->Add(make_shared<Expression>(&Expression::OpSetPlus, exprs->Add(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "templates", m_DebugInfo), MakeArray(MakeArray(MakeLiteral("templates")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, templateArray, m_DebugInfo), make_shared<Expression>(&Expression::OpLiteral, templateArray, m_DebugInfo),
m_DebugInfo)); m_DebugInfo));

View File

@ -312,14 +312,78 @@ Value Expression::OpDict(const Expression *expr, const Dictionary::Ptr& locals,
Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{ {
Value index = expr->EvaluateOperand1(locals); Array::Ptr left = expr->m_Operand1;
Array::Ptr indexer = left->Get(0);
int csop = left->Get(1);
DebugHint *sdhint = NULL; DebugHint *sdhint = dhint;
if (dhint)
sdhint = dhint->GetChild(index);
Value right = expr->EvaluateOperand2(locals, sdhint); Value parent, object;
locals->Set(index, right); String index;
for (Array::SizeType i = 0; i < indexer->GetLength(); i++) {
Expression::Ptr indexExpr = indexer->Get(i);
String tempindex = indexExpr->Evaluate(locals, dhint);
if (i == indexer->GetLength() - 1)
index = tempindex;
if (i == 0) {
parent = locals;
object = locals->Get(tempindex);
} else {
parent = object;
Expression::Ptr eparent = make_shared<Expression>(&Expression::OpLiteral, parent, expr->m_DebugInfo);
Expression::Ptr eindex = make_shared<Expression>(&Expression::OpLiteral, tempindex, expr->m_DebugInfo);
Expression::Ptr eip = make_shared<Expression>(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo);
object = eip->Evaluate(locals, dhint);
}
if (sdhint)
sdhint = sdhint->GetChild(index);
if (i != indexer->GetLength() - 1 && object.IsEmpty()) {
object = make_shared<Dictionary>();
Dictionary::Ptr pdict = parent;
pdict->Set(tempindex, object);
}
}
Value right = expr->EvaluateOperand2(locals, dhint);
if (csop != OpSetLiteral) {
Expression::OpCallback op;
switch (csop) {
case OpSetAdd:
op = &Expression::OpAdd;
break;
case OpSetSubtract:
op = &Expression::OpSubtract;
break;
case OpSetMultiply:
op = &Expression::OpMultiply;
break;
case OpSetDivide:
op = &Expression::OpDivide;
break;
default:
VERIFY(!"Invalid opcode.");
}
Expression::Ptr ecp = make_shared<Expression>(op,
make_shared<Expression>(&Expression::OpLiteral, object, expr->m_DebugInfo),
make_shared<Expression>(&Expression::OpLiteral, right, expr->m_DebugInfo),
expr->m_DebugInfo);
right = ecp->Evaluate(locals, dhint);
}
Dictionary::Ptr pdict = parent;
pdict->Set(index, right);
if (sdhint) if (sdhint)
sdhint->AddMessage("=", expr->m_DebugInfo); sdhint->AddMessage("=", expr->m_DebugInfo);
@ -327,146 +391,6 @@ Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, D
return right; return right;
} }
Value Expression::OpSetPlus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{
Value index = expr->EvaluateOperand1(locals);
Value left = locals->Get(index);
Expression::Ptr exp_right = expr->m_Operand2;
Dictionary::Ptr xlocals = locals;
if (exp_right->m_Operator == &Expression::OpDict) {
xlocals = left;
if (!xlocals)
xlocals = make_shared<Dictionary>();
xlocals->Set("__parent", locals);
}
DebugHint *sdhint = NULL;
if (dhint)
sdhint = dhint->GetChild(index);
Value result = left + expr->EvaluateOperand2(xlocals, sdhint);
if (exp_right->m_Operator == &Expression::OpDict) {
Dictionary::Ptr dict = result;
dict->Remove("__parent");
}
locals->Set(index, result);
if (sdhint)
sdhint->AddMessage("+=", expr->m_DebugInfo);
return result;
}
Value Expression::OpSetMinus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{
Value index = expr->EvaluateOperand1(locals);
Value left = locals->Get(index);
Expression::Ptr exp_right = expr->m_Operand2;
Dictionary::Ptr xlocals = locals;
if (exp_right->m_Operator == &Expression::OpDict) {
xlocals = left;
if (!xlocals)
xlocals = make_shared<Dictionary>();
xlocals->Set("__parent", locals);
}
DebugHint *sdhint = NULL;
if (dhint)
sdhint = dhint->GetChild(index);
Value result = left - expr->EvaluateOperand2(xlocals, sdhint);
if (exp_right->m_Operator == &Expression::OpDict) {
Dictionary::Ptr dict = result;
dict->Remove("__parent");
}
locals->Set(index, result);
if (sdhint)
sdhint->AddMessage("-=", expr->m_DebugInfo);
return result;
}
Value Expression::OpSetMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{
Value index = expr->EvaluateOperand1(locals);
Value left = locals->Get(index);
Expression::Ptr exp_right = expr->m_Operand2;
Dictionary::Ptr xlocals = locals;
if (exp_right->m_Operator == &Expression::OpDict) {
xlocals = left;
if (!xlocals)
xlocals = make_shared<Dictionary>();
xlocals->Set("__parent", locals);
}
DebugHint *sdhint = NULL;
if (dhint)
sdhint = dhint->GetChild(index);
Value result = left * expr->EvaluateOperand2(xlocals, sdhint);
if (exp_right->m_Operator == &Expression::OpDict) {
Dictionary::Ptr dict = result;
dict->Remove("__parent");
}
locals->Set(index, result);
if (sdhint)
sdhint->AddMessage("*=", expr->m_DebugInfo);
return result;
}
Value Expression::OpSetDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{
Value index = expr->EvaluateOperand1(locals);
Value left = locals->Get(index);
Expression::Ptr exp_right = expr->m_Operand2;
Dictionary::Ptr xlocals = locals;
if (exp_right->m_Operator == &Expression::OpDict) {
xlocals = left;
if (!xlocals)
xlocals = make_shared<Dictionary>();
xlocals->Set("__parent", locals);
}
DebugHint *sdhint = NULL;
if (dhint)
sdhint = dhint->GetChild(index);
Value result = left / expr->EvaluateOperand2(xlocals, sdhint);
if (exp_right->m_Operator == &Expression::OpDict) {
Dictionary::Ptr dict = result;
dict->Remove("__parent");
}
locals->Set(index, result);
if (sdhint)
sdhint->AddMessage("/=", expr->m_DebugInfo);
return result;
}
Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint) Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
{ {
Value value = expr->EvaluateOperand1(locals); Value value = expr->EvaluateOperand1(locals);
@ -692,3 +616,7 @@ Dictionary::Ptr DebugHint::ToDictionary(void) const
return result; return result;
} }
Expression::Ptr icinga::MakeLiteral(const Value& lit)
{
return make_shared<Expression>(&Expression::OpLiteral, lit, DebugInfo());
}

View File

@ -46,6 +46,15 @@ struct DebugHint
Dictionary::Ptr ToDictionary(void) const; Dictionary::Ptr ToDictionary(void) const;
}; };
enum CombinedSetOp
{
OpSetLiteral,
OpSetAdd,
OpSetSubtract,
OpSetMultiply,
OpSetDivide
};
/** /**
* @ingroup config * @ingroup config
*/ */
@ -91,10 +100,6 @@ public:
static Value OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpSetPlus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpSetMinus(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpSetMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpSetDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint);
static Value OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint); static Value OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint);
@ -117,6 +122,8 @@ private:
const Expression::Ptr& expr, const Dictionary::Ptr& scope); const Expression::Ptr& expr, const Dictionary::Ptr& scope);
}; };
I2_CONFIG_API Expression::Ptr MakeLiteral(const Value& lit = Value());
} }
#endif /* EXPRESSION_H */ #endif /* EXPRESSION_H */

View File

@ -59,29 +59,29 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c
tie(host, service) = GetHostService(checkable); tie(host, service) = GetHostService(checkable);
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "parent_host_name", di), MakeArray(MakeArray(MakeLiteral("parent_host_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di), MakeLiteral(host->GetName()),
di)); di));
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "child_host_name", di), MakeArray(MakeArray(MakeLiteral("child_host_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di), MakeLiteral(host->GetName()),
di)); di));
if (service) { if (service) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "child_service_name", di), MakeArray(MakeArray(MakeLiteral("child_service_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di), MakeLiteral(service->GetShortName()),
di)); di));
} }
String zone = checkable->GetZone(); String zone = checkable->GetZone();
if (!zone.IsEmpty()) { if (!zone.IsEmpty()) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "zone", di), MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, zone, di), MakeLiteral(zone),
di)); di));
} }
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());

View File

@ -59,24 +59,24 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable,
tie(host, service) = GetHostService(checkable); tie(host, service) = GetHostService(checkable);
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "host_name", di), MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di), MakeLiteral(host->GetName()),
di)); di));
if (service) { if (service) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "service_name", di), MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di), MakeLiteral(service->GetShortName()),
di)); di));
} }
String zone = checkable->GetZone(); String zone = checkable->GetZone();
if (!zone.IsEmpty()) { if (!zone.IsEmpty()) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "zone", di), MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, zone, di), MakeLiteral(zone),
di)); di));
} }
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());

View File

@ -58,24 +58,24 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
tie(host, service) = GetHostService(checkable); tie(host, service) = GetHostService(checkable);
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "host_name", di), MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di), MakeLiteral(host->GetName()),
di)); di));
if (service) { if (service) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "service_name", di), MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, service->GetShortName(), di), MakeLiteral(service->GetShortName()),
di)); di));
} }
String zone = checkable->GetZone(); String zone = checkable->GetZone();
if (!zone.IsEmpty()) { if (!zone.IsEmpty()) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "zone", di), MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, zone, di), MakeLiteral(zone),
di)); di));
} }
builder->AddExpression(rule.GetExpression()); builder->AddExpression(rule.GetExpression());

View File

@ -53,21 +53,21 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
builder->SetScope(locals); builder->SetScope(locals);
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "host_name", di), MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, host->GetName(), di), MakeLiteral(host->GetName()),
di)); di));
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "name", di), MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, name, di), MakeLiteral(name),
di)); di));
String zone = host->GetZone(); String zone = host->GetZone();
if (!zone.IsEmpty()) { if (!zone.IsEmpty()) {
builder->AddExpression(make_shared<Expression>(&Expression::OpSet, builder->AddExpression(make_shared<Expression>(&Expression::OpSet,
make_shared<Expression>(&Expression::OpLiteral, "zone", di), MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
make_shared<Expression>(&Expression::OpLiteral, zone, di), MakeLiteral(zone),
di)); di));
} }