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()));
}
Attributes::Attributes(attr_list* a, BroType* t)
Attributes::Attributes(attr_list* a, BroType* t, bool arg_in_record)
{
attrs = new attr_list(a->length());
type = t->Ref();
in_record = arg_in_record;
SetLocationInfo(&start_location, &end_location);
@ -199,7 +200,7 @@ void Attributes::CheckAttr(Attr* a)
{
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) )
a->AttrExpr()->Error("&default value has inconsistent type", type);
@ -208,18 +209,30 @@ void Attributes::CheckAttr(Attr* a)
TableType* tt = type->AsTableType();
if ( ! same_type(atype, tt->YieldType()) )
if ( ! in_record )
{
// It can still be a default function.
if ( atype->Tag() == TYPE_FUNC )
// &default applies to the type itself.
if ( ! same_type(atype, tt->YieldType()) )
{
FuncType* f = atype->AsFuncType();
if ( ! f->CheckArgs(tt->IndexTypes()) ||
! same_type(f->YieldType(), tt->YieldType()) )
Error("&default function type clash");
// It can still be a default function.
if ( atype->Tag() == TYPE_FUNC )
{
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;

View file

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

View file

@ -3400,7 +3400,7 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
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
@ -3466,7 +3466,7 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() )
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

View file

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

View file

@ -680,10 +680,10 @@ bool FuncType::DoUnserialize(UnserialInfo* info)
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;
attrs = arg_attrs ? new Attributes(arg_attrs, t) : 0;
attrs = arg_attrs ? new Attributes(arg_attrs, t, in_record) : 0;
id = i;
}

View file

@ -361,7 +361,7 @@ protected:
class TypeDecl {
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();
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);
if ( attr )
id->AddAttrs(new Attributes(attr, t));
id->AddAttrs(new Attributes(attr, t, false));
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();
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,

View file

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