From 91f946a40e0fda0ff2e4ce02fa924fca3b1d5dd4 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 9 Apr 2014 10:36:57 +0200 Subject: [PATCH] Implement the "return" keyword. Fixes #5985 --- lib/config/aexpression.cpp | 6 ++++- lib/config/config_lexer.ll | 1 + lib/config/config_parser.yy | 52 +++++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/lib/config/aexpression.cpp b/lib/config/aexpression.cpp index 3329f8b87..d557e2290 100644 --- a/lib/config/aexpression.cpp +++ b/lib/config/aexpression.cpp @@ -296,7 +296,11 @@ Value AExpression::OpDict(const AExpression *expr, const Dictionary::Ptr& locals if (arr) { ObjectLock olock(arr); BOOST_FOREACH(const AExpression::Ptr& aexpr, arr) { - aexpr->Evaluate(in_place ? locals : result); + Dictionary::Ptr alocals = in_place ? locals : result; + aexpr->Evaluate(alocals); + + if (alocals->Contains("__result")) + break; } } diff --git a/lib/config/config_lexer.ll b/lib/config/config_lexer.ll index a76968eca..2663932a7 100644 --- a/lib/config/config_lexer.ll +++ b/lib/config/config_lexer.ll @@ -229,6 +229,7 @@ assign return T_ASSIGN; ignore return T_IGNORE; function return T_FUNCTION; lambda return T_LAMBDA; +return return T_RETURN; \<\< { yylval->op = &AExpression::OpShiftLeft; return T_SHIFT_LEFT; } \>\> { yylval->op = &AExpression::OpShiftRight; return T_SHIFT_RIGHT; } \<= { yylval->op = &AExpression::OpLessThanOrEqual; return T_LESS_THAN_OR_EQUAL; } diff --git a/lib/config/config_parser.yy b/lib/config/config_parser.yy index e08cf0d1b..76d85d31d 100644 --- a/lib/config/config_parser.yy +++ b/lib/config/config_parser.yy @@ -73,7 +73,7 @@ int ignore_newlines = 0; static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *left, Value *right, DebugInfo& diLeft, DebugInfo& diRight) { - *result = new Value(make_shared(op, static_cast(*left), static_cast(*right), DebugInfoRange(diLeft, diRight))); + *result = new Value(make_shared(op, *left, *right, DebugInfoRange(diLeft, diRight))); delete left; delete right; } @@ -158,6 +158,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le %token T_IGNORE "ignore (T_IGNORE)" %token T_FUNCTION "function (T_FUNCTION)" %token T_LAMBDA "lambda (T_LAMBDA)" +%token T_RETURN "return (T_RETURN)" %type identifier %type rterm_items @@ -251,7 +252,7 @@ statement: type | include | include_recursive | library | constant | newlines include: T_INCLUDE rterm sep { - AExpression::Ptr aexpr = static_cast(*$2); + AExpression::Ptr aexpr = *$2; delete $2; context->HandleInclude(aexpr->Evaluate(m_ModuleScope), false, DebugInfoRange(@1, @2)); @@ -265,17 +266,17 @@ include: T_INCLUDE rterm sep include_recursive: T_INCLUDE_RECURSIVE rterm { - AExpression::Ptr aexpr = static_cast(*$2); + AExpression::Ptr aexpr = *$2; delete $2; context->HandleIncludeRecursive(aexpr->Evaluate(m_ModuleScope), "*.conf", DebugInfoRange(@1, @2)); } | T_INCLUDE_RECURSIVE rterm ',' rterm { - AExpression::Ptr aexpr1 = static_cast(*$2); + AExpression::Ptr aexpr1 = *$2; delete $2; - AExpression::Ptr aexpr2 = static_cast(*$4); + AExpression::Ptr aexpr2 = *$4; delete $4; context->HandleIncludeRecursive(aexpr1->Evaluate(m_ModuleScope), aexpr2->Evaluate(m_ModuleScope), DebugInfoRange(@1, @4)); @@ -291,7 +292,7 @@ library: T_LIBRARY T_STRING sep constant: T_CONST identifier T_SET rterm sep { - AExpression::Ptr aexpr = static_cast(*$4); + AExpression::Ptr aexpr = *$4; delete $4; ScriptVariable::Ptr sv = ScriptVariable::Set($2, aexpr->Evaluate(m_ModuleScope)); @@ -529,13 +530,12 @@ lterm: identifier lbinary_op rterm AExpression::Ptr aindex = make_shared(&AExpression::OpLiteral, $1, @1); free($1); - AExpression::Ptr aexpr = static_cast(*$3); - $$ = new Value(make_shared($2, aindex, aexpr, DebugInfoRange(@1, @3))); + $$ = new Value(make_shared($2, aindex, *$3, DebugInfoRange(@1, @3))); delete $3; } | identifier '[' rterm ']' lbinary_op rterm { - AExpression::Ptr subexpr = make_shared($5, static_cast(*$3), static_cast(*$6), DebugInfoRange(@1, @6)); + AExpression::Ptr subexpr = make_shared($5, *$3, *$6, DebugInfoRange(@1, @6)); delete $3; delete $6; @@ -551,7 +551,7 @@ lterm: identifier lbinary_op rterm | identifier '.' T_IDENTIFIER lbinary_op rterm { AExpression::Ptr aindex = make_shared(&AExpression::OpLiteral, $3, @3); - AExpression::Ptr subexpr = make_shared($4, aindex, static_cast(*$5), DebugInfoRange(@1, @5)); + AExpression::Ptr subexpr = make_shared($4, aindex, *$5, DebugInfoRange(@1, @5)); free($3); delete $5; @@ -567,9 +567,8 @@ lterm: identifier lbinary_op rterm | T_IMPORT rterm { AExpression::Ptr avar = make_shared(&AExpression::OpVariable, "type", DebugInfoRange(@1, @2)); - AExpression::Ptr aexpr = static_cast(*$2); + $$ = new Value(make_shared(&AExpression::OpImport, avar, *$2, DebugInfoRange(@1, @2))); delete $2; - $$ = new Value(make_shared(&AExpression::OpImport, avar, aexpr, DebugInfoRange(@1, @2))); } | T_ASSIGN T_WHERE rterm { @@ -578,7 +577,7 @@ lterm: identifier lbinary_op rterm m_SeenAssign = true; - m_Assign = make_shared(&AExpression::OpLogicalOr, m_Assign, static_cast(*$3), DebugInfoRange(@1, @3)); + m_Assign = make_shared(&AExpression::OpLogicalOr, m_Assign, *$3, DebugInfoRange(@1, @3)); delete $3; $$ = new Value(make_shared(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3))); @@ -588,12 +587,19 @@ lterm: identifier lbinary_op rterm if (!m_Apply) BOOST_THROW_EXCEPTION(ConfigError("'ignore' keyword not valid in this context.")); - m_Ignore = make_shared(&AExpression::OpLogicalOr, m_Ignore, static_cast(*$3), DebugInfoRange(@1, @3)); + m_Ignore = make_shared(&AExpression::OpLogicalOr, m_Ignore, *$3, DebugInfoRange(@1, @3)); delete $3; $$ = new Value(make_shared(&AExpression::OpLiteral, Empty, DebugInfoRange(@1, @3))); } + | T_RETURN rterm + { + AExpression::Ptr aname = make_shared(&AExpression::OpLiteral, "__result", @1); + $$ = new Value(make_shared(&AExpression::OpSet, aname, *$2, DebugInfoRange(@1, @2))); + delete $2; + + } | apply { $$ = $1; @@ -675,15 +681,15 @@ rterm: T_STRING } | rterm '.' T_IDENTIFIER { - $$ = new Value(make_shared(&AExpression::OpIndexer, static_cast(*$1), make_shared(&AExpression::OpLiteral, $3, @3), DebugInfoRange(@1, @3))); + $$ = new Value(make_shared(&AExpression::OpIndexer, *$1, make_shared(&AExpression::OpLiteral, $3, @3), DebugInfoRange(@1, @3))); delete $1; free($3); } | rterm '(' rterm_items ')' { Array::Ptr arguments = Array::Ptr($3); - $$ = new Value(make_shared(&AExpression::OpFunctionCall, static_cast(*$1), make_shared(&AExpression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4))); - free($1); + $$ = new Value(make_shared(&AExpression::OpFunctionCall, *$1, make_shared(&AExpression::OpLiteral, arguments, @3), DebugInfoRange(@1, @4))); + delete $1; } | T_IDENTIFIER { @@ -692,19 +698,19 @@ rterm: T_STRING } | '!' rterm { - $$ = new Value(make_shared(&AExpression::OpLogicalNegate, static_cast(*$2), DebugInfoRange(@1, @2))); + $$ = new Value(make_shared(&AExpression::OpLogicalNegate, *$2, DebugInfoRange(@1, @2))); delete $2; } | '~' rterm { - $$ = new Value(make_shared(&AExpression::OpNegate, static_cast(*$2), DebugInfoRange(@1, @2))); + $$ = new Value(make_shared(&AExpression::OpNegate, *$2, DebugInfoRange(@1, @2))); delete $2; } | rterm '[' rterm ']' { - $$ = new Value(make_shared(&AExpression::OpIndexer, static_cast(*$1), static_cast(*$3), DebugInfoRange(@1, @4))); + $$ = new Value(make_shared(&AExpression::OpIndexer, *$1, *$3, DebugInfoRange(@1, @4))); delete $1; - free($3); + delete $3; } | '[' newlines rterm_items newlines ']' { @@ -820,7 +826,7 @@ apply: String type = $3; free($3); - AExpression::Ptr aname = static_cast(*$4); + AExpression::Ptr aname = *$4; delete $4; String target = $5; free($5); @@ -849,7 +855,7 @@ apply: BOOST_THROW_EXCEPTION(ConfigError("'apply' target type '" + target + "' is invalid") << errinfo_debuginfo(DebugInfoRange(@2, @5))); } - AExpression::Ptr exprl = static_cast(*$6); + AExpression::Ptr exprl = *$6; delete $6; exprl->MakeInline();