src: cleanup importations
[nit.git] / src / global_compiler.nit
index e43992a..9a82243 100644 (file)
@@ -26,6 +26,29 @@ module global_compiler
 import abstract_compiler
 import rapid_type_analysis
 
+redef class ToolContext
+       # option --global
+       var opt_global = new OptionBool("Use global compilation", "--global")
+
+       var global_compiler_phase = new GlobalCompilerPhase(self, null)
+
+       redef init do
+               super
+               option_context.add_option(opt_global)
+       end
+end
+
+class GlobalCompilerPhase
+       super Phase
+       redef fun process_mainmodule(mainmodule, given_mmodules) do
+               if not toolcontext.opt_global.value then return
+
+               var modelbuilder = toolcontext.modelbuilder
+               var analysis = modelbuilder.do_rapid_type_analysis(mainmodule)
+               modelbuilder.run_global_compiler(mainmodule, analysis)
+       end
+end
+
 redef class ModelBuilder
        # Entry point to performs a global compilation on the AST of a complete program.
        # `mainmodule` is the main module of the program
@@ -54,6 +77,7 @@ redef class ModelBuilder
                end
 
                # The main function of the C
+               compiler.compile_nitni_global_ref_functions
                compiler.compile_main_function
 
                # Compile until all runtime_functions are visited
@@ -101,8 +125,8 @@ class GlobalCompiler
        # Compile class names (for the class_name and output_class_name methods)
        protected fun compile_class_names do
                var v = new_visitor
-               self.header.add_decl("extern const char const * class_names[];")
-               v.add("const char const * class_names[] = \{")
+               self.header.add_decl("extern const char *class_names[];")
+               v.add("const char *class_names[] = \{")
                for t in self.runtime_type_analysis.live_types do
                        v.add("\"{t}\", /* {self.classid(t)} */")
                end
@@ -165,6 +189,7 @@ class GlobalCompiler
 
                if mtype.mclass.name == "NativeArray" then
                        # NativeArrays are just a instance header followed by an array of values
+                       v.add_decl("int length;")
                        v.add_decl("{mtype.arguments.first.ctype} values[1];")
                end
 
@@ -212,12 +237,14 @@ class GlobalCompiler
                if is_native_array then
                        var mtype_elt = mtype.arguments.first
                        v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
+                       v.add("((struct {mtype.c_name}*){res})->length = length;")
                else
                        v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));")
                end
                v.add("{res}->classid = {self.classid(mtype)};")
 
                self.generate_init_attr(v, res, mtype)
+               v.set_finalizer res
                v.add("return {res};")
                v.add("\}")
        end
@@ -244,7 +271,14 @@ class GlobalCompiler
 
        redef fun compile_nitni_structs
        do
-               self.header.add_decl("struct nitni_instance \{ val *value; \};")
+               self.header.add_decl """
+struct nitni_instance \{
+       struct nitni_instance *next,
+               *prev; /* adjacent global references in global list */
+       int count; /* number of time this global reference has been marked */
+       val *value;
+\};"""
+               super
        end
 end
 
@@ -318,13 +352,22 @@ class GlobalCompilerVisitor
                else if pname == "[]=" then
                        self.add("{recv}[{arguments[1]}]={arguments[2]};")
                        return
+               else if pname == "length" then
+                       self.ret(self.new_expr("((struct {arguments[0].mcasttype.c_name}*){arguments[0]})->length", ret_type.as(not null)))
+                       return
                else if pname == "copy_to" then
                        var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values"
-                       self.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
+                       self.add("memmove({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
                        return
                end
        end
 
+       redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
+       do
+               var ret_type = self.get_class("NativeArray").get_mtype([elttype])
+               return self.new_expr("NEW_{ret_type.c_name}({length})", ret_type)
+       end
+
        redef fun calloc_array(ret_type, arguments)
        do
                self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type))
@@ -358,7 +401,7 @@ class GlobalCompilerVisitor
                        if res != null then self.assign(res, res2.as(not null))
                        return res
                end
-               var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value or m.name == "==" or m.name == "!="
+               var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or m.name == "==" or m.name == "!="
                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 */")
@@ -437,7 +480,8 @@ class GlobalCompilerVisitor
        do
                check_valid_reciever(recvtype)
                #debug("call {m} on {recvtype} on {args.first}:{args.first.mtype}")
-               if m.mclassdef.mclass.name == "Object" and recvtype.ctype == "val*" then
+               if m.mproperty.is_toplevel then
+                       # Do not customize top-level methods
                        recvtype = m.mclassdef.bound_mtype
                end
                return recvtype
@@ -633,7 +677,7 @@ class GlobalCompilerVisitor
                        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_other.value then
+                       if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
                                if ta.ctype == "val*" then
                                        self.add("if ({res2} == NULL) \{")
                                        self.add_abort("Uninitialized attribute {a.name}")