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
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
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
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)
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
# 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
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)
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
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])
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])
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
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
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