Allow named table constructors. Addresses #983.

This commit is contained in:
Jon Siwek 2013-05-30 10:21:15 -05:00
parent 29740d3d6e
commit bcf5c41786
5 changed files with 117 additions and 14 deletions

View file

@ -3461,12 +3461,25 @@ bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
} }
TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
attr_list* arg_attrs) attr_list* arg_attrs, BroType* arg_type)
: UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list) : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list)
{ {
if ( IsError() ) if ( IsError() )
return; return;
if ( arg_type )
{
if ( ! arg_type->IsTable() )
{
Error("bad table constructor type", arg_type);
SetError();
return;
}
SetType(arg_type->Ref());
}
else
{
if ( constructor_list->Exprs().length() == 0 ) if ( constructor_list->Exprs().length() == 0 )
SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0)); SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0));
else else
@ -3480,8 +3493,43 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
type->AsTableType()->IsSet() ) type->AsTableType()->IsSet() )
SetError("values in table(...) constructor do not specify a table"); SetError("values in table(...) constructor do not specify a table");
} }
}
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
type_list* indices = type->AsTableType()->Indices()->Types();
expr_list& cle = constructor_list->Exprs();
// check and promote all index expressions in ctor list
loop_over_list(cle, i)
{
if ( cle[i]->Tag() != EXPR_ASSIGN )
continue;
Expr* idx_expr = cle[i]->AsAssignExpr()->Op1();
if ( idx_expr->Tag() != EXPR_LIST )
continue;
expr_list& idx_exprs = idx_expr->AsListExpr()->Exprs();
if ( idx_exprs.length() != indices->length() )
continue;
loop_over_list(idx_exprs, j)
{
Expr* idx = idx_exprs[j];
if ( check_and_promote_expr(idx, (*indices)[j]) )
{
if ( idx != idx_exprs[j] )
idx_exprs.replace(j, idx);
continue;
}
ExprError("inconsistent types in table constructor");
}
}
} }
Val* TableConstructorExpr::Eval(Frame* f) const Val* TableConstructorExpr::Eval(Frame* f) const

View file

@ -58,6 +58,7 @@ class Stmt;
class Frame; class Frame;
class ListExpr; class ListExpr;
class NameExpr; class NameExpr;
class AssignExpr;
class CallExpr; class CallExpr;
class EventExpr; class EventExpr;
@ -177,6 +178,17 @@ public:
return (NameExpr*) this; return (NameExpr*) this;
} }
const AssignExpr* AsAssignExpr() const
{
CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name)
return (const AssignExpr*) this;
}
AssignExpr* AsAssignExpr()
{
CHECK_TAG(tag, EXPR_ASSIGN, "ExprVal::AsAssignExpr", expr_name)
return (AssignExpr*) this;
}
void Describe(ODesc* d) const; void Describe(ODesc* d) const;
bool Serialize(SerialInfo* info) const; bool Serialize(SerialInfo* info) const;
@ -760,7 +772,8 @@ protected:
class TableConstructorExpr : public UnaryExpr { class TableConstructorExpr : public UnaryExpr {
public: public:
TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs); TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs,
BroType* arg_type = 0);
~TableConstructorExpr() { Unref(attrs); } ~TableConstructorExpr() { Unref(attrs); }
Attributes* Attrs() { return attrs; } Attributes* Attrs() { return attrs; }

View file

@ -545,16 +545,15 @@ expr:
case TYPE_RECORD: case TYPE_RECORD:
$$ = new RecordConstructorExpr($4, ctor_type); $$ = new RecordConstructorExpr($4, ctor_type);
break; break;
case TYPE_TABLE: case TYPE_TABLE:
if ( ctor_type->IsTable() ) if ( ctor_type->IsTable() )
{ $$ = new TableConstructorExpr($4, 0, ctor_type);
$1->Error("constructor type not implemented");
YYERROR;
}
else else
$$ = new SetConstructorExpr($4, 0, ctor_type); $$ = new SetConstructorExpr($4, 0, ctor_type);
break; break;
case TYPE_VECTOR: case TYPE_VECTOR:
default: default:
$1->Error("constructor type not implemented"); $1->Error("constructor type not implemented");

View file

@ -0,0 +1,19 @@
{
[1] = one,
[5] = five,
[3] = three
}
{
[[min=<uninitialized>, max=5]] = max5,
[[min=<uninitialized>, max=2]] = max2
}
{
[test, 1] = test1,
[cool, 2] = cool2
}
{
[two] = 2.0,
[one] = 1.0,
[three] = 3.0
}
0

View file

@ -0,0 +1,24 @@
# @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: btest-diff out
type MyRec: record {
min: count &optional;
max: count;
};
type FooTable: table[count] of string;
type FooTableRec: table[MyRec] of string;
type FooTableComp: table[string, count] of string;
type FooTableY: table[string] of double;
global mytable: FooTable = FooTable([1] = "one", [5] = "five", [3] = "three");
global mytablerec: FooTableRec = FooTableRec([[$max=5]] = "max5", [[$max=2]] = "max2");
global mytablecomp: FooTableComp = FooTableComp(["test", 1] = "test1", ["cool",
2] = "cool2");
global mytabley: FooTableY = FooTableY(["one"] = 1, ["two"] = 2, ["three"] = 3) &default=0;
print mytable;
print mytablerec;
print mytablecomp;
print mytabley;
print mytabley["test"];