factor out record coercion; modernize management of coercion "map"

This commit is contained in:
Vern Paxson 2021-03-18 10:08:31 -07:00
parent 5f5ba3881c
commit 91c2e05099
3 changed files with 27 additions and 24 deletions

View file

@ -3759,8 +3759,7 @@ ValPtr ArithCoerceExpr::Fold(Val* v) const
} }
RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r) RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r)
: UnaryExpr(EXPR_RECORD_COERCE, std::move(arg_op)), : UnaryExpr(EXPR_RECORD_COERCE, std::move(arg_op))
map(nullptr), map_size(0)
{ {
if ( IsError() ) if ( IsError() )
return; return;
@ -3778,12 +3777,12 @@ RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r)
RecordType* t_r = type->AsRecordType(); RecordType* t_r = type->AsRecordType();
RecordType* sub_r = op->GetType()->AsRecordType(); RecordType* sub_r = op->GetType()->AsRecordType();
map_size = t_r->NumFields(); int map_size = t_r->NumFields();
map = new int[map_size]; map.reserve(map_size);
int i; int i;
for ( i = 0; i < map_size; ++i ) for ( i = 0; i < map_size; ++i )
map[i] = -1; // -1 = field is not mapped map.emplace_back(-1); // -1 = field is not mapped
for ( i = 0; i < sub_r->NumFields(); ++i ) for ( i = 0; i < sub_r->NumFields(); ++i )
{ {
@ -3865,11 +3864,6 @@ RecordCoerceExpr::RecordCoerceExpr(ExprPtr arg_op, RecordTypePtr r)
} }
} }
RecordCoerceExpr::~RecordCoerceExpr()
{
delete [] map;
}
ValPtr RecordCoerceExpr::InitVal(const zeek::Type* t, ValPtr aggr) const ValPtr RecordCoerceExpr::InitVal(const zeek::Type* t, ValPtr aggr) const
{ {
if ( auto v = Eval(nullptr) ) if ( auto v = Eval(nullptr) )
@ -3892,7 +3886,15 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const
if ( same_type(GetType(), Op()->GetType()) ) if ( same_type(GetType(), Op()->GetType()) )
return IntrusivePtr{NewRef{}, v}; return IntrusivePtr{NewRef{}, v};
auto val = make_intrusive<RecordVal>(GetType<RecordType>()); auto rt = cast_intrusive<RecordType>(GetType());
return coerce_to_record(rt, v, map);
}
RecordValPtr coerce_to_record(RecordTypePtr rt, Val* v,
const std::vector<int>& map)
{
auto map_size = map.size();
auto val = make_intrusive<RecordVal>(rt);
RecordType* val_type = val->GetType()->AsRecordType(); RecordType* val_type = val->GetType()->AsRecordType();
RecordVal* rv = v->AsRecordVal(); RecordVal* rv = v->AsRecordVal();
@ -3905,14 +3907,15 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const
if ( ! rhs ) if ( ! rhs )
{ {
const auto& def = rv->GetType()->AsRecordType()->FieldDecl( auto rv_rt = rv->GetType()->AsRecordType();
map[i])->GetAttr(ATTR_DEFAULT); const auto& def = rv_rt->FieldDecl(map[i])->
GetAttr(ATTR_DEFAULT);
if ( def ) if ( def )
rhs = def->GetExpr()->Eval(nullptr); rhs = def->GetExpr()->Eval(nullptr);
} }
assert(rhs || GetType()->AsRecordType()->FieldDecl(i)->GetAttr(ATTR_OPTIONAL)); assert(rhs || rt->FieldDecl(i)->GetAttr(ATTR_OPTIONAL));
if ( ! rhs ) if ( ! rhs )
{ {
@ -3934,21 +3937,19 @@ ValPtr RecordCoerceExpr::Fold(Val* v) const
else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) && else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) &&
! same_type(rhs_type, field_type) ) ! same_type(rhs_type, field_type) )
{ {
if ( auto new_val = check_and_promote(rhs, field_type.get(), false, op->GetLocationInfo()) ) auto new_val = check_and_promote(rhs, field_type.get(), false);
rhs = std::move(new_val); rhs = std::move(new_val);
else
RuntimeError("Failed type conversion");
} }
val->Assign(i, std::move(rhs)); val->Assign(i, std::move(rhs));
} }
else else
{ {
if ( const auto& def = GetType()->AsRecordType()->FieldDecl(i)->GetAttr(ATTR_DEFAULT) ) if ( const auto& def = rt->FieldDecl(i)->GetAttr(ATTR_DEFAULT) )
{ {
auto def_val = def->GetExpr()->Eval(nullptr); auto def_val = def->GetExpr()->Eval(nullptr);
const auto& def_type = def_val->GetType(); const auto& def_type = def_val->GetType();
const auto& field_type = GetType()->AsRecordType()->GetFieldType(i); const auto& field_type = rt->GetFieldType(i);
if ( def_type->Tag() == TYPE_RECORD && if ( def_type->Tag() == TYPE_RECORD &&
field_type->Tag() == TYPE_RECORD && field_type->Tag() == TYPE_RECORD &&

View file

@ -1170,21 +1170,24 @@ protected:
class RecordCoerceExpr final : public UnaryExpr { class RecordCoerceExpr final : public UnaryExpr {
public: public:
RecordCoerceExpr(ExprPtr op, RecordTypePtr r); RecordCoerceExpr(ExprPtr op, RecordTypePtr r);
~RecordCoerceExpr() override;
// Optimization-related: // Optimization-related:
ExprPtr Duplicate() override; ExprPtr Duplicate() override;
const std::vector<int>& Map() const { return map; }
protected: protected:
ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override; ValPtr InitVal(const zeek::Type* t, ValPtr aggr) const override;
ValPtr Fold(Val* v) const override; ValPtr Fold(Val* v) const override;
// For each super-record slot, gives subrecord slot with which to // For each super-record slot, gives subrecord slot with which to
// fill it. // fill it.
int* map; std::vector<int> map;
int map_size; // equivalent to Type()->AsRecordType()->NumFields()
}; };
extern RecordValPtr coerce_to_record(RecordTypePtr rt, Val* v,
const std::vector<int>& map);
class TableCoerceExpr final : public UnaryExpr { class TableCoerceExpr final : public UnaryExpr {
public: public:
TableCoerceExpr(ExprPtr op, TableTypePtr r); TableCoerceExpr(ExprPtr op, TableTypePtr r);

View file

@ -1,6 +1,5 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
error in int and ./first_set.zeek, line 46: overflow promoting from unsigned/double to signed arithmetic value (int and 9223372036854775808) error in int and ./first_set.zeek, line 46: overflow promoting from unsigned/double to signed arithmetic value (int and 9223372036854775808)
expression error in ./first_set.zeek, line 46: Failed type conversion ((coerce [$ii=9223372036854775808] to record { ii:int &optional; cc:count &optional; dd:double &optional; }))
3 3
int int
4 4