Skip to content

Commit

Permalink
Implement the 'global' keyword to differentiate between variable scopes
Browse files Browse the repository at this point in the history
refs #8074
  • Loading branch information
gunnarbeutner committed Dec 13, 2014
1 parent c0f6d65 commit dd4c04a
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 58 deletions.
1 change: 1 addition & 0 deletions lib/config/config_lexer.ll
Expand Up @@ -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;
Expand Down
75 changes: 50 additions & 25 deletions lib/config/config_parser.yy
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -880,15 +905,15 @@ 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
{
DictExpression *aexpr = dynamic_cast<DictExpression *>($5);
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;
}
;
Expand Down
4 changes: 2 additions & 2 deletions lib/config/configitembuilder.cpp
Expand Up @@ -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();
Expand Down
26 changes: 21 additions & 5 deletions lib/config/expression.cpp
Expand Up @@ -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;

Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
18 changes: 12 additions & 6 deletions lib/config/expression.hpp
Expand Up @@ -106,6 +106,13 @@ enum CombinedSetOp
OpSetBinaryOr
};

enum ScopeSpecifier
{
ScopeLocal,
ScopeCurrent,
ScopeGlobal
};

class InterruptExecutionError : virtual public std::exception, virtual public boost::exception
{
public:
Expand Down Expand Up @@ -586,8 +593,8 @@ class I2_CONFIG_API DictExpression : public DebuggableExpression
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)
Expand All @@ -602,10 +609,10 @@ class I2_CONFIG_API SetExpression : public DebuggableExpression
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;

};

Expand Down Expand Up @@ -685,16 +692,15 @@ class I2_CONFIG_API ImportExpression : public DebuggableExpression
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;
Expand Down
9 changes: 2 additions & 7 deletions lib/config/vmops.hpp
Expand Up @@ -85,16 +85,11 @@ class VMOps
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)
Expand Down
8 changes: 4 additions & 4 deletions lib/icinga/dependency-apply.cpp
Expand Up @@ -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()));

Expand Down
6 changes: 3 additions & 3 deletions lib/icinga/notification-apply.cpp
Expand Up @@ -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()));

Expand Down
6 changes: 3 additions & 3 deletions lib/icinga/scheduleddowntime-apply.cpp
Expand Up @@ -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()));

Expand Down
6 changes: 3 additions & 3 deletions lib/icinga/service-apply.cpp
Expand Up @@ -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()));

Expand Down

0 comments on commit dd4c04a

Please sign in to comment.