src: remove some `call on nullable` warning with a non-null local variable
[nit.git] / src / compiler / abstract_compiler.nit
index b58d4a3..aa24185 100644 (file)
@@ -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
@@ -1552,10 +1553,10 @@ abstract class AbstractCompilerVisitor
        do
                var t = mmodule.char_type
 
-               if value.ascii < 128 then
+               if value.code_point < 128 then
                        return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
                else
-                       return new RuntimeVariable("{value.ascii}", t, t)
+                       return new RuntimeVariable("{value.code_point}", t, t)
                end
        end
 
@@ -1598,8 +1599,9 @@ abstract class AbstractCompilerVisitor
                var native_mtype = mmodule.native_string_type
                var nat = self.new_var(native_mtype)
                self.add("{nat} = \"{string.escape_to_c}\";")
-               var length = self.int_instance(string.bytelen)
-               self.add("{res} = {self.send(self.get_property("to_s_with_length", native_mtype), [nat, length]).as(not null)};")
+               var bytelen = self.int_instance(string.bytelen)
+               var unilen = self.int_instance(string.length)
+               self.add("{res} = {self.send(self.get_property("to_s_full", native_mtype), [nat, bytelen, unilen]).as(not null)};")
                self.add("{name} = {res};")
                self.add("\}")
                return res
@@ -1731,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
@@ -2072,6 +2074,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
@@ -2081,11 +2085,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
@@ -2242,9 +2246,6 @@ redef class AMethPropdef
                        else if pname == "to_b" then
                                v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "Char" then
                        if pname == "object_id" then
@@ -2278,9 +2279,6 @@ redef class AMethPropdef
                        else if pname == "to_i" then
                                v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "Byte" then
                        if pname == "output" then
@@ -2350,9 +2348,6 @@ redef class AMethPropdef
                        else if pname == "to_u32" then
                                v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "Bool" then
                        if pname == "output" then
@@ -2538,9 +2533,6 @@ redef class AMethPropdef
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        else if pname == "&" then
                                v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
                                return true
@@ -2640,9 +2632,6 @@ redef class AMethPropdef
                        else if pname == "unary ~" then
                                v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "UInt16" then
                        if pname == "output" then
@@ -2730,9 +2719,6 @@ redef class AMethPropdef
                        else if pname == "unary ~" then
                                v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "Int32" then
                        if pname == "output" then
@@ -2820,9 +2806,6 @@ redef class AMethPropdef
                        else if pname == "unary ~" then
                                v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        end
                else if cname == "UInt32" then
                        if pname == "output" then
@@ -2910,9 +2893,6 @@ redef class AMethPropdef
                        else if pname == "unary ~" then
                                v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
                                return true
-                       else if pname == "ascii" then
-                               v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
-                               return true
                        end
                end
                if pname == "exit" then
@@ -3329,53 +3309,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
@@ -3673,6 +3668,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
@@ -3683,6 +3679,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)
@@ -3701,17 +3698,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)
@@ -3726,7 +3725,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
@@ -3754,6 +3753,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)
@@ -3893,7 +3893,12 @@ 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.check_errors
+       toolcontext.errors_info
+       if toolcontext.error_count > 0 then exit(1) else exit(0)
+end
+
 modelbuilder.run_phases
 
 for mmodule in mmodules do