mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
Merge remote-tracking branch 'origin/topic/jsiwek/983'
Closes #983. * origin/topic/jsiwek/983: Add named constructor examples to docs. Allow named vector constructors. Addresses #983. Allow named table constructors. Addresses #983. Improve set constructor argument coercion. Allow named set constructors. Addresses #983. Allow named record constructors. Addresses #983.
This commit is contained in:
commit
d3d14e10cf
15 changed files with 465 additions and 40 deletions
13
NEWS
13
NEWS
|
@ -46,6 +46,19 @@ New Functionality
|
||||||
have changed their signatures to work with opaques types rather
|
have changed their signatures to work with opaques types rather
|
||||||
than global state as it was before.
|
than global state as it was before.
|
||||||
|
|
||||||
|
- The scripting language now supports a constructing sets, tables,
|
||||||
|
vectors, and records by name:
|
||||||
|
|
||||||
|
type MyRecordType: record {
|
||||||
|
c: count;
|
||||||
|
s: string &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
global r: MyRecordType = record($c = 7);
|
||||||
|
|
||||||
|
type MySet: set[MyRec];
|
||||||
|
global s = MySet([$c=1], [$c=2]);
|
||||||
|
|
||||||
- Strings now support the subscript operator to extract individual
|
- Strings now support the subscript operator to extract individual
|
||||||
characters and substrings (e.g., s[4], s[1,5]). The index expression
|
characters and substrings (e.g., s[4], s[1,5]). The index expression
|
||||||
can take up to two indices for the start and end index of the
|
can take up to two indices for the start and end index of the
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3389de4a6045451f66b6cd52074c746ec9be551e
|
Subproject commit 0eca32b35d16a4d387f41976ab46360ee6ecaed8
|
|
@ -246,6 +246,31 @@ The Bro scripting language supports the following built-in types.
|
||||||
[5] = "five",
|
[5] = "five",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
A table constructor (equivalent to above example) can also be used
|
||||||
|
to create a table:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
global t2: table[count] of string = table(
|
||||||
|
[11] = "eleven",
|
||||||
|
[5] = "five"
|
||||||
|
);
|
||||||
|
|
||||||
|
Table constructors can also be explicitly named by a type, which is
|
||||||
|
useful for when a more complex index type could otherwise be
|
||||||
|
ambiguous:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
a: count &optional;
|
||||||
|
b: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyTable: table[MyRec] of string;
|
||||||
|
|
||||||
|
global t3 = MyTable([[$b=5]] = "b5", [[$b=7]] = "b7");
|
||||||
|
|
||||||
Accessing table elements if provided by enclosing values within square
|
Accessing table elements if provided by enclosing values within square
|
||||||
brackets (``[]``), for example:
|
brackets (``[]``), for example:
|
||||||
|
|
||||||
|
@ -308,6 +333,28 @@ The Bro scripting language supports the following built-in types.
|
||||||
The types are explicitly shown in the example above, but they could
|
The types are explicitly shown in the example above, but they could
|
||||||
have been left to type inference.
|
have been left to type inference.
|
||||||
|
|
||||||
|
A set constructor (equivalent to above example) can also be used to
|
||||||
|
create a set:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
global s3: set[port] = set(21/tcp, 23/tcp, 80/tcp, 443/tcp);
|
||||||
|
|
||||||
|
Set constructors can also be explicitly named by a type, which is
|
||||||
|
useful for when a more complex index type could otherwise be
|
||||||
|
ambiguous:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
a: count &optional;
|
||||||
|
b: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MySet: set[MyRec];
|
||||||
|
|
||||||
|
global s4 = MySet([$b=1], [$b=2]);
|
||||||
|
|
||||||
Set membership is tested with ``in``:
|
Set membership is tested with ``in``:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -349,6 +396,21 @@ The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
global v: vector of string = vector("one", "two", "three");
|
global v: vector of string = vector("one", "two", "three");
|
||||||
|
|
||||||
|
Vector constructors can also be explicitly named by a type, which
|
||||||
|
is useful for when a more complex yield type could otherwise be
|
||||||
|
ambiguous.
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
a: count &optional;
|
||||||
|
b: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MyVec: vector of MyRec;
|
||||||
|
|
||||||
|
global v2 = MyVec([$b=1], [$b=2], [$b=3]);
|
||||||
|
|
||||||
Adding an element to a vector involves accessing/assigning it:
|
Adding an element to a vector involves accessing/assigning it:
|
||||||
|
|
||||||
.. code:: bro
|
.. code:: bro
|
||||||
|
@ -402,6 +464,19 @@ The Bro scripting language supports the following built-in types.
|
||||||
if ( r?$s )
|
if ( r?$s )
|
||||||
...
|
...
|
||||||
|
|
||||||
|
Records can also be created using a constructor syntax:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
global r2: MyRecordType = record($c = 7);
|
||||||
|
|
||||||
|
And the constructor can be explicitly named by type, too, which
|
||||||
|
is arguably more readable code:
|
||||||
|
|
||||||
|
.. code:: bro
|
||||||
|
|
||||||
|
global r3 = MyRecordType($c = 42);
|
||||||
|
|
||||||
.. bro:type:: opaque
|
.. bro:type:: opaque
|
||||||
|
|
||||||
A data type whose actual representation/implementation is
|
A data type whose actual representation/implementation is
|
||||||
|
|
211
src/Expr.cc
211
src/Expr.cc
|
@ -3320,12 +3320,20 @@ bool HasFieldExpr::DoUnserialize(UnserialInfo* info)
|
||||||
return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
|
return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list,
|
||||||
|
BroType* arg_type)
|
||||||
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
|
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
|
||||||
{
|
{
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ( arg_type && arg_type->Tag() != TYPE_RECORD )
|
||||||
|
{
|
||||||
|
Error("bad record constructor type", arg_type);
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Spin through the list, which should be comprised of
|
// Spin through the list, which should be comprised of
|
||||||
// either record's or record-field-assign, and build up a
|
// either record's or record-field-assign, and build up a
|
||||||
// record type to associate with this constructor.
|
// record type to associate with this constructor.
|
||||||
|
@ -3365,7 +3373,17 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetType(new RecordType(record_types));
|
ctor_type = new RecordType(record_types);
|
||||||
|
|
||||||
|
if ( arg_type )
|
||||||
|
SetType(arg_type->Ref());
|
||||||
|
else
|
||||||
|
SetType(ctor_type->Ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordConstructorExpr::~RecordConstructorExpr()
|
||||||
|
{
|
||||||
|
Unref(ctor_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||||
|
@ -3391,7 +3409,7 @@ Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||||
Val* RecordConstructorExpr::Fold(Val* v) const
|
Val* RecordConstructorExpr::Fold(Val* v) const
|
||||||
{
|
{
|
||||||
ListVal* lv = v->AsListVal();
|
ListVal* lv = v->AsListVal();
|
||||||
RecordType* rt = type->AsRecordType();
|
RecordType* rt = ctor_type->AsRecordType();
|
||||||
|
|
||||||
if ( lv->Length() != rt->NumFields() )
|
if ( lv->Length() != rt->NumFields() )
|
||||||
Internal("inconsistency evaluating record constructor");
|
Internal("inconsistency evaluating record constructor");
|
||||||
|
@ -3401,6 +3419,19 @@ Val* RecordConstructorExpr::Fold(Val* v) const
|
||||||
for ( int i = 0; i < lv->Length(); ++i )
|
for ( int i = 0; i < lv->Length(); ++i )
|
||||||
rv->Assign(i, lv->Index(i)->Ref());
|
rv->Assign(i, lv->Index(i)->Ref());
|
||||||
|
|
||||||
|
if ( ! same_type(rt, type) )
|
||||||
|
{
|
||||||
|
RecordVal* new_val = rv->CoerceTo(type->AsRecordType());
|
||||||
|
|
||||||
|
if ( new_val )
|
||||||
|
{
|
||||||
|
Unref(rv);
|
||||||
|
rv = new_val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Internal("record constructor coercion failed");
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3416,37 +3447,89 @@ IMPLEMENT_SERIAL(RecordConstructorExpr, SER_RECORD_CONSTRUCTOR_EXPR);
|
||||||
bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
|
bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
|
||||||
{
|
{
|
||||||
DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
|
DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
|
||||||
|
SERIALIZE_OPTIONAL(ctor_type);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
|
bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
|
||||||
{
|
{
|
||||||
DO_UNSERIALIZE(UnaryExpr);
|
DO_UNSERIALIZE(UnaryExpr);
|
||||||
|
BroType* t = 0;
|
||||||
|
UNSERIALIZE_OPTIONAL(t, RecordType::Unserialize(info));
|
||||||
|
ctor_type = t->AsRecordType();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
|
TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
|
||||||
attr_list* arg_attrs)
|
attr_list* arg_attrs, BroType* arg_type)
|
||||||
: UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list)
|
: UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list)
|
||||||
{
|
{
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( constructor_list->Exprs().length() == 0 )
|
if ( arg_type )
|
||||||
SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0));
|
{
|
||||||
|
if ( ! arg_type->IsTable() )
|
||||||
|
{
|
||||||
|
Error("bad table constructor type", arg_type);
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetType(arg_type->Ref());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetType(init_type(constructor_list));
|
if ( constructor_list->Exprs().length() == 0 )
|
||||||
|
SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetType(init_type(constructor_list));
|
||||||
|
|
||||||
if ( ! type )
|
if ( ! type )
|
||||||
SetError();
|
SetError();
|
||||||
|
|
||||||
else if ( type->Tag() != TYPE_TABLE ||
|
else if ( type->Tag() != TYPE_TABLE ||
|
||||||
type->AsTableType()->IsSet() )
|
type->AsTableType()->IsSet() )
|
||||||
SetError("values in table(...) constructor do not specify a table");
|
SetError("values in table(...) constructor do not specify a table");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
|
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
|
||||||
|
|
||||||
|
type_list* indices = type->AsTableType()->Indices()->Types();
|
||||||
|
const expr_list& cle = constructor_list->Exprs();
|
||||||
|
|
||||||
|
// check and promote all index expressions in ctor list
|
||||||
|
loop_over_list(cle, i)
|
||||||
|
{
|
||||||
|
if ( cle[i]->Tag() != EXPR_ASSIGN )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Expr* idx_expr = cle[i]->AsAssignExpr()->Op1();
|
||||||
|
|
||||||
|
if ( idx_expr->Tag() != EXPR_LIST )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
expr_list& idx_exprs = idx_expr->AsListExpr()->Exprs();
|
||||||
|
|
||||||
|
if ( idx_exprs.length() != indices->length() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
loop_over_list(idx_exprs, j)
|
||||||
|
{
|
||||||
|
Expr* idx = idx_exprs[j];
|
||||||
|
|
||||||
|
if ( check_and_promote_expr(idx, (*indices)[j]) )
|
||||||
|
{
|
||||||
|
if ( idx != idx_exprs[j] )
|
||||||
|
idx_exprs.replace(j, idx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprError("inconsistent types in table constructor");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* TableConstructorExpr::Eval(Frame* f) const
|
Val* TableConstructorExpr::Eval(Frame* f) const
|
||||||
|
@ -3502,16 +3585,30 @@ bool TableConstructorExpr::DoUnserialize(UnserialInfo* info)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
|
SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
|
||||||
attr_list* arg_attrs)
|
attr_list* arg_attrs, BroType* arg_type)
|
||||||
: UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list)
|
: UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list)
|
||||||
{
|
{
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( constructor_list->Exprs().length() == 0 )
|
if ( arg_type )
|
||||||
SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0));
|
{
|
||||||
|
if ( ! arg_type->IsSet() )
|
||||||
|
{
|
||||||
|
Error("bad set constructor type", arg_type);
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetType(arg_type->Ref());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SetType(init_type(constructor_list));
|
{
|
||||||
|
if ( constructor_list->Exprs().length() == 0 )
|
||||||
|
SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0));
|
||||||
|
else
|
||||||
|
SetType(init_type(constructor_list));
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! type )
|
if ( ! type )
|
||||||
SetError();
|
SetError();
|
||||||
|
@ -3520,6 +3617,37 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
|
||||||
SetError("values in set(...) constructor do not specify a set");
|
SetError("values in set(...) constructor do not specify a set");
|
||||||
|
|
||||||
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
|
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
|
||||||
|
|
||||||
|
type_list* indices = type->AsTableType()->Indices()->Types();
|
||||||
|
expr_list& cle = constructor_list->Exprs();
|
||||||
|
|
||||||
|
if ( indices->length() == 1 )
|
||||||
|
{
|
||||||
|
if ( ! check_and_promote_exprs_to_type(constructor_list,
|
||||||
|
(*indices)[0]) )
|
||||||
|
ExprError("inconsistent type in set constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( indices->length() > 1 )
|
||||||
|
{
|
||||||
|
// Check/promote each expression in composite index.
|
||||||
|
loop_over_list(cle, i)
|
||||||
|
{
|
||||||
|
Expr* ce = cle[i];
|
||||||
|
ListExpr* le = ce->AsListExpr();
|
||||||
|
|
||||||
|
if ( ce->Tag() == EXPR_LIST &&
|
||||||
|
check_and_promote_exprs(le, type->AsTableType()->Indices()) )
|
||||||
|
{
|
||||||
|
if ( le != cle[i] )
|
||||||
|
cle.replace(i, le);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprError("inconsistent types in set constructor");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* SetConstructorExpr::Eval(Frame* f) const
|
Val* SetConstructorExpr::Eval(Frame* f) const
|
||||||
|
@ -3590,31 +3718,50 @@ bool SetConstructorExpr::DoUnserialize(UnserialInfo* info)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list)
|
VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list,
|
||||||
|
BroType* arg_type)
|
||||||
: UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, constructor_list)
|
: UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, constructor_list)
|
||||||
{
|
{
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( constructor_list->Exprs().length() == 0 )
|
if ( arg_type )
|
||||||
{
|
{
|
||||||
// vector().
|
if ( arg_type->Tag() != TYPE_VECTOR )
|
||||||
SetType(new ::VectorType(base_type(TYPE_ANY)));
|
{
|
||||||
return;
|
Error("bad vector constructor type", arg_type);
|
||||||
}
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BroType* t = merge_type_list(constructor_list);
|
SetType(arg_type->Ref());
|
||||||
if ( t )
|
|
||||||
{
|
|
||||||
SetType(new VectorType(t->Ref()));
|
|
||||||
|
|
||||||
if ( ! check_and_promote_exprs_to_type(constructor_list, t) )
|
|
||||||
ExprError("inconsistent types in vector constructor");
|
|
||||||
|
|
||||||
Unref(t);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetError();
|
{
|
||||||
|
if ( constructor_list->Exprs().length() == 0 )
|
||||||
|
{
|
||||||
|
// vector().
|
||||||
|
SetType(new ::VectorType(base_type(TYPE_ANY)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BroType* t = merge_type_list(constructor_list);
|
||||||
|
|
||||||
|
if ( t )
|
||||||
|
{
|
||||||
|
SetType(new VectorType(t->Ref()));
|
||||||
|
Unref(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! check_and_promote_exprs_to_type(constructor_list,
|
||||||
|
type->AsVectorType()->YieldType()) )
|
||||||
|
ExprError("inconsistent types in vector constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* VectorConstructorExpr::Eval(Frame* f) const
|
Val* VectorConstructorExpr::Eval(Frame* f) const
|
||||||
|
|
40
src/Expr.h
40
src/Expr.h
|
@ -57,6 +57,8 @@ extern const char* expr_name(BroExprTag t);
|
||||||
class Stmt;
|
class Stmt;
|
||||||
class Frame;
|
class Frame;
|
||||||
class ListExpr;
|
class ListExpr;
|
||||||
|
class NameExpr;
|
||||||
|
class AssignExpr;
|
||||||
class CallExpr;
|
class CallExpr;
|
||||||
class EventExpr;
|
class EventExpr;
|
||||||
|
|
||||||
|
@ -159,12 +161,37 @@ public:
|
||||||
CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name)
|
CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name)
|
||||||
return (const ListExpr*) this;
|
return (const ListExpr*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListExpr* AsListExpr()
|
ListExpr* AsListExpr()
|
||||||
{
|
{
|
||||||
CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name)
|
CHECK_TAG(tag, EXPR_LIST, "ExprVal::AsListExpr", expr_name)
|
||||||
return (ListExpr*) this;
|
return (ListExpr*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NameExpr* AsNameExpr() const
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name)
|
||||||
|
return (const NameExpr*) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
NameExpr* AsNameExpr()
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name)
|
||||||
|
return (NameExpr*) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssignExpr* AsAssignExpr() const
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name)
|
||||||
|
return (const AssignExpr*) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignExpr* AsAssignExpr()
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name)
|
||||||
|
return (AssignExpr*) this;
|
||||||
|
}
|
||||||
|
|
||||||
void Describe(ODesc* d) const;
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
bool Serialize(SerialInfo* info) const;
|
bool Serialize(SerialInfo* info) const;
|
||||||
|
@ -729,7 +756,8 @@ protected:
|
||||||
|
|
||||||
class RecordConstructorExpr : public UnaryExpr {
|
class RecordConstructorExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
RecordConstructorExpr(ListExpr* constructor_list);
|
RecordConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0);
|
||||||
|
~RecordConstructorExpr();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Expr;
|
friend class Expr;
|
||||||
|
@ -741,11 +769,14 @@ protected:
|
||||||
void ExprDescribe(ODesc* d) const;
|
void ExprDescribe(ODesc* d) const;
|
||||||
|
|
||||||
DECLARE_SERIAL(RecordConstructorExpr);
|
DECLARE_SERIAL(RecordConstructorExpr);
|
||||||
|
|
||||||
|
RecordType* ctor_type; // type inferred from the ctor expression list args
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableConstructorExpr : public UnaryExpr {
|
class TableConstructorExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs,
|
||||||
|
BroType* arg_type = 0);
|
||||||
~TableConstructorExpr() { Unref(attrs); }
|
~TableConstructorExpr() { Unref(attrs); }
|
||||||
|
|
||||||
Attributes* Attrs() { return attrs; }
|
Attributes* Attrs() { return attrs; }
|
||||||
|
@ -767,7 +798,8 @@ protected:
|
||||||
|
|
||||||
class SetConstructorExpr : public UnaryExpr {
|
class SetConstructorExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs);
|
SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs,
|
||||||
|
BroType* arg_type = 0);
|
||||||
~SetConstructorExpr() { Unref(attrs); }
|
~SetConstructorExpr() { Unref(attrs); }
|
||||||
|
|
||||||
Attributes* Attrs() { return attrs; }
|
Attributes* Attrs() { return attrs; }
|
||||||
|
@ -789,7 +821,7 @@ protected:
|
||||||
|
|
||||||
class VectorConstructorExpr : public UnaryExpr {
|
class VectorConstructorExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
VectorConstructorExpr(ListExpr* constructor_list);
|
VectorConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0);
|
||||||
|
|
||||||
Val* Eval(Frame* f) const;
|
Val* Eval(Frame* f) const;
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,11 @@ public:
|
||||||
return tag == TYPE_TABLE && (YieldType() == 0);
|
return tag == TYPE_TABLE && (YieldType() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IsTable() const
|
||||||
|
{
|
||||||
|
return tag == TYPE_TABLE && (YieldType() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
BroType* Ref() { ::Ref(this); return this; }
|
BroType* Ref() { ::Ref(this); return this; }
|
||||||
|
|
||||||
virtual void Describe(ODesc* d) const;
|
virtual void Describe(ODesc* d) const;
|
||||||
|
|
48
src/parse.y
48
src/parse.y
|
@ -522,10 +522,52 @@ expr:
|
||||||
$$ = new VectorConstructorExpr($3);
|
$$ = new VectorConstructorExpr($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr '(' opt_expr_list ')'
|
| expr '('
|
||||||
{
|
{
|
||||||
set_location(@1, @4);
|
if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() )
|
||||||
$$ = new CallExpr($1, $3, in_hook > 0);
|
++in_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_expr_list
|
||||||
|
{
|
||||||
|
if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() )
|
||||||
|
--in_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
')'
|
||||||
|
{
|
||||||
|
set_location(@1, @6);
|
||||||
|
|
||||||
|
BroType* ctor_type = 0;
|
||||||
|
|
||||||
|
if ( $1->Tag() == EXPR_NAME &&
|
||||||
|
(ctor_type = $1->AsNameExpr()->Id()->AsType()) )
|
||||||
|
{
|
||||||
|
switch ( ctor_type->Tag() ) {
|
||||||
|
case TYPE_RECORD:
|
||||||
|
$$ = new RecordConstructorExpr($4, ctor_type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_TABLE:
|
||||||
|
if ( ctor_type->IsTable() )
|
||||||
|
$$ = new TableConstructorExpr($4, 0, ctor_type);
|
||||||
|
else
|
||||||
|
$$ = new SetConstructorExpr($4, 0, ctor_type);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_VECTOR:
|
||||||
|
$$ = new VectorConstructorExpr($4, ctor_type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$1->Error("constructor type not implemented");
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
$$ = new CallExpr($1, $4, in_hook > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_HOOK { ++in_hook; } expr
|
| TOK_HOOK { ++in_hook; } expr
|
||||||
|
|
2
testing/btest/Baseline/language.named-record-ctors/out
Normal file
2
testing/btest/Baseline/language.named-record-ctors/out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[min=<uninitialized>, max=2]
|
||||||
|
[min=7, max=42]
|
13
testing/btest/Baseline/language.named-set-ctors/out
Normal file
13
testing/btest/Baseline/language.named-set-ctors/out
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
3
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[min=<uninitialized>, max=5],
|
||||||
|
[min=<uninitialized>, max=2]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[test, 1] ,
|
||||||
|
[cool, 2]
|
||||||
|
}
|
19
testing/btest/Baseline/language.named-table-ctors/out
Normal file
19
testing/btest/Baseline/language.named-table-ctors/out
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
[1] = one,
|
||||||
|
[5] = five,
|
||||||
|
[3] = three
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[min=<uninitialized>, max=5]] = max5,
|
||||||
|
[[min=<uninitialized>, max=2]] = max2
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[test, 1] = test1,
|
||||||
|
[cool, 2] = cool2
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[two] = 2.0,
|
||||||
|
[one] = 1.0,
|
||||||
|
[three] = 3.0
|
||||||
|
}
|
||||||
|
0
|
3
testing/btest/Baseline/language.named-vector-ctors/out
Normal file
3
testing/btest/Baseline/language.named-vector-ctors/out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[one, two, three]
|
||||||
|
[1.0, 2.0, 3.0]
|
||||||
|
[[min=<uninitialized>, max=1], [min=<uninitialized>, max=2], [min=<uninitialized>, max=3]]
|
12
testing/btest/language/named-record-ctors.bro
Normal file
12
testing/btest/language/named-record-ctors.bro
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
min: count &optional;
|
||||||
|
max: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
local myrec: MyRec = MyRec($max=2);
|
||||||
|
print myrec;
|
||||||
|
myrec = MyRec($min=7, $max=42);
|
||||||
|
print myrec;
|
19
testing/btest/language/named-set-ctors.bro
Normal file
19
testing/btest/language/named-set-ctors.bro
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
min: count &optional;
|
||||||
|
max: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FooSet: set[count];
|
||||||
|
type FooSetRec: set[MyRec];
|
||||||
|
type FooSetComp: set[string, count];
|
||||||
|
|
||||||
|
global myset: FooSet = FooSet(1, 5, 3);
|
||||||
|
global mysetrec: FooSetRec = FooSetRec([$max=5], [$max=2]);
|
||||||
|
global mysetcomp: FooSetComp = FooSetComp(["test", 1], ["cool", 2]);
|
||||||
|
|
||||||
|
print myset;
|
||||||
|
print mysetrec;
|
||||||
|
print mysetcomp;
|
24
testing/btest/language/named-table-ctors.bro
Normal file
24
testing/btest/language/named-table-ctors.bro
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
min: count &optional;
|
||||||
|
max: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FooTable: table[count] of string;
|
||||||
|
type FooTableRec: table[MyRec] of string;
|
||||||
|
type FooTableComp: table[string, count] of string;
|
||||||
|
type FooTableY: table[string] of double;
|
||||||
|
|
||||||
|
global mytable: FooTable = FooTable([1] = "one", [5] = "five", [3] = "three");
|
||||||
|
global mytablerec: FooTableRec = FooTableRec([[$max=5]] = "max5", [[$max=2]] = "max2");
|
||||||
|
global mytablecomp: FooTableComp = FooTableComp(["test", 1] = "test1", ["cool",
|
||||||
|
2] = "cool2");
|
||||||
|
global mytabley: FooTableY = FooTableY(["one"] = 1, ["two"] = 2, ["three"] = 3) &default=0;
|
||||||
|
|
||||||
|
print mytable;
|
||||||
|
print mytablerec;
|
||||||
|
print mytablecomp;
|
||||||
|
print mytabley;
|
||||||
|
print mytabley["test"];
|
19
testing/btest/language/named-vector-ctors.bro
Normal file
19
testing/btest/language/named-vector-ctors.bro
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
min: count &optional;
|
||||||
|
max: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type FooVector: vector of string;
|
||||||
|
type FooVectorD: vector of double;
|
||||||
|
type FooVectorRec: vector of MyRec;
|
||||||
|
|
||||||
|
global myvec: FooVector = FooVector("one", "two", "three");
|
||||||
|
global myvecd: FooVectorD = FooVectorD(1, 2, 3);
|
||||||
|
global myvecrec: FooVectorRec = FooVectorRec([$max=1], [$max=2], [$max=3]);
|
||||||
|
|
||||||
|
print myvec;
|
||||||
|
print myvecd;
|
||||||
|
print myvecrec;
|
Loading…
Add table
Add a link
Reference in a new issue