engine: handle the compilation/interpretation of multiple varargs
[nit.git] / src / interpreter / naive_interpreter.nit
index c146d11..189f293 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
@@ -216,6 +216,51 @@ class NaiveInterpreter
                return instance
        end
 
+       # Return the int8 instance associated with `val`.
+       fun int8_instance(val: Int8): Instance
+       do
+               var t = mainmodule.int8_type
+               var instance = new PrimitiveInstance[Int8](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the int16 instance associated with `val`.
+       fun int16_instance(val: Int16): Instance
+       do
+               var t = mainmodule.int16_type
+               var instance = new PrimitiveInstance[Int16](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the uint16 instance associated with `val`.
+       fun uint16_instance(val: UInt16): Instance
+       do
+               var t = mainmodule.uint16_type
+               var instance = new PrimitiveInstance[UInt16](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the int32 instance associated with `val`.
+       fun int32_instance(val: Int32): Instance
+       do
+               var t = mainmodule.int32_type
+               var instance = new PrimitiveInstance[Int32](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
+       # Return the uint32 instance associated with `val`.
+       fun uint32_instance(val: UInt32): Instance
+       do
+               var t = mainmodule.uint32_type
+               var instance = new PrimitiveInstance[UInt32](t, val)
+               init_instance_primitive(instance)
+               return instance
+       end
+
        # Return the char instance associated with `val`.
        fun char_instance(val: Char): Instance
        do
@@ -275,10 +320,10 @@ class NaiveInterpreter
        # Return a new native string initialized with `txt`
        fun native_string_instance(txt: String): Instance
        do
-               var instance = native_string_instance_len(txt.length+1)
+               var instance = native_string_instance_len(txt.bytelen+1)
                var val = instance.val
-               val[txt.length] = '\0'
-               txt.to_cstring.copy_to(val, txt.length, 0, 0)
+               val[txt.bytelen] = 0u8
+               txt.to_cstring.copy_to(val, txt.bytelen, 0, 0)
 
                return instance
        end
@@ -298,7 +343,7 @@ class NaiveInterpreter
        fun string_instance(txt: String): Instance
        do
                var nat = native_string_instance(txt)
-               var res = self.send(self.force_get_primitive_method("to_s_with_length", nat.mtype), [nat, self.int_instance(txt.length)])
+               var res = self.send(self.force_get_primitive_method("to_s_full", nat.mtype), [nat, self.int_instance(txt.bytelen), self.int_instance(txt.length)])
                assert res != null
                return res
        end
@@ -426,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)
@@ -481,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
@@ -493,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
@@ -521,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
@@ -656,6 +704,26 @@ abstract class Instance
        # else aborts
        fun to_b: Byte do abort
 
+       # Return the integer value if the instance is a int8.
+       # else aborts
+       fun to_i8: Int8 do abort
+
+       # Return the integer value if the instance is a int16.
+       # else aborts
+       fun to_i16: Int16 do abort
+
+       # Return the integer value if the instance is a uint16.
+       # else aborts
+       fun to_u16: UInt16 do abort
+
+       # Return the integer value if the instance is a int32.
+       # else aborts
+       fun to_i32: Int32 do abort
+
+       # Return the integer value if the instance is a uint32.
+       # else aborts
+       fun to_u32: UInt32 do abort
+
        # The real value encapsulated if the instance is primitive.
        # Else aborts.
        fun val: nullable Object do abort
@@ -703,6 +771,16 @@ class PrimitiveInstance[E]
        redef fun to_f do return val.as(Float)
 
        redef fun to_b do return val.as(Byte)
+
+       redef fun to_i8 do return val.as(Int8)
+
+       redef fun to_i16 do return val.as(Int16)
+
+       redef fun to_u16 do return val.as(UInt16)
+
+       redef fun to_i32 do return val.as(Int32)
+
+       redef fun to_u32 do return val.as(UInt32)
 end
 
 # Information about local variables in a running method
@@ -874,93 +952,101 @@ redef class AMethPropdef
                else if cname == "Int" then
                        var recvval = args[0].to_i
                        if pname == "unary -" then
-                               return v.int_instance(-args[0].to_i)
+                               return v.int_instance(-recvval)
                        else if pname == "unary +" then
                                return args[0]
                        else if pname == "+" then
-                               return v.int_instance(args[0].to_i + args[1].to_i)
+                               return v.int_instance(recvval + args[1].to_i)
                        else if pname == "-" then
-                               return v.int_instance(args[0].to_i - args[1].to_i)
+                               return v.int_instance(recvval - args[1].to_i)
                        else if pname == "*" then
-                               return v.int_instance(args[0].to_i * args[1].to_i)
+                               return v.int_instance(recvval * args[1].to_i)
                        else if pname == "%" then
-                               return v.int_instance(args[0].to_i % args[1].to_i)
+                               return v.int_instance(recvval % args[1].to_i)
                        else if pname == "/" then
-                               return v.int_instance(args[0].to_i / args[1].to_i)
+                               return v.int_instance(recvval / args[1].to_i)
                        else if pname == "<" then
-                               return v.bool_instance(args[0].to_i < args[1].to_i)
+                               return v.bool_instance(recvval < args[1].to_i)
                        else if pname == ">" then
-                               return v.bool_instance(args[0].to_i > args[1].to_i)
+                               return v.bool_instance(recvval > args[1].to_i)
                        else if pname == "<=" then
-                               return v.bool_instance(args[0].to_i <= args[1].to_i)
+                               return v.bool_instance(recvval <= args[1].to_i)
                        else if pname == ">=" then
-                               return v.bool_instance(args[0].to_i >= args[1].to_i)
+                               return v.bool_instance(recvval >= args[1].to_i)
                        else if pname == "<=>" then
-                               return v.int_instance(args[0].to_i <=> args[1].to_i)
-                       else if pname == "ascii" then
-                               return v.char_instance(args[0].to_i.ascii)
+                               return v.int_instance(recvval <=> args[1].to_i)
                        else if pname == "to_f" then
-                               return v.float_instance(args[0].to_i.to_f)
+                               return v.float_instance(recvval.to_f)
                        else if pname == "to_b" then
-                               return v.byte_instance(args[0].to_i.to_b)
-                       else if pname == "lshift" then
-                               return v.int_instance(args[0].to_i.lshift(args[1].to_i))
-                       else if pname == "rshift" then
-                               return v.int_instance(args[0].to_i.rshift(args[1].to_i))
+                               return v.byte_instance(recvval.to_b)
+                       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_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
                        else if pname == "rand" then
                                var res = recvval.rand
                                return v.int_instance(res)
-                       else if pname == "bin_and" then
-                               return v.int_instance(args[0].to_i.bin_and(args[1].to_i))
-                       else if pname == "bin_or" then
-                               return v.int_instance(args[0].to_i.bin_or(args[1].to_i))
-                       else if pname == "bin_xor" then
-                               return v.int_instance(args[0].to_i.bin_xor(args[1].to_i))
-                       else if pname == "bin_not" then
-                               return v.int_instance(args[0].to_i.bin_not)
                        end
                else if cname == "Byte" then
                        var recvval = args[0].to_b
                        if pname == "unary -" then
-                               return v.byte_instance(-args[0].to_b)
+                               return v.byte_instance(-recvval)
                        else if pname == "unary +" then
                                return args[0]
                        else if pname == "+" then
-                               return v.byte_instance(args[0].to_b + args[1].to_b)
+                               return v.byte_instance(recvval + args[1].to_b)
                        else if pname == "-" then
-                               return v.byte_instance(args[0].to_b - args[1].to_b)
+                               return v.byte_instance(recvval - args[1].to_b)
                        else if pname == "*" then
-                               return v.byte_instance(args[0].to_b * args[1].to_b)
+                               return v.byte_instance(recvval * args[1].to_b)
                        else if pname == "%" then
-                               return v.byte_instance(args[0].to_b % args[1].to_b)
+                               return v.byte_instance(recvval % args[1].to_b)
                        else if pname == "/" then
-                               return v.byte_instance(args[0].to_b / args[1].to_b)
+                               return v.byte_instance(recvval / args[1].to_b)
                        else if pname == "<" then
-                               return v.bool_instance(args[0].to_b < args[1].to_b)
+                               return v.bool_instance(recvval < args[1].to_b)
                        else if pname == ">" then
-                               return v.bool_instance(args[0].to_b > args[1].to_b)
+                               return v.bool_instance(recvval > args[1].to_b)
                        else if pname == "<=" then
-                               return v.bool_instance(args[0].to_b <= args[1].to_b)
+                               return v.bool_instance(recvval <= args[1].to_b)
                        else if pname == ">=" then
-                               return v.bool_instance(args[0].to_b >= args[1].to_b)
+                               return v.bool_instance(recvval >= args[1].to_b)
                        else if pname == "<=>" then
-                               return v.int_instance(args[0].to_b <=> args[1].to_b)
+                               return v.int_instance(recvval <=> args[1].to_b)
                        else if pname == "to_f" then
-                               return v.float_instance(args[0].to_b.to_f)
+                               return v.float_instance(recvval.to_f)
                        else if pname == "to_i" then
-                               return v.int_instance(args[0].to_b.to_i)
-                       else if pname == "lshift" then
-                               return v.byte_instance(args[0].to_b.lshift(args[1].to_i))
-                       else if pname == "rshift" then
-                               return v.byte_instance(args[0].to_b.rshift(args[1].to_i))
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "<<" then
+                               return v.byte_instance(recvval << args[1].to_i)
+                       else if pname == ">>" then
+                               return v.byte_instance(recvval >> args[1].to_i)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
                        else if pname == "byte_to_s_len" then
                                return v.int_instance(recvval.to_s.length)
                        end
                else if cname == "Char" then
                        var recv = args[0].val.as(Char)
-                       if pname == "ascii" then
-                               return v.int_instance(recv.ascii)
-                       else if pname == "successor" then
+                       if pname == "successor" then
                                return v.char_instance(recv.successor(args[1].to_i))
                        else if pname == "predecessor" then
                                return v.char_instance(recv.predecessor(args[1].to_i))
@@ -1001,6 +1087,16 @@ redef class AMethPropdef
                                return v.int_instance(recv.to_i)
                        else if pname == "to_b" then
                                return v.byte_instance(recv.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recv.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recv.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recv.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recv.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recv.to_u32)
                        else if pname == "cos" then
                                return v.float_instance(args[0].to_f.cos)
                        else if pname == "sin" then
@@ -1041,10 +1137,10 @@ redef class AMethPropdef
                        var recvval = args.first.val.as(NativeString)
                        if pname == "[]" then
                                var arg1 = args[1].to_i
-                               return v.char_instance(recvval[arg1])
+                               return v.byte_instance(recvval[arg1])
                        else if pname == "[]=" then
                                var arg1 = args[1].to_i
-                               recvval[arg1] = args[2].val.as(Char)
+                               recvval[arg1] = args[2].val.as(Byte)
                                return null
                        else if pname == "copy_to" then
                                # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
@@ -1057,8 +1153,8 @@ redef class AMethPropdef
                        else if pname == "atoi" then
                                return v.int_instance(recvval.atoi)
                        else if pname == "fast_cstring" then
-                               var ns = recvval.to_s.substring_from(args[1].to_i)
-                               return v.native_string_instance(ns)
+                               var ns = recvval.fast_cstring(args[1].to_i)
+                               return v.native_string_instance(ns.to_s)
                        end
                else if pname == "calloc_string" then
                        return v.native_string_instance_len(args[1].to_i)
@@ -1081,6 +1177,271 @@ redef class AMethPropdef
                                recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
                                return null
                        end
+               else if cname == "Int8" then
+                       var recvval = args[0].to_i8
+                       if pname == "unary -" then
+                               return v.int8_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int8_instance(recvval + args[1].to_i8)
+                       else if pname == "-" then
+                               return v.int8_instance(recvval - args[1].to_i8)
+                       else if pname == "*" then
+                               return v.int8_instance(recvval * args[1].to_i8)
+                       else if pname == "%" then
+                               return v.int8_instance(recvval % args[1].to_i8)
+                       else if pname == "/" then
+                               return v.int8_instance(recvval / args[1].to_i8)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i8)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i8)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i8)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i8)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i8)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int8_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int8_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int8_instance(recvval & args[1].to_i8)
+                       else if pname == "|" then
+                               return v.int8_instance(recvval | args[1].to_i8)
+                       else if pname == "^" then
+                               return v.int8_instance(recvval ^ args[1].to_i8)
+                       else if pname == "unary ~" then
+                               return v.int8_instance(~recvval)
+                       end
+               else if cname == "Int16" then
+                       var recvval = args[0].to_i16
+                       if pname == "unary -" then
+                               return v.int16_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int16_instance(recvval + args[1].to_i16)
+                       else if pname == "-" then
+                               return v.int16_instance(recvval - args[1].to_i16)
+                       else if pname == "*" then
+                               return v.int16_instance(recvval * args[1].to_i16)
+                       else if pname == "%" then
+                               return v.int16_instance(recvval % args[1].to_i16)
+                       else if pname == "/" then
+                               return v.int16_instance(recvval / args[1].to_i16)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i16)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i16)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i16)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i16)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i16)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int16_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int16_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int16_instance(recvval & args[1].to_i16)
+                       else if pname == "|" then
+                               return v.int16_instance(recvval | args[1].to_i16)
+                       else if pname == "^" then
+                               return v.int16_instance(recvval ^ args[1].to_i16)
+                       else if pname == "unary ~" then
+                               return v.int16_instance(~recvval)
+                       end
+               else if cname == "UInt16" then
+                       var recvval = args[0].to_u16
+                       if pname == "unary -" then
+                               return v.uint16_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.uint16_instance(recvval + args[1].to_u16)
+                       else if pname == "-" then
+                               return v.uint16_instance(recvval - args[1].to_u16)
+                       else if pname == "*" then
+                               return v.uint16_instance(recvval * args[1].to_u16)
+                       else if pname == "%" then
+                               return v.uint16_instance(recvval % args[1].to_u16)
+                       else if pname == "/" then
+                               return v.uint16_instance(recvval / args[1].to_u16)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_u16)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_u16)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_u16)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_u16)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_u16)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.uint16_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.uint16_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.uint16_instance(recvval & args[1].to_u16)
+                       else if pname == "|" then
+                               return v.uint16_instance(recvval | args[1].to_u16)
+                       else if pname == "^" then
+                               return v.uint16_instance(recvval ^ args[1].to_u16)
+                       else if pname == "unary ~" then
+                               return v.uint16_instance(~recvval)
+                       end
+               else if cname == "Int32" then
+                       var recvval = args[0].to_i32
+                       if pname == "unary -" then
+                               return v.int32_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.int32_instance(recvval + args[1].to_i32)
+                       else if pname == "-" then
+                               return v.int32_instance(recvval - args[1].to_i32)
+                       else if pname == "*" then
+                               return v.int32_instance(recvval * args[1].to_i32)
+                       else if pname == "%" then
+                               return v.int32_instance(recvval % args[1].to_i32)
+                       else if pname == "/" then
+                               return v.int32_instance(recvval / args[1].to_i32)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_i32)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_i32)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_i32)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_i32)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_i32)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_u32" then
+                               return v.uint32_instance(recvval.to_u32)
+                       else if pname == "<<" then
+                               return v.int32_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.int32_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.int32_instance(recvval & args[1].to_i32)
+                       else if pname == "|" then
+                               return v.int32_instance(recvval | args[1].to_i32)
+                       else if pname == "^" then
+                               return v.int32_instance(recvval ^ args[1].to_i32)
+                       else if pname == "unary ~" then
+                               return v.int32_instance(~recvval)
+                       end
+               else if cname == "UInt32" then
+                       var recvval = args[0].to_u32
+                       if pname == "unary -" then
+                               return v.uint32_instance(-recvval)
+                       else if pname == "unary +" then
+                               return args[0]
+                       else if pname == "+" then
+                               return v.uint32_instance(recvval + args[1].to_u32)
+                       else if pname == "-" then
+                               return v.uint32_instance(recvval - args[1].to_u32)
+                       else if pname == "*" then
+                               return v.uint32_instance(recvval * args[1].to_u32)
+                       else if pname == "%" then
+                               return v.uint32_instance(recvval % args[1].to_u32)
+                       else if pname == "/" then
+                               return v.uint32_instance(recvval / args[1].to_u32)
+                       else if pname == "<" then
+                               return v.bool_instance(recvval < args[1].to_u32)
+                       else if pname == ">" then
+                               return v.bool_instance(recvval > args[1].to_u32)
+                       else if pname == "<=" then
+                               return v.bool_instance(recvval <= args[1].to_u32)
+                       else if pname == ">=" then
+                               return v.bool_instance(recvval >= args[1].to_u32)
+                       else if pname == "<=>" then
+                               return v.int_instance(recvval <=> args[1].to_u32)
+                       else if pname == "to_f" then
+                               return v.float_instance(recvval.to_f)
+                       else if pname == "to_i" then
+                               return v.int_instance(recvval.to_i)
+                       else if pname == "to_b" then
+                               return v.byte_instance(recvval.to_b)
+                       else if pname == "to_i8" then
+                               return v.int8_instance(recvval.to_i8)
+                       else if pname == "to_i16" then
+                               return v.int16_instance(recvval.to_i16)
+                       else if pname == "to_u16" then
+                               return v.uint16_instance(recvval.to_u16)
+                       else if pname == "to_i32" then
+                               return v.int32_instance(recvval.to_i32)
+                       else if pname == "<<" then
+                               return v.uint32_instance(recvval << (args[1].to_i))
+                       else if pname == ">>" then
+                               return v.uint32_instance(recvval >> (args[1].to_i))
+                       else if pname == "&" then
+                               return v.uint32_instance(recvval & args[1].to_u32)
+                       else if pname == "|" then
+                               return v.uint32_instance(recvval | args[1].to_u32)
+                       else if pname == "^" then
+                               return v.uint32_instance(recvval ^ args[1].to_u32)
+                       else if pname == "unary ~" then
+                               return v.uint32_instance(~recvval)
+                       end
                else if pname == "native_argc" then
                        return v.int_instance(v.arguments.length)
                else if pname == "native_argv" then
@@ -1399,37 +1760,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
@@ -1515,17 +1886,17 @@ redef class AOrElseExpr
        end
 end
 
-redef class AIntExpr
-       redef fun expr(v)
-       do
-               return v.int_instance(self.value.as(not null))
-       end
-end
-
-redef class AByteExpr
+redef class AIntegerExpr
        redef fun expr(v)
        do
-               return v.byte_instance(self.value.as(not null))
+               if value isa Int then return v.int_instance(value.as(Int))
+               if value isa Byte then return v.byte_instance(value.as(Byte))
+               if value isa Int8 then return v.int8_instance(value.as(Int8))
+               if value isa Int16 then return v.int16_instance(value.as(Int16))
+               if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
+               if value isa Int32 then return v.int32_instance(value.as(Int32))
+               if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
+               return null
        end
 end