Allow named set constructors. Addresses #983.

This commit is contained in:
Jon Siwek 2013-05-29 15:11:44 -05:00
parent a0ad87b4c2
commit b256642f27
7 changed files with 86 additions and 5 deletions

View file

@ -3537,16 +3537,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();
@ -3555,6 +3569,43 @@ 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();
loop_over_list(cle, i)
{
Expr* ce = cle[i];
if ( ce->Tag() == EXPR_LIST )
{
// check promote each expression in composite index
expr_list& el = ce->AsListExpr()->Exprs();
if ( el.length() != indices->length() )
{
ExprError("inconsistent index type length in set constructor");
return;
}
loop_over_list(el, j)
{
Expr* e = el[j];
if ( ! check_and_promote_expr(e, (*indices)[j]) )
{
ExprError("inconsistent index type in set constructor");
return;
}
}
}
else if ( indices->length() == 1 )
{
if ( ! check_and_promote_expr(ce, (*indices)[0]) )
ExprError("inconsistent index type in set constructor");
}
}
} }
Val* SetConstructorExpr::Eval(Frame* f) const Val* SetConstructorExpr::Eval(Frame* f) const

View file

@ -782,7 +782,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; }

View file

@ -546,6 +546,15 @@ expr:
$$ = new RecordConstructorExpr($4, ctor_type); $$ = new RecordConstructorExpr($4, ctor_type);
break; break;
case TYPE_TABLE: case TYPE_TABLE:
if ( ctor_type->IsTable() )
{
$1->Error("constructor type not implemented");
YYERROR;
}
else
$$ = new SetConstructorExpr($4, 0, ctor_type);
break;
case TYPE_VECTOR: case TYPE_VECTOR:
default: default:
$1->Error("constructor type not implemented"); $1->Error("constructor type not implemented");

View file

@ -0,0 +1,9 @@
{
1,
5,
3
}
{
[test, 1] ,
[cool, 2]
}

View file

@ -0,0 +1,11 @@
# @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: btest-diff out
type FooSet: set[count];
type FooSetComp: set[string, count];
global myset: FooSet = FooSet(1, 5, 3);
global mysetcomp: FooSetComp = FooSetComp(["test", 1], ["cool", 2]);
print myset;
print mysetcomp;