Implement the 'continue' and 'break' keywords

fixes #8394
This commit is contained in:
Gunnar Beutner 2015-02-19 12:57:52 +01:00
parent 70c750250c
commit a76f816623
11 changed files with 506 additions and 255 deletions

View File

@ -703,6 +703,10 @@ Example:
num -= 1 num -= 1
} }
The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
breaks out of the loop.
## <a id="for-loops"></a> For Loops ## <a id="for-loops"></a> For Loops
The `for` statement can be used to iterate over arrays and dictionaries. The `for` statement can be used to iterate over arrays and dictionaries.
@ -726,6 +730,10 @@ Iterating over dictionaries can be accomplished in a similar manner:
log("Key: " + key + ", Value: " + value) log("Key: " + key + ", Value: " + value)
} }
The `continue` and `break` keywords can be used to control how the loop is executed: The `continue` keyword
skips over the remaining expressions for the loop body and begins the next loop evaluation. The `break` keyword
breaks out of the loop.
## <a id="types"></a> Types ## <a id="types"></a> Types
All values have a static type. The `typeof` function can be used to determine the type of a value: All values have a static type. The `typeof` function can be used to determine the type of a value:

View File

@ -88,7 +88,7 @@ void ApplyRule::AddRule(const String& sourceType, const String& targetType, cons
bool ApplyRule::EvaluateFilter(ScriptFrame& frame) const bool ApplyRule::EvaluateFilter(ScriptFrame& frame) const
{ {
return m_Filter->Evaluate(frame).ToBool(); return Convert::ToBool(m_Filter->Evaluate(frame));
} }
void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes) void ApplyRule::RegisterType(const String& sourceType, const std::vector<String>& targetTypes)

View File

@ -202,6 +202,8 @@ assign return T_ASSIGN;
ignore return T_IGNORE; ignore return T_IGNORE;
function return T_FUNCTION; function return T_FUNCTION;
return return T_RETURN; return return T_RETURN;
break return T_BREAK;
continue return T_CONTINUE;
for return T_FOR; for return T_FOR;
if return T_IF; if return T_IF;
else return T_ELSE; else return T_ELSE;

View File

@ -172,6 +172,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token T_IGNORE "ignore (T_IGNORE)" %token T_IGNORE "ignore (T_IGNORE)"
%token T_FUNCTION "function (T_FUNCTION)" %token T_FUNCTION "function (T_FUNCTION)"
%token T_RETURN "return (T_RETURN)" %token T_RETURN "return (T_RETURN)"
%token T_BREAK "break (T_BREAK)"
%token T_CONTINUE "continue (T_CONTINUE)"
%token T_FOR "for (T_FOR)" %token T_FOR "for (T_FOR)"
%token T_IF "if (T_IF)" %token T_IF "if (T_IF)"
%token T_ELSE "else (T_ELSE)" %token T_ELSE "else (T_ELSE)"
@ -213,7 +215,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%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 %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
%left T_LOGICAL_OR %left T_LOGICAL_OR
%left T_LOGICAL_AND %left T_LOGICAL_AND
%left T_RETURN %left T_RETURN T_BREAK T_CONTINUE
%left T_IDENTIFIER %left T_IDENTIFIER
%left T_BINARY_OR %left T_BINARY_OR
%left T_XOR %left T_XOR
@ -605,6 +607,14 @@ lterm: type
{ {
$$ = new ReturnExpression($2, @$); $$ = new ReturnExpression($2, @$);
} }
| T_BREAK
{
$$ = new BreakExpression(@$);
}
| T_CONTINUE
{
$$ = new ContinueExpression(@$);
}
| apply | apply
| object | object
| T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope_require_side_effect | T_FOR '(' identifier T_FOLLOWS identifier T_IN rterm ')' rterm_scope_require_side_effect

View File

@ -35,7 +35,7 @@ using namespace icinga;
Expression::~Expression(void) Expression::~Expression(void)
{ } { }
Value Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
try { try {
#ifdef I2_DEBUG #ifdef I2_DEBUG
@ -46,8 +46,6 @@ Value Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
#endif /* I2_DEBUG */ #endif /* I2_DEBUG */
return DoEvaluate(frame, dhint); return DoEvaluate(frame, dhint);
} catch (const InterruptExecutionError&) {
throw;
} catch (const ScriptError& ex) { } catch (const ScriptError& ex) {
throw; throw;
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
@ -82,7 +80,7 @@ LiteralExpression::LiteralExpression(const Value& value)
: m_Value(value) : m_Value(value)
{ } { }
Value LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Value; return m_Value;
} }
@ -92,7 +90,7 @@ const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
return m_DebugInfo; return m_DebugInfo;
} }
Value VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
if (frame.Locals && frame.Locals->Contains(m_Variable)) if (frame.Locals && frame.Locals->Contains(m_Variable))
return frame.Locals->Get(m_Variable); return frame.Locals->Get(m_Variable);
@ -127,155 +125,275 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
return true; return true;
} }
Value NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return ~(long)m_Operand->Evaluate(frame); ExpressionResult operand = m_Operand->Evaluate(frame);
CHECK_RESULT(operand);
return ~(long)operand.GetValue();
} }
Value LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return !m_Operand->Evaluate(frame).ToBool(); ExpressionResult operand = m_Operand->Evaluate(frame);
CHECK_RESULT(operand);
return !operand.GetValue().ToBool();
} }
Value AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) + m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() + operand2.GetValue();
} }
Value SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) - m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() - operand2.GetValue();
} }
Value MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) * m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() * operand2.GetValue();
} }
Value DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) / m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() / operand2.GetValue();
} }
Value ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) % m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() % operand2.GetValue();
} }
Value XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) ^ m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() ^ operand2.GetValue();
} }
Value BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) & m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() & operand2.GetValue();
} }
Value BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) | m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() | operand2.GetValue();
} }
Value ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) << m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() << operand2.GetValue();
} }
Value ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) >> m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() >> operand2.GetValue();
} }
Value EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) == m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() == operand2.GetValue();
} }
Value NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) != m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() != operand2.GetValue();
} }
Value LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) < m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() < operand2.GetValue();
} }
Value GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) > m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() > operand2.GetValue();
} }
Value LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) <= m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() <= operand2.GetValue();
} }
Value GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Operand1->Evaluate(frame) >= m_Operand2->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand1.GetValue() >= operand2.GetValue();
} }
Value InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value right = m_Operand2->Evaluate(frame); ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
if (right.IsEmpty()) if (operand2.GetValue().IsEmpty())
return false; return false;
else if (!right.IsObjectType<Array>()) else if (!operand2.GetValue().IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(right), m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
Value left = m_Operand1->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1)
Array::Ptr arr = right; Array::Ptr arr = operand2.GetValue();
return arr->Contains(left); return arr->Contains(operand1.GetValue());
} }
Value NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value right = m_Operand2->Evaluate(frame); ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
if (right.IsEmpty()) if (operand2.GetValue().IsEmpty())
return true; return true;
else if (!right.IsObjectType<Array>()) else if (!operand2.GetValue().IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(right), m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
Value left = m_Operand1->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
Array::Ptr arr = right; Array::Ptr arr = operand2.GetValue();
return !arr->Contains(left); return !arr->Contains(operand1.GetValue());
} }
Value LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value left = m_Operand1->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
if (!left.ToBool()) if (!operand1.GetValue().ToBool())
return left; return operand1;
else else {
return m_Operand2->Evaluate(frame); ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand2.GetValue();
}
} }
Value LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value left = m_Operand1->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
CHECK_RESULT(operand1);
if (left.ToBool()) if (operand1.GetValue().ToBool())
return left; return operand1;
else else {
return m_Operand2->Evaluate(frame); ExpressionResult operand2 = m_Operand2->Evaluate(frame);
CHECK_RESULT(operand2);
return operand2.GetValue();
}
} }
Value FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value self, vfunc; Value self, vfunc;
String index; String index;
if (m_FName->GetReference(frame, false, &self, &index)) if (m_FName->GetReference(frame, false, &self, &index))
vfunc = VMOps::GetField(self, index, m_DebugInfo); vfunc = VMOps::GetField(self, index, m_DebugInfo);
else else {
vfunc = m_FName->Evaluate(frame); ExpressionResult vfuncres = m_FName->Evaluate(frame);
CHECK_RESULT(vfuncres);
vfunc = vfuncres.GetValue();
}
if (!vfunc.IsObjectType<Function>()) if (!vfunc.IsObjectType<Function>())
BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));
@ -284,24 +402,30 @@ Value FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) c
std::vector<Value> arguments; std::vector<Value> arguments;
BOOST_FOREACH(Expression *arg, m_Args) { BOOST_FOREACH(Expression *arg, m_Args) {
arguments.push_back(arg->Evaluate(frame)); ExpressionResult argres = arg->Evaluate(frame);
CHECK_RESULT(argres);
arguments.push_back(argres.GetValue());
} }
return VMOps::FunctionCall(frame, self, func, arguments); return VMOps::FunctionCall(frame, self, func, arguments);
} }
Value ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Array::Ptr result = new Array(); Array::Ptr result = new Array();
BOOST_FOREACH(Expression *aexpr, m_Expressions) { BOOST_FOREACH(Expression *aexpr, m_Expressions) {
result->Add(aexpr->Evaluate(frame)); ExpressionResult element = aexpr->Evaluate(frame);
CHECK_RESULT(element);
result->Add(element.GetValue());
} }
return result; return result;
} }
Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
ScriptFrame *dframe; ScriptFrame *dframe;
ScriptFrame rframe; ScriptFrame rframe;
@ -317,7 +441,9 @@ Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
Value result; Value result;
BOOST_FOREACH(Expression *aexpr, m_Expressions) { BOOST_FOREACH(Expression *aexpr, m_Expressions) {
result = aexpr->Evaluate(*dframe, dhint); ExpressionResult element = aexpr->Evaluate(*dframe, dhint);
CHECK_RESULT(element);
result = element.GetValue();
} }
if (m_Inline) if (m_Inline)
@ -326,7 +452,7 @@ Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
return dframe->Self; return dframe->Self;
} }
Value GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
if (m_ScopeSpec == ScopeLocal) if (m_ScopeSpec == ScopeLocal)
return frame.Locals; return frame.Locals;
@ -340,7 +466,7 @@ Value GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ASSERT(!"Invalid scope."); ASSERT(!"Invalid scope.");
} }
Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
DebugHint *psdhint = dhint; DebugHint *psdhint = dhint;
@ -350,45 +476,54 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint)) if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
Value right = m_Operand2->Evaluate(frame, dhint); ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
CHECK_RESULT(operand2);
if (m_Op != OpSetLiteral) { if (m_Op != OpSetLiteral) {
Value object = VMOps::GetField(parent, index, m_DebugInfo); Value object = VMOps::GetField(parent, index, m_DebugInfo);
Expression *lhs = MakeLiteral(object); Expression *lhs = MakeLiteral(object);
Expression *rhs = MakeLiteral(right); Expression *rhs = MakeLiteral(operand2);
switch (m_Op) { switch (m_Op) {
case OpSetAdd: case OpSetAdd:
right = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetSubtract: case OpSetSubtract:
right = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetMultiply: case OpSetMultiply:
right = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetDivide: case OpSetDivide:
right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetModulo: case OpSetModulo:
right = ModuloExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = ModuloExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetXor: case OpSetXor:
right = XorExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = XorExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetBinaryAnd: case OpSetBinaryAnd:
right = BinaryAndExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = BinaryAndExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
case OpSetBinaryOr: case OpSetBinaryOr:
right = BinaryOrExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint); operand2 = BinaryOrExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break; break;
default: default:
VERIFY(!"Invalid opcode."); VERIFY(!"Invalid opcode.");
} }
} }
VMOps::SetField(parent, index, right, m_DebugInfo); VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
if (psdhint) { if (psdhint) {
psdhint->AddMessage("=", m_DebugInfo); psdhint->AddMessage("=", m_DebugInfo);
@ -400,9 +535,12 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
return Empty; return Empty;
} }
Value ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
if (m_Condition->Evaluate(frame, dhint).ToBool()) ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
CHECK_RESULT(condition);
if (condition.GetValue().ToBool())
return m_TrueBranch->Evaluate(frame, dhint); return m_TrueBranch->Evaluate(frame, dhint);
else if (m_FalseBranch) else if (m_FalseBranch)
return m_FalseBranch->Evaluate(frame, dhint); return m_FalseBranch->Evaluate(frame, dhint);
@ -410,24 +548,49 @@ Value ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) co
return Empty; return Empty;
} }
Value WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
while (m_Condition->Evaluate(frame, dhint).ToBool()) for (;;) {
m_LoopBody->Evaluate(frame, dhint); ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
CHECK_RESULT(condition);
if (!condition.GetValue().ToBool())
break;
ExpressionResult loop_body = m_LoopBody->Evaluate(frame, dhint);
CHECK_RESULT_LOOP(loop_body);
}
return Empty; return Empty;
} }
Value ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
BOOST_THROW_EXCEPTION(InterruptExecutionError(m_Operand->Evaluate(frame))); ExpressionResult operand = m_Operand->Evaluate(frame);
CHECK_RESULT(operand);
return ExpressionResult(operand.GetValue(), ResultReturn);
} }
Value IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult BreakExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value object = m_Operand1->Evaluate(frame, dhint); return ExpressionResult(Empty, ResultBreak);
String index = m_Operand2->Evaluate(frame, dhint); }
return VMOps::GetField(object, index, m_DebugInfo);
ExpressionResult ContinueExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
return ExpressionResult(Empty, ResultContinue);
}
ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ExpressionResult operand1 = m_Operand1->Evaluate(frame, dhint);
CHECK_RESULT(operand1);
ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
CHECK_RESULT(operand2);
return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), m_DebugInfo);
} }
bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
@ -440,10 +603,13 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo()); VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
*parent = VMOps::GetField(vparent, vindex, m_DebugInfo); *parent = VMOps::GetField(vparent, vindex, m_DebugInfo);
} else } else {
*parent = m_Operand1->Evaluate(frame); ExpressionResult operand1 = m_Operand1->Evaluate(frame);
*parent = operand1.GetValue();
}
*index = m_Operand2->Evaluate(frame); ExpressionResult operand2 = m_Operand2->Evaluate(frame);
*index = operand2.GetValue();
if (dhint && *dhint) if (dhint && *dhint)
*dhint = new DebugHint((*dhint)->GetChild(*index)); *dhint = new DebugHint((*dhint)->GetChild(*index));
@ -480,7 +646,7 @@ void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
LiteralExpression *lexpr = dynamic_cast<LiteralExpression *>(expr); LiteralExpression *lexpr = dynamic_cast<LiteralExpression *>(expr);
ScriptFrame frame; ScriptFrame frame;
if (lexpr && lexpr->Evaluate(frame).IsString()) { if (lexpr && lexpr->Evaluate(frame).GetValue().IsString()) {
Expression *scope = new GetScopeExpression(scopeSpec); Expression *scope = new GetScopeExpression(scopeSpec);
expr = new IndexerExpression(scope, lexpr, lexpr->GetDebugInfo()); expr = new IndexerExpression(scope, lexpr, lexpr->GetDebugInfo());
} }
@ -495,10 +661,12 @@ void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
} }
} }
Value ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
String type = VMOps::GetField(frame.Self, "type", m_DebugInfo); String type = VMOps::GetField(frame.Self, "type", m_DebugInfo);
Value name = m_Name->Evaluate(frame); ExpressionResult nameres = m_Name->Evaluate(frame);
CHECK_RESULT(nameres);
Value name = nameres.GetValue();
if (!name.IsString()) if (!name.IsString())
BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo));
@ -508,37 +676,46 @@ Value ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
if (!item) if (!item)
BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo));
item->GetExpression()->Evaluate(frame, dhint); ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
CHECK_RESULT(result);
return Empty; return Empty;
} }
Value FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return VMOps::NewFunction(frame, m_Args, m_ClosedVars, m_Expression); return VMOps::NewFunction(frame, m_Args, m_ClosedVars, m_Expression);
} }
Value ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return VMOps::NewApply(frame, m_Type, m_Target, m_Name->Evaluate(frame), m_Filter, ExpressionResult nameres = m_Name->Evaluate(frame);
CHECK_RESULT(nameres);
return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_Expression, m_DebugInfo); m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_Expression, m_DebugInfo);
} }
Value ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
String name; String name;
if (m_Name) if (m_Name) {
name = m_Name->Evaluate(frame, dhint); ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
CHECK_RESULT(nameres);
name = nameres.GetValue();
}
return VMOps::NewObject(frame, m_Abstract, m_Type, name, m_Filter, m_Zone, return VMOps::NewObject(frame, m_Abstract, m_Type, name, m_Filter, m_Zone,
m_ClosedVars, m_Expression, m_DebugInfo); m_ClosedVars, m_Expression, m_DebugInfo);
} }
Value ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value value = m_Value->Evaluate(frame, dhint); ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
CHECK_RESULT(valueres);
return VMOps::For(frame, m_FKVar, m_FVVar, m_Value->Evaluate(frame), m_Expression, m_DebugInfo); return VMOps::For(frame, m_FKVar, m_FVVar, valueres.GetValue(), m_Expression, m_DebugInfo);
} }

View File

@ -114,26 +114,63 @@ enum ScopeSpecifier
ScopeGlobal ScopeGlobal
}; };
class InterruptExecutionError : virtual public std::exception, virtual public boost::exception typedef std::map<String, String> DefinitionMap;
/**
* @ingroup config
*/
enum ExpressionResultCode
{
ResultOK,
ResultReturn,
ResultContinue,
ResultBreak
};
/**
* @ingroup config
*/
struct ExpressionResult
{ {
public: public:
InterruptExecutionError(const Value& result) template<typename T>
: m_Result(result) ExpressionResult(const T& value, ExpressionResultCode code = ResultOK)
: m_Value(value), m_Code(code)
{ } { }
~InterruptExecutionError(void) throw() operator Value(void) const
{ }
Value GetResult(void) const
{ {
return m_Result; return m_Value;
}
Value GetValue(void) const
{
return m_Value;
}
ExpressionResultCode GetCode(void) const
{
return m_Code;
} }
private: private:
Value m_Result; Value m_Value;
ExpressionResultCode m_Code;
}; };
typedef std::map<String, String> DefinitionMap; #define CHECK_RESULT(res) \
do { \
if (res.GetCode() != ResultOK) \
return res; \
} while (0);
#define CHECK_RESULT_LOOP(res) \
if (res.GetCode() == ResultReturn) \
return res; \
if (res.GetCode() == ResultContinue) \
continue; \
if (res.GetCode() == ResultBreak) \
break; \
/** /**
* @ingroup config * @ingroup config
@ -143,11 +180,11 @@ class I2_CONFIG_API Expression
public: public:
virtual ~Expression(void); virtual ~Expression(void);
Value Evaluate(ScriptFrame& frame, DebugHint *dhint = NULL) const; ExpressionResult Evaluate(ScriptFrame& frame, DebugHint *dhint = NULL) const;
virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint = NULL) const; virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint = NULL) const;
virtual const DebugInfo& GetDebugInfo(void) const; virtual const DebugInfo& GetDebugInfo(void) const;
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const = 0; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const = 0;
}; };
I2_CONFIG_API Expression *MakeIndexer(ScopeSpecifier scopeSpec, const String& index); I2_CONFIG_API Expression *MakeIndexer(ScopeSpecifier scopeSpec, const String& index);
@ -160,7 +197,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Expression->DoEvaluate(frame, dhint); return m_Expression->DoEvaluate(frame, dhint);
} }
@ -182,7 +219,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
return m_Future.get()->DoEvaluate(frame, dhint); return m_Future.get()->DoEvaluate(frame, dhint);
} }
@ -202,7 +239,7 @@ public:
LiteralExpression(const Value& value = Value()); LiteralExpression(const Value& value = Value());
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
Value m_Value; Value m_Value;
@ -274,7 +311,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult 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;
private: private:
@ -291,7 +328,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API LogicalNegateExpression : public UnaryExpression class I2_CONFIG_API LogicalNegateExpression : public UnaryExpression
@ -302,7 +339,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API AddExpression : public BinaryExpression class I2_CONFIG_API AddExpression : public BinaryExpression
@ -313,7 +350,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API SubtractExpression : public BinaryExpression class I2_CONFIG_API SubtractExpression : public BinaryExpression
@ -324,7 +361,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API MultiplyExpression : public BinaryExpression class I2_CONFIG_API MultiplyExpression : public BinaryExpression
@ -335,7 +372,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API DivideExpression : public BinaryExpression class I2_CONFIG_API DivideExpression : public BinaryExpression
@ -346,7 +383,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API ModuloExpression : public BinaryExpression class I2_CONFIG_API ModuloExpression : public BinaryExpression
@ -357,7 +394,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API XorExpression : public BinaryExpression class I2_CONFIG_API XorExpression : public BinaryExpression
@ -368,7 +405,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API BinaryAndExpression : public BinaryExpression class I2_CONFIG_API BinaryAndExpression : public BinaryExpression
@ -379,7 +416,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API BinaryOrExpression : public BinaryExpression class I2_CONFIG_API BinaryOrExpression : public BinaryExpression
@ -390,7 +427,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API ShiftLeftExpression : public BinaryExpression class I2_CONFIG_API ShiftLeftExpression : public BinaryExpression
@ -401,7 +438,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API ShiftRightExpression : public BinaryExpression class I2_CONFIG_API ShiftRightExpression : public BinaryExpression
@ -412,7 +449,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API EqualExpression : public BinaryExpression class I2_CONFIG_API EqualExpression : public BinaryExpression
@ -423,7 +460,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API NotEqualExpression : public BinaryExpression class I2_CONFIG_API NotEqualExpression : public BinaryExpression
@ -434,7 +471,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API LessThanExpression : public BinaryExpression class I2_CONFIG_API LessThanExpression : public BinaryExpression
@ -445,7 +482,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API GreaterThanExpression : public BinaryExpression class I2_CONFIG_API GreaterThanExpression : public BinaryExpression
@ -456,7 +493,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API LessThanOrEqualExpression : public BinaryExpression class I2_CONFIG_API LessThanOrEqualExpression : public BinaryExpression
@ -467,7 +504,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API GreaterThanOrEqualExpression : public BinaryExpression class I2_CONFIG_API GreaterThanOrEqualExpression : public BinaryExpression
@ -478,7 +515,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API InExpression : public BinaryExpression class I2_CONFIG_API InExpression : public BinaryExpression
@ -489,7 +526,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API NotInExpression : public BinaryExpression class I2_CONFIG_API NotInExpression : public BinaryExpression
@ -500,7 +537,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API LogicalAndExpression : public BinaryExpression class I2_CONFIG_API LogicalAndExpression : public BinaryExpression
@ -511,7 +548,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API LogicalOrExpression : public BinaryExpression class I2_CONFIG_API LogicalOrExpression : public BinaryExpression
@ -522,7 +559,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API FunctionCallExpression : public DebuggableExpression class I2_CONFIG_API FunctionCallExpression : public DebuggableExpression
@ -541,7 +578,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
public: public:
Expression *m_FName; Expression *m_FName;
@ -562,7 +599,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
std::vector<Expression *> m_Expressions; std::vector<Expression *> m_Expressions;
@ -584,7 +621,7 @@ public:
void MakeInline(void); void MakeInline(void);
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
std::vector<Expression *> m_Expressions; std::vector<Expression *> m_Expressions;
@ -601,7 +638,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
CombinedSetOp m_Op; CombinedSetOp m_Op;
@ -624,7 +661,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
Expression *m_Condition; Expression *m_Condition;
@ -646,7 +683,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
Expression *m_Condition; Expression *m_Condition;
@ -662,7 +699,29 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API BreakExpression : public DebuggableExpression
{
public:
BreakExpression(const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo)
{ }
protected:
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API ContinueExpression : public DebuggableExpression
{
public:
ContinueExpression(const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo)
{ }
protected:
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
}; };
class I2_CONFIG_API GetScopeExpression : public Expression class I2_CONFIG_API GetScopeExpression : public Expression
@ -673,7 +732,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
ScopeSpecifier m_ScopeSpec; ScopeSpecifier m_ScopeSpec;
@ -687,7 +746,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult 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 I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec); friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
@ -708,7 +767,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
Expression *m_Name; Expression *m_Name;
@ -723,7 +782,7 @@ public:
{ } { }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
std::vector<String> m_Args; std::vector<String> m_Args;
@ -749,7 +808,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
String m_Type; String m_Type;
@ -779,7 +838,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
bool m_Abstract; bool m_Abstract;
@ -805,7 +864,7 @@ public:
} }
protected: protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const; virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private: private:
String m_FKVar; String m_FKVar;

View File

@ -139,7 +139,8 @@ public:
for (Array::SizeType i = 0; i < arr->GetLength(); i++) { for (Array::SizeType i = 0; i < arr->GetLength(); i++) {
frame.Locals->Set(fkvar, arr->Get(i)); frame.Locals->Set(fkvar, arr->Get(i));
expression->Evaluate(frame); ExpressionResult res = expression->Evaluate(frame);
CHECK_RESULT_LOOP(res);
} }
} else if (value.IsObjectType<Dictionary>()) { } else if (value.IsObjectType<Dictionary>()) {
if (fvvar.IsEmpty()) if (fvvar.IsEmpty())
@ -158,7 +159,8 @@ public:
BOOST_FOREACH(const String& key, keys) { BOOST_FOREACH(const String& key, keys) {
frame.Locals->Set(fkvar, key); frame.Locals->Set(fkvar, key);
frame.Locals->Set(fvvar, dict->Get(key)); frame.Locals->Set(fvvar, dict->Get(key));
expression->Evaluate(frame); ExpressionResult res = expression->Evaluate(frame);
CHECK_RESULT_LOOP(res);
} }
} else } else
BOOST_THROW_EXCEPTION(ScriptError("Invalid type in for expression: " + value.GetTypeName(), debugInfo)); BOOST_THROW_EXCEPTION(ScriptError("Invalid type in for expression: " + value.GetTypeName(), debugInfo));
@ -304,14 +306,7 @@ private:
for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++) for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs.size()); i++)
frame.Locals->Set(funcargs[i], arguments[i]); frame.Locals->Set(funcargs[i], arguments[i]);
Value result; return expr->Evaluate(frame);
try {
result = expr->Evaluate(frame);
} catch (const InterruptExecutionError& iee) {
result = iee.GetResult();
}
return result;
} }
static inline Dictionary::Ptr EvaluateClosedVars(ScriptFrame& frame, std::map<String, Expression *> *closedVars) static inline Dictionary::Ptr EvaluateClosedVars(ScriptFrame& frame, std::map<String, Expression *> *closedVars)

View File

@ -49,7 +49,7 @@ bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr&
group->GetScope()->CopyTo(frame.Locals); group->GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("host", host); frame.Locals->Set("host", host);
if (!group->GetFilter()->Evaluate(frame).ToBool()) if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
return false; return false;
Log(LogDebug, "HostGroup") Log(LogDebug, "HostGroup")

View File

@ -52,7 +52,7 @@ bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigI
frame.Locals->Set("host", host); frame.Locals->Set("host", host);
frame.Locals->Set("service", service); frame.Locals->Set("service", service);
if (!group->GetFilter()->Evaluate(frame).ToBool()) if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
return false; return false;
Log(LogDebug, "ServiceGroup") Log(LogDebug, "ServiceGroup")

View File

@ -49,7 +49,7 @@ bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr&
group->GetScope()->CopyTo(frame.Locals); group->GetScope()->CopyTo(frame.Locals);
frame.Locals->Set("user", user); frame.Locals->Set("user", user);
if (!group->GetFilter()->Evaluate(frame).ToBool()) if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
return false; return false;
Log(LogDebug, "UserGroup") Log(LogDebug, "UserGroup")

View File

@ -31,177 +31,177 @@ BOOST_AUTO_TEST_CASE(simple)
Dictionary::Ptr dict; Dictionary::Ptr dict;
expr = ConfigCompiler::CompileText("<test>", ""); expr = ConfigCompiler::CompileText("<test>", "");
BOOST_CHECK(expr->Evaluate(frame) == Empty); BOOST_CHECK(expr->Evaluate(frame).GetValue() == Empty);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\n3"); expr = ConfigCompiler::CompileText("<test>", "\n3");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "{ 3\n\n5 }"); expr = ConfigCompiler::CompileText("<test>", "{ 3\n\n5 }");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "1 + 3"); expr = ConfigCompiler::CompileText("<test>", "1 + 3");
BOOST_CHECK(expr->Evaluate(frame) == 4); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 4);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 - 1"); expr = ConfigCompiler::CompileText("<test>", "3 - 1");
BOOST_CHECK(expr->Evaluate(frame) == 2); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 2);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "5m * 10"); expr = ConfigCompiler::CompileText("<test>", "5m * 10");
BOOST_CHECK(expr->Evaluate(frame) == 3000); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3000);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "5m / 5"); expr = ConfigCompiler::CompileText("<test>", "5m / 5");
BOOST_CHECK(expr->Evaluate(frame) == 60); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 60);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "7 & 3"); expr = ConfigCompiler::CompileText("<test>", "7 & 3");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "2 | 3"); expr = ConfigCompiler::CompileText("<test>", "2 | 3");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "true && false"); expr = ConfigCompiler::CompileText("<test>", "true && false");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "true || false"); expr = ConfigCompiler::CompileText("<test>", "true || false");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 < 5"); expr = ConfigCompiler::CompileText("<test>", "3 < 5");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 > 5"); expr = ConfigCompiler::CompileText("<test>", "3 > 5");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 <= 3"); expr = ConfigCompiler::CompileText("<test>", "3 <= 3");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 >= 3"); expr = ConfigCompiler::CompileText("<test>", "3 >= 3");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "2 + 3 * 4"); expr = ConfigCompiler::CompileText("<test>", "2 + 3 * 4");
BOOST_CHECK(expr->Evaluate(frame) == 14); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 14);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(2 + 3) * 4"); expr = ConfigCompiler::CompileText("<test>", "(2 + 3) * 4");
BOOST_CHECK(expr->Evaluate(frame) == 20); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 20);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "2 * - 3"); expr = ConfigCompiler::CompileText("<test>", "2 * - 3");
BOOST_CHECK(expr->Evaluate(frame) == -6); BOOST_CHECK(expr->Evaluate(frame).GetValue() == -6);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "-(2 + 3)"); expr = ConfigCompiler::CompileText("<test>", "-(2 + 3)");
BOOST_CHECK(expr->Evaluate(frame) == -5); BOOST_CHECK(expr->Evaluate(frame).GetValue() == -5);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "- 2 * 2 - 2 * 3 - 4 * - 5"); expr = ConfigCompiler::CompileText("<test>", "- 2 * 2 - 2 * 3 - 4 * - 5");
BOOST_CHECK(expr->Evaluate(frame) == 10); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 10);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "!0 == true"); expr = ConfigCompiler::CompileText("<test>", "!0 == true");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "~0"); expr = ConfigCompiler::CompileText("<test>", "~0");
BOOST_CHECK(expr->Evaluate(frame) == (double)~(long)0); BOOST_CHECK(expr->Evaluate(frame).GetValue() == (double)~(long)0);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "4 << 8"); expr = ConfigCompiler::CompileText("<test>", "4 << 8");
BOOST_CHECK(expr->Evaluate(frame) == 1024); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 1024);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "1024 >> 4"); expr = ConfigCompiler::CompileText("<test>", "1024 >> 4");
BOOST_CHECK(expr->Evaluate(frame) == 64); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 64);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "2 << 3 << 4"); expr = ConfigCompiler::CompileText("<test>", "2 << 3 << 4");
BOOST_CHECK(expr->Evaluate(frame) == 256); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 256);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "256 >> 4 >> 3"); expr = ConfigCompiler::CompileText("<test>", "256 >> 4 >> 3");
BOOST_CHECK(expr->Evaluate(frame) == 2); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 2);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"hello\" == \"hello\""); expr = ConfigCompiler::CompileText("<test>", "\"hello\" == \"hello\"");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"hello\" != \"hello\""); expr = ConfigCompiler::CompileText("<test>", "\"hello\" != \"hello\"");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" in [ \"foo\", \"bar\" ]"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" in [ \"foo\", \"bar\" ]");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" in [ \"bar\", \"baz\" ]"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" in [ \"bar\", \"baz\" ]");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" in null"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" in null");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" in \"bar\""); expr = ConfigCompiler::CompileText("<test>", "\"foo\" in \"bar\"");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in [ \"bar\", \"baz\" ]"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in [ \"bar\", \"baz\" ]");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in [ \"foo\", \"bar\" ]"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in [ \"foo\", \"bar\" ]");
BOOST_CHECK(!expr->Evaluate(frame)); BOOST_CHECK(!expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in null"); expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in null");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in \"bar\""); expr = ConfigCompiler::CompileText("<test>", "\"foo\" !in \"bar\"");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "{ a += 3 }"); expr = ConfigCompiler::CompileText("<test>", "{ a += 3 }");
dict = expr->Evaluate(frame); dict = expr->Evaluate(frame).GetValue();
delete expr; delete expr;
BOOST_CHECK(dict->GetLength() == 1); BOOST_CHECK(dict->GetLength() == 1);
BOOST_CHECK(dict->Get("a") == 3); BOOST_CHECK(dict->Get("a") == 3);
expr = ConfigCompiler::CompileText("<test>", "test"); expr = ConfigCompiler::CompileText("<test>", "test");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "null + 3"); expr = ConfigCompiler::CompileText("<test>", "null + 3");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 + null"); expr = ConfigCompiler::CompileText("<test>", "3 + null");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"test\" + 3"); expr = ConfigCompiler::CompileText("<test>", "\"test\" + 3");
BOOST_CHECK(expr->Evaluate(frame) == "test3"); BOOST_CHECK(expr->Evaluate(frame).GetValue() == "test3");
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"\\\"te\\\\st\""); expr = ConfigCompiler::CompileText("<test>", "\"\\\"te\\\\st\"");
BOOST_CHECK(expr->Evaluate(frame) == "\"te\\st"); BOOST_CHECK(expr->Evaluate(frame).GetValue() == "\"te\\st");
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"\\'test\""); expr = ConfigCompiler::CompileText("<test>", "\"\\'test\"");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
} }
@ -212,117 +212,117 @@ BOOST_AUTO_TEST_CASE(advanced)
Function::Ptr func; Function::Ptr func;
expr = ConfigCompiler::CompileText("<test>", "regex(\"^Hello\", \"Hello World\")"); expr = ConfigCompiler::CompileText("<test>", "regex(\"^Hello\", \"Hello World\")");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "__boost_test()"); expr = ConfigCompiler::CompileText("<test>", "__boost_test()");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
Object::Ptr self = new Object(); Object::Ptr self = new Object();
ScriptFrame frame2(self); ScriptFrame frame2(self);
expr = ConfigCompiler::CompileText("<test>", "this"); expr = ConfigCompiler::CompileText("<test>", "this");
BOOST_CHECK(expr->Evaluate(frame2) == Value(self)); BOOST_CHECK(expr->Evaluate(frame2).GetValue() == Value(self));
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "var v = 7; v"); expr = ConfigCompiler::CompileText("<test>", "var v = 7; v");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "{ a = 3 }.a"); expr = ConfigCompiler::CompileText("<test>", "{ a = 3 }.a");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "[ 2, 3 ][1]"); expr = ConfigCompiler::CompileText("<test>", "[ 2, 3 ][1]");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "var v = { a = 3}; v.a"); expr = ConfigCompiler::CompileText("<test>", "var v = { a = 3}; v.a");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3"); expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "function() { 3 }()"); expr = ConfigCompiler::CompileText("<test>", "function() { 3 }()");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "function() { return 3, 5 }()"); expr = ConfigCompiler::CompileText("<test>", "function() { return 3, 5 }()");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "typeof([]) == Array"); expr = ConfigCompiler::CompileText("<test>", "typeof([]) == Array");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "typeof({}) == Dictionary"); expr = ConfigCompiler::CompileText("<test>", "typeof({}) == Dictionary");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "typeof(3) == Number"); expr = ConfigCompiler::CompileText("<test>", "typeof(3) == Number");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "typeof(\"test\") == String"); expr = ConfigCompiler::CompileText("<test>", "typeof(\"test\") == String");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 | 8) == 15"); expr = ConfigCompiler::CompileText("<test>", "(7 | 8) == 15");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 ^ 8) == 15"); expr = ConfigCompiler::CompileText("<test>", "(7 ^ 8) == 15");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 & 15) == 7"); expr = ConfigCompiler::CompileText("<test>", "(7 & 15) == 7");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "7 in [7] == true"); expr = ConfigCompiler::CompileText("<test>", "7 in [7] == true");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "7 !in [7] == false"); expr = ConfigCompiler::CompileText("<test>", "7 !in [7] == false");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 | 8) > 14"); expr = ConfigCompiler::CompileText("<test>", "(7 | 8) > 14");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 ^ 8) > 14"); expr = ConfigCompiler::CompileText("<test>", "(7 ^ 8) > 14");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "(7 & 15) > 6"); expr = ConfigCompiler::CompileText("<test>", "(7 & 15) > 6");
BOOST_CHECK(expr->Evaluate(frame)); BOOST_CHECK(expr->Evaluate(frame).GetValue());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "\"a\" = 3"); expr = ConfigCompiler::CompileText("<test>", "\"a\" = 3");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "3 = 3"); expr = ConfigCompiler::CompileText("<test>", "3 = 3");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "var e; e"); expr = ConfigCompiler::CompileText("<test>", "var e; e");
BOOST_CHECK(expr->Evaluate(frame).IsEmpty()); BOOST_CHECK(expr->Evaluate(frame).GetValue().IsEmpty());
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "var e = 3; e"); expr = ConfigCompiler::CompileText("<test>", "var e = 3; e");
BOOST_CHECK(expr->Evaluate(frame) == 3); BOOST_CHECK(expr->Evaluate(frame).GetValue() == 3);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "Array.x"); expr = ConfigCompiler::CompileText("<test>", "Array.x");
BOOST_CHECK_THROW(expr->Evaluate(frame), ScriptError); BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
delete expr; delete expr;
expr = ConfigCompiler::CompileText("<test>", "{{ 3 }}"); expr = ConfigCompiler::CompileText("<test>", "{{ 3 }}");
func = expr->Evaluate(frame); func = expr->Evaluate(frame).GetValue();
BOOST_CHECK(func->Invoke() == 3); BOOST_CHECK(func->Invoke() == 3);
delete expr; delete expr;
} }