# 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
# --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
# --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
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
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
# Copy original .[ch] files to compile_dir
for src in compiler.files_to_copy do
- var basename = src.basename("")
+ var basename = src.basename
var dst = "{compile_dir}/{basename}"
src.file_copy_to dst
end
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
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("$","$$")}")
# Compile each required extern body into a specific .o
for f in compiler.extern_bodies do
var o = f.makefile_rule_name
- var ff = f.filename.basename("")
+ var ff = f.filename.basename
makefile.write("{o}: {ff}\n")
makefile.write("\t{f.makefile_rule_content}\n\n")
dep_rules.add(f.makefile_rule_name)
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>")
v.add_decl("int main(int argc, char** argv) \{")
end
+ v.add "#ifndef ANDROID"
v.add("signal(SIGABRT, sig_handler);")
v.add("signal(SIGFPE, sig_handler);")
v.add("signal(SIGILL, sig_handler);")
v.add("signal(SIGINT, sig_handler);")
v.add("signal(SIGTERM, sig_handler);")
v.add("signal(SIGSEGV, sig_handler);")
- v.add("signal(SIGPIPE, sig_handler);")
+ v.add "#endif"
+ v.add("signal(SIGPIPE, SIG_IGN);")
v.add("glob_argc = argc; glob_argv = argv;")
v.add("initialize_gc_option();")
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
fun calloc_array(ret_type: MType, arguments: Array[RuntimeVariable]) is abstract
- fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) is abstract
+ fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool do return false
# Return an element of a native array.
# The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
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
var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
res.add(arg)
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
- var res = new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
- return res
+
+ if value.code_point < 128 then
+ return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
+ else
+ return new RuntimeVariable("{value.code_point}", t, t)
+ end
end
# Generate a float value
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.length)
- 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
# This is used for the legacy FFI
fun add_extern(mmodule: MModule)
do
- var file = mmodule.location.file.filename
+ var file = mmodule.filepath
file = file.strip_extension(".nit")
var tryfile = file + ".nit.h"
if tryfile.file_exists then
- self.declare_once("#include \"{tryfile.basename("")}\"")
+ self.declare_once("#include \"{tryfile.basename}\"")
self.compiler.files_to_copy.add(tryfile)
end
tryfile = file + "_nit.h"
if tryfile.file_exists then
- self.declare_once("#include \"{tryfile.basename("")}\"")
+ self.declare_once("#include \"{tryfile.basename}\"")
self.compiler.files_to_copy.add(tryfile)
end
tryfile = file + "_nit.c"
if not tryfile.file_exists then return
end
- var f = new ExternCFile(tryfile.basename(""), "")
+ var f = new ExternCFile(tryfile.basename, "")
self.compiler.extern_bodies.add(f)
self.compiler.files_to_copy.add(tryfile)
end
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
# `mtype` is the expected return type, pass null if no specific type is expected.
fun expr(nexpr: AExpr, mtype: nullable MType): RuntimeVariable
do
- if nexpr.mtype == null then
+ var old = self.current_node
+ self.current_node = nexpr
+
+ var res = null
+ if nexpr.mtype != null then
+ res = nexpr.expr(self)
+ end
+
+ if res == null then
# Untyped expression.
# Might mean dead code or invalid code.
# so aborts
add_abort("FATAL: bad expression executed.")
# and return a placebo result to please the C compiler
if mtype == null then mtype = compiler.mainmodule.object_type
- return new_var(mtype)
+ res = new_var(mtype)
+
+ self.current_node = old
+ return res
end
- var old = self.current_node
- self.current_node = nexpr
- var res = nexpr.expr(self).as(not null)
+
if mtype != null then
mtype = self.anchor(mtype)
res = self.autobox(res, mtype)
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
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
fun can_inline(v: VISITOR): Bool
do
if is_abstract then return true
+ if constant_value != null then return true
var modelbuilder = v.compiler.modelbuilder
var node = modelbuilder.mpropdef2node(self)
if node isa APropdef then
do
if v.compiler.modelbuilder.toolcontext.opt_no_check_covariance.value then return
+ var msignature = self.msignature.as(not null)
+
for i in [0..msignature.arity[ do
+ 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 = self.mproperty.intro.msignature.mparameters[i].mtype
if not origmtype.need_anchor then continue
# get the parameter type
- var mtype = self.msignature.mparameters[i].mtype
+ var mtype = mp.mtype
# generate the cast
# note that v decides if and how to implements the cast
- v.add("/* Covariant cast for argument {i} ({self.msignature.mparameters[i].name}) {arguments[i+1].inspect} isa {mtype} */")
+ v.add("/* Covariant cast for argument {i} ({mp.name}) {arguments[i+1].inspect} isa {mtype} */")
v.add_cast(arguments[i+1], mtype, "covariance")
end
end
# Try special compilation
if mpropdef.is_intern then
if compile_intern_to_c(v, mpropdef, arguments) then return
- else if mpropdef.is_extern then
+ end
+ if mpropdef.is_extern then
if mpropdef.mproperty.is_init then
if compile_externinit_to_c(v, mpropdef, arguments) then return
else
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
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
+ else if pname == "code_point" then
v.ret(v.new_expr("(uint32_t){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 == "<<" then
+ v.ret(v.new_expr("{arguments[0]} << {arguments[1]}", ret.as(not null)))
+ return true
end
else if cname == "Char" then
- if pname == "output" then
- v.add("printf(\"%c\", ((unsigned char){arguments.first}));")
- return true
- else if pname == "object_id" then
+ if pname == "object_id" then
v.ret(v.new_expr("(long){arguments.first}", ret.as(not null)))
return true
else if pname == "successor" then
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
+ else if pname == "code_point" then
v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
return true
end
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
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_f" then
v.ret(v.new_expr("(double){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
else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
+ v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
end
else if cname == "Bool" then
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
- v.ret(v.new_expr("(uint32_t)(unsigned char){arguments[0]}[{arguments[1]}]", ret.as(not null)))
+ v.ret(v.new_expr("(unsigned char)((int){arguments[0]}[{arguments[1]}])", ret.as(not null)))
return true
else if pname == "[]=" then
v.add("{arguments[0]}[{arguments[1]}]=(unsigned char){arguments[2]};")
return true
end
else if cname == "NativeArray" then
- v.native_array_def(pname, ret, arguments)
- return true
+ return v.native_array_def(pname, ret, arguments)
+ 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]});")
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
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
redef fun expr(v)
do
var i = v.expr(self.n_expr, null)
- return v.type_test(i, self.cast_type.as(not null), "isa")
+ var cast_type = self.cast_type
+ if cast_type == null then return null # no-no on broken node
+ return v.type_test(i, cast_type, "isa")
end
end
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
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)
redef class ASuperExpr
redef fun expr(v)
do
- var recv = v.frame.arguments.first
+ var frame = v.frame.as(not null)
+ var recv = frame.arguments.first
var callsite = self.callsite
if callsite != null then
+ if callsite.is_broken then return null
var args
if self.n_args.n_exprs.is_empty then
# Add automatic arguments for the super init call
args = [recv]
for i in [0..callsite.msignature.arity[ do
- args.add(v.frame.arguments[i+1])
+ args.add(frame.arguments[i+1])
end
else
args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
var args
if self.n_args.n_exprs.is_empty then
- args = v.frame.arguments
+ args = frame.arguments
else
args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
end
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)
# 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.quit
+
modelbuilder.run_phases
for mmodule in mmodules do