# Generate a polymorphic attribute write
fun write_attribute(a: MAttribute, recv: RuntimeVariable, value: RuntimeVariable) is abstract
src/compiler/abstract_compiler.nit:1539,2--1540,94
redef fun write_attribute(a, recv, value)
do
self.check_recv_notnull(recv)
# What is the declared type of the attribute?
var mtype = a.intro.static_mtype.as(not null)
var intromclassdef = a.intro.mclassdef
mtype = mtype.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true)
# Adapt the value to the declared type
value = self.autobox(value, mtype)
self.require_declaration(a.const_color)
if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
var attr = "{recv}->attrs[{a.const_color}]"
if mtype.is_tagged then
# The attribute is not primitive, thus store it as tagged
var tv = autobox(value, compiler.mainmodule.object_type)
self.add("{attr} = {tv}; /* {a} on {recv.inspect} */")
else if mtype.is_c_primitive then
assert mtype isa MClassType
# The attribute is primitive, thus we store it in a box
# The trick is to create the box the first time then resuse the box
self.add("if ({attr} != NULL) \{")
self.add("((struct instance_{mtype.c_name}*){attr})->value = {value}; /* {a} on {recv.inspect} */")
self.add("\} else \{")
value = self.autobox(value, self.object_type.as_nullable)
self.add("{attr} = {value}; /* {a} on {recv.inspect} */")
self.add("\}")
else
# The attribute is not primitive, thus store it direclty
self.add("{attr} = {value}; /* {a} on {recv.inspect} */")
end
else
self.add("{recv}->attrs[{a.const_color}].{mtype.ctypename} = {value}; /* {a} on {recv.inspect} */")
end
end
src/compiler/separate_compiler.nit:1777,2--1813,4
redef fun write_attribute(a, recv, value)
do
check_recv_notnull(recv)
var types = self.collect_types(recv)
if types.is_empty then
self.add("/*BUG: no live types for {recv.inspect} . {a}*/")
self.bugtype(recv)
return
end
self.add("/* write {a} on {recv.inspect} */")
self.add("switch({recv}->classid) \{")
var last = types.last
for t in types do
if not self.compiler.hardening and t == last then
self.add("default: /*{self.compiler.classid(t)}*/")
else
self.add("case {self.compiler.classid(t)}:")
end
var recv2 = self.autoadapt(recv, t)
var ta = a.intro.static_mtype.as(not null)
ta = self.resolve_for(ta, recv2)
self.add("((struct {t.c_name}*){recv})->{a.intro.c_name} = {self.autobox(value, ta)};")
self.add("break;")
end
if self.compiler.hardening then
self.add("default: /* Bug*/")
self.bugtype(recv)
end
self.add("\}")
end
src/compiler/global_compiler.nit:827,2--858,4