Fix incorrect variable scoping

refs #8074
This commit is contained in:
Gunnar Beutner 2014-12-15 12:57:40 +01:00
parent 85af84c9fb
commit 252f3205cb
6 changed files with 59 additions and 9 deletions

View File

@ -50,6 +50,11 @@ void ScriptGlobal::Set(const String& name, const Value& value)
m_Globals->Set(name, value); m_Globals->Set(name, value);
} }
bool ScriptGlobal::Exists(const String& name)
{
return m_Globals->Contains(name);
}
Dictionary::Ptr ScriptGlobal::GetGlobals(void) Dictionary::Ptr ScriptGlobal::GetGlobals(void)
{ {
return m_Globals; return m_Globals;

View File

@ -36,6 +36,7 @@ class I2_BASE_API ScriptGlobal
public: public:
static Value Get(const String& name, const Value *defaultValue = NULL); static Value Get(const String& name, const Value *defaultValue = NULL);
static void Set(const String& name, const Value& value); static void Set(const String& name, const Value& value);
static bool Exists(const String& name);
static void WriteToFile(const String& filename); static void WriteToFile(const String& filename);

View File

@ -559,7 +559,6 @@ lterm: type
| rterm combined_set_op rterm | rterm combined_set_op rterm
{ {
Expression *expr = $1; Expression *expr = $1;
BindToScope(expr, ScopeCurrent);
$$ = new SetExpression(expr, $2, $3, DebugInfoRange(@1, @3)); $$ = new SetExpression(expr, $2, $3, DebugInfoRange(@1, @3));
} }
| T_INCLUDE T_STRING | T_INCLUDE T_STRING
@ -787,7 +786,9 @@ rterm: T_STRING
} }
| rterm_scope | rterm_scope
{ {
$$ = $1; Expression *expr = $1;
BindToScope(expr, ScopeCurrent);
$$ = expr;
} }
| '(' | '('
{ {

View File

@ -94,12 +94,37 @@ const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
Value VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const Value VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return VMOps::Variable(frame, m_Variable, m_DebugInfo); if (frame.Locals && frame.Locals->Contains(m_Variable))
return frame.Locals->Get(m_Variable);
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && VMOps::HasField(frame.Self, m_Variable))
return VMOps::GetField(frame.Self, m_Variable, m_DebugInfo);
else
return ScriptGlobal::Get(m_Variable);
} }
bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
{ {
return false; *index = m_Variable;
if (frame.Locals && frame.Locals->Contains(m_Variable)) {
*parent = frame.Locals;
if (dhint)
*dhint = NULL;
} else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && VMOps::HasField(frame.Self, m_Variable)) {
*parent = frame.Self;
if (dhint && *dhint)
*dhint = new DebugHint((*dhint)->GetChild(m_Variable));
} else if (ScriptGlobal::Exists(m_Variable)) {
*parent = ScriptGlobal::GetGlobals();
if (dhint)
*dhint = NULL;
} else
*parent = frame.Locals;
return true;
} }
Value NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const Value NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
@ -410,6 +435,23 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec) void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
{ {
DictExpression *dexpr = dynamic_cast<DictExpression *>(expr);
if (dexpr) {
BOOST_FOREACH(Expression *& expr, dexpr->m_Expressions)
BindToScope(expr, scopeSpec);
return;
}
SetExpression *aexpr = dynamic_cast<SetExpression *>(expr);
if (aexpr) {
BindToScope(aexpr->m_Operand1, scopeSpec);
return;
}
IndexerExpression *iexpr = dynamic_cast<IndexerExpression *>(expr); IndexerExpression *iexpr = dynamic_cast<IndexerExpression *>(expr);
if (iexpr) { if (iexpr) {

View File

@ -280,7 +280,7 @@ protected:
private: private:
String m_Variable; String m_Variable;
friend void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec); friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
}; };
class I2_CONFIG_API NegateExpression : public UnaryExpression class I2_CONFIG_API NegateExpression : public UnaryExpression
@ -589,6 +589,8 @@ protected:
private: private:
std::vector<Expression *> m_Expressions; std::vector<Expression *> m_Expressions;
bool m_Inline; bool m_Inline;
friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
}; };
class I2_CONFIG_API SetExpression : public BinaryExpression class I2_CONFIG_API SetExpression : public BinaryExpression
@ -603,6 +605,8 @@ protected:
private: private:
CombinedSetOp m_Op; CombinedSetOp m_Op;
friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
}; };
class I2_CONFIG_API ConditionalExpression : public DebuggableExpression class I2_CONFIG_API ConditionalExpression : public DebuggableExpression
@ -664,7 +668,7 @@ protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const; virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const;
friend void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec); friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
}; };
I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec); I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);

View File

@ -46,9 +46,6 @@ class VMOps
public: public:
static inline Value Variable(ScriptFrame& frame, const String& name, const DebugInfo& debugInfo = DebugInfo()) static inline Value Variable(ScriptFrame& frame, const String& name, const DebugInfo& debugInfo = DebugInfo())
{ {
if (name == "this")
return frame.Self;
if (frame.Locals && frame.Locals->Contains(name)) if (frame.Locals && frame.Locals->Contains(name))
return frame.Locals->Get(name); return frame.Locals->Get(name);
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && HasField(frame.Self, name)) else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && HasField(frame.Self, name))