Implementing += operator for record types.

This is per #375.

Record types can now get additional fields later via '+='. The added
fields must however either be &optional or have a &default value.

Example:

    type Foo: record {
        a: count;
        b: count &optional;
    };

    redef record Foo += {
        c: count &default=42;
        d: count &optional;
    };

    global f: Foo = [$a=21];

    print f;

Output:

    [a=21, b=<uninitialized>, c=42, d=<uninitialized>]
This commit is contained in:
Robin Sommer 2011-02-07 16:04:32 -08:00
parent cdb20e61b7
commit 95069f0993
3 changed files with 44 additions and 2 deletions

View file

@ -898,6 +898,26 @@ void RecordType::Describe(ODesc* d) const
} }
} }
const char* RecordType::AddFields(type_decl_list* others)
{
assert(types);
loop_over_list(*others, i)
{
TypeDecl* td = (*others)[i];
if ( ! td->FindAttr(ATTR_DEFAULT) && ! td->FindAttr(ATTR_OPTIONAL) )
return "extension field must be &optional or have &default";
types->append(td);
}
delete others;
num_fields = types->length();
return 0;
}
void RecordType::DescribeFields(ODesc* d) const void RecordType::DescribeFields(ODesc* d) const
{ {
if ( d->IsReadable() ) if ( d->IsReadable() )

View file

@ -409,6 +409,10 @@ public:
int NumFields() const { return num_fields; } int NumFields() const { return num_fields; }
// Returns 0 if all is ok, otherwise a pointer to an error message. Takes
// ownership of list.
const char* AddFields(type_decl_list* types);
void Describe(ODesc* d) const; void Describe(ODesc* d) const;
void DescribeFields(ODesc* d) const; void DescribeFields(ODesc* d) const;

View file

@ -815,6 +815,24 @@ decl:
} }
} }
| TOK_REDEF TOK_RECORD global_id TOK_ADD_TO
'{' type_decl_list '}' ';'
{
if ( ! $3->Type() )
$3->Error("unknown identifier");
else
{
RecordType* add_to = $3->Type()->AsRecordType();
if ( ! add_to )
$3->Error("not a record type");
else {
const char* error = add_to->AddFields($6);
if ( error )
$3->Error(error);
}
}
}
| TOK_TYPE global_id ':' refined_type opt_attr ';' | TOK_TYPE global_id ':' refined_type opt_attr ';'
{ {
add_type($2, $4, $5, 0); add_type($2, $4, $5, 0);