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);
}
bool ScriptGlobal::Exists(const String& name)
{
return m_Globals->Contains(name);
}
Dictionary::Ptr ScriptGlobal::GetGlobals(void)
{
return m_Globals;

View File

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

View File

@ -559,7 +559,6 @@ lterm: type
| rterm combined_set_op rterm
{
Expression *expr = $1;
BindToScope(expr, ScopeCurrent);
$$ = new SetExpression(expr, $2, $3, DebugInfoRange(@1, @3));
}
| T_INCLUDE T_STRING
@ -787,7 +786,9 @@ rterm: T_STRING
}
| 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
{
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
{
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
@ -410,6 +435,23 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
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);
if (iexpr) {

View File

@ -280,7 +280,7 @@ protected:
private:
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
@ -589,6 +589,8 @@ protected:
private:
std::vector<Expression *> m_Expressions;
bool m_Inline;
friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
};
class I2_CONFIG_API SetExpression : public BinaryExpression
@ -603,6 +605,8 @@ protected:
private:
CombinedSetOp m_Op;
friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
};
class I2_CONFIG_API ConditionalExpression : public DebuggableExpression
@ -664,7 +668,7 @@ protected:
virtual Value DoEvaluate(ScriptFrame& frame, 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);

View File

@ -46,9 +46,6 @@ class VMOps
public:
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))
return frame.Locals->Get(name);
else if (frame.Self.IsObject() && frame.Locals != static_cast<Object::Ptr>(frame.Self) && HasField(frame.Self, name))