diff --git a/src/Expr.cc b/src/Expr.cc index 32fc9b5acc..0888ee6336 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3537,16 +3537,30 @@ bool TableConstructorExpr::DoUnserialize(UnserialInfo* info) } SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, - attr_list* arg_attrs) + attr_list* arg_attrs, BroType* arg_type) : UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list) { if ( IsError() ) return; - if ( constructor_list->Exprs().length() == 0 ) - SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( arg_type ) + { + if ( ! arg_type->IsSet() ) + { + Error("bad set constructor type", arg_type); + SetError(); + return; + } + + SetType(arg_type->Ref()); + } 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 ) SetError(); @@ -3555,6 +3569,43 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, SetError("values in set(...) constructor do not specify a set"); 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 diff --git a/src/Expr.h b/src/Expr.h index edc1ced6e5..e2cc1375a3 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -782,7 +782,8 @@ protected: class SetConstructorExpr : public UnaryExpr { public: - SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs); + SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs, + BroType* arg_type = 0); ~SetConstructorExpr() { Unref(attrs); } Attributes* Attrs() { return attrs; } diff --git a/src/parse.y b/src/parse.y index bfaf282c6a..ac57dea5e9 100644 --- a/src/parse.y +++ b/src/parse.y @@ -546,6 +546,15 @@ expr: $$ = new RecordConstructorExpr($4, ctor_type); break; 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: default: $1->Error("constructor type not implemented"); diff --git a/testing/btest/Baseline/language.named-ctors/out b/testing/btest/Baseline/language.named-record-ctors/out similarity index 100% rename from testing/btest/Baseline/language.named-ctors/out rename to testing/btest/Baseline/language.named-record-ctors/out diff --git a/testing/btest/Baseline/language.named-set-ctors/out b/testing/btest/Baseline/language.named-set-ctors/out new file mode 100644 index 0000000000..e7b0ca6b67 --- /dev/null +++ b/testing/btest/Baseline/language.named-set-ctors/out @@ -0,0 +1,9 @@ +{ +1, +5, +3 +} +{ +[test, 1] , +[cool, 2] +} diff --git a/testing/btest/language/named-ctors.bro b/testing/btest/language/named-record-ctors.bro similarity index 100% rename from testing/btest/language/named-ctors.bro rename to testing/btest/language/named-record-ctors.bro diff --git a/testing/btest/language/named-set-ctors.bro b/testing/btest/language/named-set-ctors.bro new file mode 100644 index 0000000000..5c7e0b1398 --- /dev/null +++ b/testing/btest/language/named-set-ctors.bro @@ -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;