diff --git a/CHANGES b/CHANGES index 95eb8fc5cd..7c02e43ede 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,14 @@ +2.1-191 | 2012-12-03 14:08:56 -0800 + + * Add test of record() constructor to table initializer unit test. + (Jon Siwek) + + * Fix table(), set(), vector() constructors in table initializer + lists. Also adds type checking of yield values to table() + constructor and fixes the type checking of yield values in + vector() constructor. Addresses #5. (Jon Siwek) + 2.1-188 | 2012-12-03 14:04:29 -0800 * Hook functions now callable with "hook" expression (i.e., hook is diff --git a/VERSION b/VERSION index 481160aafd..9028e32f8b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1-188 +2.1-191 diff --git a/src/Expr.cc b/src/Expr.cc index a910e0d2fb..13faf7cef2 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2663,7 +2663,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const TableVal* tv = aggr->AsTableVal(); Val* index = op1->Eval(f); - Val* v = op2->Eval(f); + Val* v = check_and_promote(op2->Eval(f), t->YieldType(), 1); if ( ! index || ! v ) return; @@ -3386,7 +3386,14 @@ Val* TableConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + exprs[i]->EvalIntoAggregate(t, tval, 0); + + return tval; } void TableConstructorExpr::ExprDescribe(ODesc* d) const @@ -3456,7 +3463,26 @@ Val* SetConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return op->InitVal(t, aggr); + const BroType* index_type = t->AsTableType()->Indices(); + TableType* tt = Type()->AsTableType(); + TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + const expr_list& exprs = op->AsListExpr()->Exprs(); + + loop_over_list(exprs, i) + { + Expr* e = exprs[i]; + Val* element = check_and_promote(e->Eval(0), index_type, 1); + + if ( ! element || ! tval->Assign(element, 0) ) + { + Error(fmt("initialization type mismatch in set"), e); + return 0; + } + + Unref(element); + } + + return tval; } void SetConstructorExpr::ExprDescribe(ODesc* d) const @@ -3536,14 +3562,14 @@ Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - VectorVal* vec = aggr->AsVectorVal(); - const BroType* vt = vec->Type()->AsVectorType()->YieldType(); + VectorType* vt = Type()->AsVectorType(); + VectorVal* vec = aggr ? aggr->AsVectorVal() : new VectorVal(vt); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) { Expr* e = exprs[i]; - Val* v = check_and_promote(e->Eval(0), vt, 1); + Val* v = check_and_promote(e->Eval(0), t->YieldType(), 1); if ( ! v || ! vec->Assign(i, v, e) ) { diff --git a/src/Val.cc b/src/Val.cc index 79fa8a0c69..3e60fffc82 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3117,6 +3117,9 @@ void VectorVal::ValDescribe(ODesc* d) const Val* check_and_promote(Val* v, const BroType* t, int is_init) { + if ( ! v ) + return 0; + BroType* vt = v->Type(); vt = flatten_type(vt); diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output new file mode 100644 index 0000000000..27774a660a --- /dev/null +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -0,0 +1,50 @@ +table of set +{ +[13] = { +[bar, 2] , +[foo, 1] +}, +[5] = { +[bah, 3] , +[baz, 4] +} +} + +table of vector +{ +[13] = [1, 2], +[5] = [3, 4] +} + +table of table +{ +[13] = { +[bar, 2] = 2, +[foo, 1] = 1 +}, +[5] = { +[bah, 3] = 3, +[baz, 4] = 4 +} +} + +table of record +{ +[13] = [a=1, b=foo], +[5] = [a=2, b=bar] +} + +T +T +T +T +T +T +T +T +T +T +T +T +T +T diff --git a/testing/btest/language/table-init-container-ctors.bro b/testing/btest/language/table-init-container-ctors.bro new file mode 100644 index 0000000000..4829f41688 --- /dev/null +++ b/testing/btest/language/table-init-container-ctors.bro @@ -0,0 +1,95 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# The various container constructor expressions should work in table +# initialization lists. + +type set_yield: set[string, count]; +type vector_yield: vector of count; +type table_yield: table[string, count] of count; +type record_yield: record { + a: count; + b: string; +}; + +global lone_set_ctor: set_yield = set(["foo", 1], ["bar", 2]); +global lone_vector_ctor: vector_yield = vector(1, 2); +global lone_table_ctor: table_yield = table(["foo", 1] = 1, ["bar", 2] = 2); +global lone_record_ctor: record_yield = record($a=1, $b="foo"); + +global table_of_set: table[count] of set_yield = { + [13] = lone_set_ctor, + [5] = set(["bah", 3], ["baz", 4]), +}; + +global table_of_vector: table[count] of vector_yield = { + [13] = lone_vector_ctor, + [5] = vector(3, 4), +}; + +global table_of_table: table[count] of table_yield = { + [13] = lone_table_ctor, + [5] = table(["bah", 3] = 3, ["baz", 4] = 4), +}; + +global table_of_record: table[count] of record_yield = { + [13] = lone_record_ctor, + [5] = record($a=2, $b="bar"), +}; + +# Just copying the inline ctors used in the table initializer lists here +# for later comparisons. +global inline_set_ctor: set_yield = set(["bah", 3], ["baz", 4]); +global inline_vector_ctor: vector_yield = vector(3, 4); +global inline_table_ctor: table_yield = table(["bah", 3] = 3, ["baz", 4] = 4); +global inline_record_ctor: record_yield = record($a=2, $b="bar"); + +function compare_set_yield(a: set_yield, b: set_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b; + } + +function compare_vector_yield(a: vector_yield, b: vector_yield) + { + local c: count; + for ( c in a ) + print a[c] == b[c]; + } + +function compare_table_yield(a: table_yield, b: table_yield) + { + local s: string; + local c: count; + for ( [s, c] in a ) + print [s, c] in b && a[s, c] == b[s, c]; + } + +function compare_record_yield(a: record_yield, b: record_yield) + { + print a$a == b$a && a$b == b$b; + } + +print "table of set"; +print table_of_set; +print ""; +print "table of vector"; +print table_of_vector; +print ""; +print "table of table"; +print table_of_table; +print ""; +print "table of record"; +print table_of_record; +print ""; + +compare_set_yield(table_of_set[13], lone_set_ctor); +compare_set_yield(table_of_set[5], inline_set_ctor); +compare_vector_yield(table_of_vector[13], lone_vector_ctor); +compare_vector_yield(table_of_vector[5], inline_vector_ctor); +compare_table_yield(table_of_table[13], lone_table_ctor); +compare_table_yield(table_of_table[5], inline_table_ctor); +compare_record_yield(table_of_record[13], lone_record_ctor); +compare_record_yield(table_of_record[5], inline_record_ctor);