Implement for loops.

Fixes #6183
This commit is contained in:
Gunnar Beutner 2014-05-10 11:26:56 +02:00
parent ab8624d2f5
commit 0e34968e8f
7 changed files with 77 additions and 1 deletions

View File

@ -38,6 +38,7 @@ REGISTER_SCRIPTFUNCTION(len, &ScriptUtils::Len);
REGISTER_SCRIPTFUNCTION(union, &ScriptUtils::Union);
REGISTER_SCRIPTFUNCTION(intersection, &ScriptUtils::Intersection);
REGISTER_SCRIPTFUNCTION(log, &ScriptUtils::Log);
REGISTER_SCRIPTFUNCTION(range, &ScriptUtils::Range);
REGISTER_SCRIPTFUNCTION(exit, &ScriptUtils::Exit);
bool ScriptUtils::Regex(const String& pattern, const String& text)
@ -130,6 +131,41 @@ void ScriptUtils::Log(const std::vector<Value>& arguments)
::Log(severity, facility, JsonSerialize(message));
}
Array::Ptr ScriptUtils::Range(const std::vector<Value>& arguments)
{
int start, end, increment;
switch (arguments.size()) {
case 1:
start = 0;
end = arguments[0];
increment = 1;
break;
case 2:
start = arguments[0];
end = arguments[1];
increment = 1;
break;
case 3:
start = arguments[0];
end = arguments[1];
increment = arguments[2];
break;
}
Array::Ptr result = make_shared<Array>();
if ((start < end && increment <= 0) ||
(start > end && increment >= 0))
return result;
for (int i = start; i < end; i += increment) {
result->Add(i);
}
return result;
}
void ScriptUtils::Exit(int code)
{
exit(code);

View File

@ -38,6 +38,7 @@ public:
static Array::Ptr Union(const std::vector<Value>& arguments);
static Array::Ptr Intersection(const std::vector<Value>& arguments);
static void Log(const std::vector<Value>& arguments);
static Array::Ptr Range(const std::vector<Value>& arguments);
static void Exit(int code);
private:

View File

@ -574,3 +574,23 @@ Value AExpression::OpObject(const AExpression* expr, const Dictionary::Ptr& loca
return Empty;
}
Value AExpression::OpFor(const AExpression* expr, const Dictionary::Ptr& locals)
{
Array::Ptr left = expr->m_Operand1;
String varname = left->Get(0);
AExpression::Ptr aexpr = left->Get(1);
AExpression::Ptr ascope = expr->m_Operand2;
Array::Ptr arr = aexpr->Evaluate(locals);
ObjectLock olock(arr);
BOOST_FOREACH(const Value& value, arr) {
locals->Set(varname, value);
ascope->Evaluate(locals);
}
locals->Remove(varname);
return Empty;
}

View File

@ -82,6 +82,7 @@ public:
static Value OpFunction(const AExpression* expr, const Dictionary::Ptr& locals);
static Value OpApply(const AExpression* expr, const Dictionary::Ptr& locals);
static Value OpObject(const AExpression* expr, const Dictionary::Ptr& locals);
static Value OpFor(const AExpression* expr, const Dictionary::Ptr& locals);
private:
OpCallback m_Operator;

View File

@ -232,6 +232,7 @@ function return T_FUNCTION;
lambda return T_LAMBDA;
return return T_RETURN;
zone return T_ZONE;
for return T_FOR;
\<\< { 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; }

View File

@ -161,6 +161,7 @@ static void MakeRBinaryOp(Value** result, AExpression::OpCallback& op, Value *le
%token T_LAMBDA "lambda (T_LAMBDA)"
%token T_RETURN "return (T_RETURN)"
%token T_ZONE "zone (T_ZONE)"
%token T_FOR "for (T_FOR)"
%type <text> identifier
%type <array> rterm_items
@ -877,6 +878,22 @@ rterm: T_STRING
$$ = new Value(make_shared<AExpression>(&AExpression::OpFunction, arr, Array::Ptr($2), DebugInfoRange(@1, @4)));
}
| T_FOR '(' identifier T_IN rterm ')' rterm_scope
{
Array::Ptr arr = make_shared<Array>();
arr->Add($3);
free($3);
AExpression::Ptr aexpr = *$5;
delete $5;
arr->Add(aexpr);
AExpression::Ptr ascope = *$7;
delete $7;
$$ = new Value(make_shared<AExpression>(&AExpression::OpFor, arr, ascope, DebugInfoRange(@1, @7)));
}
;
target_type_specifier: /* empty */

View File

@ -937,7 +937,7 @@ Value ApiEvents::UpdateRepositoryAPIHandler(const MessageOrigin& origin, const D
fp.close();
#ifdef _WIN32
_unlink(inventoryFile.CStr());
_unlink(repositoryFile.CStr());
#endif /* _WIN32 */
if (rename(repositoryTempFile.CStr(), repositoryFile.CStr()) < 0) {