From f5766f91184e94af7fe4f06785b13e853e106ae4 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 22 Nov 2014 12:21:28 +0100 Subject: [PATCH] Refactor the stack frame handling for scripts fixes #7748 --- lib/base/scriptutils.cpp | 2 +- lib/cli/daemoncommand.cpp | 5 +- lib/config/applyrule.cpp | 10 +- lib/config/applyrule.hpp | 10 +- lib/config/config_lexer.ll | 2 + lib/config/config_parser.yy | 95 +++++++++---- lib/config/configitem.cpp | 15 +- lib/config/configitem.hpp | 6 +- lib/config/configitembuilder.cpp | 4 +- lib/config/configitembuilder.hpp | 4 +- lib/config/expression-codegen.cpp | 4 +- lib/config/expression.cpp | 186 +++++++++++++------------ lib/config/expression.hpp | 114 ++++++++------- lib/config/vmframe.hpp | 46 ++++++ lib/config/vmops.hpp | 97 +++++++------ lib/icinga/dependency-apply.cpp | 35 ++--- lib/icinga/dependency.hpp | 3 +- lib/icinga/hostgroup.cpp | 9 +- lib/icinga/notification-apply.cpp | 33 ++--- lib/icinga/notification.hpp | 3 +- lib/icinga/scheduleddowntime-apply.cpp | 36 ++--- lib/icinga/scheduleddowntime.hpp | 3 +- lib/icinga/service-apply.cpp | 31 +++-- lib/icinga/service.hpp | 2 +- lib/icinga/servicegroup.cpp | 11 +- lib/icinga/usergroup.cpp | 9 +- 26 files changed, 446 insertions(+), 329 deletions(-) create mode 100644 lib/config/vmframe.hpp diff --git a/lib/base/scriptutils.cpp b/lib/base/scriptutils.cpp index 3a7f9732f..56d685908 100644 --- a/lib/base/scriptutils.cpp +++ b/lib/base/scriptutils.cpp @@ -139,7 +139,7 @@ void ScriptUtils::Log(const std::vector& arguments) message = arguments[2]; } - if (message.IsString()) + if (message.IsString() || !message.IsObjectType() && !message.IsObjectType()) ::Log(severity, facility, message); else ::Log(severity, facility, JsonEncode(message)); diff --git a/lib/cli/daemoncommand.cpp b/lib/cli/daemoncommand.cpp index 5f1ac0513..7193d2d53 100644 --- a/lib/cli/daemoncommand.cpp +++ b/lib/cli/daemoncommand.cpp @@ -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(ex); ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index 4e192cd57..a9274463f 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -29,7 +29,7 @@ ApplyRule::TypeMap ApplyRule::m_Types; ApplyRule::ApplyRule(const String& targetType, const String& name, const boost::shared_ptr& expression, const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& 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, const boost::shared_ptr& filter, const String& fkvar, - const String& fvvar, const boost::shared_ptr& fterm, const DebugInfo& di, const Object::Ptr& scope) + const String& fvvar, const boost::shared_ptr& 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& targetTypes) diff --git a/lib/config/applyrule.hpp b/lib/config/applyrule.hpp index b85357aa8..af4b5c61b 100644 --- a/lib/config/applyrule.hpp +++ b/lib/config/applyrule.hpp @@ -45,14 +45,14 @@ public: String GetFVVar(void) const; boost::shared_ptr 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, - const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, const DebugInfo& di, const Object::Ptr& scope); + const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, const DebugInfo& di, const Dictionary::Ptr& scope); static std::vector& GetRules(const String& type); static void RegisterType(const String& sourceType, const std::vector& targetTypes); @@ -72,7 +72,7 @@ private: String m_FVVar; boost::shared_ptr 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, const boost::shared_ptr& filter, const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, - const DebugInfo& di, const Object::Ptr& scope); + const DebugInfo& di, const Dictionary::Ptr& scope); }; } diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index 64cf56fdb..acf898682 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -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; diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index 79b0face3..4b01cac68 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -98,6 +98,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig icinga::TypeSpecifier type; std::vector *slist; std::vector *elist; + std::pair *cvitem; + std::map *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 T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)" %token T_TYPE_ARRAY "array (T_TYPE_ARRAY)" %token T_TYPE_NUMBER "number (T_TYPE_NUMBER)" @@ -184,6 +188,9 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig %type apply %type optional_rterm %type target_type_specifier +%type use_specifier +%type use_specifier_items +%type use_specifier_item %left T_LOGICAL_OR %left T_LOGICAL_AND @@ -217,8 +224,6 @@ static std::stack m_Abstract; static std::stack m_RuleLists; static ConfigType::Ptr m_Type; -static Dictionary::Ptr m_ModuleScope; - static std::stack m_Apply; static std::stack m_ObjectAssign; static std::stack m_SeenAssign; @@ -231,8 +236,6 @@ static std::stack > m_Expressions; Expression *ConfigCompiler::Compile(void) { - m_ModuleScope = new Dictionary(); - m_Abstract = std::stack(); m_RuleLists = std::stack(); 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($5); + DictExpression *exprl = dynamic_cast($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 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(&$$, $1, $3, @1, @3); } | rterm T_MULTIPLY rterm { MakeRBinaryOp(&$$, $1, $3, @1, @3); } | rterm T_DIVIDE_OP rterm { MakeRBinaryOp(&$$, $1, $3, @1, @3); } - | T_FUNCTION identifier '(' identifier_items ')' rterm_scope + | T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope { - DictExpression *aexpr = dynamic_cast($6); + DictExpression *aexpr = dynamic_cast($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($5); + DictExpression *aexpr = dynamic_cast($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(); + $$->insert(*$1); + delete $1; + } + | use_specifier_items ',' use_specifier_item + { + $$ = $1; + $$->insert(*$3); + delete $3; + } + ; + +use_specifier_item: identifier + { + $$ = new std::pair($1, new VariableExpression($1, @1)); + } + | identifier T_SET rterm + { + $$ = new std::pair($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($7); + DictExpression *exprl = dynamic_cast($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)); } ; diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index fbfe514cc..65b096503 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -59,7 +59,7 @@ ConfigItem::ItemList ConfigItem::m_CommittedItems; ConfigItem::ConfigItem(const String& type, const String& name, bool abstract, const boost::shared_ptr& exprl, const boost::shared_ptr& 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(ex); ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index de7ac24d2..538b9d89d 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -42,7 +42,7 @@ public: const boost::shared_ptr& exprl, const boost::shared_ptr& 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 m_Expression; boost::shared_ptr 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; diff --git a/lib/config/configitembuilder.cpp b/lib/config/configitembuilder.cpp index 89d016801..f74cb8e7f 100644 --- a/lib/config/configitembuilder.cpp +++ b/lib/config/configitembuilder.cpp @@ -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(); diff --git a/lib/config/configitembuilder.hpp b/lib/config/configitembuilder.hpp index d44007ff8..0d976c4aa 100644 --- a/lib/config/configitembuilder.hpp +++ b/lib/config/configitembuilder.hpp @@ -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 m_Expressions; /**< Expressions for this item. */ boost::shared_ptr 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. */ }; diff --git a/lib/config/expression-codegen.cpp b/lib/config/expression-codegen.cpp index cf02cbf2e..d21d5bec0 100644 --- a/lib/config/expression-codegen.cpp +++ b/lib/config/expression-codegen.cpp @@ -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" diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index e3cbc3db3..c058789f2 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -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(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()) 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()) 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 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); } diff --git a/lib/config/expression.hpp b/lib/config/expression.hpp index 709acc9c8..4c67fb82b 100644 --- a/lib/config/expression.hpp +++ b/lib/config/expression.hpp @@ -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& indexer, CombinedSetOp op, Expression *operand2, const DebugInfo& debugInfo = DebugInfo()) - : DebuggableExpression(debugInfo), m_Op(op), m_Indexer(indexer), m_Operand2(operand2) + SetExpression(const std::vector& 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 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& 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& args, + std::map *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 m_Args; + std::map *m_ClosedVars; boost::shared_ptr 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 *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 m_FTerm; + std::map *m_ClosedVars; boost::shared_ptr 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 *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 m_Filter; String m_Zone; + std::map *m_ClosedVars; boost::shared_ptr 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 index 000000000..833058d69 --- /dev/null +++ b/lib/config/vmframe.hpp @@ -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 */ diff --git a/lib/config/vmops.hpp b/lib/config/vmops.hpp index bb53217b0..172384a9b 100644 --- a/lib/config/vmops.hpp +++ b/lib/config/vmops.hpp @@ -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& arguments) + static inline Value FunctionCall(VMFrame& frame, const Value& funcName, const std::vector& 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::Ptr dict = value; @@ -101,9 +100,11 @@ public: } } - static inline Value NewFunction(const Object::Ptr& context, const String& name, const std::vector& args, const boost::shared_ptr& expression) + static inline Value NewFunction(VMFrame& frame, const String& name, const std::vector& args, + std::map *closedVars, const boost::shared_ptr& 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& filter, - const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, + static inline Value NewApply(VMFrame& frame, const String& type, const String& target, const String& name, const boost::shared_ptr& filter, + const String& fkvar, const String& fvvar, const boost::shared_ptr& fterm, std::map *closedVars, const boost::shared_ptr& 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& filter, - const String& zone, const boost::shared_ptr& expression, const DebugInfo& debugInfo = DebugInfo()) + static inline Value NewObject(VMFrame& frame, bool abstract, const String& type, const String& name, const boost::shared_ptr& filter, + const String& zone, std::map *closedVars, const boost::shared_ptr& 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()) { 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()) { + } else if (value.IsObjectType()) { 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& arguments, - const std::vector& funcargs, const boost::shared_ptr& expr, const Object::Ptr& scope) + const std::vector& funcargs, const Dictionary::Ptr& closedVars, const boost::shared_ptr& 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::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& arguments) + static inline void SlotWrapper(const Value& funcName, const std::vector& arguments) { ScriptFunction::Ptr func; @@ -312,6 +309,22 @@ private: func->Invoke(arguments); } + + static inline Dictionary::Ptr EvaluateClosedVars(VMFrame& frame, std::map *closedVars) + { + Dictionary::Ptr locals; + + if (closedVars) { + locals = new Dictionary(); + + typedef std::pair ClosedVar; + BOOST_FOREACH(const ClosedVar& cvar, *closedVars) { + locals->Set(cvar.first, cvar.second->Evaluate(frame)); + } + } + + return locals; + } }; } diff --git a/lib/icinga/dependency-apply.cpp b/lib/icinga/dependency-apply.cpp index ef9d7f2fa..a2083cb51 100644 --- a/lib/icinga/dependency-apply.cpp +++ b/lib/icinga/dependency-apply.cpp @@ -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()) { 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); } } diff --git a/lib/icinga/dependency.hpp b/lib/icinga/dependency.hpp index f8aeeccc5..afea95920 100644 --- a/lib/icinga/dependency.hpp +++ b/lib/icinga/dependency.hpp @@ -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); }; diff --git a/lib/icinga/hostgroup.cpp b/lib/icinga/hostgroup.cpp index 055c58c85..775ab8545 100644 --- a/lib/icinga/hostgroup.cpp +++ b/lib/icinga/hostgroup.cpp @@ -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") diff --git a/lib/icinga/notification-apply.cpp b/lib/icinga/notification-apply.cpp index da9e27b41..9fb6894d7 100644 --- a/lib/icinga/notification-apply.cpp +++ b/lib/icinga/notification-apply.cpp @@ -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()) { 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); } } diff --git a/lib/icinga/notification.hpp b/lib/icinga/notification.hpp index 73b7f987c..4bc864331 100644 --- a/lib/icinga/notification.hpp +++ b/lib/icinga/notification.hpp @@ -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, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule); + static void EvaluateApplyRuleInstance(const intrusive_ptr& checkable, const String& name, VMFrame& frame, const ApplyRule& rule); static bool EvaluateApplyRule(const intrusive_ptr& checkable, const ApplyRule& rule); }; diff --git a/lib/icinga/scheduleddowntime-apply.cpp b/lib/icinga/scheduleddowntime-apply.cpp index ff9263381..e72744e00 100644 --- a/lib/icinga/scheduleddowntime-apply.cpp +++ b/lib/icinga/scheduleddowntime-apply.cpp @@ -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()) { 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); } } diff --git a/lib/icinga/scheduleddowntime.hpp b/lib/icinga/scheduleddowntime.hpp index d0d15ea13..45fb63f3f 100644 --- a/lib/icinga/scheduleddowntime.hpp +++ b/lib/icinga/scheduleddowntime.hpp @@ -29,6 +29,7 @@ namespace icinga { class ApplyRule; +class VMFrame; class Host; class Service; @@ -61,7 +62,7 @@ private: std::pair 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); }; diff --git a/lib/icinga/service-apply.cpp b/lib/icinga/service-apply.cpp index 923fbf079..591e58a65 100644 --- a/lib/icinga/service-apply.cpp +++ b/lib/icinga/service-apply.cpp @@ -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()) { 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); } } diff --git a/lib/icinga/service.hpp b/lib/icinga/service.hpp index 9dc9bf9fd..1fe1a532e 100644 --- a/lib/icinga/service.hpp +++ b/lib/icinga/service.hpp @@ -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); }; diff --git a/lib/icinga/servicegroup.cpp b/lib/icinga/servicegroup.cpp index a3c007b61..692c945bb 100644 --- a/lib/icinga/servicegroup.cpp +++ b/lib/icinga/servicegroup.cpp @@ -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") diff --git a/lib/icinga/usergroup.cpp b/lib/icinga/usergroup.cpp index 28d6e2a1e..38b4b1c94 100644 --- a/lib/icinga/usergroup.cpp +++ b/lib/icinga/usergroup.cpp @@ -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") -- 2.40.0