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
}
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
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)
}
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
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
{
return m_Filter->Evaluate(frame).ToBool();
return Convert::ToBool(m_Filter->Evaluate(frame));
}
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;
function return T_FUNCTION;
return return T_RETURN;
break return T_BREAK;
continue return T_CONTINUE;
for return T_FOR;
if return T_IF;
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_FUNCTION "function (T_FUNCTION)"
%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_IF "if (T_IF)"
%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_LOGICAL_OR
%left T_LOGICAL_AND
%left T_RETURN
%left T_RETURN T_BREAK T_CONTINUE
%left T_IDENTIFIER
%left T_BINARY_OR
%left T_XOR
@ -605,6 +607,14 @@ lterm: type
{
$$ = new ReturnExpression($2, @$);
}
| T_BREAK
{
$$ = new BreakExpression(@$);
}
| T_CONTINUE
{
$$ = new ContinueExpression(@$);
}
| apply
| object
| 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)
{ }
Value Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
{
try {
#ifdef I2_DEBUG
@ -46,8 +46,6 @@ Value Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
#endif /* I2_DEBUG */
return DoEvaluate(frame, dhint);
} catch (const InterruptExecutionError&) {
throw;
} catch (const ScriptError& ex) {
throw;
} catch (const std::exception& ex) {
@ -82,7 +80,7 @@ LiteralExpression::LiteralExpression(const Value& value)
: m_Value(value)
{ }
Value LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
return m_Value;
}
@ -92,7 +90,7 @@ const DebugInfo& DebuggableExpression::GetDebugInfo(void) const
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))
return frame.Locals->Get(m_Variable);
@ -127,155 +125,275 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
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;
else if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(right), m_DebugInfo));
else if (!operand2.GetValue().IsObjectType<Array>())
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;
return arr->Contains(left);
Array::Ptr arr = operand2.GetValue();
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;
else if (!right.IsObjectType<Array>())
BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(right), m_DebugInfo));
else if (!operand2.GetValue().IsObjectType<Array>())
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;
return !arr->Contains(left);
Array::Ptr arr = operand2.GetValue();
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())
return left;
else
return m_Operand2->Evaluate(frame);
if (!operand1.GetValue().ToBool())
return operand1;
else {
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())
return left;
else
return m_Operand2->Evaluate(frame);
if (operand1.GetValue().ToBool())
return operand1;
else {
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;
String index;
if (m_FName->GetReference(frame, false, &self, &index))
vfunc = VMOps::GetField(self, index, m_DebugInfo);
else
vfunc = m_FName->Evaluate(frame);
else {
ExpressionResult vfuncres = m_FName->Evaluate(frame);
CHECK_RESULT(vfuncres);
vfunc = vfuncres.GetValue();
}
if (!vfunc.IsObjectType<Function>())
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;
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);
}
Value ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
Array::Ptr result = new Array();
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;
}
Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
ScriptFrame *dframe;
ScriptFrame rframe;
@ -317,7 +441,9 @@ Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
Value result;
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)
@ -326,7 +452,7 @@ Value DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
return dframe->Self;
}
Value GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
if (m_ScopeSpec == ScopeLocal)
return frame.Locals;
@ -340,7 +466,7 @@ Value GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ASSERT(!"Invalid scope.");
}
Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
DebugHint *psdhint = dhint;
@ -350,45 +476,54 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
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) {
Value object = VMOps::GetField(parent, index, m_DebugInfo);
Expression *lhs = MakeLiteral(object);
Expression *rhs = MakeLiteral(right);
Expression *rhs = MakeLiteral(operand2);
switch (m_Op) {
case OpSetAdd:
right = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = AddExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetSubtract:
right = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = SubtractExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetMultiply:
right = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = MultiplyExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetDivide:
right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetModulo:
right = ModuloExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = ModuloExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetXor:
right = XorExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = XorExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetBinaryAnd:
right = BinaryAndExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = BinaryAndExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
case OpSetBinaryOr:
right = BinaryOrExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
operand2 = BinaryOrExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
CHECK_RESULT(operand2);
break;
default:
VERIFY(!"Invalid opcode.");
}
}
VMOps::SetField(parent, index, right, m_DebugInfo);
VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo);
if (psdhint) {
psdhint->AddMessage("=", m_DebugInfo);
@ -400,9 +535,12 @@ Value SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
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);
else if (m_FalseBranch)
return m_FalseBranch->Evaluate(frame, dhint);
@ -410,24 +548,49 @@ Value ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) co
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())
m_LoopBody->Evaluate(frame, dhint);
for (;;) {
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;
}
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);
String index = m_Operand2->Evaluate(frame, dhint);
return VMOps::GetField(object, index, m_DebugInfo);
return ExpressionResult(Empty, ResultBreak);
}
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
@ -440,10 +603,13 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo());
*parent = VMOps::GetField(vparent, vindex, m_DebugInfo);
} else
*parent = m_Operand1->Evaluate(frame);
} else {
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)
*dhint = new DebugHint((*dhint)->GetChild(*index));
@ -480,7 +646,7 @@ void icinga::BindToScope(Expression *& expr, ScopeSpecifier scopeSpec)
LiteralExpression *lexpr = dynamic_cast<LiteralExpression *>(expr);
ScriptFrame frame;
if (lexpr && lexpr->Evaluate(frame).IsString()) {
if (lexpr && lexpr->Evaluate(frame).GetValue().IsString()) {
Expression *scope = new GetScopeExpression(scopeSpec);
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);
Value name = m_Name->Evaluate(frame);
ExpressionResult nameres = m_Name->Evaluate(frame);
CHECK_RESULT(nameres);
Value name = nameres.GetValue();
if (!name.IsString())
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)
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;
}
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);
}
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);
}
Value ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
String name;
if (m_Name)
name = m_Name->Evaluate(frame, dhint);
if (m_Name) {
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,
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
};
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:
InterruptExecutionError(const Value& result)
: m_Result(result)
template<typename T>
ExpressionResult(const T& value, ExpressionResultCode code = ResultOK)
: m_Value(value), m_Code(code)
{ }
~InterruptExecutionError(void) throw()
{ }
Value GetResult(void) const
operator Value(void) const
{
return m_Result;
return m_Value;
}
Value GetValue(void) const
{
return m_Value;
}
ExpressionResultCode GetCode(void) const
{
return m_Code;
}
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
@ -143,11 +180,11 @@ class I2_CONFIG_API Expression
public:
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 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);
@ -160,7 +197,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
return m_Expression->DoEvaluate(frame, dhint);
}
@ -182,7 +219,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
return m_Future.get()->DoEvaluate(frame, dhint);
}
@ -202,7 +239,7 @@ public:
LiteralExpression(const Value& value = Value());
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
Value m_Value;
@ -274,7 +311,7 @@ public:
}
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;
private:
@ -291,7 +328,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API LogicalNegateExpression : public UnaryExpression
@ -302,7 +339,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API AddExpression : public BinaryExpression
@ -313,7 +350,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API SubtractExpression : public BinaryExpression
@ -324,7 +361,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API MultiplyExpression : public BinaryExpression
@ -335,7 +372,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API DivideExpression : public BinaryExpression
@ -346,7 +383,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API ModuloExpression : public BinaryExpression
@ -357,7 +394,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API XorExpression : public BinaryExpression
@ -368,7 +405,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API BinaryAndExpression : public BinaryExpression
@ -379,7 +416,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API BinaryOrExpression : public BinaryExpression
@ -390,7 +427,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API ShiftLeftExpression : public BinaryExpression
@ -401,7 +438,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API ShiftRightExpression : public BinaryExpression
@ -412,7 +449,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API EqualExpression : public BinaryExpression
@ -423,7 +460,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API NotEqualExpression : public BinaryExpression
@ -434,7 +471,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API LessThanExpression : public BinaryExpression
@ -445,7 +482,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API GreaterThanExpression : public BinaryExpression
@ -456,7 +493,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API LessThanOrEqualExpression : public BinaryExpression
@ -467,7 +504,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API GreaterThanOrEqualExpression : public BinaryExpression
@ -478,7 +515,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API InExpression : public BinaryExpression
@ -489,7 +526,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API NotInExpression : public BinaryExpression
@ -500,7 +537,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API LogicalAndExpression : public BinaryExpression
@ -511,7 +548,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API LogicalOrExpression : public BinaryExpression
@ -522,7 +559,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API FunctionCallExpression : public DebuggableExpression
@ -541,7 +578,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
public:
Expression *m_FName;
@ -562,7 +599,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
std::vector<Expression *> m_Expressions;
@ -584,7 +621,7 @@ public:
void MakeInline(void);
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
std::vector<Expression *> m_Expressions;
@ -601,7 +638,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
CombinedSetOp m_Op;
@ -624,7 +661,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
Expression *m_Condition;
@ -646,7 +683,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
Expression *m_Condition;
@ -662,7 +699,29 @@ public:
{ }
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
@ -673,7 +732,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
ScopeSpecifier m_ScopeSpec;
@ -687,7 +746,7 @@ public:
{ }
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;
friend I2_CONFIG_API void BindToScope(Expression *& expr, ScopeSpecifier scopeSpec);
@ -708,7 +767,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
Expression *m_Name;
@ -723,7 +782,7 @@ public:
{ }
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
std::vector<String> m_Args;
@ -749,7 +808,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
String m_Type;
@ -779,7 +838,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
bool m_Abstract;
@ -805,7 +864,7 @@ public:
}
protected:
virtual Value DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const;
private:
String m_FKVar;

View File

@ -139,7 +139,8 @@ public:
for (Array::SizeType i = 0; i < arr->GetLength(); 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>()) {
if (fvvar.IsEmpty())
@ -158,7 +159,8 @@ public:
BOOST_FOREACH(const String& key, keys) {
frame.Locals->Set(fkvar, key);
frame.Locals->Set(fvvar, dict->Get(key));
expression->Evaluate(frame);
ExpressionResult res = expression->Evaluate(frame);
CHECK_RESULT_LOOP(res);
}
} else
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++)
frame.Locals->Set(funcargs[i], arguments[i]);
Value result;
try {
result = expr->Evaluate(frame);
} catch (const InterruptExecutionError& iee) {
result = iee.GetResult();
}
return result;
return expr->Evaluate(frame);
}
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);
frame.Locals->Set("host", host);
if (!group->GetFilter()->Evaluate(frame).ToBool())
if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
return false;
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("service", service);
if (!group->GetFilter()->Evaluate(frame).ToBool())
if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
return false;
Log(LogDebug, "ServiceGroup")

View File

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

View File

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