diff --git a/spicy/toolchain/src/compiler/visitors/normalizer.cc b/spicy/toolchain/src/compiler/visitors/normalizer.cc index be7d579f8..86af82d2f 100644 --- a/spicy/toolchain/src/compiler/visitors/normalizer.cc +++ b/spicy/toolchain/src/compiler/visitors/normalizer.cc @@ -252,6 +252,29 @@ struct Visitor : public hilti::visitor::PostOrder { return {}; } + void operator()(const operator_::unit::MemberConst& o, position_t p) { + auto unit = o.op0().type().tryAs(); + auto id = o.op1().tryAs()->id(); + + if ( unit && id && ! unit->itemByName(id) ) { + // See if we got an anonymous bitfield with a member of that + // name. If so, rewrite the access to transparently refer to the + // member through the field's internal name. + if ( auto field_id = findBitsFieldID(unit->items(), id) ) { + auto access_field = + operator_::unit::MemberConst::Operator().instantiate({o.op0(), + hilti::expression::Member(*field_id)}, + o.meta()); + auto access_bits = + bitfield::Member::Operator().instantiate({std::move(access_field), o.op1()}, o.meta()); + + logChange(p.node, access_bits); + p.node = access_bits; + modified = true; + } + } + } + void operator()(const operator_::unit::MemberNonConst& o, position_t p) { auto unit = o.op0().type().tryAs(); auto id = o.op1().tryAs()->id(); diff --git a/tests/Baseline/spicy.types.bitfield.anonymous-field-const/output b/tests/Baseline/spicy.types.bitfield.anonymous-field-const/output new file mode 100644 index 000000000..a117324d5 --- /dev/null +++ b/tests/Baseline/spicy.types.bitfield.anonymous-field-const/output @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +255 diff --git a/tests/spicy/types/bitfield/anonymous-field-const.spicy b/tests/spicy/types/bitfield/anonymous-field-const.spicy new file mode 100644 index 000000000..500712325 --- /dev/null +++ b/tests/spicy/types/bitfield/anonymous-field-const.spicy @@ -0,0 +1,19 @@ +# @TEST-EXEC: printf '\377' | spicy-driver %INPUT >output +# @TEST-EXEC: btest-diff output + +module foo; + +type X = unit { + : bitfield(8) { + a: 0..7; + }; +}; + +type Y = unit(x: X) { + on %init { print x.a; } +}; + +public type Z = unit { + x: X; + y: Y(self.x); +};