Merge: Multi iterators
[nit.git] / src / compiler / abstract_compiler.nit
index 8850b86..55b644f 100644 (file)
@@ -654,6 +654,7 @@ abstract class AbstractCompiler
                self.header.add_decl("#include <sys/types.h>\n")
                self.header.add_decl("#include <unistd.h>\n")
                self.header.add_decl("#include <stdint.h>\n")
+               self.header.add_decl("#include <inttypes.h>\n")
                self.header.add_decl("#include \"gc_chooser.h\"")
                self.header.add_decl("#ifdef ANDROID")
                self.header.add_decl("  #include <android/log.h>")
@@ -1146,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
@@ -1506,15 +1508,55 @@ abstract class AbstractCompilerVisitor
                return res
        end
 
+       # Generate an int8 value
+       fun int8_instance(value: Int8): RuntimeVariable
+       do
+               var t = mmodule.int8_type
+               var res = new RuntimeVariable("((int8_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate an int16 value
+       fun int16_instance(value: Int16): RuntimeVariable
+       do
+               var t = mmodule.int16_type
+               var res = new RuntimeVariable("((int16_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate a uint16 value
+       fun uint16_instance(value: UInt16): RuntimeVariable
+       do
+               var t = mmodule.uint16_type
+               var res = new RuntimeVariable("((uint16_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate an int32 value
+       fun int32_instance(value: Int32): RuntimeVariable
+       do
+               var t = mmodule.int32_type
+               var res = new RuntimeVariable("((int32_t){value.to_s})", t, t)
+               return res
+       end
+
+       # Generate a uint32 value
+       fun uint32_instance(value: UInt32): RuntimeVariable
+       do
+               var t = mmodule.uint32_type
+               var res = new RuntimeVariable("((uint32_t){value.to_s})", t, t)
+               return res
+       end
+
        # Generate a char value
        fun char_instance(value: Char): RuntimeVariable
        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
 
@@ -1557,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
@@ -1690,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
@@ -1905,8 +1948,18 @@ redef class MClassType
                        return "uint32_t"
                else if mclass.name == "Float" then
                        return "double"
+               else if mclass.name == "Int8" then
+                       return "int8_t"
                else if mclass.name == "Byte" then
                        return "unsigned char"
+               else if mclass.name == "Int16" then
+                       return "int16_t"
+               else if mclass.name == "UInt16" then
+                       return "uint16_t"
+               else if mclass.name == "Int32" then
+                       return "int32_t"
+               else if mclass.name == "UInt32" then
+                       return "uint32_t"
                else if mclass.name == "NativeString" then
                        return "char*"
                else if mclass.name == "NativeArray" then
@@ -1937,8 +1990,18 @@ redef class MClassType
                        return "c"
                else if mclass.name == "Float" then
                        return "d"
+               else if mclass.name == "Int8" then
+                       return "i8"
                else if mclass.name == "Byte" then
                        return "b"
+               else if mclass.name == "Int16" then
+                       return "i16"
+               else if mclass.name == "UInt16" then
+                       return "u16"
+               else if mclass.name == "Int32" then
+                       return "i32"
+               else if mclass.name == "UInt32" then
+                       return "u32"
                else if mclass.name == "NativeString" then
                        return "str"
                else if mclass.name == "NativeArray" then
@@ -2141,12 +2204,6 @@ redef class AMethPropdef
                        else if pname == "%" then
                                v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
                                return true
-                       else if pname == "lshift" then
-                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
-                               return true
-                       else if pname == "rshift" then
-                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
-                               return true
                        else if pname == "==" then
                                v.ret(v.equal_test(arguments[0], arguments[1]))
                                return true
@@ -2166,15 +2223,27 @@ redef class AMethPropdef
                        else if pname == ">=" then
                                v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
                                return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        else if pname == "to_f" then
                                v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
                                return true
                        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
@@ -2208,9 +2277,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
@@ -2240,12 +2306,6 @@ redef class AMethPropdef
                        else if pname == "%" then
                                v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", ret.as(not null)))
                                return true
-                       else if pname == "lshift" then
-                               v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
-                               return true
-                       else if pname == "rshift" then
-                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
-                               return true
                        else if pname == "==" then
                                v.ret(v.equal_test(arguments[0], arguments[1]))
                                return true
@@ -2271,8 +2331,20 @@ 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)))
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
                                return true
                        end
                else if cname == "Bool" then
@@ -2346,6 +2418,21 @@ 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 == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
                        end
                else if cname == "NativeString" then
                        if pname == "[]" then
@@ -2370,6 +2457,441 @@ redef class AMethPropdef
                else if cname == "NativeArray" then
                        v.native_array_def(pname, ret, arguments)
                        return true
+               else if cname == "Int8" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi8 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", 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
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", 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
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", 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
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", 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
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){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
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", 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
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "Int16" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi16 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", 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
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", 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
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", 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
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", 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
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){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
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", 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
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "UInt16" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIu16 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", 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
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", 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
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", 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
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", 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
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){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
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", 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
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "Int32" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIi32 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", 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
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", 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
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", 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
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", 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
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u32" then
+                               v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){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
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", 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
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
+               else if cname == "UInt32" then
+                       if pname == "output" then
+                               v.add("printf(\"%\"PRIu32 \"\\n\", {arguments.first});")
+                               return true
+                       else if pname == "object_id" then
+                               v.ret(v.new_expr("(long){arguments.first}", 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
+                       else if pname == "-" then
+                               v.ret(v.new_expr("{arguments[0]} - {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary -" then
+                               v.ret(v.new_expr("-{arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "unary +" then
+                               v.ret(arguments[0])
+                               return true
+                       else if pname == "*" then
+                               v.ret(v.new_expr("{arguments[0]} * {arguments[1]}", 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
+                       else if pname == "%" then
+                               v.ret(v.new_expr("{arguments[0]} % {arguments[1]}", 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
+                       else if pname == ">>" then
+                               v.ret(v.new_expr("{arguments[0]} >> {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "==" then
+                               v.ret(v.equal_test(arguments[0], arguments[1]))
+                               return true
+                       else if pname == "!=" then
+                               var res = v.equal_test(arguments[0], arguments[1])
+                               v.ret(v.new_expr("!{res}", 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
+                       else if pname == ">" then
+                               v.ret(v.new_expr("{arguments[0]} > {arguments[1]}", 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
+                       else if pname == ">=" then
+                               v.ret(v.new_expr("{arguments[0]} >= {arguments[1]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i" then
+                               v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_b" then
+                               v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i8" then
+                               v.ret(v.new_expr("(int8_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i16" then
+                               v.ret(v.new_expr("(int16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_u16" then
+                               v.ret(v.new_expr("(uint16_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_i32" then
+                               v.ret(v.new_expr("(int32_t){arguments[0]}", ret.as(not null)))
+                               return true
+                       else if pname == "to_f" then
+                               v.ret(v.new_expr("(double){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
+                       else if pname == "|" then
+                               v.ret(v.new_expr("{arguments[0]} | {arguments[1]}", 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
+                       else if pname == "unary ~" then
+                               v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
+                               return true
+                       end
                end
                if pname == "exit" then
                        v.add("exit({arguments[1]});")
@@ -2785,53 +3307,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
@@ -2918,12 +3455,18 @@ redef class AOrElseExpr
        end
 end
 
-redef class AIntExpr
-       redef fun expr(v) do return v.int_instance(self.value.as(not null))
-end
-
-redef class AByteExpr
-       redef fun expr(v) do return v.byte_instance(self.value.as(not null))
+redef class AIntegerExpr
+       redef fun expr(v) do
+               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))
+               # Should never happen
+               abort
+       end
 end
 
 redef class AFloatExpr
@@ -3123,6 +3666,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
@@ -3133,6 +3677,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)
@@ -3155,6 +3700,7 @@ redef class ASuperExpr
 
                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
@@ -3204,6 +3750,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)
@@ -3343,7 +3890,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