Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow const fields in mutable structs #11

Open
Seelengrab opened this issue Jun 12, 2023 · 0 comments
Open

Allow const fields in mutable structs #11

Seelengrab opened this issue Jun 12, 2023 · 0 comments
Labels
feature New feature good first issue Good for newcomers

Comments

@Seelengrab
Copy link
Owner

Seelengrab commented Jun 12, 2023

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
@Seelengrab Seelengrab added good first issue Good for newcomers feature New feature labels Jun 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant