+ redef fun call(m, recvtype, args)
+ do
+ var recv_type = get_recvtype(m, recvtype, args)
+ var recv = get_recv(recv_type, args)
+ var new_args = args.to_a
+ self.varargize(m, m.msignature.as(not null), new_args)
+ new_args.first = recv
+ return finalize_call(m, recv_type, new_args)
+ end
+
+ # Does a call without encapsulating varargs into an array
+ # Avoids multiple encapsulation when calling a super in a variadic function
+ fun call_without_varargize(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var recv_type = get_recvtype(m, recvtype, args)
+ var recv = get_recv(recv_type, args)
+ var new_args = args.to_a
+ new_args.first = recv
+ return finalize_call(m, recv_type, new_args)
+ end
+
+ redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var types = self.collect_types(args.first)
+
+ var res: nullable RuntimeVariable
+ var ret = m.mproperty.intro.msignature.return_mtype
+ if ret == null then
+ res = null
+ else
+ ret = self.resolve_for(ret, args.first)
+ res = self.new_var(ret)
+ end
+
+ self.add("/* super {m} on {args.first.inspect} */")
+ if args.first.mtype.ctype != "val*" then
+ var mclasstype = args.first.mtype.as(MClassType)
+ if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
+ self.add("/* skip, no method {m} */")
+ return res
+ end
+ var propdef = m.lookup_next_definition(self.compiler.mainmodule, mclasstype)
+ var res2 = self.call_without_varargize(propdef, mclasstype, args)
+ if res != null then self.assign(res, res2.as(not null))
+ return res
+ end
+
+ if types.is_empty then
+ self.add("\{")
+ self.add("/*BUG: no live types for {args.first.inspect} . {m}*/")
+ self.bugtype(args.first)
+ self.add("\}")
+ return res
+ end
+
+ self.add("switch({args.first}->classid) \{")
+ var last = types.last
+ for t in types do
+ var propdef = m.lookup_next_definition(self.compiler.mainmodule, t)
+ if not self.compiler.hardening and t == last then
+ self.add("default: /* test {t} */")
+ else
+ self.add("case {self.compiler.classid(t)}: /* test {t} */")
+ end
+ var res2 = self.call_without_varargize(propdef, t, args)
+ if res != null then self.assign(res, res2.as(not null))
+ self.add "break;"
+ end
+ if self.compiler.hardening then
+ self.add("default: /* bug */")
+ self.bugtype(args.first)
+ end
+ self.add("\}")
+ return res
+ end
+