typing: move vararg_length on each argument, instead of the whole signature
[nit.git] / src / compiler / abstract_compiler.nit
index b79e9ba..f177ef6 100644 (file)
@@ -28,15 +28,15 @@ import counter
 # Add compiling options
 redef class ToolContext
        # --output
-       var opt_output = new OptionString("Output file", "-o", "--output")
+       var opt_output = new OptionString("Filename of the generated executable", "-o", "--output")
        # --dir
        var opt_dir = new OptionString("Output directory", "--dir")
        # --no-cc
-       var opt_no_cc = new OptionBool("Do not invoke C compiler", "--no-cc")
+       var opt_no_cc = new OptionBool("Do not invoke the C compiler", "--no-cc")
        # --no-main
        var opt_no_main = new OptionBool("Do not generate main entry point", "--no-main")
        # --make-flags
-       var opt_make_flags = new OptionString("Additional options to make", "--make-flags")
+       var opt_make_flags = new OptionString("Additional options to the `make` command", "--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
@@ -50,7 +50,7 @@ redef class ToolContext
        # --no-check-attr-isset
        var opt_no_check_attr_isset = new OptionBool("Disable isset tests before each attribute access (dangerous)", "--no-check-attr-isset")
        # --no-check-assert
-       var opt_no_check_assert = new OptionBool("Disable the evaluation of explicit 'assert' and 'as' (dangerous)", "--no-check-assert")
+       var opt_no_check_assert = new OptionBool("Disable the evaluation of explicit `assert` and `as` (dangerous)", "--no-check-assert")
        # --no-check-autocast
        var opt_no_check_autocast = new OptionBool("Disable implicit casts on unsafe expression usage (dangerous)", "--no-check-autocast")
        # --no-check-null
@@ -66,11 +66,11 @@ redef class ToolContext
        # --no-stacktrace
        var opt_no_stacktrace = new OptionBool("Disable the generation of stack traces", "--no-stacktrace")
        # --no-gcc-directives
-       var opt_no_gcc_directive = new OptionArray("Disable a advanced gcc directives for optimization", "--no-gcc-directive")
+       var opt_no_gcc_directive = new OptionArray("Disable advanced gcc directives for optimization", "--no-gcc-directive")
        # --release
        var opt_release = new OptionBool("Compile in release mode and finalize application", "--release")
        # -g
-       var opt_debug = new OptionBool("Compile in debug mode (no C-side optimization)", "--debug", "-g")
+       var opt_debug = new OptionBool("Compile in debug mode (no C-side optimization)", "-g", "--debug")
 
        redef init
        do
@@ -1147,6 +1147,7 @@ abstract class AbstractCompilerVisitor
 
        fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
+               if callsite.is_broken then return null
                var initializers = callsite.mpropdef.initializers
                if not initializers.is_empty then
                        var recv = arguments.first
@@ -1221,8 +1222,8 @@ abstract class AbstractCompilerVisitor
                                res.add(null_instance)
                                continue
                        end
-                       if param.is_vararg and map.vararg_decl > 0 then
-                               var vararg = exprs.sub(j, map.vararg_decl)
+                       if param.is_vararg and args[i].vararg_decl > 0 then
+                               var vararg = exprs.sub(j, args[i].vararg_decl)
                                var elttype = param.mtype
                                var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
                                res.add(arg)
@@ -1732,7 +1733,7 @@ abstract class AbstractCompilerVisitor
        fun stmt(nexpr: nullable AExpr)
        do
                if nexpr == null then return
-               if nexpr.mtype == null and not nexpr.is_typed then
+               if nexpr.is_broken then
                        # Untyped expression.
                        # Might mean dead code or invalid code
                        # so aborts
@@ -2021,6 +2022,7 @@ redef class MMethodDef
        fun can_inline(v: VISITOR): Bool
        do
                if is_abstract then return true
+               if constant_value != null then return true
                var modelbuilder = v.compiler.modelbuilder
                var node = modelbuilder.mpropdef2node(self)
                if node isa APropdef then
@@ -2073,6 +2075,8 @@ redef class MMethodDef
        do
                if v.compiler.modelbuilder.toolcontext.opt_no_check_covariance.value then return
 
+               var msignature = self.msignature.as(not null)
+
                for i in [0..msignature.arity[ do
                        # skip test for vararg since the array is instantiated with the correct polymorphic type
                        if msignature.vararg_rank == i then continue
@@ -2082,11 +2086,11 @@ redef class MMethodDef
                        if not origmtype.need_anchor then continue
 
                        # get the parameter type
-                       var mtype = self.msignature.mparameters[i].mtype
+                       var mtype = msignature.mparameters[i].mtype
 
                        # generate the cast
                        # note that v decides if and how to implements the cast
-                       v.add("/* Covariant cast for argument {i} ({self.msignature.mparameters[i].name}) {arguments[i+1].inspect} isa {mtype} */")
+                       v.add("/* Covariant cast for argument {i} ({msignature.mparameters[i].name}) {arguments[i+1].inspect} isa {mtype} */")
                        v.add_cast(arguments[i+1], mtype, "covariance")
                end
        end
@@ -3306,53 +3310,68 @@ end
 redef class AForExpr
        redef fun stmt(v)
        do
-               var cl = v.expr(self.n_expr, null)
-               var it_meth = self.method_iterator
-               assert it_meth != null
-               var it = v.compile_callsite(it_meth, [cl])
-               assert it != null
+               for g in n_groups do
+                       var cl = v.expr(g.n_expr, null)
+                       var it_meth = g.method_iterator
+                       assert it_meth != null
+                       var it = v.compile_callsite(it_meth, [cl])
+                       assert it != null
+                       g.it = it
+               end
                v.add("for(;;) \{")
-               var isok_meth = self.method_is_ok
-               assert isok_meth != null
-               var ok = v.compile_callsite(isok_meth, [it])
-               assert ok != null
-               v.add("if(!{ok}) break;")
-               if self.variables.length == 1 then
-                       var item_meth = self.method_item
-                       assert item_meth != null
-                       var i = v.compile_callsite(item_meth, [it])
-                       assert i != null
-                       v.assign(v.variable(variables.first), i)
-               else if self.variables.length == 2 then
-                       var key_meth = self.method_key
-                       assert key_meth != null
-                       var i = v.compile_callsite(key_meth, [it])
-                       assert i != null
-                       v.assign(v.variable(variables[0]), i)
-                       var item_meth = self.method_item
-                       assert item_meth != null
-                       i = v.compile_callsite(item_meth, [it])
-                       assert i != null
-                       v.assign(v.variable(variables[1]), i)
-               else
-                       abort
+               for g in n_groups do
+                       var it = g.it
+                       var isok_meth = g.method_is_ok
+                       assert isok_meth != null
+                       var ok = v.compile_callsite(isok_meth, [it])
+                       assert ok != null
+                       v.add("if(!{ok}) break;")
+                       if g.variables.length == 1 then
+                               var item_meth = g.method_item
+                               assert item_meth != null
+                               var i = v.compile_callsite(item_meth, [it])
+                               assert i != null
+                               v.assign(v.variable(g.variables.first), i)
+                       else if g.variables.length == 2 then
+                               var key_meth = g.method_key
+                               assert key_meth != null
+                               var i = v.compile_callsite(key_meth, [it])
+                               assert i != null
+                               v.assign(v.variable(g.variables[0]), i)
+                               var item_meth = g.method_item
+                               assert item_meth != null
+                               i = v.compile_callsite(item_meth, [it])
+                               assert i != null
+                               v.assign(v.variable(g.variables[1]), i)
+                       else
+                               abort
+                       end
                end
                v.stmt(self.n_block)
                v.add_escape_label(continue_mark)
-               var next_meth = self.method_next
-               assert next_meth != null
-               v.compile_callsite(next_meth, [it])
+               for g in n_groups do
+                       var next_meth = g.method_next
+                       assert next_meth != null
+                       v.compile_callsite(next_meth, [g.it])
+               end
                v.add("\}")
                v.add_escape_label(break_mark)
 
-               var method_finish = self.method_finish
-               if method_finish != null then
-                       # TODO: Find a way to call this also in long escape (e.g. return)
-                       v.compile_callsite(method_finish, [it])
+               for g in n_groups do
+                       var method_finish = g.method_finish
+                       if method_finish != null then
+                               # TODO: Find a way to call this also in long escape (e.g. return)
+                               v.compile_callsite(method_finish, [g.it])
+                       end
                end
        end
 end
 
+redef class AForGroup
+       # C variable representing the iterator
+       private var it: RuntimeVariable is noinit
+end
+
 redef class AAssertExpr
        redef fun stmt(v)
        do
@@ -3650,6 +3669,7 @@ redef class ASendExpr
        do
                var recv = v.expr(self.n_expr, null)
                var callsite = self.callsite.as(not null)
+               if callsite.is_broken then return null
                var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
                return v.compile_callsite(callsite, args)
        end
@@ -3660,6 +3680,7 @@ redef class ASendReassignFormExpr
        do
                var recv = v.expr(self.n_expr, null)
                var callsite = self.callsite.as(not null)
+               if callsite.is_broken then return
                var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
 
                var value = v.expr(self.n_value, null)
@@ -3678,17 +3699,19 @@ end
 redef class ASuperExpr
        redef fun expr(v)
        do
-               var recv = v.frame.arguments.first
+               var frame = v.frame.as(not null)
+               var recv = frame.arguments.first
 
                var callsite = self.callsite
                if callsite != null then
+                       if callsite.is_broken then return null
                        var args
 
                        if self.n_args.n_exprs.is_empty then
                                # Add automatic arguments for the super init call
                                args = [recv]
                                for i in [0..callsite.msignature.arity[ do
-                                       args.add(v.frame.arguments[i+1])
+                                       args.add(frame.arguments[i+1])
                                end
                        else
                                args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
@@ -3703,7 +3726,7 @@ redef class ASuperExpr
 
                var args
                if self.n_args.n_exprs.is_empty then
-                       args = v.frame.arguments
+                       args = frame.arguments
                else
                        args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
                end
@@ -3731,6 +3754,7 @@ redef class ANewExpr
 
                var callsite = self.callsite
                if callsite == null then return recv
+               if callsite.is_broken then return null
 
                var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
                var res2 = v.compile_callsite(callsite, args)
@@ -3870,7 +3894,8 @@ end
 # Here we load an process all modules passed on the command line
 var mmodules = modelbuilder.parse(arguments)
 
-if mmodules.is_empty then return
+if mmodules.is_empty then toolcontext.quit
+
 modelbuilder.run_phases
 
 for mmodule in mmodules do