# Call the underlying referenced function
fun routine_ref_call(mmethoddef: MMethodDef, args: Array[RuntimeVariable]) is abstract
src/compiler/abstract_compiler.nit:1374,2--1375,87
redef fun routine_ref_call(mmethoddef, arguments)
do
#debug "ENTER ref_call"
compiler.modelbuilder.nb_invok_by_tables += 1
if compiler.modelbuilder.toolcontext.opt_invocation_metrics.value then add("count_invoke_by_tables++;")
var nclasses = mmodule.model.get_mclasses_by_name("RoutineRef").as(not null)
var nclass = nclasses.first
var runtime_function = mmethoddef.virtual_runtime_function
# Save the current receiver since adapt_signature will autobox
# the routine receiver which is not the underlying receiver.
# The underlying receiver has already been adapted in the
# `routine_ref_instance` method. Here we just want to adapt the
# rest of the signature, but it's easier to pass the wrong
# receiver in adapt_signature then discards it with `shift`.
#
# ~~~~nitish
# class A; def toto do print "toto"; end
# var a = new A
# var f = &a.toto # `a` is the underlying receiver
# f.call # here `f` is the routine receiver
# ~~~~
var routine = arguments.first
# Retrieve the concrete routine type
var original_recv_c = "(((struct instance_{nclass.c_name}*){arguments[0]})->recv)"
var nitmethod = "(({runtime_function.c_funptrtype})(((struct instance_{nclass.c_name}*){arguments[0]})->method))"
if arguments.length > 1 then
adapt_signature(mmethoddef, arguments)
end
var ret_mtype = runtime_function.called_signature.return_mtype
if ret_mtype != null then
# `ret` is actually always nullable Object. When invoking
# a callref, we don't have the original callsite information.
# Thus, we need to recompute the return type of the callsite.
ret_mtype = resolve_for(ret_mtype, routine)
end
# remove the routine's receiver
arguments.shift
var ss = arguments.join(", ")
# replace the receiver with the original one
if arguments.length > 0 then
ss = "{original_recv_c}, {ss}"
else
ss = original_recv_c
end
arguments.unshift routine # put back the routine ref receiver
add "/* {mmethoddef.mproperty} on {arguments.first.inspect}*/"
var callsite = "{nitmethod}({ss})"
if ret_mtype != null then
var subres = new_expr("{callsite}", ret_mtype)
ret(subres)
else
add("{callsite};")
end
end
src/compiler/separate_compiler.nit:2293,2--2352,4
redef fun routine_ref_call(mmethoddef, arguments)
do
var routine = arguments.first
var routine_type = routine.mtype.as(MClassType)
var routine_class = routine_type.mclass
var underlying_recv = "((struct {routine.mcasttype.c_name}*){routine})->recv"
var underlying_method = "((struct {routine.mcasttype.c_name}*){routine})->method"
adapt_signature(mmethoddef, arguments)
arguments.shift
var ss = "{underlying_recv}"
if arguments.length > 0 then
ss = "{ss}, {arguments.join(", ")}"
end
arguments.unshift routine
var ret_mtype = mmethoddef.msignature.return_mtype
if ret_mtype != null then
ret_mtype = resolve_for(ret_mtype, routine)
end
var callsite = "{underlying_method}({ss})"
if ret_mtype != null then
var subres = new_expr("{callsite}", ret_mtype)
ret(subres)
else
add("{callsite};")
end
end
src/compiler/global_compiler.nit:484,9--511,11