]> granicus.if.org Git - icinga2/commitdiff
Refactor the AST
authorGunnar Beutner <gunnar@beutner.name>
Sun, 9 Nov 2014 18:48:28 +0000 (19:48 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Mon, 10 Nov 2014 11:06:25 +0000 (12:06 +0100)
refs #7622

16 files changed:
lib/config/applyrule.cpp
lib/config/applyrule.hpp
lib/config/config_lexer.ll
lib/config/config_parser.yy
lib/config/configitem.cpp
lib/config/configitem.hpp
lib/config/configitembuilder.cpp
lib/config/configitembuilder.hpp
lib/config/expression.cpp
lib/config/expression.hpp
lib/config/objectrule.cpp
lib/config/objectrule.hpp
lib/icinga/dependency-apply.cpp
lib/icinga/notification-apply.cpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/service-apply.cpp

index 8509fd00d67176161952a83a78f710ea55f387d5..d013c6b0a790dee3cd6e7fbec0cc26fc14e7f55b 100644 (file)
@@ -27,8 +27,8 @@ using namespace icinga;
 ApplyRule::RuleMap ApplyRule::m_Rules;
 ApplyRule::CallbackMap ApplyRule::m_Callbacks;
 
-ApplyRule::ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
-    const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm,
+ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
+    const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
     const DebugInfo& di, const Object::Ptr& scope)
        : m_TargetType(targetType), m_Name(name), m_Expression(expression), m_Filter(filter), m_FKVar(fkvar),
          m_FVVar(fvvar), m_FTerm(fterm), m_DebugInfo(di), m_Scope(scope)
@@ -44,12 +44,12 @@ String ApplyRule::GetName(void) const
        return m_Name;
 }
 
-Expression::Ptr ApplyRule::GetExpression(void) const
+boost::shared_ptr<Expression> ApplyRule::GetExpression(void) const
 {
        return m_Expression;
 }
 
-Expression::Ptr ApplyRule::GetFilter(void) const
+boost::shared_ptr<Expression> ApplyRule::GetFilter(void) const
 {
        return m_Filter;
 }
@@ -64,7 +64,7 @@ String ApplyRule::GetFVVar(void) const
        return m_FVVar;
 }
 
-Expression::Ptr ApplyRule::GetFTerm(void) const
+boost::shared_ptr<Expression> ApplyRule::GetFTerm(void) const
 {
        return m_FTerm;
 }
@@ -80,8 +80,8 @@ Object::Ptr ApplyRule::GetScope(void) const
 }
 
 void ApplyRule::AddRule(const String& sourceType, const String& targetType, const String& name,
-    const Expression::Ptr& expression, const Expression::Ptr& filter, const String& fkvar,
-    const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Object::Ptr& scope)
+    const boost::shared_ptr<Expression>& expression, const boost::shared_ptr<Expression>& filter, const String& fkvar,
+    const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Object::Ptr& scope)
 {
        m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fkvar, fvvar, fterm, di, scope));
 }
index 4682bfe0f91d11a851405760b629ae479db667ac..015556672e4fe7ca37cd439f3388085449c52902 100644 (file)
@@ -40,18 +40,18 @@ public:
 
        String GetTargetType(void) const;
        String GetName(void) const;
-       Expression::Ptr GetExpression(void) const;
-       Expression::Ptr GetFilter(void) const;
+       boost::shared_ptr<Expression> GetExpression(void) const;
+       boost::shared_ptr<Expression> GetFilter(void) const;
        String GetFKVar(void) const;
        String GetFVVar(void) const;
-       Expression::Ptr GetFTerm(void) const;
+       boost::shared_ptr<Expression> GetFTerm(void) const;
        DebugInfo GetDebugInfo(void) const;
        Object::Ptr GetScope(void) const;
 
        bool EvaluateFilter(const Object::Ptr& scope) const;
 
-       static void AddRule(const String& sourceType, const String& targetType, const String& name, const Expression::Ptr& expression,
-           const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, const DebugInfo& di, const Object::Ptr& scope);
+       static void AddRule(const String& sourceType, const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
+           const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Object::Ptr& scope);
        static void EvaluateRules(bool clear);
 
        static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes, const ApplyRule::Callback& callback);
@@ -62,19 +62,19 @@ public:
 private:
        String m_TargetType;
        String m_Name;
-       Expression::Ptr m_Expression;
-       Expression::Ptr m_Filter;
+       boost::shared_ptr<Expression> m_Expression;
+       boost::shared_ptr<Expression> m_Filter;
        String m_FKVar;
        String m_FVVar;
-       Expression::Ptr m_FTerm;
+       boost::shared_ptr<Expression> m_FTerm;
        DebugInfo m_DebugInfo;
        Object::Ptr m_Scope;
 
        static CallbackMap m_Callbacks;
        static RuleMap m_Rules;
 
-       ApplyRule(const String& targetType, const String& name, const Expression::Ptr& expression,
-           const Expression::Ptr& filter, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm,
+       ApplyRule(const String& targetType, const String& name, const boost::shared_ptr<Expression>& expression,
+           const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
            const DebugInfo& di, const Object::Ptr& scope);
 };
 
index a578707fbd0c6d93159752f148191643c869c70a..90f03577bb057f56080e14e3d08ee054759283fa 100644 (file)
@@ -234,16 +234,16 @@ __function                        return T_FUNCTION;
 __return                       return T_RETURN;
 __for                          return T_FOR;
 =\>                            return T_FOLLOWS;
-\<\<                           { yylval->op = &Expression::OpShiftLeft; return T_SHIFT_LEFT; }
-\>\>                           { yylval->op = &Expression::OpShiftRight; return T_SHIFT_RIGHT; }
-\<=                            { yylval->op = &Expression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; }
-\>=                            { yylval->op = &Expression::OpGreaterThanOrEqual; return T_GREATER_THAN_OR_EQUAL; }
-==                             { yylval->op = &Expression::OpEqual; return T_EQUAL; }
-!=                             { yylval->op = &Expression::OpNotEqual; return T_NOT_EQUAL; }
-!in                            { yylval->op = &Expression::OpNotIn; return T_NOT_IN; }
-in                             { yylval->op = &Expression::OpIn; return T_IN; }
-&&                             { yylval->op = &Expression::OpLogicalAnd; return T_LOGICAL_AND; }
-\|\|                           { yylval->op = &Expression::OpLogicalOr; return T_LOGICAL_OR; }
+\<\<                           return T_SHIFT_LEFT;
+\>\>                           return T_SHIFT_RIGHT;
+\<=                            return T_LESS_THAN_OR_EQUAL;
+\>=                            return T_GREATER_THAN_OR_EQUAL;
+==                             return T_EQUAL;
+!=                             return T_NOT_EQUAL;
+!in                            return T_NOT_IN;
+in                             return T_IN;
+&&                             return T_LOGICAL_AND;
+\|\|                           return T_LOGICAL_OR;
 [a-zA-Z_][a-zA-Z0-9\-_]*       { yylval->text = strdup(yytext); return T_IDENTIFIER; }
 @[a-zA-Z_][a-zA-Z0-9\-_]*      { yylval->text = strdup(yytext + 1); return T_IDENTIFIER; }
 \<[^\>]*\>                     { yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING_ANGLE; }
@@ -258,14 +258,14 @@ in                                { yylval->op = &Expression::OpIn; return T_IN; }
 -=                             { yylval->csop = OpSetSubtract; return T_SET_SUBTRACT; }
 \*=                            { yylval->csop = OpSetMultiply; return T_SET_MULTIPLY; }
 \/=                            { yylval->csop = OpSetDivide; return T_SET_DIVIDE; }
-\+                             { yylval->op = &Expression::OpAdd; return T_PLUS; }
-\-                             { yylval->op = &Expression::OpSubtract; return T_MINUS; }
-\*                             { yylval->op = &Expression::OpMultiply; return T_MULTIPLY; }
-\/                             { yylval->op = &Expression::OpMultiply; return T_DIVIDE_OP; }
-\&                             { yylval->op = &Expression::OpBinaryAnd; return T_BINARY_AND; }
-\|                             { yylval->op = &Expression::OpBinaryOr; return T_BINARY_OR; }
-\<                             { yylval->op = &Expression::OpLessThan; return T_LESS_THAN; }
-\>                             { yylval->op = &Expression::OpLessThan; return T_GREATER_THAN; }
+\+                             return T_PLUS;
+\-                             return T_MINUS;
+\*                             return T_MULTIPLY;
+\/                             return T_DIVIDE_OP;
+\&                             return T_BINARY_AND;
+\|                             return T_BINARY_OR;
+\<                             return T_LESS_THAN;
+\>                             return T_GREATER_THAN;
 }
 
 [\r\n]+                                { yycolumn -= strlen(yytext) - 1; if (!ignore_newlines) return T_NEWLINE; }
index 22fcc22a9bd3d7a3cf3b0a3e84694c2c4360f91c..0e362aa6c7e46b3545e2f2aaaa724808c30d0b1a 100644 (file)
@@ -32,7 +32,6 @@
 #include "config/objectrule.hpp"
 #include "base/value.hpp"
 #include "base/utility.hpp"
-#include "base/array.hpp"
 #include "base/scriptvariable.hpp"
 #include "base/exception.hpp"
 #include "base/dynamictype.hpp"
@@ -73,11 +72,10 @@ using namespace icinga;
 
 int ignore_newlines = 0;
 
-static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *left, Value *right, DebugInfo& diLeft, DebugInfo& diRight)
+template<typename T>
+static void MakeRBinaryOp(Expression** result, Expression *left, Expression *right, DebugInfo& diLeft, DebugInfo& diRight)
 {
-       *result = new Value(new Expression(op, *left, *right, DebugInfoRange(diLeft, diRight)));
-       delete left;
-       delete right;
+       *result = new T(left, right, DebugInfoRange(diLeft, diRight));
 }
 
 %}
@@ -94,12 +92,12 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
 %union {
        char *text;
        double num;
+       icinga::Expression *expr;
        icinga::Value *variant;
-       icinga::Expression::OpCallback op;
        CombinedSetOp csop;
        icinga::TypeSpecifier type;
        std::vector<String> *slist;
-       Array *array;
+       std::vector<Expression *> *elist;
 }
 
 %token T_NEWLINE "new-line"
@@ -115,24 +113,24 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
 %token <csop> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)"
 %token <csop> T_SET_DIVIDE "/= (T_SET_DIVIDE)"
 
-%token <op> T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
-%token <op> T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
-%token <op> T_EQUAL "== (T_EQUAL)"
-%token <op> T_NOT_EQUAL "!= (T_NOT_EQUAL)"
-%token <op> T_IN "in (T_IN)"
-%token <op> T_NOT_IN "!in (T_NOT_IN)"
-%token <op> T_LOGICAL_AND "&& (T_LOGICAL_AND)"
-%token <op> T_LOGICAL_OR "|| (T_LOGICAL_OR)"
-%token <op> T_LESS_THAN_OR_EQUAL "<= (T_LESS_THAN_OR_EQUAL)"
-%token <op> T_GREATER_THAN_OR_EQUAL ">= (T_GREATER_THAN_OR_EQUAL)"
-%token <op> T_PLUS "+ (T_PLUS)"
-%token <op> T_MINUS "- (T_MINUS)"
-%token <op> T_MULTIPLY "* (T_MULTIPLY)"
-%token <op> T_DIVIDE_OP "/ (T_DIVIDE_OP)"
-%token <op> T_BINARY_AND "& (T_BINARY_AND)"
-%token <op> T_BINARY_OR "| (T_BINARY_OR)"
-%token <op> T_LESS_THAN "< (T_LESS_THAN)"
-%token <op> T_GREATER_THAN "> (T_GREATER_THAN)"
+%token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
+%token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
+%token T_EQUAL "== (T_EQUAL)"
+%token T_NOT_EQUAL "!= (T_NOT_EQUAL)"
+%token T_IN "in (T_IN)"
+%token T_NOT_IN "!in (T_NOT_IN)"
+%token T_LOGICAL_AND "&& (T_LOGICAL_AND)"
+%token T_LOGICAL_OR "|| (T_LOGICAL_OR)"
+%token T_LESS_THAN_OR_EQUAL "<= (T_LESS_THAN_OR_EQUAL)"
+%token T_GREATER_THAN_OR_EQUAL ">= (T_GREATER_THAN_OR_EQUAL)"
+%token T_PLUS "+ (T_PLUS)"
+%token T_MINUS "- (T_MINUS)"
+%token T_MULTIPLY "* (T_MULTIPLY)"
+%token T_DIVIDE_OP "/ (T_DIVIDE_OP)"
+%token T_BINARY_AND "& (T_BINARY_AND)"
+%token T_BINARY_OR "| (T_BINARY_OR)"
+%token T_LESS_THAN "< (T_LESS_THAN)"
+%token T_GREATER_THAN "> (T_GREATER_THAN)"
 
 %token T_CONST "const (T_CONST)"
 %token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
@@ -165,25 +163,25 @@ static void MakeRBinaryOp(Value** result, Expression::OpCallback& op, Value *lef
 %token T_FOLLOWS "=> (T_FOLLOWS)"
 
 %type <text> identifier
-%type <array> rterm_items
-%type <array> rterm_items_inner
-%type <array> identifier_items
-%type <array> identifier_items_inner
-%type <array> indexer
-%type <array> indexer_items
-%type <variant> indexer_item
-%type <array> lterm_items
-%type <array> lterm_items_inner
+%type <elist> rterm_items
+%type <elist> rterm_items_inner
+%type <slist> identifier_items
+%type <slist> identifier_items_inner
+%type <elist> indexer
+%type <elist> indexer_items
+%type <expr> indexer_item
+%type <elist> lterm_items
+%type <elist> lterm_items_inner
 %type <variant> typerulelist
 %type <csop> combined_set_op
 %type <type> type
-%type <variant> rterm
-%type <variant> rterm_array
-%type <variant> rterm_scope
-%type <variant> lterm
-%type <variant> object
-%type <variant> apply
-%type <variant> optional_rterm
+%type <expr> rterm
+%type <expr> rterm_array
+%type <expr> rterm_scope
+%type <expr> lterm
+%type <expr> object
+%type <expr> apply
+%type <expr> optional_rterm
 %type <text> target_type_specifier
 
 %left T_LOGICAL_OR
@@ -223,11 +221,11 @@ static Dictionary::Ptr m_ModuleScope;
 static std::stack<bool> m_Apply;
 static std::stack<bool> m_ObjectAssign;
 static std::stack<bool> m_SeenAssign;
-static std::stack<Expression::Ptr> m_Assign;
-static std::stack<Expression::Ptr> m_Ignore;
+static std::stack<Expression *> m_Assign;
+static std::stack<Expression *> m_Ignore;
 static std::stack<String> m_FKVar;
 static std::stack<String> m_FVVar;
-static std::stack<Expression::Ptr> m_FTerm;
+static std::stack<Expression *> m_FTerm;
 
 void ConfigCompiler::Compile(void)
 {
@@ -239,11 +237,11 @@ void ConfigCompiler::Compile(void)
        m_Apply = std::stack<bool>();
        m_ObjectAssign = std::stack<bool>();
        m_SeenAssign = std::stack<bool>();
-       m_Assign = std::stack<Expression::Ptr>();
-       m_Ignore = std::stack<Expression::Ptr>();
+       m_Assign = std::stack<Expression *>();
+       m_Ignore = std::stack<Expression *>();
        m_FKVar = std::stack<String>();
        m_FVVar = std::stack<String>();
-       m_FTerm = std::stack<Expression::Ptr>();
+       m_FTerm = std::stack<Expression *>();
 
        try {
                yyparse(this);
@@ -270,18 +268,15 @@ statement: type | include | include_recursive | library | constant
        { }
        | lterm
        {
-               Expression::Ptr aexpr = *$1;
-               aexpr->Evaluate(m_ModuleScope);
+               $1->Evaluate(m_ModuleScope);
                delete $1;
        }
        ;
 
 include: T_INCLUDE rterm sep
        {
-               Expression::Ptr aexpr = *$2;
+               context->HandleInclude($2->Evaluate(m_ModuleScope), false, DebugInfoRange(@1, @2));
                delete $2;
-
-               context->HandleInclude(aexpr->Evaluate(m_ModuleScope), false, DebugInfoRange(@1, @2));
        }
        | T_INCLUDE T_STRING_ANGLE
        {
@@ -292,20 +287,14 @@ include: T_INCLUDE rterm sep
 
 include_recursive: T_INCLUDE_RECURSIVE rterm
        {
-               Expression::Ptr aexpr = *$2;
+               context->HandleIncludeRecursive($2->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2));
                delete $2;
-
-               context->HandleIncludeRecursive(aexpr->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2));
        }
        | T_INCLUDE_RECURSIVE rterm ',' rterm
        {
-               Expression::Ptr aexpr1 = *$2;
+               context->HandleIncludeRecursive($2->Evaluate(m_ModuleScope), $4->Evaluate(m_ModuleScope), DebugInfoRange(@1, @4));
                delete $2;
-
-               Expression::Ptr aexpr2 = *$4;
                delete $4;
-
-               context->HandleIncludeRecursive(aexpr1->Evaluate(m_ModuleScope), aexpr2->Evaluate(m_ModuleScope), DebugInfoRange(@1, @4));
        }
        ;
 
@@ -318,13 +307,11 @@ library: T_LIBRARY T_STRING sep
 
 constant: T_CONST identifier T_SET rterm sep
        {
-               Expression::Ptr aexpr = *$4;
+               ScriptVariable::Ptr sv = ScriptVariable::Set($2, $4->Evaluate(m_ModuleScope));
+               free($2);
                delete $4;
 
-               ScriptVariable::Ptr sv = ScriptVariable::Set($2, aexpr->Evaluate(m_ModuleScope));
                sv->SetConstant(true);
-
-               free($2);
        }
        ;
 
@@ -447,20 +434,13 @@ object:
        {
                m_ObjectAssign.pop();
 
-               Array::Ptr args = new Array();
-               
-               args->Add(m_Abstract.top());
+               bool abstract = m_Abstract.top();
                m_Abstract.pop();
 
                String type = $3;
-               args->Add(type);
                free($3);
 
-               args->Add(*$4);
-               delete $4;
-
-               Expression::Ptr exprl = *$5;
-               delete $5;
+               DictExpression *exprl = dynamic_cast<DictExpression *>($5);
                exprl->MakeInline();
 
                if (m_SeenAssign.top() && !ObjectRule::IsValidSourceType(type))
@@ -468,17 +448,13 @@ object:
 
                m_SeenAssign.pop();
 
-               Expression::Ptr rex = new Expression(&Expression::OpLogicalNegate, m_Ignore.top(), DebugInfoRange(@2, @5));
+               Expression *rex = new LogicalNegateExpression(m_Ignore.top(), DebugInfoRange(@2, @5));
                m_Ignore.pop();
 
-               Expression::Ptr filter = new Expression(&Expression::OpLogicalAnd, m_Assign.top(), rex, DebugInfoRange(@2, @5));
+               Expression *filter = new LogicalAndExpression(m_Assign.top(), rex, DebugInfoRange(@2, @5));
                m_Assign.pop();
 
-               args->Add(filter);
-
-               args->Add(context->GetZone());
-
-               $$ = new Value(new Expression(&Expression::OpObject, args, exprl, DebugInfoRange(@2, @5)));
+               $$ = new ObjectExpression(abstract, type, $4, filter, context->GetZone(), exprl, DebugInfoRange(@2, @5));
        }
        ;
 
@@ -500,12 +476,12 @@ identifier_items: identifier_items_inner
 
 identifier_items_inner: /* empty */
        {
-               $$ = new Array();
+               $$ = new std::vector<String>();
        }
        | identifier
        {
-               $$ = new Array();
-               $$->Add($1);
+               $$ = new std::vector<String>();
+               $$->push_back($1);
                free($1);
        }
        | identifier_items_inner ',' identifier
@@ -513,44 +489,42 @@ identifier_items_inner: /* empty */
                if ($1)
                        $$ = $1;
                else
-                       $$ = new Array();
+                       $$ = new std::vector<String>();
 
-               $$->Add($3);
+               $$->push_back($3);
                free($3);
        }
        ;
 
 indexer: identifier
        {
-               $$ = new Array();
-               $$->Add(MakeLiteral($1));
+               $$ = new std::vector<Expression *>();
+               $$->push_back(MakeLiteral($1));
                free($1);
        }
        | identifier indexer_items
        {
                $$ = $2;
-               $$->Insert(0, MakeLiteral($1));
+               $$->insert($$->begin(), MakeLiteral($1));
                free($1);
        }
        ;
 
 indexer_items: indexer_item
        {
-               $$ = new Array();
-               $$->Add(*$1);
-               delete $1;
+               $$ = new std::vector<Expression *>();
+               $$->push_back($1);
        }
        | indexer_items indexer_item
        {
                $$ = $1;
-               $$->Add(*$2);
-               delete $2;
+               $$->push_back($2);
        }
        ;
 
 indexer_item: '.' identifier
        {
-               $$ = new Value(MakeLiteral($2));
+               $$ = MakeLiteral($2);
                free($2);
        }
        | '[' rterm ']'
@@ -571,7 +545,7 @@ combined_set_op: T_SET
 
 lterm_items: /* empty */
        {
-               $$ = new Array();
+               $$ = new std::vector<Expression *>();
        }
        | lterm_items_inner
        {
@@ -584,32 +558,29 @@ lterm_items: /* empty */
 
 lterm_items_inner: lterm
        {
-               $$ = new Array();
-               $$->Add(*$1);
-               delete $1;
+               $$ = new std::vector<Expression *>();
+               $$->push_back($1);
        }
        | lterm_items_inner sep lterm
        {
                if ($1)
                        $$ = $1;
                else
-                       $$ = new Array();
+                       $$ = new std::vector<Expression *>();
 
-               $$->Add(*$3);
-               delete $3;
+               $$->push_back($3);
        }
        ;
 
 lterm: indexer combined_set_op rterm
        {
-               $$ = new Value(new Expression(&Expression::OpSet, MakeArray(Array::Ptr($1), $2), *$3, DebugInfoRange(@1, @3)));
-               delete $3;
+               $$ = new SetExpression(*$1, $2, $3, DebugInfoRange(@1, @3));
+               delete $1;
        }
        | T_IMPORT rterm
        {
-               Expression::Ptr avar = new Expression(&Expression::OpVariable, "type", DebugInfoRange(@1, @2));
-               $$ = new Value(new Expression(&Expression::OpImport, avar, *$2, DebugInfoRange(@1, @2)));
-               delete $2;
+               Expression *avar = new VariableExpression("type", DebugInfoRange(@1, @2));
+               $$ = new ImportExpression(avar, $2, DebugInfoRange(@1, @2));
        }
        | T_ASSIGN T_WHERE rterm
        {
@@ -618,27 +589,24 @@ lterm: indexer combined_set_op rterm
 
                m_SeenAssign.top() = true;
 
-               m_Assign.top() = new Expression(&Expression::OpLogicalOr, m_Assign.top(), *$3, DebugInfoRange(@1, @3));
-               delete $3;
+               m_Assign.top() = new LogicalOrExpression(m_Assign.top(), $3, DebugInfoRange(@1, @3));
 
-               $$ = new Value(MakeLiteral());
+               $$ = MakeLiteral();
        }
        | T_IGNORE T_WHERE rterm
        {
                if ((m_Apply.empty() || !m_Apply.top()) && (m_ObjectAssign.empty() || !m_ObjectAssign.top()))
                        BOOST_THROW_EXCEPTION(ConfigError("'ignore' keyword not valid in this context."));
 
-               m_Ignore.top() = new Expression(&Expression::OpLogicalOr, m_Ignore.top(), *$3, DebugInfoRange(@1, @3));
-               delete $3;
+               m_Ignore.top() = new LogicalOrExpression(m_Ignore.top(), $3, DebugInfoRange(@1, @3));
 
-               $$ = new Value(MakeLiteral());
+               $$ = MakeLiteral();
        }
        | T_RETURN rterm
        {
-               Expression::Ptr aname = MakeLiteral("__result");
-               $$ = new Value(new Expression(&Expression::OpSet, MakeArray(MakeArray(MakeLiteral(aname)), OpSetLiteral), *$2, DebugInfoRange(@1, @2)));
-               delete $2;
-
+               std::vector<Expression *> vname;
+               vname.push_back(MakeLiteral("__result"));
+               $$ = new SetExpression(vname, OpSetLiteral, $2, DebugInfoRange(@1, @2));
        }
        | apply
        {
@@ -656,7 +624,7 @@ lterm: indexer combined_set_op rterm
        
 rterm_items: /* empty */
        {
-               $$ = new Array();
+               $$ = new std::vector<Expression *>();
        }
        | rterm_items_inner
        {
@@ -670,98 +638,99 @@ rterm_items: /* empty */
 
 rterm_items_inner: rterm
        {
-               $$ = new Array();
-               $$->Add(*$1);
-               delete $1;
+               $$ = new std::vector<Expression *>();
+               $$->push_back($1);
        }
        | rterm_items_inner arraysep rterm
        {
                $$ = $1;
-               $$->Add(*$3);
-               delete $3;
+               $$->push_back($3);
        }
        ;
 
 rterm_array: '[' newlines rterm_items newlines ']'
        {
-               $$ = new Value(new Expression(&Expression::OpArray, Array::Ptr($3), DebugInfoRange(@1, @5)));
+               $$ = new ArrayExpression(*$3, DebugInfoRange(@1, @5));
+               delete $3;
        }
        | '[' newlines rterm_items ']'
        {
-               $$ = new Value(new Expression(&Expression::OpArray, Array::Ptr($3), DebugInfoRange(@1, @4)));
+               $$ = new ArrayExpression(*$3, DebugInfoRange(@1, @4));
+               delete $3;
        }
        | '[' rterm_items newlines ']'
        {
-               $$ = new Value(new Expression(&Expression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @4)));
+               $$ = new ArrayExpression(*$2, DebugInfoRange(@1, @4));
+               delete $2;
        }
        | '[' rterm_items ']'
        {
-               $$ = new Value(new Expression(&Expression::OpArray, Array::Ptr($2), DebugInfoRange(@1, @3)));
+               $$ = new ArrayExpression(*$2, DebugInfoRange(@1, @3));
+               delete $2;
        }
        ;
 
 rterm_scope: '{' newlines lterm_items newlines '}'
        {
-               $$ = new Value(new Expression(&Expression::OpDict, Array::Ptr($3), DebugInfoRange(@1, @5)));
+               $$ = new DictExpression(*$3, DebugInfoRange(@1, @5));
+               delete $3;
        }
        | '{' newlines lterm_items '}'
        {
-               $$ = new Value(new Expression(&Expression::OpDict, Array::Ptr($3), DebugInfoRange(@1, @4)));
+               $$ = new DictExpression(*$3, DebugInfoRange(@1, @4));
+               delete $3;
        }
        | '{' lterm_items newlines '}'
        {
-               $$ = new Value(new Expression(&Expression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @4)));
+               $$ = new DictExpression(*$2, DebugInfoRange(@1, @4));
+               delete $2;
        }
        | '{' lterm_items '}'
        {
-               $$ = new Value(new Expression(&Expression::OpDict, Array::Ptr($2), DebugInfoRange(@1, @3)));
+               $$ = new DictExpression(*$2, DebugInfoRange(@1, @3));
+               delete $2;
        }
        ;
 
 rterm: T_STRING
        {
-               $$ = new Value(MakeLiteral($1));
+               $$ = MakeLiteral($1);
                free($1);
        }
        | T_NUMBER
        {
-               $$ = new Value(MakeLiteral($1));
+               $$ = MakeLiteral($1);
        }
        | T_NULL
        {
-               $$ = new Value(MakeLiteral());
+               $$ = MakeLiteral();
        }
        | rterm '.' T_IDENTIFIER
        {
-               $$ = new Value(new Expression(&Expression::OpIndexer, *$1, MakeLiteral($3), DebugInfoRange(@1, @3)));
-               delete $1;
+               $$ = new IndexerExpression($1, MakeLiteral($3), DebugInfoRange(@1, @3));
                free($3);
        }
        | rterm '(' rterm_items ')'
        {
-               $$ = new Value(new Expression(&Expression::OpFunctionCall, *$1, MakeLiteral(Array::Ptr($3)), DebugInfoRange(@1, @4)));
-               delete $1;
+               $$ = new FunctionCallExpression($1, *$3, DebugInfoRange(@1, @4));
+               delete $3;
        }
        | T_IDENTIFIER
        {
-               $$ = new Value(new Expression(&Expression::OpVariable, $1, @1));
+               $$ = new VariableExpression($1, @1);
                free($1);
        }
        | '!' rterm
        {
-               $$ = new Value(new Expression(&Expression::OpLogicalNegate, *$2, DebugInfoRange(@1, @2)));
-               delete $2;
+               $$ = new LogicalNegateExpression($2, DebugInfoRange(@1, @2));
        }
        | '~' rterm
        {
-               $$ = new Value(new Expression(&Expression::OpNegate, *$2, DebugInfoRange(@1, @2)));
-               delete $2;
+               $$ = new NegateExpression($2, DebugInfoRange(@1, @2));
        }
        | rterm '[' rterm ']'
        {
-               $$ = new Value(new Expression(&Expression::OpIndexer, *$1, *$3, DebugInfoRange(@1, @4)));
-               delete $1;
-               delete $3;
+               $$ = new IndexerExpression($1, $3, DebugInfoRange(@1, @4));
        }
        | rterm_array
        {
@@ -780,62 +749,50 @@ rterm: T_STRING
                ignore_newlines--;
                $$ = $3;
        }
-       | rterm T_LOGICAL_OR rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_LOGICAL_AND rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_BINARY_OR rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_BINARY_AND rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_IN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_NOT_IN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_NOT_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_LESS_THAN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_LESS_THAN_OR_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_GREATER_THAN rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_GREATER_THAN_OR_EQUAL rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_SHIFT_LEFT rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_SHIFT_RIGHT rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_PLUS rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_MINUS rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_MULTIPLY rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
-       | rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $2, $1, $3, @1, @3); }
+       | rterm T_LOGICAL_OR rterm { MakeRBinaryOp<LogicalOrExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_LOGICAL_AND rterm { MakeRBinaryOp<LogicalAndExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_BINARY_OR rterm { MakeRBinaryOp<BinaryOrExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_BINARY_AND rterm { MakeRBinaryOp<BinaryAndExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_IN rterm { MakeRBinaryOp<InExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_NOT_IN rterm { MakeRBinaryOp<NotInExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_EQUAL rterm { MakeRBinaryOp<EqualExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_NOT_EQUAL rterm { MakeRBinaryOp<NotEqualExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_LESS_THAN rterm { MakeRBinaryOp<LessThanExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_LESS_THAN_OR_EQUAL rterm { MakeRBinaryOp<LessThanOrEqualExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_GREATER_THAN rterm { MakeRBinaryOp<GreaterThanExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_GREATER_THAN_OR_EQUAL rterm { MakeRBinaryOp<GreaterThanOrEqualExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_SHIFT_LEFT rterm { MakeRBinaryOp<ShiftLeftExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_SHIFT_RIGHT rterm { MakeRBinaryOp<ShiftRightExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_PLUS rterm { MakeRBinaryOp<AddExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_MINUS rterm { MakeRBinaryOp<SubtractExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_MULTIPLY rterm { MakeRBinaryOp<MultiplyExpression>(&$$, $1, $3, @1, @3); }
+       | rterm T_DIVIDE_OP rterm { MakeRBinaryOp<DivideExpression>(&$$, $1, $3, @1, @3); }
        | T_FUNCTION identifier '(' identifier_items ')' rterm_scope
        {
-               Expression::Ptr aexpr = *$6;
-               delete $6;
+               DictExpression *aexpr = dynamic_cast<DictExpression *>($6);
                aexpr->MakeInline();
 
-               $$ = new Value(new Expression(&Expression::OpFunction, MakeArray($2, aexpr), Array::Ptr($4), DebugInfoRange(@1, @6)));
+               $$ = new FunctionExpression($2, *$4, aexpr, DebugInfoRange(@1, @6));
                free($2);
+               delete $4;
        }
        | T_FUNCTION '(' identifier_items ')' rterm_scope
        {
-               Expression::Ptr aexpr = *$5;
-               delete $5;
+               DictExpression *aexpr = dynamic_cast<DictExpression *>($5);
                aexpr->MakeInline();
 
-               $$ = new Value(new Expression(&Expression::OpFunction, MakeArray(Empty, aexpr), Array::Ptr($3), DebugInfoRange(@1, @5)));
+               $$ = new FunctionExpression("", *$3, aexpr, DebugInfoRange(@1, @5));
+               delete $3;
        }
        | T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope
        {
-               Expression::Ptr aexpr = *$7;
-               delete $7;
-
-               Expression::Ptr ascope = *$9;
-               delete $9;
-
-               $$ = new Value(new Expression(&Expression::OpFor, MakeArray($3, $5, aexpr), ascope, DebugInfoRange(@1, @9)));
+               $$ = new ForExpression($3, $5, $7, $9, DebugInfoRange(@1, @9));
                free($3);
                free($5);
        }
        | T_FOR '(' identifier T_IN rterm ')' rterm_scope
        {
-               Expression::Ptr aexpr = *$5;
-               delete $5;
-
-               Expression::Ptr ascope = *$7;
-               delete $7;
-
-               $$ = new Value(new Expression(&Expression::OpFor, MakeArray($3, Empty, aexpr), ascope, DebugInfoRange(@1, @7)));
+               $$ = new ForExpression($3, "", $5, $7, DebugInfoRange(@1, @7));
                free($3);
        }
        ;
@@ -859,8 +816,7 @@ apply_for_specifier: /* empty */
                m_FVVar.top() = $5;
                free($5);
 
-               m_FTerm.top() = *$7;
-               delete $7;
+               m_FTerm.top() = $7;
        }
        | T_APPLY_FOR '(' identifier T_IN rterm ')'
        {
@@ -869,14 +825,13 @@ apply_for_specifier: /* empty */
 
                m_FVVar.top() = "";
 
-               m_FTerm.top() = *$5;
-               delete $5;
+               m_FTerm.top() = $5;
        }
        ;
 
 optional_rterm: /* empty */
        {
-               $$ = new Value(MakeLiteral(Empty));
+               $$ = MakeLiteral();
        }
        | rterm
        {
@@ -892,7 +847,7 @@ apply:
                m_Ignore.push(MakeLiteral(false));
                m_FKVar.push("");
                m_FVVar.push("");
-               m_FTerm.push(Expression::Ptr());
+               m_FTerm.push(NULL);
        }
        T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier rterm
        {
@@ -900,8 +855,6 @@ apply:
 
                String type = $3;
                free($3);
-               Expression::Ptr aname = *$4;
-               delete $4;
                String target = $6;
                free($6);
 
@@ -929,9 +882,7 @@ apply:
                                BOOST_THROW_EXCEPTION(ConfigError("'apply' target type '" + target + "' is invalid") << errinfo_debuginfo(DebugInfoRange(@2, @5)));
                }
 
-               Expression::Ptr exprl = *$7;
-               delete $7;
-
+               DictExpression *exprl = dynamic_cast<DictExpression *>($7);
                exprl->MakeInline();
 
                // assign && !ignore
@@ -940,10 +891,10 @@ apply:
 
                m_SeenAssign.pop();
 
-               Expression::Ptr rex = new Expression(&Expression::OpLogicalNegate, m_Ignore.top(), DebugInfoRange(@2, @5));
+               Expression *rex = new LogicalNegateExpression(m_Ignore.top(), DebugInfoRange(@2, @5));
                m_Ignore.pop();
 
-               Expression::Ptr filter = new Expression(&Expression::OpLogicalAnd, m_Assign.top(), rex, DebugInfoRange(@2, @5));
+               Expression *filter = new LogicalAndExpression(m_Assign.top(), rex, DebugInfoRange(@2, @5));
                m_Assign.pop();
 
                String fkvar = m_FKVar.top();
@@ -952,19 +903,10 @@ apply:
                String fvvar = m_FVVar.top();
                m_FVVar.pop();
 
-               Expression::Ptr fterm = m_FTerm.top();
+               Expression *fterm = m_FTerm.top();
                m_FTerm.pop();
 
-               Array::Ptr args = new Array();
-               args->Add(type);
-               args->Add(target);
-               args->Add(aname);
-               args->Add(filter);
-               args->Add(fkvar);
-               args->Add(fvvar);
-               args->Add(fterm);
-
-               $$ = new Value(new Expression(&Expression::OpApply, args, exprl, DebugInfoRange(@2, @5)));
+               $$ = new ApplyExpression(type, target, $4, filter, fkvar, fvvar, fterm, exprl, DebugInfoRange(@2, @5));
        }
        ;
 
index 65c1da06392c539f99311d31b0533a7ea27d2421..53ac6e31711b05e44e7cdbd5d5f895fc1c98729a 100644 (file)
@@ -56,11 +56,11 @@ ConfigItem::ItemList ConfigItem::m_UnnamedItems;
  * @param debuginfo Debug information.
  */
 ConfigItem::ConfigItem(const String& type, const String& name,
-    bool abstract, const Expression::Ptr& exprl,
+    bool abstract, const boost::shared_ptr<Expression>& exprl,
     const DebugInfo& debuginfo, const Object::Ptr& scope,
     const String& zone)
        : m_Type(type), m_Name(name), m_Abstract(abstract),
-         m_ExpressionList(exprl), m_DebugInfo(debuginfo),
+         m_Expression(exprl), m_DebugInfo(debuginfo),
          m_Scope(scope), m_Zone(zone)
 {
 }
@@ -115,9 +115,9 @@ Object::Ptr ConfigItem::GetScope(void) const
  *
  * @returns The expression list.
  */
-Expression::Ptr ConfigItem::GetExpressionList(void) const
+boost::shared_ptr<Expression> ConfigItem::GetExpression(void) const
 {
-       return m_ExpressionList;
+       return m_Expression;
 }
 
 /**
@@ -160,7 +160,7 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        DebugHint debugHints;
 
        try {
-               m_ExpressionList->Evaluate(dobj, &debugHints);
+               m_Expression->Evaluate(dobj, &debugHints);
        } catch (const ConfigError& ex) {
                const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
                ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
@@ -169,7 +169,7 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        }
 
        if (discard)
-               m_ExpressionList.reset();
+               m_Expression.reset();
 
        dobj->SetParentScope(Dictionary::Ptr());
 
index ea6bd6d0632f2fa717ac7b619fc3dab14f382654..51a74fcccf7ccb036c07c733f2cc1764c46a12a1 100644 (file)
@@ -38,7 +38,7 @@ public:
        DECLARE_PTR_TYPEDEFS(ConfigItem);
 
        ConfigItem(const String& type, const String& name, bool abstract,
-           const Expression::Ptr& exprl, const DebugInfo& debuginfo,
+           const boost::shared_ptr<Expression>& exprl, const DebugInfo& debuginfo,
            const Object::Ptr& scope, const String& zone);
 
        String GetType(void) const;
@@ -47,7 +47,7 @@ public:
 
        std::vector<ConfigItem::Ptr> GetParents(void) const;
 
-       Expression::Ptr GetExpressionList(void) const;
+       boost::shared_ptr<Expression> GetExpression(void) const;
 
        DynamicObject::Ptr Commit(bool discard = true);
        void Register(void);
@@ -70,7 +70,7 @@ private:
        String m_Name; /**< The name. */
        bool m_Abstract; /**< Whether this is a template. */
 
-       Expression::Ptr m_ExpressionList;
+       boost::shared_ptr<Expression> m_Expression;
        std::vector<String> m_ParentNames; /**< The names of parent configuration
                                       items. */
        DebugInfo m_DebugInfo; /**< Debug information. */
index 7820aedf26cf9456a4914022004eb3c753e26203..994a9dac2986102de9c9b7ecb52fa16917f78f75 100644 (file)
@@ -25,7 +25,7 @@
 using namespace icinga;
 
 ConfigItemBuilder::ConfigItemBuilder(void)
-       : m_Abstract(false), m_Expressions(new Array())
+       : m_Abstract(false)
 {
        m_DebugInfo.FirstLine = 0;
        m_DebugInfo.FirstColumn = 0;
@@ -34,7 +34,7 @@ ConfigItemBuilder::ConfigItemBuilder(void)
 }
 
 ConfigItemBuilder::ConfigItemBuilder(const DebugInfo& debugInfo)
-       : m_Abstract(false), m_Expressions(new Array())
+       : m_Abstract(false)
 {
        m_DebugInfo = debugInfo;
 }
@@ -64,9 +64,9 @@ void ConfigItemBuilder::SetZone(const String& zone)
        m_Zone = zone;
 }
 
-void ConfigItemBuilder::AddExpression(const Expression::Ptr& expr)
+void ConfigItemBuilder::AddExpression(Expression *expr)
 {
-       m_Expressions->Add(expr);
+       m_Expressions.push_back(expr);
 }
 
 ConfigItem::Ptr ConfigItemBuilder::Compile(void)
@@ -89,19 +89,25 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
                BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
        }
 
-       Array::Ptr exprs = new Array();
+       std::vector<Expression *> exprs;
+
        Array::Ptr templateArray = new Array();
        templateArray->Add(m_Name);
 
-       exprs->Add(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("templates")), OpSetAdd),
-           new Expression(&Expression::OpLiteral, templateArray, m_DebugInfo),
-           m_DebugInfo));
+       std::vector<Expression *> indexer;
+       indexer.push_back(new LiteralExpression("templates"));
+
+       exprs.push_back(new SetExpression(indexer, OpSetAdd,
+           new LiteralExpression(templateArray), m_DebugInfo));
 
-       exprs->Add(new Expression(&Expression::OpDict, m_Expressions, true, m_DebugInfo));
-       
-       Expression::Ptr exprl = new Expression(&Expression::OpDict, exprs, true, m_DebugInfo);
+       DictExpression *dexpr = new DictExpression(m_Expressions, m_DebugInfo);
+       dexpr->MakeInline();
+       exprs.push_back(dexpr);
 
-       return new ConfigItem(m_Type, m_Name, m_Abstract, exprl,
+       DictExpression *exprl = new DictExpression(exprs, m_DebugInfo);
+       exprl->MakeInline();
+
+       return new ConfigItem(m_Type, m_Name, m_Abstract, boost::shared_ptr<Expression>(exprl),
            m_DebugInfo, m_Scope, m_Zone);
 }
+
index 923ce138ffcf9089164c3f63f66a37b7be4d3713..b9795c6cc80d9a4baf868f14325063a8fe9e18ad 100644 (file)
@@ -48,7 +48,7 @@ public:
        void SetScope(const Object::Ptr& scope);
        void SetZone(const String& zone);
 
-       void AddExpression(const Expression::Ptr& expr);
+       void AddExpression(Expression *expr);
 
        ConfigItem::Ptr Compile(void);
 
@@ -56,7 +56,7 @@ private:
        String m_Type; /**< The object type. */
        String m_Name; /**< The name. */
        bool m_Abstract; /**< Whether the item is abstract. */
-       Array::Ptr m_Expressions; /**< Expressions for this item. */
+       std::vector<Expression *> m_Expressions; /**< Expressions for this item. */
        DebugInfo m_DebugInfo; /**< Debug information. */
        Object::Ptr m_Scope; /**< variable scope. */
        String m_Zone; /**< The zone. */
index b1514d70b0953a0e50fe1f073fe14c26f45838a0..0e6cd204aaae2716105ac5a9231d6acbbea015c6 100644 (file)
 
 using namespace icinga;
 
-Expression::Expression(OpCallback op, const Value& operand1, const DebugInfo& di)
-       : m_Operator(op), m_Operand1(operand1), m_Operand2(), m_DebugInfo(di)
-{ }
-
-Expression::Expression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di)
-       : m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
+Expression::~Expression(void)
 { }
 
 Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
        try {
 #ifdef _DEBUG
-               if (m_Operator != &Expression::OpLiteral) {
-                       std::ostringstream msgbuf;
-                       ShowCodeFragment(msgbuf, m_DebugInfo, false);
-                       Log(LogDebug, "Expression")
-                           << "Executing:\n" << msgbuf.str();
-               }
+               std::ostringstream msgbuf;
+               ShowCodeFragment(msgbuf, GetDebugInfo(), false);
+               Log(LogDebug, "Expression")
+                       << "Executing:\n" << msgbuf.str();
 #endif /* _DEBUG */
 
-               return m_Operator(this, context, dhint);
+               return DoEvaluate(context, dhint);
        } catch (const std::exception& ex) {
                if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
                        throw;
                else
-                       BOOST_THROW_EXCEPTION(ConfigError("Error while evaluating expression: " + String(ex.what())) << boost::errinfo_nested_exception(boost::current_exception()) << errinfo_debuginfo(m_DebugInfo));
+                       BOOST_THROW_EXCEPTION(ConfigError("Error while evaluating expression: " + String(ex.what()))
+                           << boost::errinfo_nested_exception(boost::current_exception())
+                           << errinfo_debuginfo(GetDebugInfo()));
        }
 }
 
-void Expression::MakeInline(void)
+const DebugInfo& Expression::GetDebugInfo(void) const
 {
-       if (m_Operator == &Expression::OpDict)
-               m_Operand2 = true;
-}
-
-void Expression::DumpOperand(std::ostream& stream, const Value& operand, int indent) {
-       if (operand.IsObjectType<Array>()) {
-               Array::Ptr arr = operand;
-               stream << String(indent, ' ') << "Array:\n";
-               ObjectLock olock(arr);
-               BOOST_FOREACH(const Value& elem, arr) {
-                       DumpOperand(stream, elem, indent + 1);
-               }
-       } else if (operand.IsObjectType<Expression>()) {
-               Expression::Ptr left = operand;
-               left->Dump(stream, indent);
-       } else {
-               stream << String(indent, ' ') << JsonEncode(operand) << "\n";
-       }
+       static DebugInfo debugInfo;
+       return debugInfo;
 }
 
-void Expression::Dump(std::ostream& stream, int indent) const
+std::vector<Expression *> icinga::MakeIndexer(const String& index1)
 {
-       String sym = Utility::GetSymbolName(reinterpret_cast<const void *>(m_Operator));
-       stream << String(indent, ' ') << "op: " << Utility::DemangleSymbolName(sym) << "\n";
-       stream << String(indent, ' ') << "left:\n";
-       DumpOperand(stream, m_Operand1, indent + 1);
-       
-       stream << String(indent, ' ') << "right:\n";
-       DumpOperand(stream, m_Operand2, indent + 1);
+       std::vector<Expression *> result;
+       result.push_back(MakeLiteral(index1));
+       return result;
 }
 
-Value Expression::EvaluateOperand1(const Object::Ptr& context, DebugHint *dhint) const
+void DictExpression::MakeInline(void)
 {
-       return static_cast<Expression::Ptr>(m_Operand1)->Evaluate(context, dhint);
+       m_Inline = true;
 }
 
-Value Expression::EvaluateOperand2(const Object::Ptr& context, DebugHint *dhint) const
+LiteralExpression::LiteralExpression(const Value& value)
+       : m_Value(value)
+{ }
+
+Value LiteralExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return static_cast<Expression::Ptr>(m_Operand2)->Evaluate(context, dhint);
+       return m_Value;
 }
 
-Value Expression::OpLiteral(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
 {
-       return expr->m_Operand1;
+       return m_DebugInfo;
 }
 
-Value Expression::OpVariable(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value VariableExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
        Object::Ptr scope = context;
 
        while (scope) {
-               if (HasField(scope, expr->m_Operand1))
-                       return GetField(scope, expr->m_Operand1);
+               if (HasField(scope, m_Variable))
+                       return GetField(scope, m_Variable);
 
                scope = GetField(scope, "__parent");
        }
 
-       return ScriptVariable::Get(expr->m_Operand1);
+       return ScriptVariable::Get(m_Variable);
 }
 
-Value Expression::OpNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value NegateExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return ~(long)expr->EvaluateOperand1(context);
+       return ~(long)m_Operand->Evaluate(context);
 }
 
-Value Expression::OpLogicalNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value LogicalNegateExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return !expr->EvaluateOperand1(context).ToBool();
+       return !m_Operand->Evaluate(context).ToBool();
 }
 
-Value Expression::OpAdd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value AddExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) + expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) + m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpSubtract(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value SubtractExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) - expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) - m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpMultiply(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value MultiplyExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) * expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) * m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpDivide(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value DivideExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) / expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) / m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpBinaryAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value BinaryAndExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) & expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) & m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpBinaryOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value BinaryOrExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) | expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) | m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpShiftLeft(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value ShiftLeftExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) << expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) << m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpShiftRight(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value ShiftRightExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) >> expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) >> m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value EqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) == expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) == m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpNotEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value NotEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) != expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) != m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpLessThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value LessThanExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) < expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) < m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpGreaterThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value GreaterThanExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) > expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) > m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpLessThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value LessThanOrEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) <= expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) <= m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpGreaterThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value GreaterThanOrEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context) >= expr->EvaluateOperand2(context);
+       return m_Operand1->Evaluate(context) >= m_Operand2->Evaluate(context);
 }
 
-Value Expression::OpIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value InExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Value right = expr->EvaluateOperand2(context);
+       Value right = m_Operand2->Evaluate(context);
 
        if (right.IsEmpty())
                return false;
        else if (!right.IsObjectType<Array>())
                BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonEncode(right)));
 
-       Value left = expr->EvaluateOperand1(context);
+       Value left = m_Operand1->Evaluate(context);
                
        Array::Ptr arr = right;
-       bool found = false;
        ObjectLock olock(arr);
        BOOST_FOREACH(const Value& value, arr) {
                if (value == left) {
-                       found = true;
-                       break;
+                       return true;
                }
        }
 
-       return found;
+       return false;
 }
 
-Value Expression::OpNotIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value NotInExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return !OpIn(expr, context, dhint);
+       Value right = m_Operand2->Evaluate(context);
+
+       if (right.IsEmpty())
+               return false;
+       else if (!right.IsObjectType<Array>())
+               BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonEncode(right)));
+
+       Value left = m_Operand1->Evaluate(context);
+
+       Array::Ptr arr = right;
+       ObjectLock olock(arr);
+       BOOST_FOREACH(const Value& value, arr) {
+               if (value == left)
+                       return false;
+       }
+
+       return true;
 }
 
-Value Expression::OpLogicalAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value LogicalAndExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context).ToBool() && expr->EvaluateOperand2(context).ToBool();
+       return m_Operand1->Evaluate(context).ToBool() && m_Operand2->Evaluate(context).ToBool();
 }
 
-Value Expression::OpLogicalOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value LogicalOrExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       return expr->EvaluateOperand1(context).ToBool() || expr->EvaluateOperand2(context).ToBool();
+       return m_Operand1->Evaluate(context).ToBool() || m_Operand2->Evaluate(context).ToBool();
 }
 
-Value Expression::OpFunctionCall(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value FunctionCallExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Value funcName = expr->EvaluateOperand1(context);
+       Value funcName = m_FName->Evaluate(context);
 
        ScriptFunction::Ptr func;
 
@@ -262,48 +255,37 @@ Value Expression::OpFunctionCall(const Expression *expr, const Object::Ptr& cont
        if (!func)
                BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist."));
 
-       Array::Ptr arr = expr->EvaluateOperand2(context);
        std::vector<Value> arguments;
-       for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
-               const Expression::Ptr& aexpr = arr->Get(index);
-               arguments.push_back(aexpr->Evaluate(context));
+       BOOST_FOREACH(Expression *arg, m_Args) {
+               arguments.push_back(arg->Evaluate(context));
        }
 
        return func->Invoke(arguments);
 }
 
-Value Expression::OpArray(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value ArrayExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr arr = expr->m_Operand1;
        Array::Ptr result = new Array();
 
-       if (arr) {
-               for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
-                       const Expression::Ptr& aexpr = arr->Get(index);
-                       result->Add(aexpr->Evaluate(context));
-               }
+       BOOST_FOREACH(Expression *aexpr, m_Expressions) {
+               result->Add(aexpr->Evaluate(context));
        }
 
        return result;
 }
 
-Value Expression::OpDict(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value DictExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr arr = expr->m_Operand1;
-       bool in_place = expr->m_Operand2;
        Dictionary::Ptr result = new Dictionary();
 
        result->Set("__parent", context);
 
-       if (arr) {
-               for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
-                       const Expression::Ptr& aexpr = arr->Get(index);
-                       Object::Ptr acontext = in_place ? context : result;
-                       aexpr->Evaluate(acontext, dhint);
+       BOOST_FOREACH(Expression *aexpr, m_Expressions) {
+               Object::Ptr acontext = m_Inline ? context : result;
+               aexpr->Evaluate(acontext, dhint);
 
-                       if (HasField(acontext, "__result"))
-                               break;
-               }
+               if (HasField(acontext, "__result"))
+                       break;
        }
 
        Dictionary::Ptr xresult = result->ShallowClone();
@@ -311,22 +293,18 @@ Value Expression::OpDict(const Expression *expr, const Object::Ptr& context, Deb
        return xresult;
 }
 
-Value Expression::OpSet(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr left = expr->m_Operand1;
-       Array::Ptr indexer = left->Get(0);
-       int csop = left->Get(1);
-
        DebugHint *sdhint = dhint;
 
        Value parent, object;
        String index;
 
-       for (Array::SizeType i = 0; i < indexer->GetLength(); i++) {
-               Expression::Ptr indexExpr = indexer->Get(i);
+       for (Array::SizeType i = 0; i < m_Indexer.size(); i++) {
+               Expression *indexExpr = m_Indexer[i];
                String tempindex = indexExpr->Evaluate(context, dhint);
 
-               if (i == indexer->GetLength() - 1)
+               if (i == m_Indexer.size() - 1)
                        index = tempindex;
 
                if (i == 0) {
@@ -335,65 +313,59 @@ Value Expression::OpSet(const Expression *expr, const Object::Ptr& context, Debu
                } else {
                        parent = object;
 
-                       Expression::Ptr eparent = new Expression(&Expression::OpLiteral, parent, expr->m_DebugInfo);
-                       Expression::Ptr eindex = new Expression(&Expression::OpLiteral, tempindex, expr->m_DebugInfo);
+                       LiteralExpression *eparent = MakeLiteral(parent);
+                       LiteralExpression *eindex = MakeLiteral(tempindex);
 
-                       Expression::Ptr eip = new Expression(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo);
-                       object = eip->Evaluate(context, dhint);
+                       IndexerExpression eip(eparent, eindex, m_DebugInfo);
+                       object = eip.Evaluate(context, dhint);
                }
 
                if (sdhint)
                        sdhint = sdhint->GetChild(index);
 
-               if (i != indexer->GetLength() - 1 && object.IsEmpty()) {
+               if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
                        object = new Dictionary();
 
                        SetField(parent, tempindex, object);
                }
        }
 
-       Value right = expr->EvaluateOperand2(context, dhint);
+       Value right = m_Operand2->Evaluate(context, dhint);
 
-       if (csop != OpSetLiteral) {
-               Expression::OpCallback op;
+       if (m_Op != OpSetLiteral) {
+               Expression *lhs = MakeLiteral(object);
+               Expression *rhs = MakeLiteral(right);
 
-               switch (csop) {
+               switch (m_Op) {
                        case OpSetAdd:
-                               op = &Expression::OpAdd;
+                               right = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
                                break;
                        case OpSetSubtract:
-                               op = &Expression::OpSubtract;
+                               right = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
                                break;
                        case OpSetMultiply:
-                               op = &Expression::OpMultiply;
+                               right = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
                                break;
                        case OpSetDivide:
-                               op = &Expression::OpDivide;
+                               right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
                                break;
                        default:
                                VERIFY(!"Invalid opcode.");
                }
-
-               Expression::Ptr ecp = new Expression(op,
-                   new Expression(&Expression::OpLiteral, object, expr->m_DebugInfo),
-                   new Expression(&Expression::OpLiteral, right, expr->m_DebugInfo),
-                   expr->m_DebugInfo);
-
-               right = ecp->Evaluate(context, dhint);
        }
 
        SetField(parent, index, right);
 
        if (sdhint)
-               sdhint->AddMessage("=", expr->m_DebugInfo);
+               sdhint->AddMessage("=", m_DebugInfo);
 
        return right;
 }
 
-Value Expression::OpIndexer(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value IndexerExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Value value = expr->EvaluateOperand1(context);
-       Value index = expr->EvaluateOperand2(context);
+       Value value = m_Operand1->Evaluate(context);
+       Value index = m_Operand2->Evaluate(context);
 
        if (value.IsObjectType<Dictionary>()) {
                Dictionary::Ptr dict = value;
@@ -421,88 +393,69 @@ Value Expression::OpIndexer(const Expression *expr, const Object::Ptr& context,
        }
 }
 
-Value Expression::OpImport(const Expression *expr, const Object::Ptr& context, DebugHint *dhint)
+Value ImportExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Value type = expr->EvaluateOperand1(context);
-       Value name = expr->EvaluateOperand2(context);
+       Value type = m_Type->Evaluate(context);
+       Value name = m_Name->Evaluate(context);
 
        ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
 
        if (!item)
                BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'"));
 
-       item->GetExpressionList()->Evaluate(context, dhint);
+       item->GetExpression()->Evaluate(context, dhint);
 
        return Empty;
 }
 
-Value Expression::FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs, const Expression::Ptr& expr, const Object::Ptr& scope)
+Value Expression::FunctionWrapper(const std::vector<Value>& arguments,
+    const std::vector<String>& funcargs, const boost::shared_ptr<Expression>& expr, const Object::Ptr& scope)
 {
-       if (arguments.size() < funcargs->GetLength())
+       if (arguments.size() < funcargs.size())
                BOOST_THROW_EXCEPTION(ConfigError("Too few arguments for function"));
 
        Dictionary::Ptr context = new Dictionary();
        context->Set("__parent", scope);
 
-       for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs->GetLength()); i++)
-               context->Set(funcargs->Get(i), arguments[i]);
+       for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++)
+               context->Set(funcargs[i], arguments[i]);
 
        expr->Evaluate(context);
        return context->Get("__result");
 }
 
-Value Expression::OpFunction(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
+Value FunctionExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr left = expr->m_Operand1;
-       Expression::Ptr aexpr = left->Get(1);
-       String name = left->Get(0);
-
-       Array::Ptr funcargs = expr->m_Operand2;
-       ScriptFunction::Ptr func = new ScriptFunction(boost::bind(&Expression::FunctionWrapper, _1, funcargs, aexpr, context));
+       ScriptFunction::Ptr func = new ScriptFunction(boost::bind(&Expression::FunctionWrapper, _1, m_Args, m_Expression, context));
 
-       if (!name.IsEmpty())
-               ScriptFunction::Register(name, func);
+       if (!m_Name.IsEmpty())
+               ScriptFunction::Register(m_Name, func);
 
        return func;
 }
 
-Value Expression::OpApply(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
+Value ApplyExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr left = expr->m_Operand1;
-       Expression::Ptr exprl = expr->m_Operand2;
-       String type = left->Get(0);
-       String target = left->Get(1);
-       Expression::Ptr aname = left->Get(2);
-       Expression::Ptr filter = left->Get(3);
-       String fkvar = left->Get(4);
-       String fvvar = left->Get(5);
-       Expression::Ptr fterm = left->Get(6);
+       String name = m_Name->Evaluate(context, dhint);
 
-       String name = aname->Evaluate(context, dhint);
-
-       ApplyRule::AddRule(type, target, name, exprl, filter, fkvar, fvvar, fterm, expr->m_DebugInfo, context);
+       ApplyRule::AddRule(m_Type, m_Target, name, m_Expression, m_Filter, m_FKVar, m_FVVar, m_FTerm, m_DebugInfo, context);
 
        return Empty;
 }
 
-Value Expression::OpObject(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
+Value ObjectExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr left = expr->m_Operand1;
-       Expression::Ptr exprl = expr->m_Operand2;
-       bool abstract = left->Get(0);
-       String type = left->Get(1);
-       Expression::Ptr aname = left->Get(2);
-       Expression::Ptr filter = left->Get(3);
-       String zone = left->Get(4);
+       String name;
 
-       String name = aname->Evaluate(context, dhint);
+       if (m_Name)
+               name = m_Name->Evaluate(context, dhint);
 
-       ConfigItemBuilder::Ptr item = new ConfigItemBuilder(expr->m_DebugInfo);
+       ConfigItemBuilder::Ptr item = new ConfigItemBuilder(m_DebugInfo);
 
        String checkName = name;
 
-       if (!abstract) {
-               Type::Ptr ptype = Type::GetByName(type);
+       if (!m_Abstract) {
+               Type::Ptr ptype = Type::GetByName(m_Type);
 
                NameComposer *nc = dynamic_cast<NameComposer *>(ptype.get());
 
@@ -511,50 +464,44 @@ Value Expression::OpObject(const Expression* expr, const Object::Ptr& context, D
        }
 
        if (!checkName.IsEmpty()) {
-               ConfigItem::Ptr oldItem = ConfigItem::GetObject(type, checkName);
+               ConfigItem::Ptr oldItem = ConfigItem::GetObject(m_Type, checkName);
 
                if (oldItem) {
                        std::ostringstream msgbuf;
-                       msgbuf << "Object '" << name << "' of type '" << type << "' re-defined: " << expr->m_DebugInfo << "; previous definition: " << oldItem->GetDebugInfo();
-                       BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(expr->m_DebugInfo));
+                       msgbuf << "Object '" << name << "' of type '" << m_Type << "' re-defined: " << m_DebugInfo << "; previous definition: " << oldItem->GetDebugInfo();
+                       BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(m_DebugInfo));
                }
        }
 
-       item->SetType(type);
+       item->SetType(m_Type);
 
        if (name.FindFirstOf("!") != String::NPos) {
                std::ostringstream msgbuf;
-               msgbuf << "Name for object '" << name << "' of type '" << type << "' is invalid: Object names may not contain '!'";
-               BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(expr->m_DebugInfo));
+               msgbuf << "Name for object '" << name << "' of type '" << m_Type << "' is invalid: Object names may not contain '!'";
+               BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(m_DebugInfo));
        }
 
        item->SetName(name);
 
-       item->AddExpression(exprl);
-       item->SetAbstract(abstract);
+       item->AddExpression(new OwnedExpression(m_Expression));
+       item->SetAbstract(m_Abstract);
        item->SetScope(context);
-       item->SetZone(zone);
+       item->SetZone(m_Zone);
        item->Compile()->Register();
 
-       if (ObjectRule::IsValidSourceType(type))
-               ObjectRule::AddRule(type, name, filter, expr->m_DebugInfo, context);
+       if (ObjectRule::IsValidSourceType(m_Type))
+               ObjectRule::AddRule(m_Type, name, m_Filter, m_DebugInfo, context);
 
        return Empty;
 }
 
-Value Expression::OpFor(const Expression* expr, const Object::Ptr& context, DebugHint *dhint)
+Value ForExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
 {
-       Array::Ptr left = expr->m_Operand1;
-       String kvar = left->Get(0);
-       String vvar = left->Get(1);
-       Expression::Ptr aexpr = left->Get(2);
-       Expression::Ptr ascope = expr->m_Operand2;
-
-       Value value = aexpr->Evaluate(context, dhint);
+       Value value = m_Value->Evaluate(context, dhint);
 
        if (value.IsObjectType<Array>()) {
-               if (!vvar.IsEmpty())
-                       BOOST_THROW_EXCEPTION(ConfigError("Cannot use dictionary iterator for array.") << errinfo_debuginfo(expr->m_DebugInfo));
+               if (!m_FVVar.IsEmpty())
+                       BOOST_THROW_EXCEPTION(ConfigError("Cannot use dictionary iterator for array.") << errinfo_debuginfo(m_DebugInfo));
 
                Array::Ptr arr = value;
 
@@ -562,13 +509,13 @@ Value Expression::OpFor(const Expression* expr, const Object::Ptr& context, Debu
                BOOST_FOREACH(const Value& value, arr) {
                        Dictionary::Ptr xcontext = new Dictionary();
                        xcontext->Set("__parent", context);
-                       xcontext->Set(kvar, value);
+                       xcontext->Set(m_FKVar, value);
 
-                       ascope->Evaluate(xcontext, dhint);
+                       m_Expression->Evaluate(xcontext, dhint);
                }
        } else if (value.IsObjectType<Dictionary>()) {
-               if (vvar.IsEmpty())
-                       BOOST_THROW_EXCEPTION(ConfigError("Cannot use array iterator for dictionary.") << errinfo_debuginfo(expr->m_DebugInfo));
+               if (m_FVVar.IsEmpty())
+                       BOOST_THROW_EXCEPTION(ConfigError("Cannot use array iterator for dictionary.") << errinfo_debuginfo(m_DebugInfo));
 
                Dictionary::Ptr dict = value;
 
@@ -576,13 +523,13 @@ Value Expression::OpFor(const Expression* expr, const Object::Ptr& context, Debu
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
                        Dictionary::Ptr xcontext = new Dictionary();
                        xcontext->Set("__parent", context);
-                       xcontext->Set(kvar, kv.first);
-                       xcontext->Set(vvar, kv.second);
+                       xcontext->Set(m_FKVar, kv.first);
+                       xcontext->Set(m_FVVar, kv.second);
 
-                       ascope->Evaluate(xcontext, dhint);
+                       m_Expression->Evaluate(xcontext, dhint);
                }
        } else
-               BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(expr->m_DebugInfo));
+               BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(m_DebugInfo));
 
        return Empty;
 }
@@ -618,11 +565,6 @@ Dictionary::Ptr DebugHint::ToDictionary(void) const
        return result;
 }
 
-Expression::Ptr icinga::MakeLiteral(const Value& lit)
-{
-       return new Expression(&Expression::OpLiteral, lit, DebugInfo());
-}
-
 bool Expression::HasField(const Object::Ptr& context, const String& field)
 {
        Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
index 0a6a7348c29fe04060f91f785e0dc2e2dee40598..0d58372509a39ec1bd9ef545ef76c87206603306 100644 (file)
@@ -24,6 +24,7 @@
 #include "base/debuginfo.hpp"
 #include "base/array.hpp"
 #include "base/dictionary.hpp"
+#include <boost/foreach.hpp>
 
 namespace icinga
 {
@@ -58,75 +59,564 @@ enum CombinedSetOp
 /**
  * @ingroup config
  */
-class I2_CONFIG_API Expression : public Object
+class I2_CONFIG_API Expression
 {
 public:
-       DECLARE_PTR_TYPEDEFS(Expression);
+       virtual ~Expression(void);
+
+       Value Evaluate(const Object::Ptr& context, DebugHint *dhint = NULL) const;
+
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const = 0;
+       virtual const DebugInfo& GetDebugInfo(void) const;
+
+public:
+       static Value FunctionWrapper(const std::vector<Value>& arguments,
+           const std::vector<String>& funcargs,
+           const boost::shared_ptr<Expression>& expr, const Object::Ptr& scope);
+
+       static bool HasField(const Object::Ptr& context, const String& field);
+       static Value GetField(const Object::Ptr& context, const String& field);
+       static void SetField(const Object::Ptr& context, const String& field, const Value& value);
+};
+
+I2_CONFIG_API std::vector<Expression *> MakeIndexer(const String& index1);
+
+class I2_CONFIG_API OwnedExpression : public Expression
+{
+public:
+       OwnedExpression(const boost::shared_ptr<Expression>& expression)
+               : m_Expression(expression)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+       {
+               return m_Expression->DoEvaluate(context, dhint);
+       }
+
+       virtual const DebugInfo& GetDebugInfo(void) const
+       {
+               return m_Expression->GetDebugInfo();
+       }
+
+private:
+       boost::shared_ptr<Expression> m_Expression;
+};
+
+class I2_CONFIG_API LiteralExpression : public Expression
+{
+public:
+       LiteralExpression(const Value& value = Value());
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       Value m_Value;
+};
+
+inline LiteralExpression *MakeLiteral(const Value& literal = Value())
+{
+       return new LiteralExpression(literal);
+}
+
+class I2_CONFIG_API DebuggableExpression : public Expression
+{
+public:
+       DebuggableExpression(const DebugInfo& debugInfo)
+               : m_DebugInfo(debugInfo)
+       { }
+
+protected:
+       virtual const DebugInfo& GetDebugInfo(void) const;
+
+       DebugInfo m_DebugInfo;
+};
+
+class I2_CONFIG_API UnaryExpression : public DebuggableExpression
+{
+public:
+       UnaryExpression(Expression *operand, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Operand(operand)
+       { }
+
+       ~UnaryExpression(void)
+       {
+               delete m_Operand;
+       }
+
+protected:
+       Expression *m_Operand;
+};
+
+class I2_CONFIG_API BinaryExpression : public DebuggableExpression
+{
+public:
+       BinaryExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Operand1(operand1), m_Operand2(operand2)
+       { }
        
-       typedef Value (*OpCallback)(const Expression *, const Object::Ptr&, DebugHint *dhint);
+       ~BinaryExpression(void)
+       {
+               delete m_Operand1;
+               delete m_Operand2;
+       }
 
-       Expression(OpCallback op, const Value& operand1, const DebugInfo& di);
-       Expression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di);
+protected:
+       Expression *m_Operand1;
+       Expression *m_Operand2;
+};
 
-       Value Evaluate(const Object::Ptr& context, DebugHint *dhint = NULL) const;
+       
+class I2_CONFIG_API VariableExpression : public DebuggableExpression
+{
+public:
+       VariableExpression(const String& variable, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Variable(variable)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       String m_Variable;
+};
+       
+class I2_CONFIG_API NegateExpression : public UnaryExpression
+{
+public:
+       NegateExpression(Expression *operand, const DebugInfo& debugInfo)
+               : UnaryExpression(operand, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API LogicalNegateExpression : public UnaryExpression
+{
+public:
+       LogicalNegateExpression(Expression *operand, const DebugInfo& debugInfo)
+               : UnaryExpression(operand, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+
+class I2_CONFIG_API AddExpression : public BinaryExpression
+{
+public:
+       AddExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API SubtractExpression : public BinaryExpression
+{
+public:
+       SubtractExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API MultiplyExpression : public BinaryExpression
+{
+public:
+       MultiplyExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API DivideExpression : public BinaryExpression
+{
+public:
+       DivideExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API BinaryAndExpression : public BinaryExpression
+{
+public:
+       BinaryAndExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API BinaryOrExpression : public BinaryExpression
+{
+public:
+       BinaryOrExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API ShiftLeftExpression : public BinaryExpression
+{
+public:
+       ShiftLeftExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API ShiftRightExpression : public BinaryExpression
+{
+public:
+       ShiftRightExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API EqualExpression : public BinaryExpression
+{
+public:
+       EqualExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API NotEqualExpression : public BinaryExpression
+{
+public:
+       NotEqualExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API LessThanExpression : public BinaryExpression
+{
+public:
+       LessThanExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API GreaterThanExpression : public BinaryExpression
+{
+public:
+       GreaterThanExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API LessThanOrEqualExpression : public BinaryExpression
+{
+public:
+       LessThanOrEqualExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API GreaterThanOrEqualExpression : public BinaryExpression
+{
+public:
+       GreaterThanOrEqualExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API InExpression : public BinaryExpression
+{
+public:
+       InExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API NotInExpression : public BinaryExpression
+{
+public:
+       NotInExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API LogicalAndExpression : public BinaryExpression
+{
+public:
+       LogicalAndExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API LogicalOrExpression : public BinaryExpression
+{
+public:
+       LogicalOrExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API FunctionCallExpression : public DebuggableExpression
+{
+public:
+       FunctionCallExpression(Expression *fname, const std::vector<Expression *>& args, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_FName(fname), m_Args(args)
+       { }
+
+       ~FunctionCallExpression(void)
+       {
+               delete m_FName;
+
+               BOOST_FOREACH(Expression *expr, m_Args)
+                       delete expr;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+public:
+       Expression *m_FName;
+       std::vector<Expression *> m_Args;
+};
+       
+class I2_CONFIG_API ArrayExpression : public DebuggableExpression
+{
+public:
+       ArrayExpression(const std::vector<Expression *>& expressions, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Expressions(expressions)
+       { }
+
+       ~ArrayExpression(void)
+       {
+               BOOST_FOREACH(Expression *expr, m_Expressions)
+                       delete expr;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       std::vector<Expression *> m_Expressions;
+};
+       
+class I2_CONFIG_API DictExpression : public DebuggableExpression
+{
+public:
+       DictExpression(const std::vector<Expression *>& expressions, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Expressions(expressions), m_Inline(false)
+       { }
+
+       ~DictExpression(void)
+       {
+               BOOST_FOREACH(Expression *expr, m_Expressions)
+                       delete expr;
+       }
 
        void MakeInline(void);
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       std::vector<Expression *> m_Expressions;
+       bool m_Inline;
+};
        
-       void Dump(std::ostream& stream, int indent = 0) const;
-
-       static Value OpLiteral(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpVariable(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpLogicalNegate(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpAdd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpSubtract(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpMultiply(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpDivide(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpBinaryAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpBinaryOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpShiftLeft(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpShiftRight(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpNotEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpLessThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpGreaterThan(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpLessThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpGreaterThanOrEqual(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpNotIn(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpLogicalAnd(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpLogicalOr(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpFunctionCall(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpArray(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpDict(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpSet(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpIndexer(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpImport(const Expression *expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpFunction(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpApply(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpObject(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
-       static Value OpFor(const Expression* expr, const Object::Ptr& context, DebugHint *dhint);
+class I2_CONFIG_API SetExpression : public DebuggableExpression
+{
+public:
+       SetExpression(const std::vector<Expression *>& indexer, CombinedSetOp op, Expression *operand2, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Op(op), m_Indexer(indexer), m_Operand2(operand2)
+       { }
+
+       ~SetExpression(void)
+       {
+               BOOST_FOREACH(Expression *expr, m_Indexer)
+                       delete expr;
+
+               delete m_Operand2;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
 
 private:
-       OpCallback m_Operator;
-       Value m_Operand1;
-       Value m_Operand2;
-       DebugInfo m_DebugInfo;
+       CombinedSetOp m_Op;
+       std::vector<Expression *> m_Indexer;
+       Expression *m_Operand2;
+
+};
+       
+class I2_CONFIG_API IndexerExpression : public BinaryExpression
+{
+public:
+       IndexerExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo)
+               : BinaryExpression(operand1, operand2, debugInfo)
+       { }
 
-       Value EvaluateOperand1(const Object::Ptr& context, DebugHint *dhint = NULL) const;
-       Value EvaluateOperand2(const Object::Ptr& context, DebugHint *dhint = NULL) const;
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+};
+       
+class I2_CONFIG_API ImportExpression : public DebuggableExpression
+{
+public:
+       ImportExpression(Expression *type, Expression *name, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Type(type), m_Name(name)
+       { }
 
-       static void DumpOperand(std::ostream& stream, const Value& operand, int indent);
+       ~ImportExpression(void)
+       {
+               delete m_Type;
+               delete m_Name;
+       }
 
-       static Value FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs,
-           const Expression::Ptr& expr, const Object::Ptr& scope);
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
 
-       static bool HasField(const Object::Ptr& context, const String& field);
-       static Value GetField(const Object::Ptr& context, const String& field);
-       static void SetField(const Object::Ptr& context, const String& field, const Value& value);
+private:
+       Expression *m_Type;
+       Expression *m_Name;
 };
 
-I2_CONFIG_API Expression::Ptr MakeLiteral(const Value& lit = Value());
+class I2_CONFIG_API FunctionExpression : public DebuggableExpression
+{
+public:
+       FunctionExpression(const String& name, const std::vector<String>& args, Expression *expression, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Name(name), m_Args(args), m_Expression(expression)
+       { }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       String m_Name;
+       std::vector<String> m_Args;
+       boost::shared_ptr<Expression> m_Expression;
+};
+
+class I2_CONFIG_API ApplyExpression : public DebuggableExpression
+{
+public:
+       ApplyExpression(const String& type, const String& target, Expression *name,
+           Expression *filter, const String& fkvar, const String& fvvar,
+           Expression *fterm, Expression *expression, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Type(type), m_Target(target),
+                   m_Name(name), m_Filter(filter), m_FKVar(fkvar), m_FVVar(fvvar),
+                   m_FTerm(fterm), m_Expression(expression)
+       { }
+
+       ~ApplyExpression(void)
+       {
+               delete m_Name;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       String m_Type;
+       String m_Target;
+       Expression *m_Name;
+       boost::shared_ptr<Expression> m_Filter;
+       String m_FKVar;
+       String m_FVVar;
+       boost::shared_ptr<Expression> m_FTerm;
+       boost::shared_ptr<Expression> m_Expression;
+};
+       
+class I2_CONFIG_API ObjectExpression : public DebuggableExpression
+{
+public:
+       ObjectExpression(bool abstract, const String& type, Expression *name, Expression *filter, const String& zone, Expression *expression, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_Abstract(abstract), m_Type(type), m_Name(name), m_Filter(filter), m_Zone(zone), m_Expression(expression)
+       { }
+
+       ~ObjectExpression(void)
+       {
+               delete m_Name;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       bool m_Abstract;
+       String m_Type;
+       Expression *m_Name;
+       boost::shared_ptr<Expression> m_Filter;
+       String m_Zone;
+       boost::shared_ptr<Expression> m_Expression;
+};
+       
+class I2_CONFIG_API ForExpression : public DebuggableExpression
+{
+public:
+       ForExpression(const String& fkvar, const String& fvvar, Expression *value, Expression *expression, const DebugInfo& debugInfo)
+               : DebuggableExpression(debugInfo), m_FKVar(fkvar), m_FVVar(fvvar), m_Value(value), m_Expression(expression)
+       { }
+
+       ~ForExpression(void)
+       {
+               delete m_Value;
+               delete m_Expression;
+       }
+
+protected:
+       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+
+private:
+       String m_FKVar;
+       String m_FVVar;
+       Expression *m_Value;
+       Expression *m_Expression;
+};
 
 }
 
index 1b2c1952bbb3fbc59e59828abef58f91ab56e3d4..fb38b81fec036c34b5a20c1ea9de41848e1fdf59 100644 (file)
@@ -26,7 +26,7 @@ using namespace icinga;
 ObjectRule::RuleMap ObjectRule::m_Rules;
 ObjectRule::CallbackMap ObjectRule::m_Callbacks;
 
-ObjectRule::ObjectRule(const String& name, const Expression::Ptr& filter,
+ObjectRule::ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter,
     const DebugInfo& di, const Object::Ptr& scope)
        : m_Name(name), m_Filter(filter), m_DebugInfo(di), m_Scope(scope)
 { }
@@ -36,7 +36,7 @@ String ObjectRule::GetName(void) const
        return m_Name;
 }
 
-Expression::Ptr ObjectRule::GetFilter(void) const
+boost::shared_ptr<Expression> ObjectRule::GetFilter(void) const
 {
        return m_Filter;
 }
@@ -52,7 +52,7 @@ Object::Ptr ObjectRule::GetScope(void) const
 }
 
 void ObjectRule::AddRule(const String& sourceType, const String& name,
-    const Expression::Ptr& filter, const DebugInfo& di, const Object::Ptr& scope)
+    const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope)
 {
        m_Rules[sourceType].push_back(ObjectRule(name, filter, di, scope));
 }
index cdb94af408258a7700420b871f824098f1a3b0d1..42bf19cb33b1edfe65bcfd0077b924ecd3e4ed3e 100644 (file)
@@ -39,14 +39,14 @@ public:
        typedef std::map<String, std::vector<ObjectRule> > RuleMap;
 
        String GetName(void) const;
-       Expression::Ptr GetFilter(void) const;
+       boost::shared_ptr<Expression> GetFilter(void) const;
        DebugInfo GetDebugInfo(void) const;
        Object::Ptr GetScope(void) const;
 
        bool EvaluateFilter(const Object::Ptr& scope) const;
 
        static void AddRule(const String& sourceType, const String& name,
-           const Expression::Ptr& filter, const DebugInfo& di, const Object::Ptr& scope);
+           const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
        static void EvaluateRules(bool clear);
 
        static void RegisterType(const String& sourceType, const ObjectRule::Callback& callback);
@@ -54,15 +54,14 @@ public:
 
 private:
        String m_Name;
-       Expression::Ptr m_Filter;
+       boost::shared_ptr<Expression> m_Filter;
        DebugInfo m_DebugInfo;
        Object::Ptr m_Scope;
 
        static CallbackMap m_Callbacks;
        static RuleMap m_Rules;
 
-       ObjectRule(const String& name, const Expression::Ptr& filter,
-           const DebugInfo& di, const Object::Ptr& scope);
+       ObjectRule(const String& name, const boost::shared_ptr<Expression>& filter, const DebugInfo& di, const Object::Ptr& scope);
 };
 
 }
index ed5756afc358cc79f6e90561d6a7949117e4362d..3868615230cec5f8dbf5494a187500c52a547107 100644 (file)
@@ -58,33 +58,18 @@ void Dependency::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable, c
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("parent_host_name")), OpSetLiteral),
-           MakeLiteral(host->GetName()),
-           di));
-
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("child_host_name")), OpSetLiteral),
-           MakeLiteral(host->GetName()),
-           di));
-
-       if (service) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("child_service_name")), OpSetLiteral),
-                   MakeLiteral(service->GetShortName()),
-                   di));
-       }
+       builder->AddExpression(new SetExpression(MakeIndexer("parent_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+       builder->AddExpression(new SetExpression(MakeIndexer("child_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+
+       if (service)
+               builder->AddExpression(new SetExpression(MakeIndexer("child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
 
        String zone = checkable->GetZone();
 
-       if (!zone.IsEmpty()) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
-                   MakeLiteral(zone),
-                   di));
-       }
+       if (!zone.IsEmpty())
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
 
-       builder->AddExpression(rule.GetExpression());
+       builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr dependencyItem = builder->Compile();
        DynamicObject::Ptr dobj = dependencyItem->Commit();
index f9f299486dd7d02018204226342b0b35f4f0b5cd..160933cc473ba25b5f79674218ba6d357f11c01f 100644 (file)
@@ -58,28 +58,17 @@ void Notification::EvaluateApplyRuleOneInstance(const Checkable::Ptr& checkable,
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
-           MakeLiteral(host->GetName()),
-           di));
-
-       if (service) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
-                   MakeLiteral(service->GetShortName()),
-                   di));
-       }
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+
+       if (service)
+               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
 
        String zone = checkable->GetZone();
 
-       if (!zone.IsEmpty()) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
-                   MakeLiteral(zone),
-                   di));
-       }
+       if (!zone.IsEmpty())
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
 
-       builder->AddExpression(rule.GetExpression());
+       builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr notificationItem = builder->Compile();
        DynamicObject::Ptr dobj = notificationItem->Commit();
index 8b830f4012c05a0ea51089e87a95019783112a89..27b3ba5ae7157defe7425e4360076e880e4e23a7 100644 (file)
@@ -57,28 +57,18 @@ void ScheduledDowntime::EvaluateApplyRuleOneInstance(const Checkable::Ptr& check
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
-           MakeLiteral(host->GetName()),
-           di));
-
-       if (service) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("service_name")), OpSetLiteral),
-                   MakeLiteral(service->GetShortName()),
-                   di));
-       }
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+
+       if (service)
+               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty()) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
-                   MakeLiteral(zone),
-                   di));
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
        }
 
-       builder->AddExpression(rule.GetExpression());
+       builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr downtimeItem = builder->Compile();
        DynamicObject::Ptr dobj = downtimeItem->Commit();
index 83543261fc59c30e206746866de0ae77af4963dc..7b24b58a85bbba2a076ce5b59541773968a4f650 100644 (file)
@@ -52,26 +52,16 @@ void Service::EvaluateApplyRuleOneInstance(const Host::Ptr& host, const String&
        builder->SetName(name);
        builder->SetScope(locals);
 
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("host_name")), OpSetLiteral),
-           MakeLiteral(host->GetName()),
-           di));
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
 
-       builder->AddExpression(new Expression(&Expression::OpSet,
-           MakeArray(MakeArray(MakeLiteral("name")), OpSetLiteral),
-           MakeLiteral(name),
-           di));
+       builder->AddExpression(new SetExpression(MakeIndexer("name"), OpSetLiteral, MakeLiteral(name), di));
 
        String zone = host->GetZone();
 
-       if (!zone.IsEmpty()) {
-               builder->AddExpression(new Expression(&Expression::OpSet,
-                   MakeArray(MakeArray(MakeLiteral("zone")), OpSetLiteral),
-                   MakeLiteral(zone),
-                   di));
-       }
+       if (!zone.IsEmpty())
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
 
-       builder->AddExpression(rule.GetExpression());
+       builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
        ConfigItem::Ptr serviceItem = builder->Compile();
        DynamicObject::Ptr dobj = serviceItem->Commit();