nitg: fix tests/sav/nitg with new options added in nitg-s
[nit.git] / src / global_compiler.nit
index aec5002..3a9d53c 100644 (file)
@@ -109,6 +109,7 @@ redef class ModelBuilder
                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
@@ -379,17 +380,50 @@ class GlobalCompiler
                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)
@@ -587,28 +621,6 @@ redef class MGenericType
        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
@@ -946,7 +958,9 @@ class GlobalCompilerVisitor
        # 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)
@@ -1608,7 +1622,7 @@ class GlobalCompilerVisitor
                        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}*/")
@@ -1636,21 +1650,16 @@ class GlobalCompilerVisitor
        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
@@ -1677,7 +1686,7 @@ class GlobalCompilerVisitor
                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
@@ -1698,7 +1707,7 @@ class GlobalCompilerVisitor
                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
@@ -2196,14 +2205,33 @@ redef class AAttrPropdef
        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
@@ -2606,9 +2634,10 @@ redef class ACrangeExpr
        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
@@ -2618,9 +2647,10 @@ redef class AOrangeExpr
        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
@@ -2806,7 +2836,7 @@ redef class ANewExpr
                        #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