is to call another function. Like a class wrapper or decorator, a thunk is used to computer things (conversions, log, etc) before or after a function call. It's an intermediary between the caller and the callee.
The most basic use of a thunk is to unbox its argument before invoking the real callee. Virtual functions are a use case of thunk function:
redef class Object
fun toto(x: Int): Int do return 1 + x
end
redef class Int
redef fun toto(x) do return x + self
end
long Object__toto(val self, long x) { return 1 + x } long Inttoto(long self, long x) { return x + self } long THUNK_Inttoto(val self, long x) {
long self2 = (long)(self)>>2 // Unboxing from Object to Int
return Int_toto(self2, x)
}
A thunk has its OWN SIGNATURE and is considered like any other AbstractRuntimeFunction.
Thus, one might need to be careful when overriding parent's method. Since most usage of
thunks in Nit is to unbox and box things between a caller and a callee, the default
implementation is doing just that. In other words, a thunk takes a signature and a method
and tries to cast its signature to the underlying method's signature.
A virtual function has the same signature as its mmethoddef field, except for
its receiver is of type Object.
In the same vibe, a call reference has all of its argument boxed as Object.
nitc :: ThunkFunction :: _polymorph_call_flag
Determines if the callsite should be polymorphic or static.nitc :: ThunkFunction :: defaultinit
nitc :: ThunkFunction :: polymorph_call_flag
Determines if the callsite should be polymorphic or static.nitc :: ThunkFunction :: polymorph_call_flag=
Determines if the callsite should be polymorphic or static.nitc :: ThunkFunction :: target_recv
The type expected by the callee. Used to resolvemmethoddef's formal
nitc $ ThunkFunction :: SELF
Type of this instance, automatically specialized in every classnitc $ ThunkFunction :: body_to_c
Generate the code for the body without return statement at the end andnitc :: AbstractRuntimeFunction :: _mmethoddef
The associated Nit methodnitc :: ThunkFunction :: _polymorph_call_flag
Determines if the callsite should be polymorphic or static.nitc :: AbstractRuntimeFunction :: body_to_c
Generate the code for the body without return statement at the end andnitc :: AbstractRuntimeFunction :: build_c_name
Non cached version ofc_name
nitc :: AbstractRuntimeFunction :: build_frame
Builds the static frame for current runtime methodnitc :: AbstractRuntimeFunction :: c_name
The mangled c name of the runtime_functionnitc :: AbstractRuntimeFunction :: c_ref
nitc :: AbstractRuntimeFunction :: call
Implements a call of the runtime_functioncore :: Object :: class_factory
Implementation used byget_class to create the specific class.
nitc :: AbstractRuntimeFunction :: compile_to_c
Generate the codenitc :: AbstractRuntimeFunction :: declare_signature
How the concrete compiler will declare the method, e.g inside a global header file,nitc :: ThunkFunction :: defaultinit
core :: Object :: defaultinit
nitc :: AbstractRuntimeFunction :: end_compile_to_c
Hook called at the end ofcompile_to_c function. This function
nitc :: AbstractRuntimeFunction :: fill_parameters
Fills the argument array inside v.frame.arguments, callingresolve_ith_parameter
nitc :: AbstractRuntimeFunction :: has_return
Returnstrue if the associated mmethoddef's return type isn't null,
core :: Object :: is_same_instance
Return true ifself and other are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself the same as other in a serialization context?
core :: Object :: is_same_type
Return true ifself and other have the same dynamic type.
nitc :: AbstractRuntimeFunction :: mmethoddef=
The associated Nit methodnitc :: AbstractRuntimeFunction :: msignature
The current msignature to use when compiling :signature_to_c and body_to_c.
core :: Object :: native_class_name
The class name of the object in CString format.core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: ThunkFunction :: polymorph_call_flag
Determines if the callsite should be polymorphic or static.nitc :: ThunkFunction :: polymorph_call_flag=
Determines if the callsite should be polymorphic or static.nitc :: AbstractRuntimeFunction :: recv_mtype
The current receiver type to compile :signature_to_c and body_to_c.
nitc :: AbstractRuntimeFunction :: resolve_ith_parameter
Step 4 : CreatesRuntimeVariable for each method argument.
nitc :: AbstractRuntimeFunction :: resolve_receiver
Prepare theself runtime variable to be used by the rest of
nitc :: AbstractRuntimeFunction :: resolve_return_mtype
Step 3 : Returns the return type used by the runtime function.nitc :: AbstractRuntimeFunction :: signature_to_c
Generate the code for the signature with an open curly bracenitc :: ThunkFunction :: target_recv
The type expected by the callee. Used to resolvemmethoddef's formal
nitc :: AbstractRuntimeFunction
A C function associated to a Nit methodnitc :: CustomizedThunkFunction
Thunk implementation for global compiler.
# Base class for all thunk-like function. A thunk is a function whose purpose
# is to call another function. Like a class wrapper or decorator, a thunk is used
# to computer things (conversions, log, etc) before or after a function call. It's
# an intermediary between the caller and the callee.
#
# The most basic use of a thunk is to unbox its argument before invoking the real callee.
# Virtual functions are a use case of thunk function:
#
# ~~~~nitish
# redef class Object
# fun toto(x: Int): Int do return 1 + x
# end
# redef class Int
# redef fun toto(x) do return x + self
# end
#
# ```generated C code
# long Object__toto(val* self, long x) { return 1 + x }
# long Int__toto(long self, long x) { return x + self }
# long THUNK_Int__toto(val* self, long x) {
# long self2 = (long)(self)>>2 // Unboxing from Object to Int
# return Int_toto(self2, x)
# }
#
# ```
# ~~~~
#
# A thunk has its OWN SIGNATURE and is considered like any other `AbstractRuntimeFunction`.
# Thus, one might need to be careful when overriding parent's method. Since most usage of
# thunks in Nit is to unbox and box things between a caller and a callee, the default
# implementation is doing just that. In other words, a thunk takes a signature and a method
# and tries to cast its signature to the underlying method's signature.
#
# A virtual function has the same signature as its `mmethoddef` field, except for
# its receiver is of type `Object`.
# In the same vibe, a call reference has all of its argument boxed as `Object`.
abstract class ThunkFunction
super AbstractRuntimeFunction
# Determines if the callsite should be polymorphic or static.
var polymorph_call_flag = false is writable
# The type expected by the callee. Used to resolve `mmethoddef`'s formal
# parameters and virtual type. This type must NOT need anchor.
fun target_recv: MType is abstract
redef fun body_to_c(v)
do
assert not target_recv.need_anchor
var frame = v.frame
assert frame != null
var selfvar = frame.selfvar
var arguments = frame.arguments
var arguments2 = new Array[RuntimeVariable]
arguments2.push(v.autobox(selfvar, target_recv))
var resolved_sig = msignature.resolve_for(target_recv, target_recv.as(MClassType), v.mmodule, true)
for i in [0..resolved_sig.arity[ do
var param = resolved_sig.mparameters[i]
var mtype = param.mtype
if param.is_vararg then
mtype = v.mmodule.array_type(mtype)
end
var temp = v.autobox(arguments[i+1], mtype)
arguments2.push(temp)
end
v.add("/* {mmethoddef}, {recv_mtype.ctype} */")
var subret: nullable RuntimeVariable = null
if polymorph_call_flag then
subret = v.send(mmethoddef.mproperty, arguments2)
else
subret = v.call(mmethoddef, arguments2[0].mcasttype.as(MClassType), arguments2)
end
if has_return then
assert subret != null
var subret2 = v.autobox(subret, return_mtype.as(not null))
v.assign(frame.returnvar.as(not null), subret2)
end
end
end
src/compiler/abstract_compiler.nit:2267,1--2347,3