niti: rename `args` as `arguments` in `call`
[nit.git] / src / interpreter / naive_interpreter.nit
index da7b288..bbe07d1 100644 (file)
@@ -25,7 +25,7 @@ import primitive_types
 
 redef class ToolContext
        # --discover-call-trace
-       var opt_discover_call_trace = new OptionBool("Trace calls of the first invocation of a method", "--discover-call-trace")
+       var opt_discover_call_trace = new OptionBool("Trace calls of the first invocation of methods", "--discover-call-trace")
 
        redef init
        do
@@ -157,7 +157,7 @@ class NaiveInterpreter
                        n.debug("inconsitance: no value and not escaping.")
                end
                var implicit_cast_to = n.implicit_cast_to
-               if implicit_cast_to != null then
+               if i != null and implicit_cast_to != null then
                        var mtype = self.unanchor_type(implicit_cast_to)
                        if not self.is_subtype(i.mtype, mtype) then n.fatal(self, "Cast failed. Expected `{implicit_cast_to}`, got `{i.mtype}`")
                end
@@ -471,8 +471,8 @@ class NaiveInterpreter
                                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.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
                                var arg = self.array_instance(vararg, elttype)
                                res.add(arg)
@@ -526,10 +526,12 @@ class NaiveInterpreter
        # Execute type checks of covariant parameters
        fun parameter_check(node: ANode, mpropdef: MMethodDef, args: Array[Instance])
        do
-               var msignature = mpropdef.msignature
+               var msignature = mpropdef.msignature.as(not null)
                for i in [0..msignature.arity[ do
+                       var mp = msignature.mparameters[i]
+
                        # skip test for vararg since the array is instantiated with the correct polymorphic type
-                       if msignature.vararg_rank == i then continue
+                       if mp.is_vararg then continue
 
                        # skip if the cast is not required
                        var origmtype =  mpropdef.mproperty.intro.msignature.mparameters[i].mtype
@@ -538,7 +540,7 @@ class NaiveInterpreter
                        #print "{mpropdef}: {mpropdef.mproperty.intro.msignature.mparameters[i]}"
 
                        # get the parameter type
-                       var mtype = msignature.mparameters[i].mtype
+                       var mtype = mp.mtype
                        var anchor = args.first.mtype.as(MClassType)
                        var amtype = mtype.anchor_to(self.mainmodule, anchor)
                        if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
@@ -566,6 +568,7 @@ class NaiveInterpreter
        # Use this method, instead of `send` to execute and control the additional behavior of the call-sites
        fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
        do
+               if callsite == null then return null
                var initializers = callsite.mpropdef.initializers
                if not initializers.is_empty then
                        var recv = arguments.first
@@ -873,21 +876,27 @@ redef class AMethPropdef
                        v.call(superpd, arguments)
                end
 
+               # First, try intern
                if mpropdef.is_intern or mpropdef.is_extern then
                        var res = intern_call(v, mpropdef, arguments)
                        if res != v.error_instance then return res
                end
-
+               # Then, try extern
+               if mpropdef.is_extern then
+                       var res = call_extern(v, mpropdef, arguments, f)
+                       if res != v.error_instance then return res
+               end
+               # Else try block
                if n_block != null then
                        v.stmt(self.n_block)
                        return null
                end
 
+               # Fail if nothing succeed
                if mpropdef.is_intern then
                        fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
                else if mpropdef.is_extern then
-                       var res = call_extern(v, mpropdef, arguments, f)
-                       if res != v.error_instance then return res
+                       fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
                else
                        fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
                end
@@ -897,7 +906,6 @@ redef class AMethPropdef
        # Call this extern method
        protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
        do
-               fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
                return v.error_instance
        end
 
@@ -972,6 +980,10 @@ redef class AMethPropdef
                                return v.bool_instance(recvval >= args[1].to_i)
                        else if pname == "<=>" then
                                return v.int_instance(recvval <=> args[1].to_i)
+                       else if pname == "&" then
+                               return v.int_instance(recvval & args[1].to_i)
+                       else if pname == "|" then
+                               return v.int_instance(recvval | args[1].to_i)
                        else if pname == "to_f" then
                                return v.float_instance(recvval.to_f)
                        else if pname == "to_b" then
@@ -1020,6 +1032,10 @@ redef class AMethPropdef
                                return v.bool_instance(recvval >= args[1].to_b)
                        else if pname == "<=>" then
                                return v.int_instance(recvval <=> args[1].to_b)
+                       else if pname == "&" then
+                               return v.byte_instance(recvval & args[1].to_b)
+                       else if pname == "|" then
+                               return v.byte_instance(recvval | args[1].to_b)
                        else if pname == "to_f" then
                                return v.float_instance(recvval.to_f)
                        else if pname == "to_i" then
@@ -1152,6 +1168,12 @@ redef class AMethPropdef
                        else if pname == "fast_cstring" then
                                var ns = recvval.fast_cstring(args[1].to_i)
                                return v.native_string_instance(ns.to_s)
+                       else if pname == "fetch_4_chars" then
+                               return v.int_instance(args[0].val.as(NativeString).fetch_4_chars(args[1].to_i))
+                       else if pname == "fetch_4_hchars" then
+                               return v.int_instance(args[0].val.as(NativeString).fetch_4_hchars(args[1].to_i))
+                       else if pname == "utf8_length" then
+                               return v.int_instance(args[0].val.as(NativeString).utf8_length(args[1].to_i, args[2].to_i))
                        end
                else if pname == "calloc_string" then
                        return v.native_string_instance_len(args[1].to_i)
@@ -1531,14 +1553,14 @@ end
 
 redef class AClassdef
        # Execute an implicit `mpropdef` associated with the current node.
-       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
+       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
        do
                if mpropdef.mproperty.is_root_init then
-                       assert args.length == 1
+                       assert arguments.length == 1
                        if not mpropdef.is_intro then
                                # standard call-next-method
-                               var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
-                               v.call(superpd, args)
+                               var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
+                               v.call(superpd, arguments)
                        end
                        return null
                else
@@ -1757,37 +1779,47 @@ end
 redef class AForExpr
        redef fun stmt(v)
        do
-               var col = v.expr(self.n_expr)
-               if col == null then return
-               if col.mtype isa MNullType then fatal(v, "Receiver is null")
+               var iters = new Array[Instance]
+
+               for g in n_groups do
+                       var col = v.expr(g.n_expr)
+                       if col == null then return
+                       if col.mtype isa MNullType then fatal(v, "Receiver is null")
+
+                       var iter = v.callsite(g.method_iterator, [col]).as(not null)
+                       iters.add iter
+               end
 
-               #self.debug("col {col}")
-               var iter = v.callsite(method_iterator, [col]).as(not null)
-               #self.debug("iter {iter}")
                loop
-                       var isok = v.callsite(method_is_ok, [iter]).as(not null)
-                       if not isok.is_true then break
-                       if self.variables.length == 1 then
-                               var item = v.callsite(method_item, [iter]).as(not null)
-                               #self.debug("item {item}")
-                               v.write_variable(self.variables.first, item)
-                       else if self.variables.length == 2 then
-                               var key = v.callsite(method_key, [iter]).as(not null)
-                               v.write_variable(self.variables[0], key)
-                               var item = v.callsite(method_item, [iter]).as(not null)
-                               v.write_variable(self.variables[1], item)
-                       else
-                               abort
+                       for g in n_groups, iter in iters do
+                               var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
+                               if not isok.is_true then break label
+                               if g.variables.length == 1 then
+                                       var item = v.callsite(g.method_item, [iter]).as(not null)
+                                       #self.debug("item {item}")
+                                       v.write_variable(g.variables.first, item)
+                               else if g.variables.length == 2 then
+                                       var key = v.callsite(g.method_key, [iter]).as(not null)
+                                       v.write_variable(g.variables[0], key)
+                                       var item = v.callsite(g.method_item, [iter]).as(not null)
+                                       v.write_variable(g.variables[1], item)
+                               else
+                                       abort
+                               end
                        end
                        v.stmt(self.n_block)
                        if v.is_escape(self.break_mark) then break
                        v.is_escape(self.continue_mark) # Clear the break
                        if v.is_escaping then break
-                       v.callsite(method_next, [iter])
-               end
-               var method_finish = self.method_finish
-               if method_finish != null then
-                       v.callsite(method_finish, [iter])
+                       for g in n_groups, iter in iters do
+                               v.callsite(g.method_next, [iter])
+                       end
+               end label
+               for g in n_groups, iter in iters do
+                       var method_finish = g.method_finish
+                       if method_finish != null then
+                               v.callsite(method_finish, [iter])
+                       end
                end
        end
 end