Property definitions

nitc $ ThunkFunction :: defaultinit
# 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