X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 3dcfab1..560dc60 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -28,15 +28,15 @@ import counter # Add compiling options redef class ToolContext # --output - var opt_output = new OptionString("Output file", "-o", "--output") + var opt_output = new OptionString("Filename of the generated executable", "-o", "--output") # --dir var opt_dir = new OptionString("Output directory", "--dir") # --no-cc - var opt_no_cc = new OptionBool("Do not invoke C compiler", "--no-cc") + var opt_no_cc = new OptionBool("Do not invoke the C compiler", "--no-cc") # --no-main var opt_no_main = new OptionBool("Do not generate main entry point", "--no-main") # --make-flags - var opt_make_flags = new OptionString("Additional options to make", "--make-flags") + var opt_make_flags = new OptionString("Additional options to the `make` command", "--make-flags") # --max-c-lines var opt_max_c_lines = new OptionInt("Maximum number of lines in generated C files. Use 0 for unlimited", 10000, "--max-c-lines") # --group-c-files @@ -50,7 +50,7 @@ redef class ToolContext # --no-check-attr-isset var opt_no_check_attr_isset = new OptionBool("Disable isset tests before each attribute access (dangerous)", "--no-check-attr-isset") # --no-check-assert - var opt_no_check_assert = new OptionBool("Disable the evaluation of explicit 'assert' and 'as' (dangerous)", "--no-check-assert") + var opt_no_check_assert = new OptionBool("Disable the evaluation of explicit `assert` and `as` (dangerous)", "--no-check-assert") # --no-check-autocast var opt_no_check_autocast = new OptionBool("Disable implicit casts on unsafe expression usage (dangerous)", "--no-check-autocast") # --no-check-null @@ -66,9 +66,11 @@ redef class ToolContext # --no-stacktrace var opt_no_stacktrace = new OptionBool("Disable the generation of stack traces", "--no-stacktrace") # --no-gcc-directives - var opt_no_gcc_directive = new OptionArray("Disable a advanced gcc directives for optimization", "--no-gcc-directive") + var opt_no_gcc_directive = new OptionArray("Disable advanced gcc directives for optimization", "--no-gcc-directive") # --release var opt_release = new OptionBool("Compile in release mode and finalize application", "--release") + # -g + var opt_debug = new OptionBool("Compile in debug mode (no C-side optimization)", "-g", "--debug") redef init do @@ -80,6 +82,7 @@ redef class ToolContext self.option_context.add_option(self.opt_no_gcc_directive) self.option_context.add_option(self.opt_release) self.option_context.add_option(self.opt_max_c_lines, self.opt_group_c_files) + self.option_context.add_option(self.opt_debug) opt_no_main.hidden = true end @@ -156,10 +159,13 @@ class MakefileToolchain redef fun write_and_make do + var debug = toolcontext.opt_debug.value var compile_dir = compile_dir # Remove the compilation directory unless explicitly set var auto_remove = toolcontext.opt_compile_dir.value == null + # If debug flag is set, do not remove sources + if debug then auto_remove = false # Generate the .h and .c files # A single C file regroups many compiled rumtime functions @@ -341,8 +347,9 @@ class MakefileToolchain var libs = m.collect_linker_libs if libs != null then linker_options.add_all(libs) end + var debug = toolcontext.opt_debug.value - makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g -O2 -Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") + makefile.write("CC = ccache cc\nCXX = ccache c++\nCFLAGS = -g{ if not debug then " -O2 " else " "}-Wno-unused-value -Wno-switch -Wno-attributes\nCINCL =\nLDFLAGS ?= \nLDLIBS ?= -lm {linker_options.join(" ")}\n\n") makefile.write "\n# SPECIAL CONFIGURATION FLAGS\n" if platform.supports_libunwind then @@ -389,6 +396,15 @@ endif makefile.write("CFLAGS += -D NO_STACKTRACE\n\n") end + makefile.write """ +# Special configuration for Darwin +ifeq ($(uname_S),Darwin) + # Remove POSIX flag -lrt + LDLIBS := $(filter-out -lrt,$(LDLIBS)) +endif + +""" + makefile.write("all: {outpath}\n") if outpath != real_outpath then makefile.write("\tcp -- {outpath.escape_to_sh} {real_outpath.escape_to_sh.replace("$","$$")}") @@ -638,6 +654,7 @@ abstract class AbstractCompiler self.header.add_decl("#include \n") self.header.add_decl("#include \n") self.header.add_decl("#include \n") + self.header.add_decl("#include \n") self.header.add_decl("#include \"gc_chooser.h\"") self.header.add_decl("#ifdef ANDROID") self.header.add_decl(" #include ") @@ -1130,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 @@ -1490,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 @@ -1541,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 @@ -1674,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 @@ -1889,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 @@ -1921,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 @@ -2125,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 @@ -2150,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 @@ -2192,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 @@ -2224,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 @@ -2255,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 @@ -2330,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 @@ -2354,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]});") @@ -2769,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 @@ -2902,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 @@ -3107,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 @@ -3117,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) @@ -3139,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 @@ -3188,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) @@ -3327,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