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 ']'
{
// 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);
Expr* e0 = $2->Exprs()[0];
if ( e0->Tag() == EXPR_FIELD_ASSIGN ||
e0->Type()->Tag() == TYPE_RECORD )
bool is_record_ctor = true;
// 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);
else
$$ = $2;

View file

@ -12,6 +12,7 @@ cardinality (PASS)
cardinality (PASS)
cardinality (PASS)
cardinality (PASS)
cardinality (PASS)
iterate over table (PASS)
iterate over table (PASS)
iterate over table (PASS)
@ -30,6 +31,11 @@ add element (PASS)
in operator (PASS)
add element (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)
!in operator (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
function test_case(msg: string, expect: bool)
@ -26,6 +26,9 @@ event bro_init()
local t10: table[port, string, bool] of string = {
[10/udp, "curly", F] = "first",
[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
@ -45,6 +48,7 @@ event bro_init()
test_case( "cardinality", |t8| == 0 );
test_case( "cardinality", |t9| == 1 );
test_case( "cardinality", |t10| == 2 );
test_case( "cardinality", |t11| == 1 );
test_case( "cardinality", |tg1| == 3 );
# Test iterating over each table
@ -121,6 +125,13 @@ event bro_init()
test_case( "add element", |t5| == 3 );
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
# from tables of multiple types)
@ -145,5 +156,8 @@ event bro_init()
test_case( "remove element", |t5| == 2 );
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 );
}