mirror of https://github.com/Icinga/icinga2.git
Implement the 'global' keyword to differentiate between variable scopes
refs #8074
This commit is contained in:
parent
c0f6d65b66
commit
dd4c04aa9b
|
@ -179,6 +179,7 @@ true { yylval->boolean = 1; return T_BOOLEAN; }
|
|||
false { yylval->boolean = 0; return T_BOOLEAN; }
|
||||
const return T_CONST;
|
||||
local return T_LOCAL;
|
||||
global return T_GLOBAL;
|
||||
use return T_USE;
|
||||
apply return T_APPLY;
|
||||
to return T_TO;
|
||||
|
|
|
@ -99,6 +99,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
|
|||
std::vector<Expression *> *elist;
|
||||
std::pair<String, Expression *> *cvitem;
|
||||
std::map<String, Expression *> *cvlist;
|
||||
icinga::ScopeSpecifier scope;
|
||||
}
|
||||
|
||||
%token T_NEWLINE "new-line"
|
||||
|
@ -201,13 +202,14 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
|
|||
%type <cvlist> use_specifier_items
|
||||
%type <cvitem> use_specifier_item
|
||||
%type <num> object_declaration
|
||||
%type <scope> scope_specifier
|
||||
|
||||
%right T_FOLLOWS
|
||||
%right T_INCLUDE T_INCLUDE_RECURSIVE T_OBJECT T_TEMPLATE T_APPLY T_IMPORT T_ASSIGN T_IGNORE T_WHERE
|
||||
%right T_FUNCTION T_SIGNAL T_FOR
|
||||
%left T_LOGICAL_OR
|
||||
%left T_LOGICAL_AND
|
||||
%left T_LOCAL T_RETURN
|
||||
%left T_GLOBAL T_LOCAL T_RETURN
|
||||
%left T_IDENTIFIER
|
||||
%left T_SET T_SET_ADD T_SET_SUBTRACT T_SET_MULTIPLY T_SET_DIVIDE T_SET_MODULO T_SET_XOR T_SET_BINARY_AND T_SET_BINARY_OR
|
||||
%nonassoc T_EQUAL T_NOT_EQUAL
|
||||
|
@ -551,6 +553,16 @@ indexer_item: '.' identifier
|
|||
}
|
||||
;
|
||||
|
||||
scope_specifier: T_LOCAL
|
||||
{
|
||||
$$ = ScopeLocal;
|
||||
}
|
||||
| T_GLOBAL
|
||||
{
|
||||
$$ = ScopeGlobal;
|
||||
}
|
||||
;
|
||||
|
||||
combined_set_op: T_SET
|
||||
| T_SET_ADD
|
||||
| T_SET_SUBTRACT
|
||||
|
@ -577,26 +589,26 @@ lterm: type
|
|||
{
|
||||
$$ = MakeLiteral(); // ASTify this
|
||||
}
|
||||
| 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, false, DebugInfoRange(@1, @3));
|
||||
$$ = new SetExpression(ScopeCurrent, *$1, $2, $3, DebugInfoRange(@1, @3));
|
||||
delete $1;
|
||||
}
|
||||
| T_LOCAL identifier combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression(MakeIndexer($2), $3, $4, true, DebugInfoRange(@1, @4));
|
||||
free($2);
|
||||
}
|
||||
| identifier combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression(MakeIndexer($1), $2, $3, false, DebugInfoRange(@1, @3));
|
||||
$$ = new SetExpression(ScopeCurrent, MakeIndexer($1), $2, $3, DebugInfoRange(@1, @3));
|
||||
free($1);
|
||||
}
|
||||
| scope_specifier indexer combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression($1, *$2, $3, $4, DebugInfoRange(@1, @4));
|
||||
delete $2;
|
||||
}
|
||||
| scope_specifier identifier combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression($1, MakeIndexer($2), $3, $4, DebugInfoRange(@1, @4));
|
||||
free($2);
|
||||
}
|
||||
| T_INCLUDE T_STRING
|
||||
{
|
||||
$$ = context->HandleInclude($2, false, DebugInfoRange(@1, @2));
|
||||
|
@ -699,6 +711,28 @@ lterm: type
|
|||
|
||||
$$ = new ConditionalExpression($3, atrue, afalse, DebugInfoRange(@1, @7));
|
||||
}
|
||||
| T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope
|
||||
{
|
||||
DictExpression *aexpr = dynamic_cast<DictExpression *>($7);
|
||||
aexpr->MakeInline();
|
||||
|
||||
FunctionExpression *fexpr = new FunctionExpression(*$4, $6, aexpr, DebugInfoRange(@1, @7));
|
||||
delete $4;
|
||||
|
||||
$$ = new SetExpression(ScopeCurrent, MakeIndexer($2), OpSetLiteral, fexpr, DebugInfoRange(@1, @7));
|
||||
free($2);
|
||||
}
|
||||
| scope_specifier T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope
|
||||
{
|
||||
DictExpression *aexpr = dynamic_cast<DictExpression *>($8);
|
||||
aexpr->MakeInline();
|
||||
|
||||
FunctionExpression *fexpr = new FunctionExpression(*$5, $7, aexpr, DebugInfoRange(@1, @8));
|
||||
delete $5;
|
||||
|
||||
$$ = new SetExpression($1, MakeIndexer($3), OpSetLiteral, fexpr, DebugInfoRange(@1, @8));
|
||||
free($3);
|
||||
}
|
||||
| rterm
|
||||
{
|
||||
$$ = $1;
|
||||
|
@ -853,21 +887,12 @@ rterm_without_indexer: T_STRING
|
|||
| rterm T_DIVIDE_OP rterm { MakeRBinaryOp<DivideExpression>(&$$, $1, $3, @1, @3); }
|
||||
| rterm T_MODULO rterm { MakeRBinaryOp<ModuloExpression>(&$$, $1, $3, @1, @3); }
|
||||
| rterm T_XOR rterm { MakeRBinaryOp<XorExpression>(&$$, $1, $3, @1, @3); }
|
||||
| T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope
|
||||
{
|
||||
DictExpression *aexpr = dynamic_cast<DictExpression *>($7);
|
||||
aexpr->MakeInline();
|
||||
|
||||
$$ = new FunctionExpression($2, *$4, $6, aexpr, DebugInfoRange(@1, @6));
|
||||
free($2);
|
||||
delete $4;
|
||||
}
|
||||
| T_FUNCTION '(' identifier_items ')' use_specifier rterm_scope
|
||||
{
|
||||
DictExpression *aexpr = dynamic_cast<DictExpression *>($6);
|
||||
aexpr->MakeInline();
|
||||
|
||||
$$ = new FunctionExpression("", *$3, $5, aexpr, DebugInfoRange(@1, @5));
|
||||
$$ = new FunctionExpression(*$3, $5, aexpr, DebugInfoRange(@1, @5));
|
||||
delete $3;
|
||||
}
|
||||
| identifier T_FOLLOWS rterm
|
||||
|
@ -880,7 +905,7 @@ rterm_without_indexer: T_STRING
|
|||
args.push_back($1);
|
||||
free($1);
|
||||
|
||||
$$ = new FunctionExpression("", args, new std::map<String, Expression *>(), $3, DebugInfoRange(@1, @3));
|
||||
$$ = new FunctionExpression(args, new std::map<String, Expression *>(), $3, DebugInfoRange(@1, @3));
|
||||
}
|
||||
| T_BINARY_OR identifier_items T_BINARY_OR T_FOLLOWS rterm
|
||||
{
|
||||
|
@ -888,7 +913,7 @@ rterm_without_indexer: T_STRING
|
|||
if (aexpr)
|
||||
aexpr->MakeInline();
|
||||
|
||||
$$ = new FunctionExpression("", *$2, new std::map<String, Expression *>(), $5, DebugInfoRange(@1, @5));
|
||||
$$ = new FunctionExpression(*$2, new std::map<String, Expression *>(), $5, DebugInfoRange(@1, @5));
|
||||
delete $2;
|
||||
}
|
||||
;
|
||||
|
|
|
@ -100,8 +100,8 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
|
|||
Array::Ptr templateArray = new Array();
|
||||
templateArray->Add(m_Name);
|
||||
|
||||
exprs.push_back(new SetExpression(MakeIndexer("templates"), OpSetAdd,
|
||||
new LiteralExpression(templateArray), false, m_DebugInfo));
|
||||
exprs.push_back(new SetExpression(ScopeCurrent, MakeIndexer("templates"), OpSetAdd,
|
||||
new LiteralExpression(templateArray), m_DebugInfo));
|
||||
|
||||
DictExpression *dexpr = new DictExpression(m_Expressions, m_DebugInfo);
|
||||
dexpr->MakeInline();
|
||||
|
|
|
@ -333,10 +333,20 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
|||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (m_Local)
|
||||
if (m_ScopeSpec == ScopeLocal)
|
||||
parent = frame.Locals;
|
||||
else
|
||||
else if (m_ScopeSpec == ScopeCurrent)
|
||||
parent = frame.Self;
|
||||
else if (m_ScopeSpec == ScopeGlobal) {
|
||||
ScriptVariable::Ptr sv = ScriptVariable::GetByName(tempindex);
|
||||
|
||||
Dictionary::Ptr fglobals = new Dictionary();
|
||||
|
||||
if (sv)
|
||||
fglobals->Set(tempindex, sv->GetData());
|
||||
|
||||
parent = fglobals;
|
||||
}
|
||||
} else
|
||||
parent = object;
|
||||
|
||||
|
@ -353,7 +363,10 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
|||
if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
|
||||
object = new Dictionary();
|
||||
|
||||
VMOps::SetField(parent, tempindex, object, m_DebugInfo);
|
||||
if (i == 0 && m_ScopeSpec == ScopeGlobal)
|
||||
ScriptVariable::Set(tempindex, object);
|
||||
else
|
||||
VMOps::SetField(parent, tempindex, object, m_DebugInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,7 +406,10 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
|||
}
|
||||
}
|
||||
|
||||
VMOps::SetField(parent, index, right, m_DebugInfo);
|
||||
if (m_Indexer.size() == 1 && m_ScopeSpec == ScopeGlobal)
|
||||
ScriptVariable::Set(index, right);
|
||||
else
|
||||
VMOps::SetField(parent, index, right, m_DebugInfo);
|
||||
|
||||
if (psdhint)
|
||||
psdhint->AddMessage("=", m_DebugInfo);
|
||||
|
@ -438,7 +454,7 @@ Value ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
|||
|
||||
Value FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
|
||||
return VMOps::NewFunction(frame, m_Args, m_ClosedVars, m_Expression);
|
||||
}
|
||||
|
||||
Value SlotExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
|
|
|
@ -106,6 +106,13 @@ enum CombinedSetOp
|
|||
OpSetBinaryOr
|
||||
};
|
||||
|
||||
enum ScopeSpecifier
|
||||
{
|
||||
ScopeLocal,
|
||||
ScopeCurrent,
|
||||
ScopeGlobal
|
||||
};
|
||||
|
||||
class InterruptExecutionError : virtual public std::exception, virtual public boost::exception
|
||||
{
|
||||
public:
|
||||
|
@ -586,8 +593,8 @@ private:
|
|||
class I2_CONFIG_API SetExpression : public DebuggableExpression
|
||||
{
|
||||
public:
|
||||
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(ScopeSpecifier scopeSpec, const std::vector<Expression *>& indexer, CombinedSetOp op, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
|
||||
: DebuggableExpression(debugInfo), m_ScopeSpec(scopeSpec), m_Op(op), m_Indexer(indexer), m_Operand2(operand2)
|
||||
{ }
|
||||
|
||||
~SetExpression(void)
|
||||
|
@ -602,10 +609,10 @@ protected:
|
|||
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
|
||||
|
||||
private:
|
||||
ScopeSpecifier m_ScopeSpec;
|
||||
CombinedSetOp m_Op;
|
||||
std::vector<Expression *> m_Indexer;
|
||||
Expression *m_Operand2;
|
||||
bool m_Local;
|
||||
|
||||
};
|
||||
|
||||
|
@ -685,16 +692,15 @@ private:
|
|||
class I2_CONFIG_API FunctionExpression : public DebuggableExpression
|
||||
{
|
||||
public:
|
||||
FunctionExpression(const String& name, const std::vector<String>& args,
|
||||
FunctionExpression(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)
|
||||
: DebuggableExpression(debugInfo), m_Args(args), m_ClosedVars(closedVars), m_Expression(expression)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
|
||||
|
||||
private:
|
||||
String m_Name;
|
||||
std::vector<String> m_Args;
|
||||
std::map<String, Expression *> *m_ClosedVars;
|
||||
boost::shared_ptr<Expression> m_Expression;
|
||||
|
|
|
@ -85,16 +85,11 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
static inline Value NewFunction(ScriptFrame& frame, const String& name, const std::vector<String>& args,
|
||||
static inline Value NewFunction(ScriptFrame& frame, 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,
|
||||
return new ScriptFunction(boost::bind(&FunctionWrapper, _1, args,
|
||||
EvaluateClosedVars(frame, closedVars), expression));
|
||||
|
||||
if (!name.IsEmpty())
|
||||
ScriptFunction::Register(name, func);
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
static inline Value NewSlot(ScriptFrame& frame, const String& signal, const Value& slot)
|
||||
|
|
|
@ -58,16 +58,16 @@ void Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
|
|||
Service::Ptr service;
|
||||
tie(host, service) = GetHostService(checkable);
|
||||
|
||||
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));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("parent_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("child_host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
|
||||
|
||||
if (service)
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("child_service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
|
||||
|
||||
String zone = checkable->GetZone();
|
||||
|
||||
if (!zone.IsEmpty())
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
|
||||
|
||||
builder->AddExpression(new OwnedExpression(rule.GetExpression()));
|
||||
|
||||
|
|
|
@ -58,15 +58,15 @@ void Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
|
|||
Service::Ptr service;
|
||||
tie(host, service) = GetHostService(checkable);
|
||||
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
|
||||
|
||||
if (service)
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
|
||||
|
||||
String zone = checkable->GetZone();
|
||||
|
||||
if (!zone.IsEmpty())
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
|
||||
|
||||
builder->AddExpression(new OwnedExpression(rule.GetExpression()));
|
||||
|
||||
|
|
|
@ -57,15 +57,15 @@ void ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
|
|||
Service::Ptr service;
|
||||
tie(host, service) = GetHostService(checkable);
|
||||
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
|
||||
|
||||
if (service)
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("service_name"), OpSetLiteral, MakeLiteral(service->GetShortName()), di));
|
||||
|
||||
String zone = checkable->GetZone();
|
||||
|
||||
if (!zone.IsEmpty())
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
|
||||
|
||||
builder->AddExpression(new OwnedExpression(rule.GetExpression()));
|
||||
|
||||
|
|
|
@ -52,14 +52,14 @@ void Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
|
|||
builder->SetName(name);
|
||||
builder->SetScope(frame.Locals);
|
||||
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("host_name"), OpSetLiteral, MakeLiteral(host->GetName()), di));
|
||||
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("name"), OpSetLiteral, MakeLiteral(name), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("name"), OpSetLiteral, MakeLiteral(name), di));
|
||||
|
||||
String zone = host->GetZone();
|
||||
|
||||
if (!zone.IsEmpty())
|
||||
builder->AddExpression(new SetExpression(MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), false, di));
|
||||
builder->AddExpression(new SetExpression(ScopeCurrent, MakeIndexer("zone"), OpSetLiteral, MakeLiteral(zone), di));
|
||||
|
||||
builder->AddExpression(new OwnedExpression(rule.GetExpression()));
|
||||
|
||||
|
|
Loading…
Reference in New Issue