Skip to content

Allow const fields in mutable structs #11

Open
@Seelengrab

Description

@Seelengrab

Currently, const-per-field annotations are not allowed by the interface, but it would be nice to support this.

The way this would be implemented is by allowing the annotation through here:

for ex in expr.args[3].args
!(ex isa Expr) && continue
(ex.head == :call
&& length(ex.args) == 3
&& first(ex.args) === :(:)) || continue # only Intx bitfields supported right now
fieldname = ex.args[2]
fieldname isa Symbol || throw(ArgumentError("Name of field is not a symbol: `$fieldname`"))
fieldsize = ex.args[3]
fieldsize isa Integer || throw(ArgumentError("Declared size of field `$fieldname` is not an integer literal!"))
numbits += fieldsize
push!(fields, fieldname => fieldsize)
end

as well as simply not generating the various setindex! branches here:

# only build the expression if we actually need to
if mutable
push!(setpropexpr.args, :(s === $(QuoteNode(fieldname))))
ifbody = :(
offsetshift = cast_extend_truncate($Ti, propertyoffset($T, s));
shifted = Core.Intrinsics.shl_int(val, offsetshift);
mask = Core.Intrinsics.not_int(Core.Intrinsics.shl_int(maskbase, fieldsize($T, s)));
mask = Core.Intrinsics.not_int(Core.Intrinsics.shl_int(mask, propertyoffset($T, s)));
cleareddata = Core.Intrinsics.and_int(getfield(x, :fields), mask);
newdata = Core.Intrinsics.or_int(cleareddata, shifted);
setfield!(x, :fields, newdata);
return maskeddata;
)
push!(setpropexpr.args, ifbody)
nsetprop = Expr(:elseif)
push!(setpropexpr.args, nsetprop)
setpropexpr = nsetprop
end

Annotating a field with const currently doesn't error, but the field is ignored entirely, so adding this shouldn't break anything:

julia> @bitfield mutable struct Foo
           const a:2
           b:3
       end

julia> methods(Foo)
# 3 methods for type constructor:
 [1] Foo()
     @ none:0
 [2] Foo(t::Foo_fields)
     @ none:0
 [3] Foo(b::Union{Bool, Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8})
     @ none:0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions