mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
directly construct records of known types, rather than requiring coercion
This commit is contained in:
parent
d165db6909
commit
9a429808ab
6 changed files with 81 additions and 12 deletions
59
src/Expr.cc
59
src/Expr.cc
|
@ -3218,12 +3218,16 @@ void HasFieldExpr::ExprDescribe(ODesc* d) const
|
|||
d->Add(field);
|
||||
}
|
||||
|
||||
|
||||
RecordConstructorExpr::RecordConstructorExpr(ListExprPtr constructor_list)
|
||||
: Expr(EXPR_RECORD_CONSTRUCTOR), op(std::move(constructor_list))
|
||||
: Expr(EXPR_RECORD_CONSTRUCTOR)
|
||||
{
|
||||
if ( IsError() )
|
||||
return;
|
||||
|
||||
map = std::nullopt;
|
||||
op = std::move(constructor_list);
|
||||
|
||||
// Spin through the list, which should be comprised only of
|
||||
// record-field-assign expressions, and build up a
|
||||
// record type to associate with this constructor.
|
||||
|
@ -3248,8 +3252,46 @@ RecordConstructorExpr::RecordConstructorExpr(ListExprPtr constructor_list)
|
|||
SetType(make_intrusive<RecordType>(record_types));
|
||||
}
|
||||
|
||||
RecordConstructorExpr::~RecordConstructorExpr()
|
||||
RecordConstructorExpr::RecordConstructorExpr(RecordTypePtr known_rt,
|
||||
ListExprPtr constructor_list)
|
||||
: Expr(EXPR_RECORD_CONSTRUCTOR)
|
||||
{
|
||||
if ( IsError() )
|
||||
return;
|
||||
|
||||
SetType(known_rt);
|
||||
op = std::move(constructor_list);
|
||||
|
||||
const auto& exprs = op->AsListExpr()->Exprs();
|
||||
map = std::vector<int>(exprs.length());
|
||||
|
||||
int i = 0;
|
||||
for ( const auto& e : exprs )
|
||||
{
|
||||
if ( e->Tag() != EXPR_FIELD_ASSIGN )
|
||||
{
|
||||
Error("bad type in record constructor", e);
|
||||
SetError();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto field = e->AsFieldAssignExpr();
|
||||
int index = known_rt->FieldOffset(field->FieldName());
|
||||
|
||||
if ( index < 0 )
|
||||
{
|
||||
Error("no such field in record", e);
|
||||
SetError();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto known_ft = known_rt->GetFieldType(index);
|
||||
|
||||
if ( ! field->PromoteTo(known_ft) )
|
||||
SetError();
|
||||
|
||||
(*map)[i++] = index;
|
||||
}
|
||||
}
|
||||
|
||||
ValPtr RecordConstructorExpr::InitVal(const zeek::Type* t, ValPtr aggr) const
|
||||
|
@ -3289,13 +3331,16 @@ ValPtr RecordConstructorExpr::Eval(Frame* f) const
|
|||
const auto& exprs = op->Exprs();
|
||||
auto rt = cast_intrusive<RecordType>(type);
|
||||
|
||||
if ( exprs.length() != rt->NumFields() )
|
||||
if ( ! map && exprs.length() != rt->NumFields() )
|
||||
RuntimeErrorWithCallStack("inconsistency evaluating record constructor");
|
||||
|
||||
auto rv = make_intrusive<RecordVal>(std::move(rt));
|
||||
|
||||
for ( int i = 0; i < exprs.length(); ++i )
|
||||
rv->Assign(i, exprs[i]->Eval(f));
|
||||
{
|
||||
int ind = map ? (*map)[i] : i;
|
||||
rv->Assign(ind, exprs[i]->Eval(f));
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -3697,6 +3742,12 @@ FieldAssignExpr::FieldAssignExpr(const char* arg_field_name, ExprPtr value)
|
|||
SetType(op->GetType());
|
||||
}
|
||||
|
||||
bool FieldAssignExpr::PromoteTo(TypePtr t)
|
||||
{
|
||||
op = check_and_promote_expr(op.get(), t.get());
|
||||
return op != nullptr;
|
||||
}
|
||||
|
||||
void FieldAssignExpr::EvalIntoAggregate(const zeek::Type* t, Val* aggr, Frame* f)
|
||||
const
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue