Fix ambiguity between composite table index and record ctor expressions.

For tables of a composite index type with the first type being a
record, membership checks with an inline index key could be
misinterpreted as a record constructor instead of an expression list.
E.g, if the table type is "global t = table[conn_id, bool] of count",
then checking membership like "[c$id, is_orig] in t" now works.

Addresses #80.
This commit is contained in:
Jon Siwek 2012-11-16 12:43:39 -06:00
parent 5508a5bb80
commit 56e359ca9d
3 changed files with 37 additions and 10 deletions

View file

@ -456,17 +456,24 @@ expr:
| '[' expr_list ']' | '[' expr_list ']'
{ {
// A little crufty: we peek at the type of
// the first expression in the list. If it's
// a record or a field assignment, then this
// is a record constructor. If not, then this
// is a list used for an initializer.
set_location(@1, @3); set_location(@1, @3);
Expr* e0 = $2->Exprs()[0]; bool is_record_ctor = true;
if ( e0->Tag() == EXPR_FIELD_ASSIGN ||
e0->Type()->Tag() == TYPE_RECORD ) // If every expression in the list is a field assignment,
// then treat it as a record constructor, else as a list
// used for an initializer.
for ( int i = 0; i < $2->Exprs().length(); ++i )
{
if ( $2->Exprs()[i]->Tag() != EXPR_FIELD_ASSIGN )
{
is_record_ctor = false;
break;
}
}
if ( is_record_ctor )
$$ = new RecordConstructorExpr($2); $$ = new RecordConstructorExpr($2);
else else
$$ = $2; $$ = $2;

View file

@ -12,6 +12,7 @@ cardinality (PASS)
cardinality (PASS) cardinality (PASS)
cardinality (PASS) cardinality (PASS)
cardinality (PASS) cardinality (PASS)
cardinality (PASS)
iterate over table (PASS) iterate over table (PASS)
iterate over table (PASS) iterate over table (PASS)
iterate over table (PASS) iterate over table (PASS)
@ -30,6 +31,11 @@ add element (PASS)
in operator (PASS) in operator (PASS)
add element (PASS) add element (PASS)
in operator (PASS) in operator (PASS)
composite index add element (PASS)
composite index in operator (PASS)
composite index in operator (PASS)
remove element (PASS)
!in operator (PASS)
remove element (PASS) remove element (PASS)
!in operator (PASS) !in operator (PASS)
remove element (PASS) remove element (PASS)

View file

@ -1,4 +1,4 @@
# @TEST-EXEC: bro %INPUT >out # @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff out
function test_case(msg: string, expect: bool) function test_case(msg: string, expect: bool)
@ -26,6 +26,9 @@ event bro_init()
local t10: table[port, string, bool] of string = { local t10: table[port, string, bool] of string = {
[10/udp, "curly", F] = "first", [10/udp, "curly", F] = "first",
[11/udp, "braces", T] = "second" }; [11/udp, "braces", T] = "second" };
local t11: table[conn_id, bool] of count = {
[ [$orig_h=1.1.1.1, $orig_p=1234/tcp,
$resp_h=2.2.2.2, $resp_p=4321/tcp], T ] = 42 };
# Type inference tests # Type inference tests
@ -45,6 +48,7 @@ event bro_init()
test_case( "cardinality", |t8| == 0 ); test_case( "cardinality", |t8| == 0 );
test_case( "cardinality", |t9| == 1 ); test_case( "cardinality", |t9| == 1 );
test_case( "cardinality", |t10| == 2 ); test_case( "cardinality", |t10| == 2 );
test_case( "cardinality", |t11| == 1 );
test_case( "cardinality", |tg1| == 3 ); test_case( "cardinality", |tg1| == 3 );
# Test iterating over each table # Test iterating over each table
@ -121,6 +125,13 @@ event bro_init()
test_case( "add element", |t5| == 3 ); test_case( "add element", |t5| == 3 );
test_case( "in operator", 10 in t5 ); test_case( "in operator", 10 in t5 );
local cid = [$orig_h=1.1.1.1, $orig_p=1234/tcp,
$resp_h=2.2.2.2, $resp_p=4321/tcp];
t11[[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] = 3;
test_case( "composite index add element", |t11| == 2 );
test_case( "composite index in operator", [cid, T] in t11 );
test_case( "composite index in operator", [[$orig_h=[::1], $orig_p=3/tcp, $resp_h=[::2], $resp_p=3/tcp], F] in t11 );
# Test removing elements from each table (Note: cannot remove elements # Test removing elements from each table (Note: cannot remove elements
# from tables of multiple types) # from tables of multiple types)
@ -145,5 +156,8 @@ event bro_init()
test_case( "remove element", |t5| == 2 ); test_case( "remove element", |t5| == 2 );
test_case( "!in operator", 1 !in t5 ); test_case( "!in operator", 1 !in t5 );
delete t11[cid, T];
test_case( "remove element", |t11| == 1 );
test_case( "!in operator", [cid, T] !in t11 );
} }