stmt: Support iterating over vector values

I ran into wanting to iterate over just the values of a vector and wondering
whether that could just work.

This adds support for the following, where v will be value of vec[i].

    local vec = vector("zero", "one", "two");

    for ( i, v in vec )
        print i, v;
This commit is contained in:
Arne Welzel 2022-08-21 17:14:28 +02:00
parent 0f8e675a49
commit f334df3b79
4 changed files with 66 additions and 16 deletions

8
NEWS
View file

@ -96,6 +96,14 @@ New Functionality
``disable_analyzer()`` at a later point when it finds the condition due ``disable_analyzer()`` at a later point when it finds the condition due
to which it vetoed fulfilled (which may be never). to which it vetoed fulfilled (which may be never).
- Add support for iterating over indices and values of a vector using the
same syntax as used for iterating over key-value pairs of tables, where
``value`` will be set to ``vec[idx]``.
local vec = vector("zero", "one", "two");
for ( idx, value in vec )
print idx, value;
Changed Functionality Changed Functionality
--------------------- ---------------------

View file

@ -1290,23 +1290,29 @@ ForStmt::ForStmt(IDPList* arg_loop_vars, ExprPtr loop_expr, IDPtr val_var)
{ {
value_var = std::move(val_var); value_var = std::move(val_var);
if ( e->GetType()->IsTable() ) auto t = e->GetType();
{ zeek::TypePtr yield_type;
const auto& yield_type = e->GetType()->AsTableType()->Yield();
// Verify value_vars type if its already been defined if ( t->IsTable() )
if ( value_var->GetType() ) yield_type = t->AsTableType()->Yield();
{
if ( ! same_type(value_var->GetType(), yield_type) ) else if ( t->Tag() == TYPE_VECTOR )
value_var->GetType()->Error("type clash in iteration", yield_type.get()); yield_type = t->AsVectorType()->Yield();
}
else else
{ {
add_local(value_var, yield_type, INIT_NONE, nullptr, nullptr, VAR_REGULAR); e->Error("key value for loops only support iteration over tables or vectors");
} return;
}
// Verify value_vars type if it's already been defined
if ( value_var->GetType() )
{
if ( ! same_type(value_var->GetType(), yield_type) )
value_var->GetType()->Error("type clash in iteration", yield_type.get());
} }
else else
e->Error("key value for loops only support iteration over tables"); add_local(value_var, yield_type, INIT_NONE, nullptr, nullptr, VAR_REGULAR);
} }
ForStmt::~ForStmt() ForStmt::~ForStmt()
@ -1358,8 +1364,11 @@ ValPtr ForStmt::DoExec(Frame* f, Val* v, StmtFlowType& flow)
if ( ! raw_vv[i] ) if ( ! raw_vv[i] )
continue; continue;
// Set the loop variable to the current index, and make // Set the loop variable to the current index, the value variable
// another pass over the loop body. // to the current value, and make another pass over the loop body.
if ( value_var )
f->SetElement(value_var, vv->ValAt(i));
f->SetElement((*loop_vars)[0], val_mgr->Count(i)); f->SetElement((*loop_vars)[0], val_mgr->Count(i));
flow = FLOW_NEXT; flow = FLOW_NEXT;
ret = body->Exec(f, flow); ret = body->Exec(f, flow);

View file

@ -0,0 +1,13 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
0, zero
1, one
2, two
4, four
0, zero
1, one
2, two
4, four
zero
one
two
four

View file

@ -0,0 +1,20 @@
# @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC: btest-diff out
local vec: vector of string = { "zero", "one", "two" };
vec[4] = "four";
for ( i, v in vec )
{
print i, v;
}
for ( [i], v in vec )
{
print i, v;
}
for ( _, v in vec )
{
print v;
}