mixin: introduce -D option to redefine functions from the command-line
[nit.git] / src / compiler / abstract_compiler.nit
index ef02aec..b9987c0 100644 (file)
@@ -22,6 +22,7 @@ import semantize
 import platform
 import c_tools
 private import annotation
+import mixin
 
 # Add compiling options
 redef class ToolContext
@@ -310,7 +311,16 @@ class MakefileToolchain
 
        fun makefile_name(mainmodule: MModule): String do return "{mainmodule.name}.mk"
 
-       fun default_outname(mainmodule: MModule): String do return mainmodule.name
+       fun default_outname(mainmodule: MModule): String
+       do
+               # Search a non fictive module
+               var res = mainmodule.name
+               while mainmodule.is_fictive do
+                       mainmodule = mainmodule.in_importation.direct_greaters.first
+                       res = mainmodule.name
+               end
+               return res
+       end
 
        # Combine options and platform informations to get the final path of the outfile
        fun outfile(mainmodule: MModule): String
@@ -330,7 +340,7 @@ class MakefileToolchain
 
                var outname = outfile(mainmodule)
 
-               var orig_dir=".." # FIXME only works if `compile_dir` is a subdirectory of cwd
+               var orig_dir = compile_dir.relpath(".")
                var outpath = orig_dir.join_path(outname).simplify_path
                var makename = makefile_name(mainmodule)
                var makepath = "{compile_dir}/{makename}"
@@ -891,6 +901,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ) {
                var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
                self.mainmodule.linearize_mclassdefs(cds)
                for cd in cds do
+                       if not self.modelbuilder.mclassdef2nclassdef.has_key(cd) then continue
                        var n = self.modelbuilder.mclassdef2nclassdef[cd]
                        for npropdef in n.n_propdefs do
                                if npropdef isa AAttrPropdef then
@@ -906,6 +917,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ) {
                var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
                self.mainmodule.linearize_mclassdefs(cds)
                for cd in cds do
+                       if not self.modelbuilder.mclassdef2nclassdef.has_key(cd) then continue
                        var n = self.modelbuilder.mclassdef2nclassdef[cd]
                        for npropdef in n.n_propdefs do
                                if npropdef isa AAttrPropdef then
@@ -1044,7 +1056,7 @@ abstract class AbstractCompilerVisitor
        fun get_property(name: String, recv: MType): MMethod
        do
                assert recv isa MClassType
-               return self.compiler.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, recv.mclass, self.compiler.mainmodule)
+               return self.compiler.modelbuilder.force_get_primitive_method(self.current_node, name, recv.mclass, self.compiler.mainmodule)
        end
 
        fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
@@ -1053,16 +1065,21 @@ abstract class AbstractCompilerVisitor
                if not initializers.is_empty then
                        var recv = arguments.first
 
-                       assert initializers.length == arguments.length - 1 else debug("expected {initializers.length}, got {arguments.length - 1}")
                        var i = 1
                        for p in initializers do
                                if p isa MMethod then
-                                       self.send(p, [recv, arguments[i]])
+                                       var args = [recv]
+                                       for x in p.intro.msignature.mparameters do
+                                               args.add arguments[i]
+                                               i += 1
+                                       end
+                                       self.send(p, args)
                                else if p isa MAttribute then
                                        self.write_attribute(p, recv, arguments[i])
+                                       i += 1
                                else abort
-                               i += 1
                        end
+                       assert i == arguments.length
 
                        return self.send(callsite.mproperty, [recv])
                end
@@ -1348,6 +1365,18 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       # Generate an integer value
+       fun bool_instance(value: Bool): RuntimeVariable
+       do
+               var res = self.new_var(self.get_class("Bool").mclass_type)
+               if value then
+                       self.add("{res} = 1;")
+               else
+                       self.add("{res} = 0;")
+               end
+               return res
+       end
+
        # Generate a string value
        fun string_instance(string: String): RuntimeVariable
        do
@@ -1368,6 +1397,19 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       fun value_instance(object: Object): RuntimeVariable
+       do
+               if object isa Int then
+                       return int_instance(object)
+               else if object isa Bool then
+                       return bool_instance(object)
+               else if object isa String then
+                       return string_instance(object)
+               else
+                       abort
+               end
+       end
+
        # Generate an array value
        fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable is abstract
 
@@ -1808,6 +1850,7 @@ redef class MMethodDef
        fun compile_inside_to_c(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
                var modelbuilder = v.compiler.modelbuilder
+               var val = constant_value
                if modelbuilder.mpropdef2npropdef.has_key(self) then
                        var npropdef = modelbuilder.mpropdef2npropdef[self]
                        var oldnode = v.current_node
@@ -1822,6 +1865,8 @@ redef class MMethodDef
                        self.compile_parameter_check(v, arguments)
                        nclassdef.compile_to_c(v, self, arguments)
                        v.current_node = oldnode
+               else if val != null then
+                       v.ret(v.value_instance(val))
                else
                        abort
                end
@@ -2179,9 +2224,7 @@ redef class AMethPropdef
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
-                       var nextern = self.n_extern
-                       if nextern == null then return false
-                       externname = nextern.text.substring(1, nextern.text.length-2)
+                       return false
                end
                if location.file != null then
                        var file = location.file.filename
@@ -2216,9 +2259,7 @@ redef class AMethPropdef
                        externname = at.arg_as_string(v.compiler.modelbuilder)
                        if externname == null then return false
                else
-                       var nextern = self.n_extern
-                       if nextern == null then return false
-                       externname = nextern.text.substring(1, nextern.text.length-2)
+                       return false
                end
                if location.file != null then
                        var file = location.file.filename
@@ -2323,33 +2364,12 @@ redef class AClassdef
        private fun compile_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable])
        do
                if mpropdef == self.mfree_init then
-                       if mpropdef.mproperty.is_root_init then
-                               assert self.super_inits == null
-                               assert arguments.length == 1
-                               if not mpropdef.is_intro then
-                                       v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
-                               end
-                               return
-                       end
-
-                       var super_inits = self.super_inits
-                       if super_inits != null then
-                               var args_of_super = arguments
-                               if arguments.length > 1 then args_of_super = [arguments.first]
-                               for su in super_inits do
-                                       v.send(su, args_of_super)
-                               end
-                       end
-
-                       var recv = arguments.first
-                       var i = 1
-                       # Collect undefined attributes
-                       for npropdef in self.n_propdefs do
-                               if npropdef isa AAttrPropdef and npropdef.n_expr == null and not npropdef.noinit then
-                                       v.write_attribute(npropdef.mpropdef.mproperty, recv, arguments[i])
-                                       i += 1
-                               end
+                       assert mpropdef.mproperty.is_root_init
+                       assert arguments.length == 1
+                       if not mpropdef.is_intro then
+                               v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
                        end
+                       return
                else
                        abort
                end
@@ -3039,9 +3059,6 @@ end
 # Create a tool context to handle options and paths
 var toolcontext = new ToolContext
 
-var opt_mixins = new OptionArray("Additionals module to min-in", "-m")
-toolcontext.option_context.add_option(opt_mixins)
-
 toolcontext.tooldescription = "Usage: nitg [OPTION]... file.nit...\nCompiles Nit programs."
 
 # We do not add other options, so process them now!
@@ -3060,7 +3077,6 @@ end
 
 # Here we load an process all modules passed on the command line
 var mmodules = modelbuilder.parse(arguments)
-var mixins = modelbuilder.parse(opt_mixins.value)
 
 if mmodules.is_empty then return
 modelbuilder.run_phases
@@ -3068,8 +3084,5 @@ modelbuilder.run_phases
 for mmodule in mmodules do
        toolcontext.info("*** PROCESS {mmodule} ***", 1)
        var ms = [mmodule]
-       if not mixins.is_empty then
-               ms.add_all mixins
-       end
        toolcontext.run_global_phases(ms)
 end