mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 02:28:21 +00:00
Allow named record constructors. Addresses #983.
This commit is contained in:
parent
d67123d0c3
commit
a0ad87b4c2
6 changed files with 105 additions and 7 deletions
41
src/Expr.cc
41
src/Expr.cc
|
@ -3320,12 +3320,20 @@ bool HasFieldExpr::DoUnserialize(UnserialInfo* info)
|
||||||
return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
|
return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list,
|
||||||
|
BroType* arg_type)
|
||||||
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
|
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
|
||||||
{
|
{
|
||||||
if ( IsError() )
|
if ( IsError() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ( arg_type && arg_type->Tag() != TYPE_RECORD )
|
||||||
|
{
|
||||||
|
Error("bad record constructor type", arg_type);
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Spin through the list, which should be comprised of
|
// Spin through the list, which should be comprised of
|
||||||
// either record's or record-field-assign, and build up a
|
// either record's or record-field-assign, and build up a
|
||||||
// record type to associate with this constructor.
|
// record type to associate with this constructor.
|
||||||
|
@ -3365,7 +3373,17 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetType(new RecordType(record_types));
|
ctor_type = new RecordType(record_types);
|
||||||
|
|
||||||
|
if ( arg_type )
|
||||||
|
SetType(arg_type->Ref());
|
||||||
|
else
|
||||||
|
SetType(ctor_type->Ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordConstructorExpr::~RecordConstructorExpr()
|
||||||
|
{
|
||||||
|
Unref(ctor_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||||
|
@ -3391,7 +3409,7 @@ Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||||
Val* RecordConstructorExpr::Fold(Val* v) const
|
Val* RecordConstructorExpr::Fold(Val* v) const
|
||||||
{
|
{
|
||||||
ListVal* lv = v->AsListVal();
|
ListVal* lv = v->AsListVal();
|
||||||
RecordType* rt = type->AsRecordType();
|
RecordType* rt = ctor_type->AsRecordType();
|
||||||
|
|
||||||
if ( lv->Length() != rt->NumFields() )
|
if ( lv->Length() != rt->NumFields() )
|
||||||
Internal("inconsistency evaluating record constructor");
|
Internal("inconsistency evaluating record constructor");
|
||||||
|
@ -3401,6 +3419,19 @@ Val* RecordConstructorExpr::Fold(Val* v) const
|
||||||
for ( int i = 0; i < lv->Length(); ++i )
|
for ( int i = 0; i < lv->Length(); ++i )
|
||||||
rv->Assign(i, lv->Index(i)->Ref());
|
rv->Assign(i, lv->Index(i)->Ref());
|
||||||
|
|
||||||
|
if ( ! same_type(rt, type) )
|
||||||
|
{
|
||||||
|
RecordVal* new_val = rv->CoerceTo(type->AsRecordType());
|
||||||
|
|
||||||
|
if ( new_val )
|
||||||
|
{
|
||||||
|
Unref(rv);
|
||||||
|
rv = new_val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Internal("record constructor coercion failed");
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3416,12 +3447,16 @@ IMPLEMENT_SERIAL(RecordConstructorExpr, SER_RECORD_CONSTRUCTOR_EXPR);
|
||||||
bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
|
bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
|
||||||
{
|
{
|
||||||
DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
|
DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
|
||||||
|
SERIALIZE_OPTIONAL(ctor_type);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
|
bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
|
||||||
{
|
{
|
||||||
DO_UNSERIALIZE(UnaryExpr);
|
DO_UNSERIALIZE(UnaryExpr);
|
||||||
|
BroType* t = 0;
|
||||||
|
UNSERIALIZE_OPTIONAL(t, RecordType::Unserialize(info));
|
||||||
|
ctor_type = t->AsRecordType();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/Expr.h
17
src/Expr.h
|
@ -57,6 +57,7 @@ extern const char* expr_name(BroExprTag t);
|
||||||
class Stmt;
|
class Stmt;
|
||||||
class Frame;
|
class Frame;
|
||||||
class ListExpr;
|
class ListExpr;
|
||||||
|
class NameExpr;
|
||||||
class CallExpr;
|
class CallExpr;
|
||||||
class EventExpr;
|
class EventExpr;
|
||||||
|
|
||||||
|
@ -165,6 +166,17 @@ public:
|
||||||
return (ListExpr*) this;
|
return (ListExpr*) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NameExpr* AsNameExpr() const
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name)
|
||||||
|
return (const NameExpr*) this;
|
||||||
|
}
|
||||||
|
NameExpr* AsNameExpr()
|
||||||
|
{
|
||||||
|
CHECK_TAG(tag, EXPR_NAME, "ExprVal::AsNameExpr", expr_name)
|
||||||
|
return (NameExpr*) this;
|
||||||
|
}
|
||||||
|
|
||||||
void Describe(ODesc* d) const;
|
void Describe(ODesc* d) const;
|
||||||
|
|
||||||
bool Serialize(SerialInfo* info) const;
|
bool Serialize(SerialInfo* info) const;
|
||||||
|
@ -729,7 +741,8 @@ protected:
|
||||||
|
|
||||||
class RecordConstructorExpr : public UnaryExpr {
|
class RecordConstructorExpr : public UnaryExpr {
|
||||||
public:
|
public:
|
||||||
RecordConstructorExpr(ListExpr* constructor_list);
|
RecordConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0);
|
||||||
|
~RecordConstructorExpr();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Expr;
|
friend class Expr;
|
||||||
|
@ -741,6 +754,8 @@ protected:
|
||||||
void ExprDescribe(ODesc* d) const;
|
void ExprDescribe(ODesc* d) const;
|
||||||
|
|
||||||
DECLARE_SERIAL(RecordConstructorExpr);
|
DECLARE_SERIAL(RecordConstructorExpr);
|
||||||
|
|
||||||
|
RecordType* ctor_type; // type inferred from the ctor expression list args
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableConstructorExpr : public UnaryExpr {
|
class TableConstructorExpr : public UnaryExpr {
|
||||||
|
|
|
@ -217,6 +217,11 @@ public:
|
||||||
return tag == TYPE_TABLE && (YieldType() == 0);
|
return tag == TYPE_TABLE && (YieldType() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IsTable() const
|
||||||
|
{
|
||||||
|
return tag == TYPE_TABLE && (YieldType() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
BroType* Ref() { ::Ref(this); return this; }
|
BroType* Ref() { ::Ref(this); return this; }
|
||||||
|
|
||||||
virtual void Describe(ODesc* d) const;
|
virtual void Describe(ODesc* d) const;
|
||||||
|
|
35
src/parse.y
35
src/parse.y
|
@ -522,10 +522,39 @@ expr:
|
||||||
$$ = new VectorConstructorExpr($3);
|
$$ = new VectorConstructorExpr($3);
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr '(' opt_expr_list ')'
|
| expr '('
|
||||||
{
|
{
|
||||||
set_location(@1, @4);
|
if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() )
|
||||||
$$ = new CallExpr($1, $3, in_hook > 0);
|
++in_init;
|
||||||
|
}
|
||||||
|
opt_expr_list
|
||||||
|
{
|
||||||
|
if ( $1->Tag() == EXPR_NAME && $1->Type()->IsTable() )
|
||||||
|
--in_init;
|
||||||
|
}
|
||||||
|
')'
|
||||||
|
{
|
||||||
|
set_location(@1, @6);
|
||||||
|
|
||||||
|
BroType* ctor_type = 0;
|
||||||
|
|
||||||
|
if ( $1->Tag() == EXPR_NAME &&
|
||||||
|
(ctor_type = $1->AsNameExpr()->Id()->AsType()) )
|
||||||
|
{
|
||||||
|
switch ( ctor_type->Tag() ) {
|
||||||
|
case TYPE_RECORD:
|
||||||
|
$$ = new RecordConstructorExpr($4, ctor_type);
|
||||||
|
break;
|
||||||
|
case TYPE_TABLE:
|
||||||
|
case TYPE_VECTOR:
|
||||||
|
default:
|
||||||
|
$1->Error("constructor type not implemented");
|
||||||
|
YYERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
$$ = new CallExpr($1, $4, in_hook > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_HOOK { ++in_hook; } expr
|
| TOK_HOOK { ++in_hook; } expr
|
||||||
|
|
2
testing/btest/Baseline/language.named-ctors/out
Normal file
2
testing/btest/Baseline/language.named-ctors/out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[min=<uninitialized>, max=2]
|
||||||
|
[min=7, max=42]
|
12
testing/btest/language/named-ctors.bro
Normal file
12
testing/btest/language/named-ctors.bro
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
type MyRec: record {
|
||||||
|
min: count &optional;
|
||||||
|
max: count;
|
||||||
|
};
|
||||||
|
|
||||||
|
local myrec: MyRec = MyRec($max=2);
|
||||||
|
print myrec;
|
||||||
|
myrec = MyRec($min=7, $max=42);
|
||||||
|
print myrec;
|
Loading…
Add table
Add a link
Reference in a new issue