X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index f579a32..853feb1 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -95,12 +95,12 @@ redef class ToolContext # Default is nitstack opt_stacktrace.value = "nitstack" else - print "Error: unknown value `{st}` for --stacktrace. Use `none`, `libunwind`, `nitstack` or `auto`." + print "Option Error: unknown value `{st}` for --stacktrace. Use `none`, `libunwind`, `nitstack` or `auto`." exit(1) end if opt_output.value != null and opt_dir.value != null then - print "Error: cannot use both --dir and --output" + print "Option Error: cannot use both --dir and --output" exit(1) end @@ -463,16 +463,18 @@ endif var makeflags = self.toolcontext.opt_make_flags.value if makeflags == null then makeflags = "" - self.toolcontext.info("make -B -C {compile_dir} -f {makename} -j 4 {makeflags}", 2) + + var command = "make -B -C {compile_dir} -f {makename} -j 4 {makeflags}" + self.toolcontext.info(command, 2) var res if self.toolcontext.verbose_level >= 3 then - res = sys.system("make -B -C {compile_dir} -f {makename} -j 4 {makeflags} 2>&1") + res = sys.system("{command} 2>&1") else - res = sys.system("make -B -C {compile_dir} -f {makename} -j 4 {makeflags} 2>&1 >/dev/null") + res = sys.system("{command} 2>&1 >/dev/null") end if res != 0 then - toolcontext.error(null, "make failed! Error code: {res}.") + toolcontext.error(null, "Compilation Error: `make` failed with error code: {res}. The command was `{command}`.") end end end @@ -689,7 +691,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref ); var finalize_meth = mainmodule.try_get_primitive_method("finalize", finalizable_type.mclass) if finalize_meth == null then - modelbuilder.toolcontext.error(null, "The `Finalizable` class doesn't declare the `finalize` method.") + modelbuilder.toolcontext.error(null, "Error: the `Finalizable` class does not declare the `finalize` method.") return end @@ -1144,40 +1146,45 @@ abstract class AbstractCompilerVisitor # Evaluate `args` as expressions in the call of `mpropdef` on `recv`. # This method is used to manage varargs in signatures and returns the real array # of runtime variables to use in the call. - fun varargize(mpropdef: MMethodDef, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable] + fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable] do var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null) var res = new Array[RuntimeVariable] res.add(recv) - if args.is_empty then return res + if msignature.arity == 0 then return res - var vararg_rank = msignature.vararg_rank - var vararg_len = args.length - msignature.arity - if vararg_len < 0 then vararg_len = 0 + if map == null then + assert args.length == msignature.arity + for ne in args do + res.add self.expr(ne, null) + end + return res + end + # Eval in order of arguments, not parameters + var exprs = new Array[RuntimeVariable].with_capacity(args.length) + for ne in args do + exprs.add self.expr(ne, null) + end + + # Fill `res` with the result of the evaluation according to the mapping for i in [0..msignature.arity[ do - if i == vararg_rank then - var ne = args[i] - if ne isa AVarargExpr then - var e = self.expr(ne.n_expr, null) - res.add(e) - continue - end - var vararg = new Array[RuntimeVariable] - for j in [vararg_rank..vararg_rank+vararg_len] do - var e = self.expr(args[j], null) - vararg.add(e) - end - var elttype = msignature.mparameters[vararg_rank].mtype + var param = msignature.mparameters[i] + var j = map.map.get_or_null(i) + if j == null then + # default value + res.add(null_instance) + continue + end + if param.is_vararg and map.vararg_decl > 0 then + var vararg = exprs.sub(j, map.vararg_decl) + var elttype = param.mtype var arg = self.vararg_instance(mpropdef, recv, vararg, elttype) res.add(arg) - else - var j = i - if i > vararg_rank then j += vararg_len - var e = self.expr(args[j], null) - res.add(e) + continue end + res.add exprs[j] end return res end @@ -1448,6 +1455,14 @@ abstract class AbstractCompilerVisitor return res end + # Generate a byte value + fun byte_instance(value: Byte): RuntimeVariable + do + var t = mmodule.byte_type + var res = new RuntimeVariable("((unsigned char){value.to_s})", t, t) + return res + end + # Generate a char value fun char_instance(value: Char): RuntimeVariable do @@ -1831,6 +1846,8 @@ redef class MClassType return "char" else if mclass.name == "Float" then return "double" + else if mclass.name == "Byte" then + return "unsigned char" else if mclass.name == "NativeString" then return "char*" else if mclass.name == "NativeArray" then @@ -1861,6 +1878,8 @@ redef class MClassType return "c" else if mclass.name == "Float" then return "d" + else if mclass.name == "Byte" then + return "b" else if mclass.name == "NativeString" then return "str" else if mclass.name == "NativeArray" then @@ -2051,6 +2070,9 @@ redef class AMethPropdef 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 @@ -2088,6 +2110,9 @@ 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 == "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("{arguments[0]}", ret.as(not null))) return true @@ -2131,6 +2156,69 @@ redef class AMethPropdef v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null))) return true end + else if cname == "Byte" then + if pname == "output" then + v.add("printf(\"%x\\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 == "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 + 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_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))) + return true + end else if cname == "Bool" then if pname == "output" then v.add("printf({arguments.first}?\"true\\n\":\"false\\n\");") @@ -2162,6 +2250,9 @@ redef class AMethPropdef 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 == "succ" then v.ret(v.new_expr("{arguments[0]}+1", ret.as(not null))) return true @@ -2196,6 +2287,9 @@ redef class AMethPropdef 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 end else if cname == "NativeString" then if pname == "[]" then @@ -2772,6 +2866,10 @@ 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)) +end + redef class AFloatExpr redef fun expr(v) do return v.float_instance("{self.n_float.text}") # FIXME use value, not n_float end @@ -2967,7 +3065,7 @@ redef class ASendExpr do var recv = v.expr(self.n_expr, null) var callsite = self.callsite.as(not null) - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) return v.compile_callsite(callsite, args) end end @@ -2977,7 +3075,7 @@ redef class ASendReassignFormExpr do var recv = v.expr(self.n_expr, null) var callsite = self.callsite.as(not null) - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) var value = v.expr(self.n_value, null) @@ -2999,26 +3097,33 @@ redef class ASuperExpr var callsite = self.callsite if callsite != null then - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) + var args - # Add additional arguments for the super init call - if args.length == 1 then + 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]) end + else + args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) end + # Super init call var res = v.compile_callsite(callsite, args) return res end var mpropdef = self.mpropdef.as(not null) - var args = v.varargize(mpropdef, recv, self.n_args.n_exprs) - if args.length == 1 then + + var args + if self.n_args.n_exprs.is_empty then args = v.frame.arguments + else + args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs) end - # stantard call-next-method + # Standard call-next-method return v.supercall(mpropdef, recv.mtype.as(MClassType), args) end end @@ -3039,8 +3144,10 @@ redef class ANewExpr var recv = v.init_instance_or_extern(mtype) - var callsite = self.callsite.as(not null) - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) + var callsite = self.callsite + if callsite == null then return recv + + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) var res2 = v.compile_callsite(callsite, args) if res2 != null then #self.debug("got {res2} from {mproperty}. drop {recv}") @@ -3092,6 +3199,20 @@ redef class AIssetAttrExpr end end +redef class AVarargExpr + redef fun expr(v) + do + return v.expr(self.n_expr, null) + end +end + +redef class ANamedargExpr + redef fun expr(v) + do + return v.expr(self.n_expr, null) + end +end + redef class ADebugTypeExpr redef fun stmt(v) do @@ -3157,7 +3278,7 @@ var modelbuilder = new ModelBuilder(model, toolcontext) var arguments = toolcontext.option_context.rest if arguments.length > 1 and toolcontext.opt_output.value != null then - print "Error: --output needs a single source file. Do you prefer --dir?" + print "Option Error: --output needs a single source file. Do you prefer --dir?" exit 1 end