src: update most tools to new constructors
[nit.git] / src / compiler / abstract_compiler.nit
index dbf3794..62c0987 100644 (file)
@@ -40,6 +40,8 @@ redef class ToolContext
        var opt_make_flags = new OptionString("Additional options to make", "--make-flags")
        # --max-c-lines
        var opt_max_c_lines = new OptionInt("Maximum number of lines in generated C files. Use 0 for unlimited", 10000, "--max-c-lines")
+       # --group-c-files
+       var opt_group_c_files = new OptionBool("Group all generated code in the same series of files", "--group-c-files")
        # --compile-dir
        var opt_compile_dir = new OptionString("Directory used to generate temporary files", "--compile-dir")
        # --hardening
@@ -78,7 +80,7 @@ redef class ToolContext
                self.option_context.add_option(self.opt_stacktrace)
                self.option_context.add_option(self.opt_no_gcc_directive)
                self.option_context.add_option(self.opt_release)
-               self.option_context.add_option(self.opt_max_c_lines)
+               self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files)
        end
 
        redef fun process_options(args)
@@ -157,17 +159,20 @@ class MakefileToolchain
        # Path can be added (or removed) by the client
        var cc_paths = new Array[String]
 
+       # The clib directory of Nit
+       # Used to found some common runtime
+       var clib: String is noinit
+
        protected fun gather_cc_paths
        do
                # Look for the the Nit clib path
                var path_env = toolcontext.nit_dir
                if path_env != null then
                        var libname = "{path_env}/clib"
-                       if libname.file_exists then cc_paths.add(libname)
-               end
-
-               if cc_paths.is_empty then
-                       toolcontext.error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
+                       if not libname.file_exists then
+                               toolcontext.fatal_error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.")
+                       end
+                       clib = libname
                end
 
                # Add user defined cc_paths
@@ -226,8 +231,8 @@ class MakefileToolchain
                # Add gc_choser.h to aditionnal bodies
                var gc_chooser = new ExternCFile("gc_chooser.c", cc_opt_with_libgc)
                compiler.extern_bodies.add(gc_chooser)
-               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.c"
-               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
+               compiler.files_to_copy.add "{clib}/gc_chooser.c"
+               compiler.files_to_copy.add "{clib}/gc_chooser.h"
 
                # FFI
                for m in compiler.mainmodule.in_importation.greaters do
@@ -424,6 +429,8 @@ class MakefileToolchain
                makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n")
                makefile.close
                self.toolcontext.info("Generated makefile: {makepath}", 2)
+
+               makepath.file_copy_to "{compile_dir}/Makefile"
        end
 
        fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
@@ -458,7 +465,7 @@ abstract class AbstractCompiler
        var mainmodule: MModule is writable
 
        # The real main module of the program
-       var realmainmodule: MModule
+       var realmainmodule: MModule is noinit
 
        # The modelbuilder used to know the model and the AST
        var modelbuilder: ModelBuilder is protected writable
@@ -466,17 +473,22 @@ abstract class AbstractCompiler
        # Is hardening asked? (see --hardening)
        fun hardening: Bool do return self.modelbuilder.toolcontext.opt_hardening.value
 
-       init(mainmodule: MModule, modelbuilder: ModelBuilder)
+       init
        do
-               self.mainmodule = mainmodule
                self.realmainmodule = mainmodule
-               self.modelbuilder = modelbuilder
        end
 
        # Force the creation of a new file
        # The point is to avoid contamination between must-be-compiled-separately files
        fun new_file(name: String): CodeFile
        do
+               if modelbuilder.toolcontext.opt_group_c_files.value then
+                       if self.files.is_empty then
+                               var f = new CodeFile(mainmodule.name)
+                               self.files.add(f)
+                       end
+                       return self.files.first
+               end
                var f = new CodeFile(name)
                self.files.add(f)
                return f
@@ -490,7 +502,7 @@ abstract class AbstractCompiler
        fun new_visitor: VISITOR is abstract
 
        # Where global declaration are stored (the main .h)
-       var header: CodeWriter is writable
+       var header: CodeWriter is writable, noinit
 
        # Provide a declaration that can be requested (before or latter) by a visitor
        fun provide_declaration(key: String, s: String)
@@ -1012,9 +1024,8 @@ class CodeWriter
        # (used for local or global declaration)
        fun add_decl(s: String) do self.decl_lines.add(s)
 
-       init(file: CodeFile)
+       init
        do
-               self.file = file
                file.writers.add(self)
        end
 end
@@ -1031,7 +1042,7 @@ abstract class AbstractCompilerVisitor
        var current_node: nullable ANode = null is writable
 
        # The current `Frame`
-       var frame: nullable Frame is writable
+       var frame: nullable Frame = null is writable
 
        # Alias for self.compiler.mainmodule.object_type
        fun object_type: MClassType do return self.compiler.mainmodule.object_type
@@ -1039,11 +1050,10 @@ abstract class AbstractCompilerVisitor
        # Alias for self.compiler.mainmodule.bool_type
        fun bool_type: MClassType do return self.compiler.mainmodule.bool_type
 
-       var writer: CodeWriter
+       var writer: CodeWriter is noinit
 
-       init(compiler: COMPILER)
+       init
        do
-               self.compiler = compiler
                self.writer = new CodeWriter(compiler.files.last)
        end
 
@@ -1627,11 +1637,8 @@ class RuntimeVariable
        # false (usual value) means that the variable is a mcasttype or a subtype.
        var is_exact: Bool = false is writable
 
-       init(name: String, mtype: MType, mcasttype: MType)
+       init
        do
-               self.name = name
-               self.mtype = mtype
-               self.mcasttype = mcasttype
                assert not mtype.need_anchor
                assert not mcasttype.need_anchor
        end
@@ -2294,24 +2301,24 @@ redef class AAttrPropdef
        do
                if mpropdef == mreadpropdef then
                        assert arguments.length == 1
+                       var recv = arguments.first
                        var res
                        if is_lazy then
-                               var nexpr = n_expr
-                               assert nexpr != null
                                var set
                                var ret = self.mpropdef.static_mtype
                                var useiset = ret.ctype == "val*" and not ret isa MNullableType
                                var guard = self.mlazypropdef.mproperty
                                if useiset then
-                                       set = v.isset_attribute(self.mpropdef.mproperty, arguments.first)
+                                       set = v.isset_attribute(self.mpropdef.mproperty, recv)
                                else
-                                       set = v.read_attribute(guard, arguments.first)
+                                       set = v.read_attribute(guard, recv)
                                end
                                v.add("if(likely({set})) \{")
-                               res = v.read_attribute(self.mpropdef.mproperty, arguments.first)
+                               res = v.read_attribute(self.mpropdef.mproperty, recv)
                                v.add("\} else \{")
-                               var value = v.expr(nexpr, self.mpropdef.static_mtype)
-                               v.write_attribute(self.mpropdef.mproperty, arguments.first, value)
+
+                               var value = evaluate_expr(v, recv)
+
                                v.assign(res, value)
                                if not useiset then
                                        var true_v = v.new_expr("1", v.bool_type)
@@ -2339,18 +2346,44 @@ redef class AAttrPropdef
 
        fun init_expr(v: AbstractCompilerVisitor, recv: RuntimeVariable)
        do
+               if has_value and not is_lazy then evaluate_expr(v, recv)
+       end
+
+       # Evaluate, store and return the default value of the attribute
+       private fun evaluate_expr(v: AbstractCompilerVisitor, recv: RuntimeVariable): RuntimeVariable
+       do
+               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.mcasttype.as(MClassType), [recv])
+               v.frame = frame
+
+               var value
+               var mtype = self.mpropdef.static_mtype
+               assert mtype != null
+
                var nexpr = self.n_expr
-               if nexpr != null and not is_lazy 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
+               var nblock = self.n_block
+               if nexpr != null then
+                       value = v.expr(nexpr, mtype)
+               else if nblock != null then
+                       value = v.new_var(mtype)
+                       frame.returnvar = value
+                       frame.returnlabel = v.get_name("RET_LABEL")
+                       v.add("\{")
+                       v.stmt(nblock)
+                       v.add("{frame.returnlabel.as(not null)}:(void)0;")
+                       v.add("\}")
+               else
+                       abort
                end
+
+               v.write_attribute(self.mpropdef.mproperty, recv, value)
+
+               v.frame = old_frame
+               v.current_node = oldnode
+
+               return value
        end
 
        fun check_expr(v: AbstractCompilerVisitor, recv: RuntimeVariable)