Merge branch 'pu/qualified-modules' into wip
[nit.git] / src / compiling / compiling_global.nit
index 66e670b..df5b326 100644 (file)
@@ -20,32 +20,24 @@ package compiling_global
 import table_computation
 private import compiling_icode
 
-class GlobalCompilerVisitor
-special CompilerVisitor
-       # The global analysis result
-       readable var _program: Program
-       init(m: MMModule, tc: ToolContext, prog: Program)
-       do
-               super(m, tc)
-               _program = prog
-       end
-end
-
 redef class Program
        # Compile module and class tables
-       fun compile_tables_to_c(v: GlobalCompilerVisitor)
+       fun compile_tables_to_c(v: CompilerVisitor)
        do
-               for m in module.mhe.greaters_and_self do
+               for m in main_module.mhe.greaters_and_self do
                        m.compile_local_table_to_c(v)
                end
 
-               for c in module.local_classes do
+               with_each_live_local_classes !action(c) do
+                       if c.global.is_abstract or c.global.is_interface then continue
                        c.compile_tables_to_c(v)
                end
+
                var s = new Buffer.from("classtable_t TAG2VFT[4] = \{NULL")
                for t in ["Int","Char","Bool"] do
-                       if module.has_global_class_named(t.to_symbol) then
-                               s.append(", (const classtable_t)VFT_{t}")
+                       if main_module.has_global_class_named(t.to_symbol) then
+                               var c = main_module.class_by_name(t.to_symbol)
+                               s.append(", (const classtable_t)VFT_{c.cname}")
                        else
                                s.append(", NULL")
                        end
@@ -55,26 +47,19 @@ redef class Program
        end
 
        # Compile main part (for _table.c)
-       fun compile_main_part(v: GlobalCompilerVisitor)
+       fun compile_main_part(v: CompilerVisitor)
        do
                v.add_instr("int main(int argc, char **argv) \{")
                v.indent
                v.add_instr("prepare_signals();")
                v.add_instr("glob_argc = argc; glob_argv = argv;")
-               var sysname = once "Sys".to_symbol
-               if not module.has_global_class_named(sysname) then
+               if v.program.main_method == null then
                        print("No main")
                else
-                       var sys = module.class_by_name(sysname)
-                       var name = once "main".to_symbol
-                       if not sys.has_global_property_by_name(name) then
-                               print("No main")
-                       else
-                               var mainm = sys.select_method(name)
-                               v.add_instr("G_sys = NEW_Sys();")
-                               v.add_instr("register_static_object(&G_sys);")
-                               v.add_instr("{mainm.cname}(G_sys);")
-                       end
+                       var c = v.program.main_class
+                       v.add_instr("G_sys = NEW_{c.cname}();")
+                       v.add_instr("register_static_object(&G_sys);")
+                       v.add_instr("{v.program.main_method.cname}(G_sys);")
                end
                v.add_instr("return 0;")
                v.unindent
@@ -83,30 +68,30 @@ redef class Program
 end
 
 redef class MMModule
-       # Declare class table (for _sep.h)
-       fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
+       # Declare class table (for _sep.h or _glob.h)
+       fun declare_class_tables_to_c(v: CompilerVisitor)
        do
                for c in local_classes do
-                       if c.global.module == self then
+                       if c.global.mmmodule == self then
                                c.declare_tables_to_c(v)
                        end
                end
        end
 
        # Compile sep files
-       fun compile_mod_to_c(v: GlobalCompilerVisitor)
+       fun compile_mod_to_c(v: CompilerVisitor)
        do
-               v.add_decl("extern const char *LOCATE_{name};")
-               if not v.tc.global then
-                       v.add_decl("extern const int SFT_{name}[];")
+               v.add_decl("extern const char *LOCATE_{cname};")
+               if not v.program.tc.use_SFT_optimization then
+                       v.add_decl("extern const int SFT_{cname}[];")
                end
                var i = 0
                for e in local_table do
                        var value: String
-                       if v.tc.global then
+                       if v.program.tc.use_SFT_optimization then
                                value = "{e.value(v.program)}"
                        else
-                               value = "SFT_{name}[{i}]"
+                               value = "SFT_{cname}[{i}]"
                                i = i + 1
                        end
                        e.compile_macros(v, value)
@@ -131,15 +116,15 @@ redef class MMModule
        end
 
        # Compile module file for the current module
-       fun compile_local_table_to_c(v: GlobalCompilerVisitor)
+       fun compile_local_table_to_c(v: CompilerVisitor)
        do
-               v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
+               v.add_instr("const char *LOCATE_{cname} = \"{location.file.filename}\";")
 
-               if v.tc.global or local_table.is_empty then
+               if v.program.tc.use_SFT_optimization or local_table.is_empty then
                        return
                end
 
-               v.add_instr("const int SFT_{name}[{local_table.length}] = \{")
+               v.add_instr("const int SFT_{cname}[{local_table.length}] = \{")
                v.indent
                for e in local_table do
                        v.add_instr(e.value(v.program) + ",")
@@ -153,12 +138,12 @@ end
 
 redef class AbsTableElt
        # Compile the macro needed to use the element and other related elements
-       fun compile_macros(v: GlobalCompilerVisitor, value: String) is abstract
+       fun compile_macros(v: CompilerVisitor, value: String) is abstract
 end
 
 redef class TableElt
        # Return the value of the element for a given class
-       fun compile_to_c(v: GlobalCompilerVisitor, c: MMLocalClass): String is abstract
+       fun compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
 end
 
 redef class ModuleTableElt
@@ -298,6 +283,14 @@ redef class TableEltClassSelfId
        end
 end
 
+redef class TableEltClassSelfName
+       redef fun compile_to_c(v, c)
+       do
+               var prog = v.program
+               return "\"{c.global.name}\" /* {prog.table_information.color(self)}: Class Name */"
+       end
+end
+
 redef class TableEltClassObjectSize
        redef fun compile_to_c(v, c)
        do
@@ -335,26 +328,13 @@ end
 ###############################################################################
 
 redef class MMLocalClass
-       # IRoutine for the initialization of the default attributes (called by IInitAttributes)
-       var _init_var_iroutine: nullable IRoutine = null
-       # IRoutine to validate the instance after initialization (called by ICheckInstance)
-       var _checknew_iroutine: nullable IRoutine = null
-       # IRoutines to call to create a new valid instance (memory allocated, object initialized and validated)
-       # These iroutines will call: IAllocateInstance, IInitAttributes, some init function and ICheckInstance
-       # These routines will be called by INew
-       var _new_instance_iroutine: HashMap[MMMethod, IRoutine] = new HashMap[MMMethod, IRoutine]
-
        # Declaration and macros related to the class table
-       fun declare_tables_to_c(v: GlobalCompilerVisitor)
+       fun declare_tables_to_c(v: CompilerVisitor)
        do
                v.add_decl("")
                var pi = primitive_info
-               v.add_decl("extern const classtable_elt_t VFT_{name}[];")
-               if name == "NativeArray".to_symbol then
-                       v.add_decl("val_t NEW_NativeArray(size_t length, size_t size);")
-               else if pi == null then
-                       # v.add_decl("val_t NEW_{name}(void);")
-               else if not pi.tagged then
+               v.add_decl("extern const classtable_elt_t VFT_{cname}[];")
+               if pi != null and not pi.tagged then
                        var t = pi.cname
                        var tbox = "struct TBOX_{name}"
                        v.add_decl("{tbox} \{ const classtable_elt_t * vft; bigint object_id; {t} val;};")
@@ -363,83 +343,8 @@ redef class MMLocalClass
                end
        end
 
-       # Generation of allocation function of this class
-       fun generate_allocation_iroutines(prog: Program)
-       do
-               var cc = prog.compiled_classes[self.global]
-
-               var pi = primitive_info
-               if pi == null then
-                       do
-                               # Generate INIT_ATTRIBUTES routine
-                               var iself = new IRegister(get_type)
-                               var iselfa = [iself]
-                               var iroutine = new IRoutine(iselfa, null)
-                               var icb = new ICodeBuilder(module, iroutine)
-
-                               for g in global_properties do
-                                       var p = self[g]
-                                       var t = p.signature.return_type
-                                       if p isa MMAttribute and t != null then
-                                               var ir = p.iroutine
-                                               if ir == null then continue
-                                               # FIXME: Not compatible with sep compilation
-                                               var e = icb.inline_routine(ir, iselfa, null).as(not null)
-                                               icb.stmt(new IAttrWrite(p, iself, e))
-                                       end
-                               end
-
-                               _init_var_iroutine = iroutine
-                       end
-                       do
-                               # Compile CHECKNAME
-                               var iself = new IRegister(get_type)
-                               var iselfa = [iself]
-                               var iroutine = new IRoutine(iselfa, null)
-                               var icb = new ICodeBuilder(module, iroutine)
-                               for g in global_properties do
-                                       var p = self[g]
-                                       var t = p.signature.return_type
-                                       if p isa MMAttribute and t != null and not t.is_nullable then
-                                               icb.add_attr_check(p, iself)
-                                       end
-                               end
-
-                               _checknew_iroutine = iroutine
-                       end
-
-                       var init_table_size = cshe.greaters.length + 1
-
-                       for g in global_properties do
-                               var p = self[g]
-                               # FIXME skip invisible constructors
-                               if not p.global.is_init_for(self) then continue
-                               assert p isa MMMethod
-
-                               var iself = new IRegister(get_type)
-                               var iparams = new Array[IRegister]
-                               for i in [0..p.signature.arity[ do iparams.add(new IRegister(p.signature[i]))
-                               var iroutine = new IRoutine(iparams, iself)
-                               iroutine.location = p.iroutine.location
-                               var icb = new ICodeBuilder(module, iroutine)
-
-                               var inew = new IAllocateInstance(get_type)
-                               inew.result = iself
-                               icb.stmt(inew)
-                               var iargs = [iself]
-                               iargs.add_all(iparams)
-
-                               icb.stmt(new IInitAttributes(get_type, iself))
-                               icb.stmt(new IStaticCall(p, iargs))
-                               icb.stmt(new ICheckInstance(get_type, iself))
-
-                               _new_instance_iroutine[p] = iroutine
-                       end
-               end
-       end
-
        # Compilation of table and new (or box)
-       fun compile_tables_to_c(v: GlobalCompilerVisitor)
+       fun compile_tables_to_c(v: CompilerVisitor)
        do
                var cc = v.program.compiled_classes[self.global]
                var ctab = cc.class_table
@@ -448,7 +353,7 @@ redef class MMLocalClass
                        clen = v.program.table_information.max_class_table_length
                end
 
-               v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
+               v.add_instr("const classtable_elt_t VFT_{cname}[{clen}] = \{")
                v.indent
                for e in ctab do
                        if e == null then
@@ -477,7 +382,7 @@ redef class MMLocalClass
                        v.indent
                        v.add_instr("Nit_NativeArray array;")
                        v.add_instr("array = (Nit_NativeArray)alloc(sizeof(struct Nit_NativeArray) + ((length - 1) * size));")
-                       v.add_instr("array->vft = (classtable_elt_t*)VFT_{name};")
+                       v.add_instr("array->vft = (classtable_elt_t*)VFT_{cname};")
                        v.add_instr("array->object_id = object_id_counter;")
                        v.add_instr("object_id_counter = object_id_counter + 1;")
                        v.add_instr("array->size = length;")
@@ -487,25 +392,24 @@ redef class MMLocalClass
                else if pi == null then
                        do
                                # Generate INIT_ATTRIBUTES routine
-                               var cname = "INIT_ATTRIBUTES__{name}"
-                               var args = _init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null)
-                               var ctx_old = v.ctx
-                               v.ctx = new CContext
-                               _init_var_iroutine.compile_to_c(v, cname, args)
-                               ctx_old.append(v.ctx)
-                               v.ctx = ctx_old
+                               var cname = "INIT_ATTRIBUTES__{cname}"
+                               var args = init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null)
+                               var decl_writer_old = v.decl_writer
+                               v.decl_writer = v.writer.sub
+                               init_var_iroutine.compile_to_c(v, cname, args)
+                               v.decl_writer = decl_writer_old
                                v.unindent
                                v.add_instr("}")
                        end
                        do
                                # Generate NEW routine
-                               v.add_decl("val_t NEW_{name}(void);")
-                               v.add_instr("val_t NEW_{name}(void)")
+                               v.add_decl("val_t NEW_{cname}(void);")
+                               v.add_instr("val_t NEW_{cname}(void)")
                                v.add_instr("\{")
                                v.indent
                                v.add_instr("obj_t obj;")
                                v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
-                               v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
+                               v.add_instr("obj->vft = (classtable_elt_t*)VFT_{cname};")
                                v.add_instr("obj[1].object_id = object_id_counter;")
                                v.add_instr("object_id_counter = object_id_counter + 1;")
                                v.add_instr("return OBJ2VAL(obj);")
@@ -514,13 +418,12 @@ redef class MMLocalClass
                        end
                        do
                                # Compile CHECKNAME
-                               var cname = "CHECKNEW_{name}"
-                               var args = _checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
-                               var ctx_old = v.ctx
-                               v.ctx = new CContext
-                               _checknew_iroutine.compile_to_c(v, cname, args)
-                               ctx_old.append(v.ctx)
-                               v.ctx = ctx_old
+                               var cname = "CHECKNEW_{cname}"
+                               var args = checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
+                               var decl_writer_old = v.decl_writer
+                               v.decl_writer = v.writer.sub
+                               checknew_iroutine.compile_to_c(v, cname, args)
+                               v.decl_writer = decl_writer_old
                                v.unindent
                                v.add_instr("}")
                        end
@@ -535,14 +438,13 @@ redef class MMLocalClass
                                assert p isa MMMethod
 
                                var cname = "NEW_{self}_{p.global.intro.cname}"
-                               var new_args = _new_instance_iroutine[p].compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null)
-                               var ctx_old = v.ctx
-                               v.ctx = new CContext
+                               var new_args = new_instance_iroutine[p].compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null)
+                               var decl_writer_old = v.decl_writer
+                               v.decl_writer = v.writer.sub
                                v.add_instr(init_table_decl)
-                               var e = _new_instance_iroutine[p].compile_to_c(v, cname, new_args).as(not null)
+                               var e = new_instance_iroutine[p].compile_to_c(v, cname, new_args).as(not null)
                                v.add_instr("return {e};")
-                               ctx_old.append(v.ctx)
-                               v.ctx = ctx_old
+                               v.decl_writer = decl_writer_old
                                v.unindent
                                v.add_instr("}")
                        end
@@ -552,7 +454,7 @@ redef class MMLocalClass
                        v.add_instr("val_t BOX_{name}({t} val) \{")
                        v.indent
                        v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
-                       v.add_instr("box->vft = VFT_{name};")
+                       v.add_instr("box->vft = VFT_{cname};")
                        v.add_instr("box->val = val;")
                        v.add_instr("box->object_id = object_id_counter;")
                        v.add_instr("object_id_counter = object_id_counter + 1;")
@@ -572,10 +474,10 @@ redef class MMMethod
                var more_params: nullable String = null
                if global.is_init then more_params = "int* init_table"
                var args = ir.compile_signature_to_c(v, cname, full_name, null, more_params)
-               var ctx_old = v.ctx
-               v.ctx = new CContext
-
-               v.out_contexts.clear
+               var writer_old = v.writer
+               v.writer = v.writer.sub
+               var decl_writer_old = v.decl_writer
+               v.decl_writer = v.writer.sub
 
                var itpos: nullable String = null
                if global.is_init then
@@ -592,15 +494,13 @@ redef class MMMethod
                if s == null then
                        v.add_instr("return;")
                else
-                       v.add_instr("return ", s, ";")
+                       v.add_instr("return {s};")
                end
-
-               ctx_old.append(v.ctx)
-               v.ctx = ctx_old
                v.unindent
                v.add_instr("}")
 
-               for ctx in v.out_contexts do v.ctx.merge(ctx)
+               v.writer = writer_old
+               v.decl_writer = decl_writer_old
        end
 end