]> granicus.if.org Git - icinga2/commitdiff
Refactor the stack frame handling for scripts
authorGunnar Beutner <gunnar@beutner.name>
Sat, 22 Nov 2014 11:21:28 +0000 (12:21 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 22 Nov 2014 18:24:03 +0000 (19:24 +0100)
fixes #7748

26 files changed:
lib/base/scriptutils.cpp
lib/cli/daemoncommand.cpp
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-codegen.cpp
lib/config/expression.cpp
lib/config/expression.hpp
lib/config/vmframe.hpp [new file with mode: 0644]
lib/config/vmops.hpp
lib/icinga/dependency-apply.cpp
lib/icinga/dependency.hpp
lib/icinga/hostgroup.cpp
lib/icinga/notification-apply.cpp
lib/icinga/notification.hpp
lib/icinga/scheduleddowntime-apply.cpp
lib/icinga/scheduleddowntime.hpp
lib/icinga/service-apply.cpp
lib/icinga/service.hpp
lib/icinga/servicegroup.cpp
lib/icinga/usergroup.cpp

index 3a7f9732ff073f9331a4616de77acd0f71f561be..56d68590827b9d5f63913321f0c8f0b48ee663ad 100644 (file)
@@ -139,7 +139,7 @@ void ScriptUtils::Log(const std::vector<Value>& arguments)
                message = arguments[2];
        }
 
-       if (message.IsString())
+       if (message.IsString() || !message.IsObjectType<Array>() && !message.IsObjectType<Dictionary>())
                ::Log(severity, facility, message);
        else
                ::Log(severity, facility, JsonEncode(message));
index 5f1ac05132e8233c2c1fa8e3673ff5e74e3875f1..7193d2d53418e041719adde3b84523f59b6ffd6c 100644 (file)
@@ -64,10 +64,9 @@ static String LoadAppType(const String& typeSpec)
 
 static void ExecuteExpression(Expression *expression)
 {
-       Dictionary::Ptr context = new Dictionary();
-
        try {
-               expression->Evaluate(context);
+               VMFrame frame;
+               expression->Evaluate(frame);
        } catch (const ConfigError& ex) {
                const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
                ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
index 4e192cd57636eaef693f7f33dccf92788bd45d30..a9274463fd00e45eead0a9cb55d3ac881f7f1f10 100644 (file)
@@ -29,7 +29,7 @@ ApplyRule::TypeMap ApplyRule::m_Types;
 
 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)
+    const DebugInfo& di, const Dictionary::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), m_HasMatches(false)
 { }
@@ -74,21 +74,21 @@ DebugInfo ApplyRule::GetDebugInfo(void) const
        return m_DebugInfo;
 }
 
-Object::Ptr ApplyRule::GetScope(void) const
+Dictionary::Ptr ApplyRule::GetScope(void) const
 {
        return m_Scope;
 }
 
 void ApplyRule::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)
+    const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Dictionary::Ptr& scope)
 {
        m_Rules[sourceType].push_back(ApplyRule(targetType, name, expression, filter, fkvar, fvvar, fterm, di, scope));
 }
 
-bool ApplyRule::EvaluateFilter(const Object::Ptr& scope) const
+bool ApplyRule::EvaluateFilter(VMFrame& frame) const
 {
-       return m_Filter->Evaluate(scope).ToBool();
+       return m_Filter->Evaluate(frame).ToBool();
 }
 
 void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes)
index b85357aa8232269f0f297c1ceec753fb9b9e1b5a..af4b5c61b37f401f7237cb92a53cff450c0b9369 100644 (file)
@@ -45,14 +45,14 @@ public:
        String GetFVVar(void) const;
        boost::shared_ptr<Expression> GetFTerm(void) const;
        DebugInfo GetDebugInfo(void) const;
-       Object::Ptr GetScope(void) const;
+       Dictionary::Ptr GetScope(void) const;
        void AddMatch(void);
        bool HasMatches(void) const;
 
-       bool EvaluateFilter(const Object::Ptr& scope) const;
+       bool EvaluateFilter(VMFrame& frame) const;
 
        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);
+           const boost::shared_ptr<Expression>& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, const DebugInfo& di, const Dictionary::Ptr& scope);
        static std::vector<ApplyRule>& GetRules(const String& type);
 
        static void RegisterType(const String& sourceType, const std::vector<String>& targetTypes);
@@ -72,7 +72,7 @@ private:
        String m_FVVar;
        boost::shared_ptr<Expression> m_FTerm;
        DebugInfo m_DebugInfo;
-       Object::Ptr m_Scope;
+       Dictionary::Ptr m_Scope;
        bool m_HasMatches;
 
        static TypeMap m_Types;
@@ -80,7 +80,7 @@ private:
 
        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);
+           const DebugInfo& di, const Dictionary::Ptr& scope);
 };
 
 }
index 64cf56fdb47c06402b9464db2c402a6ba4b1f8c7..acf8986828ff5e2b788f5a3fdd14e57fa15704fe 100644 (file)
@@ -238,6 +238,8 @@ null                                return T_NULL;
 true                           { yylval->num = 1; return T_NUMBER; }
 false                          { yylval->num = 0; return T_NUMBER; }
 const                          return T_CONST;
+local                          return T_LOCAL;
+use                            return T_USE;
 apply                          return T_APPLY;
 to                             return T_TO;
 where                          return T_WHERE;
index 79b0face37e8aab87ff2c391855648646c92c7ae..4b01cac68eb50a560353cd2391b5a32ef45e71c1 100644 (file)
@@ -98,6 +98,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
        icinga::TypeSpecifier type;
        std::vector<String> *slist;
        std::vector<Expression *> *elist;
+       std::pair<String, Expression *> *cvitem;
+       std::map<String, Expression *> *cvlist;
 }
 
 %token T_NEWLINE "new-line"
@@ -133,6 +135,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
 %token T_GREATER_THAN "> (T_GREATER_THAN)"
 
 %token T_CONST "const (T_CONST)"
+%token T_LOCAL "local (T_LOCAL)"
+%token T_USE "use (T_USE)"
 %token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
 %token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
 %token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
@@ -184,6 +188,9 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
 %type <expr> apply
 %type <expr> optional_rterm
 %type <text> target_type_specifier
+%type <cvlist> use_specifier
+%type <cvlist> use_specifier_items
+%type <cvitem> use_specifier_item
 
 %left T_LOGICAL_OR
 %left T_LOGICAL_AND
@@ -217,8 +224,6 @@ static std::stack<bool> m_Abstract;
 static std::stack<TypeRuleList::Ptr> m_RuleLists;
 static ConfigType::Ptr m_Type;
 
-static Dictionary::Ptr m_ModuleScope;
-
 static std::stack<bool> m_Apply;
 static std::stack<bool> m_ObjectAssign;
 static std::stack<bool> m_SeenAssign;
@@ -231,8 +236,6 @@ static std::stack<std::vector<Expression *> > m_Expressions;
 
 Expression *ConfigCompiler::Compile(void)
 {
-       m_ModuleScope = new Dictionary();
-
        m_Abstract = std::stack<bool>();
        m_RuleLists = std::stack<TypeRuleList::Ptr>();
        m_Type.reset();
@@ -293,7 +296,8 @@ library: T_LIBRARY T_STRING sep
 
 constant: T_CONST identifier T_SET rterm sep
        {
-               ScriptVariable::Ptr sv = ScriptVariable::Set($2, $4->Evaluate(m_ModuleScope));
+               VMFrame frame;
+               ScriptVariable::Ptr sv = ScriptVariable::Set($2, $4->Evaluate(frame));
                free($2);
                delete $4;
 
@@ -416,7 +420,7 @@ object:
                m_Assign.push(NULL);
                m_Ignore.push(NULL);
        }
-       object_declaration identifier rterm rterm_scope
+       object_declaration identifier rterm use_specifier rterm_scope
        {
                m_ObjectAssign.pop();
 
@@ -426,7 +430,7 @@ object:
                String type = $3;
                free($3);
 
-               DictExpression *exprl = dynamic_cast<DictExpression *>($5);
+               DictExpression *exprl = dynamic_cast<DictExpression *>($6);
                exprl->MakeInline();
 
                bool seen_assign = m_SeenAssign.top();
@@ -452,7 +456,7 @@ object:
                                filter = assign;
                }
 
-               $$ = new ObjectExpression(abstract, type, $4, filter, context->GetZone(), exprl, DebugInfoRange(@2, @5));
+               $$ = new ObjectExpression(abstract, type, $4, filter, context->GetZone(), $5, exprl, DebugInfoRange(@2, @5));
        }
        ;
 
@@ -570,14 +574,20 @@ lterm_items_inner: lterm
        }
        ;
 
-lterm: indexer combined_set_op rterm
+lterm: T_LOCAL indexer combined_set_op rterm
+       {
+               $$ = new SetExpression(*$2, $3, $4, true, DebugInfoRange(@1, @4));
+               delete $2;
+       }
+       | indexer combined_set_op rterm
        {
-               $$ = new SetExpression(*$1, $2, $3, DebugInfoRange(@1, @3));
+               $$ = new SetExpression(*$1, $2, $3, false, DebugInfoRange(@1, @3));
                delete $1;
        }
        | T_INCLUDE rterm sep
        {
-               $$ = context->HandleInclude($2->Evaluate(m_ModuleScope), false, DebugInfoRange(@1, @2));
+               VMFrame frame;
+               $$ = context->HandleInclude($2->Evaluate(frame), false, DebugInfoRange(@1, @2));
                delete $2;
        }
        | T_INCLUDE T_STRING_ANGLE
@@ -587,19 +597,20 @@ lterm: indexer combined_set_op rterm
        }
        | T_INCLUDE_RECURSIVE rterm
        {
-               $$ = context->HandleIncludeRecursive($2->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2));
+               VMFrame frame;
+               $$ = context->HandleIncludeRecursive($2->Evaluate(frame), "*.conf", DebugInfoRange(@1, @2));
                delete $2;
        }
        | T_INCLUDE_RECURSIVE rterm ',' rterm
        {
-               $$ = context->HandleIncludeRecursive($2->Evaluate(m_ModuleScope), $4->Evaluate(m_ModuleScope), DebugInfoRange(@1, @4));
+               VMFrame frame;
+               $$ = context->HandleIncludeRecursive($2->Evaluate(frame), $4->Evaluate(frame), DebugInfoRange(@1, @4));
                delete $2;
                delete $4;
        }
        | T_IMPORT rterm
        {
-               Expression *avar = new VariableExpression("type", DebugInfoRange(@1, @2));
-               $$ = new ImportExpression(avar, $2, DebugInfoRange(@1, @2));
+               $$ = new ImportExpression($2, DebugInfoRange(@1, @2));
        }
        | T_ASSIGN T_WHERE rterm
        {
@@ -631,7 +642,7 @@ lterm: indexer combined_set_op rterm
        {
                std::vector<Expression *> vname;
                vname.push_back(MakeLiteral("__result"));
-               $$ = new SetExpression(vname, OpSetLiteral, $2, DebugInfoRange(@1, @2));
+               $$ = new SetExpression(vname, OpSetLiteral, $2, false, DebugInfoRange(@1, @2));
        }
        | apply
        {
@@ -792,21 +803,21 @@ rterm: T_STRING
        | 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
+       | T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope
        {
-               DictExpression *aexpr = dynamic_cast<DictExpression *>($6);
+               DictExpression *aexpr = dynamic_cast<DictExpression *>($7);
                aexpr->MakeInline();
 
-               $$ = new FunctionExpression($2, *$4, aexpr, DebugInfoRange(@1, @6));
+               $$ = new FunctionExpression($2, *$4, $6, aexpr, DebugInfoRange(@1, @6));
                free($2);
                delete $4;
        }
-       | T_FUNCTION '(' identifier_items ')' rterm_scope
+       | T_FUNCTION '(' identifier_items ')' use_specifier rterm_scope
        {
-               DictExpression *aexpr = dynamic_cast<DictExpression *>($5);
+               DictExpression *aexpr = dynamic_cast<DictExpression *>($6);
                aexpr->MakeInline();
 
-               $$ = new FunctionExpression("", *$3, aexpr, DebugInfoRange(@1, @5));
+               $$ = new FunctionExpression("", *$3, $5, aexpr, DebugInfoRange(@1, @5));
                delete $3;
        }
        | T_SIGNAL identifier T_SET_ADD rterm
@@ -837,6 +848,40 @@ target_type_specifier: /* empty */
        }
        ;
 
+use_specifier: /* empty */
+       {
+               $$ = NULL;
+       }
+       | T_USE '(' use_specifier_items ')'
+       {
+               $$ = $3;
+       }
+       ;
+
+use_specifier_items: use_specifier_item
+       {
+               $$ = new std::map<String, Expression *>();
+               $$->insert(*$1);
+               delete $1;
+       }
+       | use_specifier_items ',' use_specifier_item
+       {
+               $$ = $1;
+               $$->insert(*$3);
+               delete $3;
+       }
+       ;
+
+use_specifier_item: identifier
+       {
+               $$ = new std::pair<String, Expression *>($1, new VariableExpression($1, @1));
+       }
+       | identifier T_SET rterm
+       {
+               $$ = new std::pair<String, Expression *>($1, $3);
+       }
+       ;
+
 apply_for_specifier: /* empty */
        | T_APPLY_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')'
        {
@@ -879,7 +924,7 @@ apply:
                m_FVVar.push("");
                m_FTerm.push(NULL);
        }
-       T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier rterm
+       T_APPLY identifier optional_rterm apply_for_specifier target_type_specifier use_specifier rterm
        {
                m_Apply.pop();
 
@@ -912,7 +957,7 @@ apply:
                                BOOST_THROW_EXCEPTION(ConfigError("'apply' target type '" + target + "' is invalid") << errinfo_debuginfo(DebugInfoRange(@2, @5)));
                }
 
-               DictExpression *exprl = dynamic_cast<DictExpression *>($7);
+               DictExpression *exprl = dynamic_cast<DictExpression *>($8);
                exprl->MakeInline();
 
                // assign && !ignore
@@ -945,7 +990,7 @@ apply:
                Expression *fterm = m_FTerm.top();
                m_FTerm.pop();
 
-               $$ = new ApplyExpression(type, target, $4, filter, fkvar, fvvar, fterm, exprl, DebugInfoRange(@2, @5));
+               $$ = new ApplyExpression(type, target, $4, filter, fkvar, fvvar, fterm, $7, exprl, DebugInfoRange(@2, @7));
        }
        ;
 
index fbfe514cc3d148151a78c76eb1524e9e565693f3..65b096503b23b8cd97b1ce12fd9b159630aa421b 100644 (file)
@@ -59,7 +59,7 @@ ConfigItem::ItemList ConfigItem::m_CommittedItems;
 ConfigItem::ConfigItem(const String& type, const String& name,
     bool abstract, const boost::shared_ptr<Expression>& exprl,
     const boost::shared_ptr<Expression>& filter,
-    const DebugInfo& debuginfo, const Object::Ptr& scope,
+    const DebugInfo& debuginfo, const Dictionary::Ptr& scope,
     const String& zone)
        : m_Type(type), m_Name(name), m_Abstract(abstract),
          m_Expression(exprl), m_Filter(filter),
@@ -107,7 +107,7 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
        return m_DebugInfo;
 }
 
-Object::Ptr ConfigItem::GetScope(void) const
+Dictionary::Ptr ConfigItem::GetScope(void) const
 {
        return m_Scope;
 }
@@ -159,19 +159,14 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        dobj->SetDebugInfo(m_DebugInfo);
        dobj->SetTypeName(m_Type);
        dobj->SetZone(m_Zone);
-
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", m_Scope);
-
-       dobj->SetParentScope(locals);
-       locals.reset();
-
        dobj->SetName(m_Name);
 
        DebugHint debugHints;
 
        try {
-               m_Expression->Evaluate(dobj, &debugHints);
+               VMFrame frame(dobj);
+               frame.Locals = m_Scope;
+               m_Expression->Evaluate(frame, &debugHints);
        } catch (const ConfigError& ex) {
                const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
                ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
index de7ac24d2659c4341ace222e4ea9693ed8cad78d..538b9d89dbd426d25d5630ad4ba7d91f48033f6d 100644 (file)
@@ -42,7 +42,7 @@ public:
            const boost::shared_ptr<Expression>& exprl,
            const boost::shared_ptr<Expression>& filter,
            const DebugInfo& debuginfo,
-           const Object::Ptr& scope, const String& zone);
+           const Dictionary::Ptr& scope, const String& zone);
 
        String GetType(void) const;
        String GetName(void) const;
@@ -57,7 +57,7 @@ public:
        void Register(void);
 
        DebugInfo GetDebugInfo(void) const;
-       Object::Ptr GetScope(void) const;
+       Dictionary::Ptr GetScope(void) const;
 
        String GetZone(void) const;
 
@@ -78,7 +78,7 @@ private:
        boost::shared_ptr<Expression> m_Expression;
        boost::shared_ptr<Expression> m_Filter;
        DebugInfo m_DebugInfo; /**< Debug information. */
-       Object::Ptr m_Scope; /**< variable scope. */
+       Dictionary::Ptr m_Scope; /**< variable scope. */
        String m_Zone; /**< The zone. */
 
        DynamicObject::Ptr m_Object;
index 89d016801cd0b9a629fabb2d59e32b27892a5762..f74cb8e7f59d308960baa8721c2f74db1ecda6d8 100644 (file)
@@ -55,7 +55,7 @@ void ConfigItemBuilder::SetAbstract(bool abstract)
        m_Abstract = abstract;
 }
 
-void ConfigItemBuilder::SetScope(const Object::Ptr& scope)
+void ConfigItemBuilder::SetScope(const Dictionary::Ptr& scope)
 {
        m_Scope = scope;
 }
@@ -104,7 +104,7 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
        indexer.push_back(new LiteralExpression("templates"));
 
        exprs.push_back(new SetExpression(indexer, OpSetAdd,
-           new LiteralExpression(templateArray), m_DebugInfo));
+           new LiteralExpression(templateArray), false, m_DebugInfo));
 
        DictExpression *dexpr = new DictExpression(m_Expressions, m_DebugInfo);
        dexpr->MakeInline();
index d44007ff87260dff47385136d6135c9a2fd898df..0d976c4aab7871a8ab666e17bcf56c94ee2522fa 100644 (file)
@@ -45,7 +45,7 @@ public:
        void SetType(const String& type);
        void SetName(const String& name);
        void SetAbstract(bool abstract);
-       void SetScope(const Object::Ptr& scope);
+       void SetScope(const Dictionary::Ptr& scope);
        void SetZone(const String& zone);
 
        void AddExpression(Expression *expr);
@@ -60,7 +60,7 @@ private:
        std::vector<Expression *> m_Expressions; /**< Expressions for this item. */
        boost::shared_ptr<Expression> m_Filter; /**< Filter expression. */
        DebugInfo m_DebugInfo; /**< Debug information. */
-       Object::Ptr m_Scope; /**< variable scope. */
+       Dictionary::Ptr m_Scope; /**< variable scope. */
        String m_Zone; /**< The zone. */
 };
 
index cf02cbf2e50f28dab7f173fc310dbd5ca55f5a72..d21d5bec0fc9f1ebd94796c61135b720ef1397d0 100644 (file)
@@ -418,9 +418,7 @@ void ImportExpression::GenerateCode(DefinitionMap& definitions, std::ostream& fp
           << "  String name = (";
        m_Name->GenerateCode(definitions, df);
        df << ");" << "\n"
-          << "  String type = (";
-       m_Type->GenerateCode(definitions, df);
-       df << ");" << "\n"
+          << "  String type = VMOps::GetField(context, \"type\");" << "\n"
           << "\n"
           << "  ConfigItem::Ptr item = ConfigItem::GetObject(type, name);" << "\n"
           << "\n"
index e3cbc3db34c8b39304379d372c0c75807a4d510d..c058789f2e3657e81f5dd258f176aad4fe8f99c3 100644 (file)
@@ -34,7 +34,7 @@ using namespace icinga;
 Expression::~Expression(void)
 { }
 
-Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value Expression::Evaluate(VMFrame& frame, DebugHint *dhint) const
 {
        try {
 #ifdef _DEBUG
@@ -44,7 +44,7 @@ Value Expression::Evaluate(const Object::Ptr& context, DebugHint *dhint) const
                        << "Executing:\n" << msgbuf.str();*/
 #endif /* _DEBUG */
 
-               return DoEvaluate(context, dhint);
+               return DoEvaluate(frame, dhint);
        } catch (const std::exception& ex) {
                if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
                        throw;
@@ -77,7 +77,7 @@ LiteralExpression::LiteralExpression(const Value& value)
        : m_Value(value)
 { }
 
-Value LiteralExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LiteralExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
        return m_Value;
 }
@@ -87,174 +87,175 @@ const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
        return m_DebugInfo;
 }
 
-Value VariableExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value VariableExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::Variable(context, m_Variable);
+       return VMOps::Variable(frame, m_Variable);
 }
 
-Value NegateExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value NegateExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return ~(long)m_Operand->Evaluate(context);
+       return ~(long)m_Operand->Evaluate(frame);
 }
 
-Value LogicalNegateExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LogicalNegateExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return !m_Operand->Evaluate(context).ToBool();
+       return !m_Operand->Evaluate(frame).ToBool();
 }
 
-Value AddExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value AddExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) + m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) + m_Operand2->Evaluate(frame);
 }
 
-Value SubtractExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value SubtractExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) - m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) - m_Operand2->Evaluate(frame);
 }
 
-Value MultiplyExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value MultiplyExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) * m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) * m_Operand2->Evaluate(frame);
 }
 
-Value DivideExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value DivideExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) / m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) / m_Operand2->Evaluate(frame);
 }
 
-Value BinaryAndExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value BinaryAndExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) & m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) & m_Operand2->Evaluate(frame);
 }
 
-Value BinaryOrExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value BinaryOrExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) | m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) | m_Operand2->Evaluate(frame);
 }
 
-Value ShiftLeftExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ShiftLeftExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) << m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) << m_Operand2->Evaluate(frame);
 }
 
-Value ShiftRightExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ShiftRightExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) >> m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) >> m_Operand2->Evaluate(frame);
 }
 
-Value EqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value EqualExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) == m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) == m_Operand2->Evaluate(frame);
 }
 
-Value NotEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value NotEqualExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) != m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) != m_Operand2->Evaluate(frame);
 }
 
-Value LessThanExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LessThanExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) < m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) < m_Operand2->Evaluate(frame);
 }
 
-Value GreaterThanExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value GreaterThanExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) > m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) > m_Operand2->Evaluate(frame);
 }
 
-Value LessThanOrEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LessThanOrEqualExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) <= m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) <= m_Operand2->Evaluate(frame);
 }
 
-Value GreaterThanOrEqualExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value GreaterThanOrEqualExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context) >= m_Operand2->Evaluate(context);
+       return m_Operand1->Evaluate(frame) >= m_Operand2->Evaluate(frame);
 }
 
-Value InExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value InExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Value right = m_Operand2->Evaluate(context);
+       Value right = m_Operand2->Evaluate(frame);
 
        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);
+       Value left = m_Operand1->Evaluate(frame);
 
        Array::Ptr arr = right;
        return arr->Contains(left);
 }
 
-Value NotInExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value NotInExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Value right = m_Operand2->Evaluate(context);
+       Value right = m_Operand2->Evaluate(frame);
 
        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);
+       Value left = m_Operand1->Evaluate(frame);
 
        Array::Ptr arr = right;
        return !arr->Contains(left);
 }
 
-Value LogicalAndExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LogicalAndExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context).ToBool() && m_Operand2->Evaluate(context).ToBool();
+       return m_Operand1->Evaluate(frame).ToBool() && m_Operand2->Evaluate(frame).ToBool();
 }
 
-Value LogicalOrExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value LogicalOrExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return m_Operand1->Evaluate(context).ToBool() || m_Operand2->Evaluate(context).ToBool();
+       return m_Operand1->Evaluate(frame).ToBool() || m_Operand2->Evaluate(frame).ToBool();
 }
 
-Value FunctionCallExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value FunctionCallExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Value funcName = m_FName->Evaluate(context);
+       Value funcName = m_FName->Evaluate(frame);
 
        std::vector<Value> arguments;
        BOOST_FOREACH(Expression *arg, m_Args) {
-               arguments.push_back(arg->Evaluate(context));
+               arguments.push_back(arg->Evaluate(frame));
        }
 
-       return VMOps::FunctionCall(context, funcName, arguments);
+       return VMOps::FunctionCall(frame, funcName, arguments);
 }
 
-Value ArrayExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ArrayExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
        Array::Ptr result = new Array();
 
        BOOST_FOREACH(Expression *aexpr, m_Expressions) {
-               result->Add(aexpr->Evaluate(context));
+               result->Add(aexpr->Evaluate(frame));
        }
 
        return result;
 }
 
-Value DictExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value DictExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Dictionary::Ptr result = new Dictionary();
+       VMFrame *dframe;
+       VMFrame rframe;
 
-       result->Set("__parent", context);
+       if (!m_Inline) {
+               dframe = &rframe;
+               rframe.Locals = frame.Locals;
+               rframe.Self = new Dictionary();
+       } else {
+               dframe = &frame;
+       }
 
        BOOST_FOREACH(Expression *aexpr, m_Expressions) {
-               Object::Ptr acontext = m_Inline ? context : result;
-               aexpr->Evaluate(acontext, dhint);
-
-               if (VMOps::HasField(acontext, "__result"))
-                       break;
+               aexpr->Evaluate(*dframe, dhint);
        }
 
-       Dictionary::Ptr xresult = result->ShallowClone();
-       xresult->Remove("__parent");
-       return xresult;
+       return dframe->Self;
 }
 
-Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
        DebugHint *psdhint = dhint;
        DebugHint sdhint;
@@ -264,7 +265,7 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
 
        for (Array::SizeType i = 0; i < m_Indexer.size(); i++) {
                Expression *indexExpr = m_Indexer[i];
-               String tempindex = indexExpr->Evaluate(context, dhint);
+               String tempindex = indexExpr->Evaluate(frame, dhint);
 
                if (psdhint) {
                        sdhint = psdhint->GetChild(tempindex);
@@ -272,7 +273,7 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
                }
 
                if (i == 0)
-                       parent = context;
+                       parent = m_Local ? frame.Locals : frame.Self;
                else
                        parent = object;
 
@@ -284,7 +285,7 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
                                break;
                }
 
-               object = VMOps::Indexer(context, parent, tempindex);
+               object = VMOps::Indexer(frame, parent, tempindex);
 
                if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
                        object = new Dictionary();
@@ -293,7 +294,7 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
                }
        }
 
-       Value right = m_Operand2->Evaluate(context, dhint);
+       Value right = m_Operand2->Evaluate(frame, dhint);
 
        if (m_Op != OpSetLiteral) {
                Expression *lhs = MakeLiteral(object);
@@ -301,16 +302,16 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
 
                switch (m_Op) {
                        case OpSetAdd:
-                               right = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
+                               right = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
                                break;
                        case OpSetSubtract:
-                               right = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
+                               right = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
                                break;
                        case OpSetMultiply:
-                               right = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
+                               right = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
                                break;
                        case OpSetDivide:
-                               right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(context, dhint);
+                               right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
                                break;
                        default:
                                VERIFY(!"Invalid opcode.");
@@ -325,56 +326,57 @@ Value SetExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) co
        return right;
 }
 
-Value IndexerExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value IndexerExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::Indexer(context, m_Operand1->Evaluate(context), m_Operand2->Evaluate(context));
+       return VMOps::Indexer(frame, m_Operand1->Evaluate(frame), m_Operand2->Evaluate(frame));
 }
 
-Value ImportExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ImportExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Value type = m_Type->Evaluate(context);
-       Value name = m_Name->Evaluate(context);
+       String type = VMOps::GetField(frame.Self, "type");
+       Value name = m_Name->Evaluate(frame);
 
        ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
 
        if (!item)
                BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'"));
 
-       item->GetExpression()->Evaluate(context, dhint);
+       item->GetExpression()->Evaluate(frame, dhint);
 
        return Empty;
 }
 
-Value FunctionExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value FunctionExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::NewFunction(context, m_Name, m_Args, m_Expression);
+       return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
 }
 
-Value SlotExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value SlotExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::NewSlot(context, m_Signal, m_Slot->Evaluate(context));
+       return VMOps::NewSlot(frame, m_Signal, m_Slot->Evaluate(frame));
 }
 
-Value ApplyExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ApplyExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       return VMOps::NewApply(context, m_Type, m_Target, m_Name->Evaluate(context), m_Filter, m_FKVar, m_FVVar, m_FTerm, m_Expression, m_DebugInfo);
+       return VMOps::NewApply(frame, m_Type, m_Target, m_Name->Evaluate(frame), m_Filter,
+           m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_Expression, m_DebugInfo);
 }
 
-Value ObjectExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ObjectExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
        String name;
 
        if (m_Name)
-               name = m_Name->Evaluate(context, dhint);
+               name = m_Name->Evaluate(frame, dhint);
 
-       return VMOps::NewObject(context, m_Abstract, m_Type, name, m_Filter, m_Zone,
-           m_Expression, m_DebugInfo);
+       return VMOps::NewObject(frame, m_Abstract, m_Type, name, m_Filter, m_Zone,
+           m_ClosedVars, m_Expression, m_DebugInfo);
 }
 
-Value ForExpression::DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+Value ForExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
 {
-       Value value = m_Value->Evaluate(context, dhint);
+       Value value = m_Value->Evaluate(frame, dhint);
 
-       return VMOps::For(context, m_FKVar, m_FVVar, m_Value->Evaluate(context), m_Expression, m_DebugInfo);
+       return VMOps::For(frame, m_FKVar, m_FVVar, m_Value->Evaluate(frame), m_Expression, m_DebugInfo);
 }
 
index 709acc9c86ca9b6878cc2388bf6279d920aac605..4c67fb82b1e699ee07236875c34e08da0be63d3a 100644 (file)
@@ -21,6 +21,7 @@
 #define EXPRESSION_H
 
 #include "config/i2-config.hpp"
+#include "config/vmframe.hpp"
 #include "base/debuginfo.hpp"
 #include "base/array.hpp"
 #include "base/dictionary.hpp"
@@ -110,9 +111,9 @@ class I2_CONFIG_API Expression
 public:
        virtual ~Expression(void);
 
-       Value Evaluate(const Object::Ptr& context, DebugHint *dhint = NULL) const;
+       Value Evaluate(VMFrame& frame, DebugHint *dhint = NULL) const;
 
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const = 0;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const = 0;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fp) const = 0;
        virtual const DebugInfo& GetDebugInfo(void) const;
 };
@@ -127,9 +128,9 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const
        {
-               return m_Expression->DoEvaluate(context, dhint);
+               return m_Expression->DoEvaluate(frame, dhint);
        }
 
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fp) const
@@ -149,16 +150,16 @@ private:
 class I2_CONFIG_API NativeExpression : public Expression
 {
 public:
-       typedef Value (*Callback)(const Object::Ptr& context);
+       typedef Value (*Callback)(VMFrame& frame);
 
        NativeExpression(Callback callback)
                : m_Callback(callback)
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const
        {
-               return m_Callback(context);
+               return m_Callback(frame);
        }
 
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fp) const
@@ -176,7 +177,7 @@ public:
        LiteralExpression(const Value& value = Value());
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fp) const;
 
 private:
@@ -244,7 +245,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -259,7 +260,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -271,7 +272,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
 
@@ -283,7 +284,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -295,7 +296,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -307,7 +308,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -319,7 +320,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -331,7 +332,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -343,7 +344,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -355,7 +356,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -367,7 +368,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -379,7 +380,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -391,7 +392,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -403,7 +404,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -415,7 +416,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -427,7 +428,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -439,7 +440,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -451,7 +452,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -463,7 +464,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -475,7 +476,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -487,7 +488,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
        
@@ -507,7 +508,7 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 public:
@@ -529,7 +530,7 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -552,7 +553,7 @@ public:
        void MakeInline(void);
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -563,8 +564,8 @@ private:
 class I2_CONFIG_API SetExpression : public DebuggableExpression
 {
 public:
-       SetExpression(const std::vector<Expression *>& indexer, CombinedSetOp op, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
-               : DebuggableExpression(debugInfo), m_Op(op), m_Indexer(indexer), m_Operand2(operand2)
+       SetExpression(const std::vector<Expression *>& indexer, CombinedSetOp op, Expression *operand2, bool local, const DebugInfo& debugInfo = DebugInfo())
+               : DebuggableExpression(debugInfo), m_Op(op), m_Indexer(indexer), m_Operand2(operand2), m_Local(local)
        { }
 
        ~SetExpression(void)
@@ -576,13 +577,14 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
        CombinedSetOp m_Op;
        std::vector<Expression *> m_Indexer;
        Expression *m_Operand2;
+       bool m_Local;
 
 };
 
@@ -594,29 +596,27 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 };
 
 class I2_CONFIG_API ImportExpression : public DebuggableExpression
 {
 public:
-       ImportExpression(Expression *type, Expression *name, const DebugInfo& debugInfo = DebugInfo())
-               : DebuggableExpression(debugInfo), m_Type(type), m_Name(name)
+       ImportExpression(Expression *name, const DebugInfo& debugInfo = DebugInfo())
+               : DebuggableExpression(debugInfo), m_Name(name)
        { }
 
        ~ImportExpression(void)
        {
-               delete m_Type;
                delete m_Name;
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
-       Expression *m_Type;
        Expression *m_Name;
 };
 
@@ -625,17 +625,19 @@ I2_CONFIG_API String CodeGenExpression(DefinitionMap& definitions, Expression *e
 class I2_CONFIG_API FunctionExpression : public DebuggableExpression
 {
 public:
-       FunctionExpression(const String& name, const std::vector<String>& args, Expression *expression, const DebugInfo& debugInfo = DebugInfo())
-               : DebuggableExpression(debugInfo), m_Name(name), m_Args(args), m_Expression(expression)
+       FunctionExpression(const String& name, const std::vector<String>& args,
+           std::map<String, Expression *> *closedVars, Expression *expression, const DebugInfo& debugInfo = DebugInfo())
+               : DebuggableExpression(debugInfo), m_Name(name), m_Args(args), m_ClosedVars(closedVars), m_Expression(expression)
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
        String m_Name;
        std::vector<String> m_Args;
+       std::map<String, Expression *> *m_ClosedVars;
        boost::shared_ptr<Expression> m_Expression;
 };
 
@@ -647,7 +649,7 @@ public:
        { }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -660,10 +662,11 @@ 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 = DebugInfo())
+           Expression *fterm, std::map<String, Expression *> *closedVars,
+           Expression *expression, const DebugInfo& 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)
+                   m_FTerm(fterm), m_ClosedVars(closedVars), m_Expression(expression)
        { }
 
        ~ApplyExpression(void)
@@ -672,7 +675,7 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -683,14 +686,18 @@ private:
        String m_FKVar;
        String m_FVVar;
        boost::shared_ptr<Expression> m_FTerm;
+       std::map<String, Expression *> *m_ClosedVars;
        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 = DebugInfo())
-               : DebuggableExpression(debugInfo), m_Abstract(abstract), m_Type(type), m_Name(name), m_Filter(filter), m_Zone(zone), m_Expression(expression)
+       ObjectExpression(bool abstract, const String& type, Expression *name, Expression *filter,
+           const String& zone, std::map<String, Expression *> *closedVars,
+           Expression *expression, const DebugInfo& debugInfo = DebugInfo())
+               : DebuggableExpression(debugInfo), m_Abstract(abstract), m_Type(type),
+                 m_Name(name), m_Filter(filter), m_Zone(zone), m_ClosedVars(closedVars), m_Expression(expression)
        { }
 
        ~ObjectExpression(void)
@@ -699,7 +706,7 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
@@ -708,6 +715,7 @@ private:
        Expression *m_Name;
        boost::shared_ptr<Expression> m_Filter;
        String m_Zone;
+       std::map<String, Expression *> *m_ClosedVars;
        boost::shared_ptr<Expression> m_Expression;
 };
        
@@ -725,7 +733,7 @@ public:
        }
 
 protected:
-       virtual Value DoEvaluate(const Object::Ptr& context, DebugHint *dhint) const;
+       virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
        virtual void GenerateCode(DefinitionMap& definitions, std::ostream& fpg) const;
 
 private:
diff --git a/lib/config/vmframe.hpp b/lib/config/vmframe.hpp
new file mode 100644 (file)
index 0000000..833058d
--- /dev/null
@@ -0,0 +1,46 @@
+/******************************************************************************
+* Icinga 2                                                                   *
+* Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
+*                                                                            *
+* This program is free software; you can redistribute it and/or              *
+* modify it under the terms of the GNU General Public License                *
+* as published by the Free Software Foundation; either version 2             *
+* of the License, or (at your option) any later version.                     *
+*                                                                            *
+* This program is distributed in the hope that it will be useful,            *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of             *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
+* GNU General Public License for more details.                               *
+*                                                                            *
+* You should have received a copy of the GNU General Public License          *
+* along with this program; if not, write to the Free Software Foundation     *
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+******************************************************************************/
+
+#ifndef VMFRAME_H
+#define VMFRAME_H
+
+#include "config/i2-config.hpp"
+#include "base/dictionary.hpp"
+
+namespace icinga
+{
+
+struct VMFrame
+{
+       Dictionary::Ptr Locals;
+       Object::Ptr Self;
+       Value Result;
+
+       VMFrame(void)
+               : Locals(new Dictionary()), Self(Locals)
+       { }
+
+       VMFrame(const Object::Ptr& self)
+               : Locals(new Dictionary()), Self(self)
+       { }
+};
+
+}
+
+#endif /* VMOPS_H */
index bb53217b02c27377858267454a259ad030908f7d..172384a9b043fa41e7e8774aba595a7217a84b8b 100644 (file)
@@ -44,21 +44,20 @@ namespace icinga
 class VMOps
 {
 public:
-       static inline Value Variable(const Object::Ptr& context, const String& name)
+       static inline Value Variable(VMFrame& frame, const String& name)
        {
-               Object::Ptr scope = context;
+               if (name == "this")
+                       return frame.Self;
 
-               while (scope) {
-                       if (HasField(scope, name))
-                               return GetField(scope, name);
-
-                       scope = GetField(scope, "__parent");
-               }
-
-               return ScriptVariable::Get(name);
+               if (frame.Locals && frame.Locals->Contains(name))
+                       return frame.Locals->Get(name);
+               else if (frame.Locals != frame.Self && HasField(frame.Self, name))
+                       return GetField(frame.Self, name);
+               else
+                       return ScriptVariable::Get(name);
        }
 
-       static inline Value FunctionCall(const Object::Ptr& context, const Value& funcName, const std::vector<Value>& arguments)
+       static inline Value FunctionCall(VMFrame& frame, const Value& funcName, const std::vector<Value>& arguments)
        {
                ScriptFunction::Ptr func;
 
@@ -73,7 +72,7 @@ public:
                return func->Invoke(arguments);
        }
 
-       static inline Value Indexer(const Object::Ptr& context, const Value& value, const String& index)
+       static inline Value Indexer(VMFrame& frame, const Value& value, const String& index)
        {
                if (value.IsObjectType<Dictionary>()) {
                        Dictionary::Ptr dict = value;
@@ -101,9 +100,11 @@ public:
                }
        }
 
-       static inline Value NewFunction(const Object::Ptr& context, const String& name, const std::vector<String>& args, const boost::shared_ptr<Expression>& expression)
+       static inline Value NewFunction(VMFrame& frame, const String& name, const std::vector<String>& args,
+           std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression)
        {
-               ScriptFunction::Ptr func = new ScriptFunction(boost::bind(&FunctionWrapper, _1, args, expression, context));
+               ScriptFunction::Ptr func = new ScriptFunction(boost::bind(&FunctionWrapper, _1, args,
+                   EvaluateClosedVars(frame, closedVars), expression));
 
                if (!name.IsEmpty())
                        ScriptFunction::Register(name, func);
@@ -111,7 +112,7 @@ public:
                return func;
        }
 
-       static inline Value NewSlot(const Object::Ptr& context, const String& signal, const Value& slot)
+       static inline Value NewSlot(VMFrame& frame, const String& signal, const Value& slot)
        {
                ScriptSignal::Ptr sig = ScriptSignal::GetByName(signal);
 
@@ -123,17 +124,18 @@ public:
                return Empty;
        }
 
-       static inline Value NewApply(const Object::Ptr& context, const String& type, const String& target, const String& name, const boost::shared_ptr<Expression>& filter,
-               const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm,
+       static inline Value NewApply(VMFrame& frame, const String& type, const String& target, const String& name, const boost::shared_ptr<Expression>& filter,
+               const String& fkvar, const String& fvvar, const boost::shared_ptr<Expression>& fterm, std::map<String, Expression *> *closedVars,
                const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
        {
-               ApplyRule::AddRule(type, target, name, expression, filter, fkvar, fvvar, fterm, debugInfo, context);
+               ApplyRule::AddRule(type, target, name, expression, filter, fkvar,
+                   fvvar, fterm, debugInfo, EvaluateClosedVars(frame, closedVars));
 
                return Empty;
        }
 
-       static inline Value NewObject(const Object::Ptr& context, bool abstract, const String& type, const String& name, const boost::shared_ptr<Expression>& filter,
-               const String& zone, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
+       static inline Value NewObject(VMFrame& frame, bool abstract, const String& type, const String& name, const boost::shared_ptr<Expression>& filter,
+               const String& zone, std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
        {
                ConfigItemBuilder::Ptr item = new ConfigItemBuilder(debugInfo);
 
@@ -170,7 +172,7 @@ public:
 
                item->AddExpression(new OwnedExpression(expression));
                item->SetAbstract(abstract);
-               item->SetScope(context);
+               item->SetScope(EvaluateClosedVars(frame, closedVars));
                item->SetZone(zone);
                item->SetFilter(filter);
                item->Compile()->Register();
@@ -178,7 +180,7 @@ public:
                return Empty;
        }
 
-       static inline Value For(const Object::Ptr& context, const String& fkvar, const String& fvvar, const Value& value, Expression *expression, const DebugInfo& debugInfo = DebugInfo())
+       static inline Value For(VMFrame& frame, const String& fkvar, const String& fvvar, const Value& value, Expression *expression, const DebugInfo& debugInfo = DebugInfo())
        {
                if (value.IsObjectType<Array>()) {
                        if (!fvvar.IsEmpty())
@@ -188,14 +190,10 @@ public:
 
                        ObjectLock olock(arr);
                        BOOST_FOREACH(const Value& value, arr) {
-                               Dictionary::Ptr xcontext = new Dictionary();
-                               xcontext->Set("__parent", context);
-                               xcontext->Set(fkvar, value);
-
-                               expression->Evaluate(xcontext);
+                               frame.Locals->Set(fkvar, value);
+                               expression->Evaluate(frame);
                        }
-               }
-               else if (value.IsObjectType<Dictionary>()) {
+               } else if (value.IsObjectType<Dictionary>()) {
                        if (fvvar.IsEmpty())
                                BOOST_THROW_EXCEPTION(ConfigError("Cannot use array iterator for dictionary.") << errinfo_debuginfo(debugInfo));
 
@@ -203,12 +201,9 @@ public:
 
                        ObjectLock olock(dict);
                        BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                               Dictionary::Ptr xcontext = new Dictionary();
-                               xcontext->Set("__parent", context);
-                               xcontext->Set(fkvar, kv.first);
-                               xcontext->Set(fvvar, kv.second);
-
-                               expression->Evaluate(xcontext);
+                               frame.Locals->Set(fkvar, kv.first);
+                               frame.Locals->Set(fvvar, kv.second);
+                               expression->Evaluate(frame);
                        }
                }
                else
@@ -283,22 +278,24 @@ public:
 
 private:
        static inline Value FunctionWrapper(const std::vector<Value>& arguments,
-           const std::vector<String>& funcargs, const boost::shared_ptr<Expression>& expr, const Object::Ptr& scope)
+           const std::vector<String>& funcargs, const Dictionary::Ptr& closedVars, const boost::shared_ptr<Expression>& expr)
        {
                if (arguments.size() < funcargs.size())
                        BOOST_THROW_EXCEPTION(ConfigError("Too few arguments for function"));
 
-               Dictionary::Ptr context = new Dictionary();
-               context->Set("__parent", scope);
+               VMFrame frame;
+
+               if (closedVars)
+                       closedVars->CopyTo(frame.Locals);
 
                for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++)
-                       context->Set(funcargs[i], arguments[i]);
+                       frame.Locals->Set(funcargs[i], arguments[i]);
 
-               expr->Evaluate(context);
-               return context->Get("__result");
+               expr->Evaluate(frame);
+               return frame.Result;
        }
 
-       static void SlotWrapper(const Value& funcName, const std::vector<Value>& arguments)
+       static inline void SlotWrapper(const Value& funcName, const std::vector<Value>& arguments)
        {
                ScriptFunction::Ptr func;
 
@@ -312,6 +309,22 @@ private:
 
                func->Invoke(arguments);
        }
+
+       static inline Dictionary::Ptr EvaluateClosedVars(VMFrame& frame, std::map<String, Expression *> *closedVars)
+       {
+               Dictionary::Ptr locals;
+
+               if (closedVars) {
+                       locals = new Dictionary();
+
+                       typedef std::pair<String, Expression *> ClosedVar;
+                       BOOST_FOREACH(const ClosedVar& cvar, *closedVars) {
+                               locals->Set(cvar.first, cvar.second->Evaluate(frame));
+                       }
+               }
+
+               return locals;
+       }
 };
 
 }
index ef9d7f2faecfbd49838acdfbd7ed26a2a8c9982e..a2083cb517bc7a462c110440b0e43c2b30ac0c9c 100644 (file)
@@ -42,7 +42,7 @@ void Dependency::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Dependency", targets);
 }
 
-void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -52,22 +52,22 @@ void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
        ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
        builder->SetType("Dependency");
        builder->SetName(name);
-       builder->SetScope(locals);
+       builder->SetScope(frame.Locals);
 
        Host::Ptr host;
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       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));
+       builder->AddExpression(new SetExpression(MakeIndexer("parent_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
+       builder->AddExpression(new SetExpression(MakeIndexer("child_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
 
        if (service)
-               builder->AddExpression(new SetExpression(MakeIndexer("child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty())
-               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
 
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
@@ -87,19 +87,20 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
-       locals->Set("host", host);
+       VMFrame frame;
+       if (rule.GetScope())
+               rule.GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
        if (service)
-               locals->Set("service", service);
+               frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!rule.EvaluateFilter(frame))
                return false;
 
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(locals);
+               vinstances = rule.GetFTerm()->Evaluate(frame);
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
@@ -117,11 +118,11 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
-                               locals->Set(rule.GetFKVar(), instance);
+                               frame.Locals->Set(rule.GetFKVar(), instance);
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -131,10 +132,10 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
 
                ObjectLock olock(dict);
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       locals->Set(rule.GetFKVar(), kv.first);
-                       locals->Set(rule.GetFVVar(), kv.second);
+                       frame.Locals->Set(rule.GetFKVar(), kv.first);
+                       frame.Locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
                }
        }
 
index f8aeeccc5b08c508cd85e61eb5de03cc0b39d4ff..afea95920a316207a0cb4156f206d0a7101445aa 100644 (file)
@@ -28,6 +28,7 @@ namespace icinga
 {
 
 class ApplyRule;
+class VMFrame;
 class Host;
 class Service;
 
@@ -65,7 +66,7 @@ private:
        Checkable::Ptr m_Parent;
        Checkable::Ptr m_Child;
 
-       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
index 055c58c854b80dd5068c45cdf475c5481a61e5ce..775ab8545ef17e8d6fd12a312d7254060cb852ef 100644 (file)
@@ -44,11 +44,12 @@ bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr&
 
        CONTEXT("Evaluating rule for group '" + group_name + "'");
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", group->GetScope());
-       locals->Set("host", host);
+       VMFrame frame;
+       if (group->GetScope())
+               group->GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
 
-       if (!group->GetFilter()->Evaluate(locals))
+       if (!group->GetFilter()->Evaluate(frame))
                return false;
 
        Log(LogDebug, "HostGroup")
index da9e27b4106e6366063fc3492a733bb00ed7994f..9fb6894d761542efc3a22e6fe4b47c88d4620333 100644 (file)
@@ -42,7 +42,7 @@ void Notification::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Notification", targets);
 }
 
-void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -52,21 +52,21 @@ void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
        ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
        builder->SetType("Notification");
        builder->SetName(name);
-       builder->SetScope(locals);
+       builder->SetScope(frame.Locals);
 
        Host::Ptr host;
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
 
        if (service)
-               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
 
        String zone = checkable->GetZone();
 
        if (!zone.IsEmpty())
-               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
 
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
@@ -86,19 +86,20 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
-       locals->Set("host", host);
+       VMFrame frame;
+       if (rule.GetScope())
+               rule.GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
        if (service)
-               locals->Set("service", service);
+               frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!rule.EvaluateFilter(frame))
                return false;
 
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(locals);
+               vinstances = rule.GetFTerm()->Evaluate(frame);
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
@@ -116,11 +117,11 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
-                               locals->Set(rule.GetFKVar(), instance);
+                               frame.Locals->Set(rule.GetFKVar(), instance);
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -130,10 +131,10 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
 
                ObjectLock olock(dict);
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       locals->Set(rule.GetFKVar(), kv.first);
-                       locals->Set(rule.GetFVVar(), kv.second);
+                       frame.Locals->Set(rule.GetFKVar(), kv.first);
+                       frame.Locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
                }
        }
 
index 73b7f987cbdc20b809274b826998f81374ec60ec..4bc864331954d8838ff62276220d7f0a26fc01cb 100644 (file)
@@ -68,6 +68,7 @@ enum NotificationType
 class NotificationCommand;
 class Checkable;
 class ApplyRule;
+class VMFrame;
 class Host;
 class Service;
 
@@ -122,7 +123,7 @@ protected:
 private:
        void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
 
-       static void EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static void EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, VMFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule);
 };
 
index ff92633814f83fdcf0e0a3dd4630f560a7560fd5..e72744e007a1be8e3fe41ff616ce0a8ee0a0b66d 100644 (file)
@@ -41,7 +41,7 @@ void ScheduledDowntime::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("ScheduledDowntime", targets);
 }
 
-void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -51,22 +51,21 @@ void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
        ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
        builder->SetType("ScheduledDowntime");
        builder->SetName(name);
-       builder->SetScope(locals);
+       builder->SetScope(frame.Locals);
 
        Host::Ptr host;
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
 
        if (service)
-               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
 
        String zone = checkable->GetZone();
 
-       if (!zone.IsEmpty()) {
-               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
-       }
+       if (!zone.IsEmpty())
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
 
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
@@ -86,19 +85,20 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
        Service::Ptr service;
        tie(host, service) = GetHostService(checkable);
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
-       locals->Set("host", host);
+       VMFrame frame;
+       if (rule.GetScope())
+               rule.GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
        if (service)
-               locals->Set("service", service);
+               frame.Locals->Set("service", service);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!rule.EvaluateFilter(frame))
                return false;
 
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(locals);
+               vinstances = rule.GetFTerm()->Evaluate(frame);
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
@@ -116,11 +116,11 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
-                               locals->Set(rule.GetFKVar(), instance);
+                               frame.Locals->Set(rule.GetFKVar(), instance);
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(checkable, name, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, name, frame, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -130,10 +130,10 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
 
                ObjectLock olock(dict);
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       locals->Set(rule.GetFKVar(), kv.first);
-                       locals->Set(rule.GetFVVar(), kv.second);
+                       frame.Locals->Set(rule.GetFKVar(), kv.first);
+                       frame.Locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule);
                }
        }
 
index d0d15ea1357977d1eccdbca66c7458ade8e4ce0a..45fb63f3f2711e6de83308209d3f6273e3227b3e 100644 (file)
@@ -29,6 +29,7 @@ namespace icinga
 {
 
 class ApplyRule;
+class VMFrame;
 class Host;
 class Service;
 
@@ -61,7 +62,7 @@ private:
        std::pair<double, double> FindNextSegment(void);
        void CreateNextDowntime(void);
 
-       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static void EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule);
 };
 
index 923fbf07915b7ff50723ec6f360a8d109b8ba0e0..591e58a656b2ff3531af0643b5321e208e7bcd52 100644 (file)
@@ -40,7 +40,7 @@ void Service::RegisterApplyRuleHandler(void)
        ApplyRule::RegisterType("Service", targets);
 }
 
-void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule)
+void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, VMFrame& frame, const ApplyRule& rule)
 {
        DebugInfo di = rule.GetDebugInfo();
 
@@ -50,16 +50,16 @@ void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
        ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(di);
        builder->SetType("Service");
        builder->SetName(name);
-       builder->SetScope(locals);
+       builder->SetScope(frame.Locals);
 
-       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
+       builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
 
-       builder->AddExpression(new SetExpression(MakeIndexer("name"), OpSetLiteral, MakeLiteral(name), di));
+       builder->AddExpression(new SetExpression(MakeIndexer("name"), OpSetLiteral, MakeLiteral(name), false, di));
 
        String zone = host->GetZone();
 
        if (!zone.IsEmpty())
-               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
+               builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
 
        builder->AddExpression(new OwnedExpression(rule.GetExpression()));
 
@@ -75,17 +75,18 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
        msgbuf << "Evaluating 'apply' rule (" << di << ")";
        CONTEXT(msgbuf.str());
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", rule.GetScope());
-       locals->Set("host", host);
+       VMFrame frame;
+       if (rule.GetScope())
+               rule.GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
 
-       if (!rule.EvaluateFilter(locals))
+       if (!rule.EvaluateFilter(frame))
                return false;
 
        Value vinstances;
 
        if (rule.GetFTerm()) {
-               vinstances = rule.GetFTerm()->Evaluate(locals);
+               vinstances = rule.GetFTerm()->Evaluate(frame);
        } else {
                Array::Ptr instances = new Array();
                instances->Add("");
@@ -103,11 +104,11 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
                        String name = rule.GetName();
 
                        if (!rule.GetFKVar().IsEmpty()) {
-                               locals->Set(rule.GetFKVar(), instance);
+                               frame.Locals->Set(rule.GetFKVar(), instance);
                                name += instance;
                        }
 
-                       EvaluateApplyRuleInstance(host, name, locals, rule);
+                       EvaluateApplyRuleInstance(host, name, frame, rule);
                }
        } else if (vinstances.IsObjectType<Dictionary>()) {
                if (rule.GetFVVar().IsEmpty())
@@ -117,10 +118,10 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule)
 
                ObjectLock olock(dict);
                BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
-                       locals->Set(rule.GetFKVar(), kv.first);
-                       locals->Set(rule.GetFVVar(), kv.second);
+                       frame.Locals->Set(rule.GetFKVar(), kv.first);
+                       frame.Locals->Set(rule.GetFVVar(), kv.second);
 
-                       EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, locals, rule);
+                       EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, frame, rule);
                }
        }
 
index 9dc9bf9fd409815dc5450cc9a9b576a998062180..1fe1a532e00a3ab4b23f18d4e7f2b93fd099240f 100644 (file)
@@ -61,7 +61,7 @@ protected:
 private:
        Host::Ptr m_Host;
 
-       static void EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
+       static void EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, VMFrame& frame, const ApplyRule& rule);
        static bool EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule);
 };
 
index a3c007b61915f98bfeafa9a1a34a6b1df272a621..692c945bbe46eabb43da2b1596142f8d97bf80b7 100644 (file)
@@ -46,12 +46,13 @@ bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigI
 
        Host::Ptr host = service->GetHost();
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", group->GetScope());
-       locals->Set("host", host);
-       locals->Set("service", service);
+       VMFrame frame;
+       if (group->GetScope())
+               group->GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("host", host);
+       frame.Locals->Set("service", service);
 
-       if (!group->GetFilter()->Evaluate(locals))
+       if (!group->GetFilter()->Evaluate(frame))
                return false;
 
        Log(LogDebug, "ServiceGroup")
index 28d6e2a1ef77012a780f82744cc442ca5185edc0..38b4b1c94c93dc97520794ea0d4e80a986fad75c 100644 (file)
@@ -44,11 +44,12 @@ bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr&
 
        CONTEXT("Evaluating rule for group '" + group_name + "'");
 
-       Dictionary::Ptr locals = new Dictionary();
-       locals->Set("__parent", group->GetScope());
-       locals->Set("user", user);
+       VMFrame frame;
+       if (group->GetScope())
+               group->GetScope()->CopyTo(frame.Locals);
+       frame.Locals->Set("user", user);
 
-       if (!group->GetFilter()->Evaluate(locals))
+       if (!group->GetFilter()->Evaluate(frame))
                return false;
 
        Log(LogDebug, "UserGroup")