Fixing attributes to allow &default in tables/sets to be associated

with the field.

This works now:

    type X: record {
        a: table[string] of bool &default=table( ["foo"] = T );
        b: table[string] of bool &default=table();
        c: set[string] &default=set("A", "B", "C");
        d: set[string] &default=set();
    };

I think previously the intend was to associate &default with the
table/set (i.e., define the default value for non-existing indices).
However, that was already not working: the error checking was
reporting type mismatches. So, this shouldn't break anything and make
things more consistent.
This commit is contained in:
Robin Sommer 2011-04-05 16:17:12 -07:00
parent 68a30a0b5a
commit 0a97a9e82a
10 changed files with 72 additions and 24 deletions

View file

@ -57,10 +57,11 @@ void Attr::AddTag(ODesc* d) const
d->Add(attr_name(Tag())); d->Add(attr_name(Tag()));
} }
Attributes::Attributes(attr_list* a, BroType* t) Attributes::Attributes(attr_list* a, BroType* t, bool arg_in_record)
{ {
attrs = new attr_list(a->length()); attrs = new attr_list(a->length());
type = t->Ref(); type = t->Ref();
in_record = arg_in_record;
SetLocationInfo(&start_location, &end_location); SetLocationInfo(&start_location, &end_location);
@ -199,7 +200,7 @@ void Attributes::CheckAttr(Attr* a)
{ {
BroType* atype = a->AttrExpr()->Type(); BroType* atype = a->AttrExpr()->Type();
if ( type->Tag() != TYPE_TABLE || type->IsSet() ) if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
{ {
if ( ! same_type(atype, type) ) if ( ! same_type(atype, type) )
a->AttrExpr()->Error("&default value has inconsistent type", type); a->AttrExpr()->Error("&default value has inconsistent type", type);
@ -208,18 +209,30 @@ void Attributes::CheckAttr(Attr* a)
TableType* tt = type->AsTableType(); TableType* tt = type->AsTableType();
if ( ! same_type(atype, tt->YieldType()) ) if ( ! in_record )
{ {
// It can still be a default function. // &default applies to the type itself.
if ( atype->Tag() == TYPE_FUNC ) if ( ! same_type(atype, tt->YieldType()) )
{ {
FuncType* f = atype->AsFuncType(); // It can still be a default function.
if ( ! f->CheckArgs(tt->IndexTypes()) || if ( atype->Tag() == TYPE_FUNC )
! same_type(f->YieldType(), tt->YieldType()) ) {
Error("&default function type clash"); FuncType* f = atype->AsFuncType();
if ( ! f->CheckArgs(tt->IndexTypes()) ||
! same_type(f->YieldType(), tt->YieldType()) )
Error("&default function type clash");
}
else
Error("&default value has inconsistent type");
} }
else }
Error("&default value has inconsistent type"); else
{
// &default applies to record field.
if ( ! same_type(atype, type) &&
! (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
Error("&default value has inconsistent type");
break;
} }
} }
break; break;

View file

@ -62,7 +62,7 @@ protected:
// Manages a collection of attributes. // Manages a collection of attributes.
class Attributes : public BroObj { class Attributes : public BroObj {
public: public:
Attributes(attr_list* a, BroType* t); Attributes(attr_list* a, BroType* t, bool in_record);
~Attributes(); ~Attributes();
void AddAttr(Attr* a); void AddAttr(Attr* a);
@ -87,6 +87,7 @@ protected:
BroType* type; BroType* type;
attr_list* attrs; attr_list* attrs;
bool in_record;
}; };
#endif #endif

View file

@ -3400,7 +3400,7 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
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) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
} }
Val* TableConstructorExpr::Eval(Frame* f) const Val* TableConstructorExpr::Eval(Frame* f) const
@ -3466,7 +3466,7 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() ) else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() )
SetError("values in set(...) constructor do not specify a set"); SetError("values in set(...) constructor do not specify a set");
attrs = arg_attrs ? new Attributes(arg_attrs, type) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
} }
Val* SetConstructorExpr::Eval(Frame* f) const Val* SetConstructorExpr::Eval(Frame* f) const

View file

@ -935,7 +935,7 @@ void NotifierRegistry::Register(ID* id, NotifierRegistry::Notifier* notifier)
attr_list* a = new attr_list; attr_list* a = new attr_list;
Attr* attr = new Attr(ATTR_TRACKED); Attr* attr = new Attr(ATTR_TRACKED);
a->append(attr); a->append(attr);
id->SetAttrs(new Attributes(a, id->Type())); id->SetAttrs(new Attributes(a, id->Type(), false));
Unref(attr); Unref(attr);
} }

View file

@ -680,10 +680,10 @@ bool FuncType::DoUnserialize(UnserialInfo* info)
return UNSERIALIZE(&is_event); return UNSERIALIZE(&is_event);
} }
TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs) TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs, bool in_record)
{ {
type = t; type = t;
attrs = arg_attrs ? new Attributes(arg_attrs, t) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, t, in_record) : 0;
id = i; id = i;
} }

View file

@ -361,7 +361,7 @@ protected:
class TypeDecl { class TypeDecl {
public: public:
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0); TypeDecl(BroType* t, const char* i, attr_list* attrs = 0, bool in_record = false);
~TypeDecl(); ~TypeDecl();
const Attr* FindAttr(attr_tag a) const const Attr* FindAttr(attr_tag a) const

View file

@ -107,7 +107,7 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
id->SetType(t); id->SetType(t);
if ( attr ) if ( attr )
id->AddAttrs(new Attributes(attr, t)); id->AddAttrs(new Attributes(attr, t, false));
if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) ) if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) )
{ {
@ -221,7 +221,7 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */)
id->MakeType(); id->MakeType();
if ( attr ) if ( attr )
id->SetAttrs(new Attributes(attr, t)); id->SetAttrs(new Attributes(attr, t, false));
} }
void begin_func(ID* id, const char* module_name, function_flavor flavor, void begin_func(ID* id, const char* module_name, function_flavor flavor,

View file

@ -100,6 +100,7 @@ extern Expr* g_curr_debug_expr;
Expr* bro_this = 0; Expr* bro_this = 0;
int in_init = 0; int in_init = 0;
int in_record = 0;
bool in_debug = false; bool in_debug = false;
bool resolving_global_ID = false; bool resolving_global_ID = false;
@ -704,10 +705,10 @@ type:
$$ = new SetType($3, 0); $$ = new SetType($3, 0);
} }
| TOK_RECORD '{' type_decl_list '}' | TOK_RECORD '{' { ++in_record; } type_decl_list { --in_record; } '}'
{ {
set_location(@1, @4); set_location(@1, @5);
$$ = new RecordType($3); $$ = new RecordType($4);
} }
| TOK_UNION '{' type_list '}' | TOK_UNION '{' type_list '}'
@ -805,7 +806,7 @@ type_decl:
TOK_ID ':' type opt_attr ';' TOK_ID ':' type opt_attr ';'
{ {
set_location(@1, @5); set_location(@1, @5);
$$ = new TypeDecl($3, $1, $4); $$ = new TypeDecl($3, $1, $4, (in_record > 0));
} }
; ;

View file

@ -0,0 +1,14 @@
{
[foo] = T
}
{
}
{
A,
B,
C
}
{
}

View file

@ -0,0 +1,19 @@
# @TEST-EXEC: bro %INPUT >output 2>&1
# @TEST-EXEC: btest-diff output
type X: record {
a: table[string] of bool &default=table( ["foo"] = T );
b: table[string] of bool &default=table();
c: set[string] &default=set("A", "B", "C");
d: set[string] &default=set();
};
global x: X;
global y: table[string] of bool &default=T;
print x$a;
print x$b;
print x$c;
print x$d;