X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index f111e0d..50f3c8e 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -1086,39 +1086,45 @@ abstract class AbstractCompilerVisitor fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]) is abstract - # Transform varargs, in raw arguments, into a single argument of type `Array` - # Note: this method modify the given `args` - # If there is no vararg, then `args` is not modified. - fun varargize(mpropdef: MPropDef, msignature: MSignature, args: Array[RuntimeVariable]) + # 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] do - var recv = args.first - var vararg_rank = msignature.vararg_rank - if vararg_rank >= 0 then - assert args.length >= msignature.arity + 1 # because of self - var rawargs = args - args = new Array[RuntimeVariable] - - args.add(rawargs.first) # recv + var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null) + var res = new Array[RuntimeVariable] + res.add(recv) - for i in [0..vararg_rank[ do - args.add(rawargs[i+1]) - end + if args.is_empty then return res - var vararg_lastrank = vararg_rank + rawargs.length-1-msignature.arity - var vararg = new Array[RuntimeVariable] - for i in [vararg_rank..vararg_lastrank] do - vararg.add(rawargs[i+1]) - end - - var elttype = msignature.mparameters[vararg_rank].mtype - args.add(self.vararg_instance(mpropdef, recv, vararg, elttype)) + var vararg_rank = msignature.vararg_rank + var vararg_len = args.length - msignature.arity + if vararg_len < 0 then vararg_len = 0 - for i in [vararg_lastrank+1..rawargs.length-1[ do - args.add(rawargs[i+1]) + 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 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) end - rawargs.clear - rawargs.add_all(args) end + return res end # Type handling @@ -1839,7 +1845,7 @@ redef class MMethodDef if modelbuilder.mpropdef2npropdef.has_key(self) then var npropdef = modelbuilder.mpropdef2npropdef[self] return npropdef.can_inline - else if self.mproperty.name == "init" then + else if self.mproperty.is_root_init then # Automatic free init is always inlined since it is empty or contains only attribtes assigments return true else @@ -1859,7 +1865,7 @@ redef class MMethodDef self.compile_parameter_check(v, arguments) npropdef.compile_to_c(v, self, arguments) v.current_node = oldnode - else if self.mproperty.name == "init" then + else if self.mproperty.is_root_init then var nclassdef = modelbuilder.mclassdef2nclassdef[self.mclassdef] var oldnode = v.current_node v.current_node = nclassdef @@ -1983,8 +1989,6 @@ redef class AMethPropdef var ret = mpropdef.msignature.return_mtype if ret != null then ret = v.resolve_for(ret, arguments.first) - else if mpropdef.mproperty.is_new then - ret = arguments.first.mcasttype end if pname != "==" and pname != "!=" then v.adapt_signature(mpropdef, arguments) @@ -2165,7 +2169,7 @@ redef class AMethPropdef else if pname == "atoi" then v.ret(v.new_expr("atoi({arguments[0]});", ret.as(not null))) return true - else if pname == "init" then + else if pname == "new" then v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null))) return true end @@ -2397,8 +2401,7 @@ redef class AExpr # Do not call this method directly, use `v.stmt` instead private fun stmt(v: AbstractCompilerVisitor) do - var res = expr(v) - if res != null then v.add("{res};") + expr(v) end end @@ -2440,12 +2443,6 @@ redef class AVarExpr end redef class AVarAssignExpr - redef fun stmt(v) - do - var variable = self.variable.as(not null) - var i = v.expr(self.n_value, variable.declared_type) - v.assign(v.variable(variable), i) - end redef fun expr(v) do var variable = self.variable.as(not null) @@ -2841,11 +2838,9 @@ redef class ASendExpr redef fun expr(v) do var recv = v.expr(self.n_expr, null) - var args = [recv] - for a in self.raw_arguments do - args.add(v.expr(a, null)) - end - return v.compile_callsite(self.callsite.as(not null), args) + var callsite = self.callsite.as(not null) + var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + return v.compile_callsite(callsite, args) end end @@ -2853,13 +2848,12 @@ redef class ASendReassignFormExpr redef fun stmt(v) do var recv = v.expr(self.n_expr, null) - var args = [recv] - for a in self.raw_arguments do - args.add(v.expr(a, null)) - end + var callsite = self.callsite.as(not null) + var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var value = v.expr(self.n_value, null) - var left = v.compile_callsite(self.callsite.as(not null), args) + var left = v.compile_callsite(callsite, args) assert left != null var res = v.compile_callsite(self.reassign_callsite.as(not null), [left, value]) @@ -2874,14 +2868,12 @@ redef class ASuperExpr redef fun expr(v) do var recv = v.frame.arguments.first - var args = [recv] - for a in self.n_args.n_exprs do - args.add(v.expr(a, null)) - end var callsite = self.callsite if callsite != null then - # Add additionnals arguments for the super init call + var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) + + # Add additional arguments for the super init call if args.length == 1 then for i in [0..callsite.msignature.arity[ do args.add(v.frame.arguments[i+1]) @@ -2892,12 +2884,14 @@ redef class ASuperExpr 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 args = v.frame.arguments end # stantard call-next-method - return v.supercall(mpropdef.as(not null), recv.mtype.as(MClassType), args) + return v.supercall(mpropdef, recv.mtype.as(MClassType), args) end end @@ -2920,11 +2914,10 @@ redef class ANewExpr else recv = v.new_expr("({ctype})0/*special!*/", mtype) end - var args = [recv] - for a in self.n_args.n_exprs do - args.add(v.expr(a, null)) - end - var res2 = v.compile_callsite(self.callsite.as(not null), args) + + var callsite = self.callsite.as(not null) + var args = v.varargize(callsite.mpropdef, 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}") return res2 @@ -2943,12 +2936,13 @@ redef class AAttrExpr end redef class AAttrAssignExpr - redef fun stmt(v) + redef fun expr(v) do var recv = v.expr(self.n_expr, null) var i = v.expr(self.n_value, null) var mproperty = self.mproperty.as(not null) v.write_attribute(mproperty, recv, i) + return i end end