From a0590b2140adae5b9cc4ae5520bd566d12a4331d Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:19:48 -0600 Subject: [PATCH 1/2] 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. --- src/Expr.cc | 38 ++++++++-- src/Val.cc | 2 + .../output | 42 +++++++++++ .../language/table-init-container-ctors.bro | 74 +++++++++++++++++++ 4 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 testing/btest/Baseline/language.table-init-container-ctors/output create mode 100644 testing/btest/language/table-init-container-ctors.bro diff --git a/src/Expr.cc b/src/Expr.cc index 733e0fe9a5..89680b9b5b 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..0e30218b4b 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3117,6 +3117,8 @@ 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..feda20fea7 --- /dev/null +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -0,0 +1,42 @@ +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 +} +} + +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..8882cb5640 --- /dev/null +++ b/testing/btest/language/table-init-container-ctors.bro @@ -0,0 +1,74 @@ +# @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; + +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 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), +}; + +# 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); + +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]; + } + +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 ""; + +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); From 00f7bbda96d32d3c323ad03559669e757e4d20c4 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 28 Nov 2012 14:53:36 -0600 Subject: [PATCH 2/2] Add test of record() constructor to table initializer unit test. --- .../output | 8 +++++++ .../language/table-init-container-ctors.bro | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/testing/btest/Baseline/language.table-init-container-ctors/output b/testing/btest/Baseline/language.table-init-container-ctors/output index feda20fea7..27774a660a 100644 --- a/testing/btest/Baseline/language.table-init-container-ctors/output +++ b/testing/btest/Baseline/language.table-init-container-ctors/output @@ -28,6 +28,14 @@ table of table } } +table of record +{ +[13] = [a=1, b=foo], +[5] = [a=2, b=bar] +} + +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 index 8882cb5640..4829f41688 100644 --- a/testing/btest/language/table-init-container-ctors.bro +++ b/testing/btest/language/table-init-container-ctors.bro @@ -7,10 +7,15 @@ 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, @@ -27,11 +32,17 @@ global table_of_table: table[count] of table_yield = { [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) { @@ -56,6 +67,11 @@ function compare_table_yield(a: table_yield, b: table_yield) 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 ""; @@ -65,6 +81,9 @@ 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); @@ -72,3 +91,5 @@ 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);