for t in runtime_type_analysis.live_types do
if t.ctype == "val*" then
compiler.generate_init_instance(t)
+ compiler.generate_check_init_instance(t)
else
compiler.generate_box_instance(t)
end
end
v.add("{res}->classid = {self.classid(mtype)};")
+ self.generate_init_attr(v, res, mtype)
+ v.add("return {res};")
+ v.add("\}")
+ end
+
+ fun generate_check_init_instance(mtype: MClassType)
+ do
+ if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return
+
+ var v = self.new_visitor
+ var res = new RuntimeVariable("self", mtype, mtype)
+ self.header.add_decl("void CHECK_NEW_{mtype.c_name}({mtype.ctype});")
+ v.add_decl("/* allocate {mtype} */")
+ v.add_decl("void CHECK_NEW_{mtype.c_name}({mtype.ctype} {res}) \{")
+ self.generate_check_attr(v, res, mtype)
+ v.add("\}")
+ end
+
+ # Generate code that collect initialize the attributes on a new instance
+ fun generate_init_attr(v: GlobalCompilerVisitor, recv: RuntimeVariable, mtype: MClassType)
+ do
for cd in mtype.collect_mclassdefs(self.mainmodule)
do
var n = self.modelbuilder.mclassdef2nclassdef[cd]
for npropdef in n.n_propdefs do
if npropdef isa AAttrPropdef then
- npropdef.init_expr(v, res)
+ npropdef.init_expr(v, recv)
+ end
+ end
+ end
+ end
+
+ # Generate a check-init-instance
+ fun generate_check_attr(v: GlobalCompilerVisitor, recv: RuntimeVariable, mtype: MClassType)
+ do
+ for cd in mtype.collect_mclassdefs(self.mainmodule)
+ do
+ var n = self.modelbuilder.mclassdef2nclassdef[cd]
+ for npropdef in n.n_propdefs do
+ if npropdef isa AAttrPropdef then
+ npropdef.check_expr(v, recv)
end
end
end
- v.add("return {res};")
- v.add("\}")
end
fun generate_box_instance(mtype: MClassType)
end
end
-redef class MParameterType
- redef fun c_name
- do
- var res = self.c_name_cache
- if res != null then return res
- res = "FT{self.rank}"
- self.c_name_cache = res
- return res
- end
-end
-
-redef class MNullableType
- redef fun c_name
- do
- var res = self.c_name_cache
- if res != null then return res
- res = "nullable_{self.mtype.c_name}"
- self.c_name_cache = res
- return res
- end
-end
-
# A C function associated to a Nit method
# Because of customization, a given Nit method can be compiler more that once
abstract class AbstractRuntimeFunction
# ENSURE: result.mtype.ctype == mtype.ctype
fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable
do
- if value.mtype.ctype == mtype.ctype then
+ if value.mtype == mtype then
+ return value
+ else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
return value
else if value.mtype.ctype == "val*" then
return self.new_expr("((struct {mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
value2 = tmp
end
if value1.mtype.ctype != "val*" then
- if value2.mtype.ctype == value1.mtype.ctype then
+ if value2.mtype == value1.mtype then
self.add("{res} = {value1} == {value2};")
else if value2.mtype.ctype != "val*" then
self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
end
# Generate a check-init-instance
- fun check_init_instance(recv: RuntimeVariable)
+ fun check_init_instance(recv: RuntimeVariable, mtype: MClassType)
do
if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return
- var mtype = self.anchor(recv.mcasttype)
- for cd in mtype.collect_mclassdefs(self.compiler.mainmodule)
- do
- var n = self.compiler.modelbuilder.mclassdef2nclassdef[cd]
- for npropdef in n.n_propdefs do
- if npropdef isa AAttrPropdef then
- # Force read to check the initialization
- self.read_attribute(npropdef.mpropdef.mproperty, recv)
- end
- end
+ mtype = self.anchor(mtype).as(MClassType)
+ if not self.compiler.runtime_type_analysis.live_types.has(mtype) then
+ debug "problem: {mtype} was detected dead"
end
+
+ self.add("CHECK_NEW_{mtype.c_name}({recv});")
end
# Generate an integer value
end
var length = self.int_instance(array.length)
self.send(self.get_property("with_native", arraytype), [res, nat, length])
- self.check_init_instance(res)
+ self.check_init_instance(res, arraytype)
self.add("\}")
return res
end
self.add("{res} = {res2};")
var length = self.int_instance(string.length)
self.send(self.get_property("with_native", mtype), [res, nat, length])
- self.check_init_instance(res)
+ self.check_init_instance(res, mtype)
self.add("{name} = {res};")
self.add("\}")
return res
do
var nexpr = self.n_expr
if nexpr != null then
+ var oldnode = v.current_node
+ v.current_node = self
var old_frame = v.frame
var frame = new Frame(v, self.mpropdef.as(not null), recv.mtype.as(MClassType), [recv])
v.frame = frame
var value = v.expr(nexpr, self.mpropdef.static_mtype)
v.write_attribute(self.mpropdef.mproperty, recv, value)
v.frame = old_frame
+ v.current_node = oldnode
end
end
+
+ fun check_expr(v: GlobalCompilerVisitor, recv: RuntimeVariable)
+ do
+ var nexpr = self.n_expr
+ if nexpr != null then return
+
+ var oldnode = v.current_node
+ v.current_node = self
+ var old_frame = v.frame
+ var frame = new Frame(v, self.mpropdef.as(not null), recv.mtype.as(MClassType), [recv])
+ v.frame = frame
+ # Force read to check the initialization
+ v.read_attribute(self.mpropdef.mproperty, recv)
+ v.frame = old_frame
+ v.current_node = oldnode
+ end
end
redef class AClassdef
do
var i1 = v.expr(self.n_expr, null)
var i2 = v.expr(self.n_expr2, null)
- var res = v.init_instance(self.mtype.as(MClassType))
+ var mtype = self.mtype.as(MClassType)
+ var res = v.init_instance(mtype)
var it = v.send(v.get_property("init", res.mtype), [res, i1, i2])
- v.check_init_instance(res)
+ v.check_init_instance(res, mtype)
return res
end
end
do
var i1 = v.expr(self.n_expr, null)
var i2 = v.expr(self.n_expr2, null)
- var res = v.init_instance(self.mtype.as(MClassType))
+ var mtype = self.mtype.as(MClassType)
+ var res = v.init_instance(mtype)
var it = v.send(v.get_property("without_last", res.mtype), [res, i1, i2])
- v.check_init_instance(res)
+ v.check_init_instance(res, mtype)
return res
end
end
#self.debug("got {res2} from {mproperty}. drop {recv}")
return res2
end
- v.check_init_instance(recv)
+ v.check_init_instance(recv, mtype)
return recv
end
end