# Generate a polymorphic attribute read
fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable is abstract
src/compiler/abstract_compiler.nit:1536,2--1537,86
redef fun read_attribute(a, recv)
do
self.check_recv_notnull(recv)
# What is the declared type of the attribute?
var ret = a.intro.static_mtype.as(not null)
var intromclassdef = a.intro.mclassdef
ret = ret.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true)
if self.compiler.modelbuilder.toolcontext.opt_isset_checks_metrics.value then
self.compiler.attr_read_count += 1
self.add("count_attr_reads++;")
end
self.require_declaration(a.const_color)
if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
# Get the attribute or a box (ie. always a val*)
var cret = self.object_type.as_nullable
var res = self.new_var(cret)
res.mcasttype = ret
self.add("{res} = {recv}->attrs[{a.const_color}]; /* {a} on {recv.inspect} */")
# Check for Uninitialized attribute
if not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
self.add("if (unlikely({res} == NULL)) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
if self.compiler.modelbuilder.toolcontext.opt_isset_checks_metrics.value then
self.compiler.isset_checks_count += 1
self.add("count_isset_checks++;")
end
end
# Return the attribute or its unboxed version
# Note: it is mandatory since we reuse the box on write, we do not whant that the box escapes
return self.autobox(res, ret)
else
var res = self.new_var(ret)
self.add("{res} = {recv}->attrs[{a.const_color}].{ret.ctypename}; /* {a} on {recv.inspect} */")
# Check for Uninitialized attribute
if not ret.is_c_primitive and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
self.add("if (unlikely({res} == NULL)) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
if self.compiler.modelbuilder.toolcontext.opt_isset_checks_metrics.value then
self.compiler.isset_checks_count += 1
self.add("count_isset_checks++;")
end
end
return res
end
end
src/compiler/separate_compiler.nit:1720,2--1775,4
redef fun read_attribute(a, recv)
do
check_recv_notnull(recv)
var types = self.collect_types(recv)
var ret = a.intro.static_mtype.as(not null)
ret = self.resolve_for(ret, recv)
var res = self.new_var(ret)
if types.is_empty then
self.add("/*BUG: no live types for {recv.inspect} . {a}*/")
self.bugtype(recv)
return res
end
self.add("/* read {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)
var res2 = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
if not ta.is_c_primitive then
self.add("if ({res2} == NULL) \{")
self.add_abort("Uninitialized attribute {a.name}")
self.add("\}")
else
self.add("/*NOTYET isset on primitive attributes*/")
end
end
self.assign(res, res2)
self.add("break;")
end
if self.compiler.hardening then
self.add("default: /* Bug */")
self.bugtype(recv)
end
self.add("\}")
return res
end
src/compiler/global_compiler.nit:778,2--825,4