typing: remove most top-level things
[nit.git] / src / compiler / global_compiler.nit
index 94dda37..ede1beb 100644 (file)
@@ -59,6 +59,43 @@ redef class ModelBuilder
                self.toolcontext.info("*** GENERATING C ***", 1)
 
                var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis)
+               compiler.do_compilation
+               compiler.display_stats
+
+               var time1 = get_time
+               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
+               write_and_make(compiler)
+       end
+end
+
+# Compiler that use global compilation and perform hard optimisations like:
+#   * customization
+#   * switch dispatch
+#   * inlining
+class GlobalCompiler
+       super AbstractCompiler
+
+       redef type VISITOR: GlobalCompilerVisitor
+
+       # The result of the RTA (used to know live types and methods)
+       var runtime_type_analysis: RapidTypeAnalysis
+
+       init
+       do
+               var file = new_file("{mainmodule.c_name}.nitgg")
+               self.header = new CodeWriter(file)
+               self.live_primitive_types = new Array[MClassType]
+               for t in runtime_type_analysis.live_types do
+                       if t.is_c_primitive or t.mclass.name == "Pointer" then
+                               self.live_primitive_types.add(t)
+                       end
+               end
+       end
+
+       redef fun do_compilation
+       do
+               var compiler = self
+
                compiler.compile_header
 
                if mainmodule.model.get_mclasses_by_name("Pointer") != null then
@@ -72,7 +109,7 @@ redef class ModelBuilder
 
                # Init instance code (allocate and init-arguments)
                for t in runtime_type_analysis.live_types do
-                       if t.ctype == "val*" then
+                       if not t.is_c_primitive then
                                compiler.generate_init_instance(t)
                                if t.mclass.kind == extern_kind then
                                        compiler.generate_box_instance(t)
@@ -89,41 +126,11 @@ redef class ModelBuilder
                # Compile until all runtime_functions are visited
                while not compiler.todos.is_empty do
                        var m = compiler.todos.shift
-                       self.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3)
+                       modelbuilder.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3)
                        m.compile_to_c(compiler)
                end
-               self.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2)
-
-               compiler.display_stats
+               modelbuilder.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2)
 
-               var time1 = get_time
-               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
-               write_and_make(compiler)
-       end
-end
-
-# Compiler that use global compilation and perform hard optimisations like:
-#   * customization
-#   * switch dispatch
-#   * inlining
-class GlobalCompiler
-       super AbstractCompiler
-
-       redef type VISITOR: GlobalCompilerVisitor
-
-       # The result of the RTA (used to know live types and methods)
-       var runtime_type_analysis: RapidTypeAnalysis
-
-       init
-       do
-               var file = new_file("{mainmodule.c_name}.nitgg")
-               self.header = new CodeWriter(file)
-               self.live_primitive_types = new Array[MClassType]
-               for t in runtime_type_analysis.live_types do
-                       if t.ctype != "val*" or t.mclass.name == "Pointer" then
-                               self.live_primitive_types.add(t)
-                       end
-               end
        end
 
        # Compile class names (for the class_name and output_class_name methods)
@@ -221,7 +228,7 @@ class GlobalCompiler
        fun generate_init_instance(mtype: MClassType)
        do
                assert self.runtime_type_analysis.live_types.has(mtype)
-               assert mtype.ctype == "val*"
+               assert not mtype.is_c_primitive
                var v = self.new_visitor
 
                var is_native_array = mtype.mclass.name == "NativeArray"
@@ -296,16 +303,16 @@ class GlobalCompilerVisitor
        do
                if value.mtype == mtype then
                        return value
-               else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive and not mtype.is_c_primitive then
                        return value
-               else if value.mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive then
                        return self.new_expr("((struct {mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
-               else if mtype.ctype == "val*" then
+               else if not mtype.is_c_primitive then
                        var valtype = value.mtype.as(MClassType)
                        var res = self.new_var(mtype)
                        if not compiler.runtime_type_analysis.live_types.has(valtype) then
                                self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                                return res
                        end
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
@@ -316,7 +323,7 @@ class GlobalCompilerVisitor
                        # Bad things will appen!
                        var res = self.new_var(mtype)
                        self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
-                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); fatal_exit(1);")
                        return res
                end
        end
@@ -342,7 +349,7 @@ class GlobalCompilerVisitor
                var res = self.new_var(mtype)
                if not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
                        self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
-                       self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                        return res
                end
                self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
@@ -395,11 +402,24 @@ class GlobalCompilerVisitor
 
        redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
        do
-               var ret_type = self.get_class("NativeArray").get_mtype([elttype])
+               var ret_type = mmodule.native_array_type(elttype)
                ret_type = anchor(ret_type).as(MClassType)
                return self.new_expr("NEW_{ret_type.c_name}({length})", ret_type)
        end
 
+       redef fun native_array_get(nat, i)
+       do
+               var recv = "((struct {nat.mcasttype.c_name}*){nat})->values"
+               var ret_type = nat.mcasttype.as(MClassType).arguments.first
+               return self.new_expr("{recv}[{i}]", ret_type)
+       end
+
+       redef fun native_array_set(nat, i, val)
+       do
+               var recv = "((struct {nat.mcasttype.c_name}*){nat})->values"
+               self.add("{recv}[{i}]={val};")
+       end
+
        redef fun calloc_array(ret_type, arguments)
        do
                self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type))
@@ -419,7 +439,7 @@ class GlobalCompilerVisitor
                end
 
                self.add("/* send {m} on {args.first.inspect} */")
-               if args.first.mtype.ctype != "val*" then
+               if args.first.mtype.is_c_primitive then
                        var mclasstype = args.first.mtype.as(MClassType)
                        if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
                                self.add("/* skip, no method {m} */")
@@ -434,7 +454,7 @@ class GlobalCompilerVisitor
                if args.first.mcasttype isa MNullableType or args.first.mcasttype isa MNullType and consider_null then
                        # The reciever is potentially null, so we have to 3 cases: ==, != or NullPointerException
                        self.add("if ({args.first} == NULL) \{ /* Special null case */")
-                       if m.name == "==" then
+                       if m.name == "==" or m.name == "is_same_instance" then
                                assert res != null
                                if args[1].mcasttype isa MNullableType then
                                        self.add("{res} = ({args[1]} == NULL);")
@@ -470,7 +490,7 @@ class GlobalCompilerVisitor
                var defaultpropdef: nullable MMethodDef = null
                for t in types do
                        var propdef = m.lookup_first_definition(self.compiler.mainmodule, t)
-                       if propdef.mclassdef.mclass.name == "Object" and t.ctype == "val*" then
+                       if propdef.mclassdef.mclass.name == "Object" and not t.is_c_primitive then
                                defaultpropdef = propdef
                                continue
                        end
@@ -508,11 +528,6 @@ class GlobalCompilerVisitor
        private fun get_recvtype(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): MClassType
        do
                check_valid_reciever(recvtype)
-               #debug("call {m} on {recvtype} on {args.first}:{args.first.mtype}")
-               if m.mproperty.is_toplevel then
-                       # Do not customize top-level methods
-                       recvtype = m.mclassdef.bound_mtype
-               end
                return recvtype
        end
 
@@ -545,7 +560,7 @@ class GlobalCompilerVisitor
                end
 
                self.add("/* super {m} on {args.first.inspect} */")
-               if args.first.mtype.ctype != "val*" then
+               if args.first.mtype.is_c_primitive then
                        var mclasstype = args.first.mtype.as(MClassType)
                        if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
                                self.add("/* skip, no method {m} */")
@@ -621,9 +636,9 @@ class GlobalCompilerVisitor
 
        fun bugtype(recv: RuntimeVariable)
        do
-               if recv.mtype.ctype != "val*" then return
+               if recv.mtype.is_c_primitive then return
                self.add("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
-               self.add("show_backtrace(1);")
+               self.add("fatal_exit(1);")
        end
 
        redef fun isset_attribute(a, recv)
@@ -652,7 +667,7 @@ class GlobalCompilerVisitor
                        ta = self.resolve_for(ta, recv2)
                        var attr = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
                        if not ta isa MNullableType then
-                               if ta.ctype == "val*" then
+                               if not ta.is_c_primitive then
                                        self.add("{res} = ({attr} != NULL);")
                                else
                                        self.add("{res} = 1; /*NOTYET isset on primitive attributes*/")
@@ -698,7 +713,7 @@ class GlobalCompilerVisitor
                        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 ta.ctype == "val*" then
+                               if not ta.is_c_primitive then
                                        self.add("if ({res2} == NULL) \{")
                                        self.add_abort("Uninitialized attribute {a.name}")
                                        self.add("\}")
@@ -774,7 +789,7 @@ class GlobalCompilerVisitor
                var res = self.new_var(bool_type)
 
                self.add("/* isa {mtype} on {value.inspect} */")
-               if value.mtype.ctype != "val*" then
+               if value.mtype.is_c_primitive then
                        if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
                                self.add("{res} = 1;")
                        else
@@ -809,14 +824,14 @@ class GlobalCompilerVisitor
        redef fun is_same_type_test(value1, value2)
        do
                var res = self.new_var(bool_type)
-               if value2.mtype.ctype == "val*" then
-                       if value1.mtype.ctype == "val*" then
+               if not value2.mtype.is_c_primitive then
+                       if not value1.mtype.is_c_primitive then
                                self.add "{res} = {value1}->classid == {value2}->classid;"
                        else
                                self.add "{res} = {self.compiler.classid(value1.mtype.as(MClassType))} == {value2}->classid;"
                        end
                else
-                       if value1.mtype.ctype == "val*" then
+                       if not value1.mtype.is_c_primitive then
                                self.add "{res} = {value1}->classid == {self.compiler.classid(value2.mtype.as(MClassType))};"
                        else if value1.mcasttype == value2.mcasttype then
                                self.add "{res} = 1;"
@@ -831,7 +846,7 @@ class GlobalCompilerVisitor
        do
                var res = self.get_name("var_class_name")
                self.add_decl("const char* {res};")
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        self.add "{res} = class_names[{value}->classid];"
                else
                        self.add "{res} = class_names[{self.compiler.classid(value.mtype.as(MClassType))}];"
@@ -842,15 +857,15 @@ class GlobalCompilerVisitor
        redef fun equal_test(value1, value2)
        do
                var res = self.new_var(bool_type)
-               if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+               if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
                        var tmp = value1
                        value1 = value2
                        value2 = tmp
                end
-               if value1.mtype.ctype != "val*" then
+               if value1.mtype.is_c_primitive then
                        if value2.mtype == value1.mtype then
                                self.add("{res} = {value1} == {value2};")
-                       else if value2.mtype.ctype != "val*" then
+                       else if value2.mtype.is_c_primitive then
                                self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
                        else
                                var mtype1 = value1.mtype.as(MClassType)
@@ -887,10 +902,10 @@ class GlobalCompilerVisitor
        redef fun array_instance(array, elttype)
        do
                elttype = self.anchor(elttype)
-               var arraytype = self.get_class("Array").get_mtype([elttype])
+               var arraytype = mmodule.array_type(elttype)
                var res = self.init_instance(arraytype)
                self.add("\{ /* {res} = array_instance Array[{elttype}] */")
-               var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype]))
+               var nat = self.new_var(mmodule.native_array_type(elttype))
                nat.is_exact = true
                self.add("{nat} = NEW_{nat.mtype.c_name}({array.length});")
                for i in [0..array.length[ do
@@ -965,7 +980,7 @@ private class CustomizedRuntimeFunction
                        selfvar.is_exact = true
                end
                var arguments = new Array[RuntimeVariable]
-               var frame = new Frame(v, mmethoddef, recv, arguments)
+               var frame = new StaticFrame(v, mmethoddef, recv, arguments)
                v.frame = frame
 
                var sig = new FlatBuffer
@@ -984,7 +999,7 @@ private class CustomizedRuntimeFunction
                for i in [0..mmethoddef.msignature.arity[ do
                        var mtype = mmethoddef.msignature.mparameters[i].mtype
                        if i == mmethoddef.msignature.vararg_rank then
-                               mtype = v.get_class("Array").get_mtype([mtype])
+                               mtype = v.mmodule.array_type(mtype)
                        end
                        mtype = v.resolve_for(mtype, selfvar)
                        comment.append(", {mtype}")
@@ -1024,7 +1039,7 @@ private class CustomizedRuntimeFunction
                        ret = v.resolve_for(ret, arguments.first)
                end
                if self.mmethoddef.can_inline(v) then
-                       var frame = new Frame(v, self.mmethoddef, self.recv, arguments)
+                       var frame = new StaticFrame(v, self.mmethoddef, self.recv, arguments)
                        frame.returnlabel = v.get_name("RET_LABEL")
                        if ret != null then
                                frame.returnvar = v.new_var(ret)