From 9c8081ed802119f957e26267ba812de82981be40 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Thu, 16 Apr 2015 16:57:27 +0700 Subject: [PATCH] interpreter: use SignatureMap to make varargize more robust Signed-off-by: Jean Privat --- src/interpreter/naive_interpreter.nit | 97 ++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 7d7cab9..c1bd59b 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -370,42 +370,48 @@ class NaiveInterpreter # This method is used to manage varargs in signatures and returns the real array # of instances to use in the call. # Return `null` if one of the evaluation of the arguments return null. - fun varargize(mpropdef: MMethodDef, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance] + fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance] do var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null) var res = new Array[Instance] res.add(recv) - if args.is_empty then return res + if msignature.arity == 0 then return res + + if map == null then + assert args.length == msignature.arity else debug("Expected {msignature.arity} args, got {args.length}") + for ne in args do + var e = self.expr(ne) + if e == null then return null + res.add e + end + return res + end + + # Eval in order of arguments, not parameters + var exprs = new Array[Instance].with_capacity(args.length) + for ne in args do + var e = self.expr(ne) + if e == null then return null + exprs.add e + end - var vararg_rank = msignature.vararg_rank - var vararg_len = args.length - msignature.arity - if vararg_len < 0 then vararg_len = 0 + # 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) - if e == null then return null - res.add(e) - continue - end - var vararg = new Array[Instance] - for j in [vararg_rank..vararg_rank+vararg_len] do - var e = self.expr(args[j]) - if e == null then return null - vararg.add(e) - end - var elttype = msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType)) - res.add(self.array_instance(vararg, elttype)) - else - var j = i - if i > vararg_rank then j += vararg_len - var e = self.expr(args[j]) - if e == null then return null - res.add(e) + var param = msignature.mparameters[i] + var j = map.map.get_or_null(i) + if j == null then + continue + end + if param.is_vararg and map.vararg_decl > 0 then + var vararg = exprs.sub(j, map.vararg_decl) + var elttype = param.mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType)) + var arg = self.array_instance(vararg, elttype) + res.add(arg) + continue end + res.add exprs[j] end return res end @@ -1740,7 +1746,7 @@ redef class ASendExpr do var recv = v.expr(self.n_expr) if recv == null then return null - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) if args == null then return null var res = v.callsite(callsite, args) @@ -1753,7 +1759,7 @@ redef class ASendReassignFormExpr do var recv = v.expr(self.n_expr) if recv == null then return - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) if args == null then return var value = v.expr(self.n_value) if value == null then return @@ -1777,29 +1783,35 @@ redef class ASuperExpr var callsite = self.callsite if callsite != null then - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) - if args == null then return null - # Add additional arguments for the super init call - if args.length == 1 then + 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]) end + else + args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) + if args == null then return null end + # Super init call var res = v.callsite(callsite, args) return res end - # standard call-next-method + # Standard call-next-method var mpropdef = self.mpropdef mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype) - var args = v.varargize(mpropdef, recv, self.n_args.n_exprs) - if args == null then return null - - 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) + if args == null then return null end + var res = v.call(mpropdef, args) return res end @@ -1814,7 +1826,7 @@ redef class ANewExpr var callsite = self.callsite if callsite == null then return recv - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) if args == null then return null var res2 = v.callsite(callsite, args) if res2 != null then @@ -1876,6 +1888,13 @@ redef class AIssetAttrExpr end end +redef class AVarargExpr + redef fun expr(v) + do + return v.expr(self.n_expr) + end +end + redef class ADebugTypeExpr redef fun stmt(v) do -- 1.7.9.5