A C function associated to a Nit method

This is the base class for all runtime representation of a nit method. It implements the Template Design Pattern whose steps are :

  1. create the receiver `RuntimeVariable` (selfvar)
  2. create a `StaticFrame`
  3. resolve the return type.
  4. write the function signature
  5. Declare the function signature (for C header files)
  6. writer the function body
  7. post-compiler hook (optional)

Each step is called in AbstractRuntimeFunction::compile_to_c. A default body is provided foreach step except for compilation hooks. Subclasses may redefine any of the above mentioned steps. However, it's not recommanded to override compile_to_c since there's an ordering of the compilation steps. Any information between steps must be saved in the visitor. Currently most of the future runtime info are stored in the StaticFrame of the visitor, e.g. the receiver (selfvar), the arguments, etc.

Moreover, any subclass may redefine : the receiver type, the return type and the signature. This allow for a better customization for the final implementation. Because of customization, a given Nit method can be compile more that once.

Introduced properties

private var _mmethoddef: MMethodDef

nitc :: AbstractRuntimeFunction :: _mmethoddef

The associated Nit method
protected fun body_to_c(v: VISITOR)

nitc :: AbstractRuntimeFunction :: body_to_c

Generate the code for the body without return statement at the end and
protected abstract fun build_c_name: String

nitc :: AbstractRuntimeFunction :: build_c_name

Non cached version of c_name
protected fun build_frame(v: VISITOR, arguments: Array[RuntimeVariable]): StaticFrame

nitc :: AbstractRuntimeFunction :: build_frame

Builds the static frame for current runtime method
fun c_name: String

nitc :: AbstractRuntimeFunction :: c_name

The mangled c name of the runtime_function
protected fun c_name_cache: nullable String

nitc :: AbstractRuntimeFunction :: c_name_cache

fun c_name_cache=(c_name_cache: nullable String)

nitc :: AbstractRuntimeFunction :: c_name_cache=

abstract fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractRuntimeFunction :: call

Implements a call of the runtime_function
fun compile_to_c(compiler: COMPILER)

nitc :: AbstractRuntimeFunction :: compile_to_c

Generate the code
protected abstract fun declare_signature(v: VISITOR, signature: String)

nitc :: AbstractRuntimeFunction :: declare_signature

How the concrete compiler will declare the method, e.g inside a global header file,
protected fun end_compile_to_c(v: VISITOR)

nitc :: AbstractRuntimeFunction :: end_compile_to_c

Hook called at the end of compile_to_c function. This function
private fun fill_parameters(v: VISITOR)

nitc :: AbstractRuntimeFunction :: fill_parameters

Fills the argument array inside v.frame.arguments, calling resolve_ith_parameter
fun has_return: Bool

nitc :: AbstractRuntimeFunction :: has_return

Returns true if the associated mmethoddef's return type isn't null,
fun mmethoddef: MMethodDef

nitc :: AbstractRuntimeFunction :: mmethoddef

The associated Nit method
protected fun mmethoddef=(mmethoddef: MMethodDef)

nitc :: AbstractRuntimeFunction :: mmethoddef=

The associated Nit method
fun msignature: MSignature

nitc :: AbstractRuntimeFunction :: msignature

The current msignature to use when compiling : signature_to_c and body_to_c.
protected fun recv_mtype: MType

nitc :: AbstractRuntimeFunction :: recv_mtype

The current receiver type to compile : signature_to_c and body_to_c.
protected fun resolve_ith_parameter(v: VISITOR, i: Int): RuntimeVariable

nitc :: AbstractRuntimeFunction :: resolve_ith_parameter

Step 4 : Creates RuntimeVariable for each method argument.
protected fun resolve_receiver(v: VISITOR): RuntimeVariable

nitc :: AbstractRuntimeFunction :: resolve_receiver

Prepare the self runtime variable to be used by the rest of
protected fun resolve_return_mtype(v: VISITOR)

nitc :: AbstractRuntimeFunction :: resolve_return_mtype

Step 3 : Returns the return type used by the runtime function.
protected fun return_mtype: nullable MType

nitc :: AbstractRuntimeFunction :: return_mtype

protected fun return_mtype=(return_mtype: nullable MType)

nitc :: AbstractRuntimeFunction :: return_mtype=

protected fun signature_to_c(v: VISITOR): String

nitc :: AbstractRuntimeFunction :: signature_to_c

Generate the code for the signature with an open curly brace

Redefined properties

redef type SELF: AbstractRuntimeFunction

nitc $ AbstractRuntimeFunction :: SELF

Type of this instance, automatically specialized in every class

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
private var _mmethoddef: MMethodDef

nitc :: AbstractRuntimeFunction :: _mmethoddef

The associated Nit method
protected fun body_to_c(v: VISITOR)

nitc :: AbstractRuntimeFunction :: body_to_c

Generate the code for the body without return statement at the end and
protected abstract fun build_c_name: String

nitc :: AbstractRuntimeFunction :: build_c_name

Non cached version of c_name
protected fun build_frame(v: VISITOR, arguments: Array[RuntimeVariable]): StaticFrame

nitc :: AbstractRuntimeFunction :: build_frame

Builds the static frame for current runtime method
fun c_name: String

nitc :: AbstractRuntimeFunction :: c_name

The mangled c name of the runtime_function
protected fun c_name_cache: nullable String

nitc :: AbstractRuntimeFunction :: c_name_cache

fun c_name_cache=(c_name_cache: nullable String)

nitc :: AbstractRuntimeFunction :: c_name_cache=

abstract fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractRuntimeFunction :: call

Implements a call of the runtime_function
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
fun compile_to_c(compiler: COMPILER)

nitc :: AbstractRuntimeFunction :: compile_to_c

Generate the code
protected abstract fun declare_signature(v: VISITOR, signature: String)

nitc :: AbstractRuntimeFunction :: declare_signature

How the concrete compiler will declare the method, e.g inside a global header file,
protected fun end_compile_to_c(v: VISITOR)

nitc :: AbstractRuntimeFunction :: end_compile_to_c

Hook called at the end of compile_to_c function. This function
private fun fill_parameters(v: VISITOR)

nitc :: AbstractRuntimeFunction :: fill_parameters

Fills the argument array inside v.frame.arguments, calling resolve_ith_parameter
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun has_return: Bool

nitc :: AbstractRuntimeFunction :: has_return

Returns true if the associated mmethoddef's return type isn't null,
fun hash: Int

core :: Object :: hash

The hash code of the object.
init init

core :: Object :: init

fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
fun mmethoddef: MMethodDef

nitc :: AbstractRuntimeFunction :: mmethoddef

The associated Nit method
protected fun mmethoddef=(mmethoddef: MMethodDef)

nitc :: AbstractRuntimeFunction :: mmethoddef=

The associated Nit method
fun msignature: MSignature

nitc :: AbstractRuntimeFunction :: msignature

The current msignature to use when compiling : signature_to_c and body_to_c.
private intern fun native_class_name: CString

core :: Object :: native_class_name

The class name of the object in CString format.
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
protected fun recv_mtype: MType

nitc :: AbstractRuntimeFunction :: recv_mtype

The current receiver type to compile : signature_to_c and body_to_c.
protected fun resolve_ith_parameter(v: VISITOR, i: Int): RuntimeVariable

nitc :: AbstractRuntimeFunction :: resolve_ith_parameter

Step 4 : Creates RuntimeVariable for each method argument.
protected fun resolve_receiver(v: VISITOR): RuntimeVariable

nitc :: AbstractRuntimeFunction :: resolve_receiver

Prepare the self runtime variable to be used by the rest of
protected fun resolve_return_mtype(v: VISITOR)

nitc :: AbstractRuntimeFunction :: resolve_return_mtype

Step 3 : Returns the return type used by the runtime function.
protected fun return_mtype: nullable MType

nitc :: AbstractRuntimeFunction :: return_mtype

protected fun return_mtype=(return_mtype: nullable MType)

nitc :: AbstractRuntimeFunction :: return_mtype=

fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
protected fun signature_to_c(v: VISITOR): String

nitc :: AbstractRuntimeFunction :: signature_to_c

Generate the code for the signature with an open curly brace
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_s: String

core :: Object :: to_s

User readable representation of self.
package_diagram nitc::AbstractRuntimeFunction AbstractRuntimeFunction core::Object Object nitc::AbstractRuntimeFunction->core::Object nitc::SeparateRuntimeFunction SeparateRuntimeFunction nitc::SeparateRuntimeFunction->nitc::AbstractRuntimeFunction nitc::ThunkFunction ThunkFunction nitc::ThunkFunction->nitc::AbstractRuntimeFunction nitc::global_compiler::CustomizedRuntimeFunction CustomizedRuntimeFunction nitc::global_compiler::CustomizedRuntimeFunction->nitc::AbstractRuntimeFunction nitc::SeparateThunkFunction SeparateThunkFunction nitc::SeparateThunkFunction->nitc::SeparateRuntimeFunction nitc::SeparateThunkFunction->nitc::ThunkFunction nitc::SeparateThunkFunction... ... nitc::SeparateThunkFunction...->nitc::SeparateThunkFunction nitc::CustomizedThunkFunction CustomizedThunkFunction nitc::CustomizedThunkFunction->nitc::ThunkFunction nitc::CustomizedThunkFunction->nitc::global_compiler::CustomizedRuntimeFunction nitc::CustomizedThunkFunction... ... nitc::CustomizedThunkFunction...->nitc::CustomizedThunkFunction

Parents

interface Object

core :: Object

The root of the class hierarchy.

Children

private class CustomizedRuntimeFunction

nitc :: CustomizedRuntimeFunction

A runtime function customized on a specific monomorph receiver type
class SeparateRuntimeFunction

nitc :: SeparateRuntimeFunction

The C function associated to a methoddef separately compiled
abstract class ThunkFunction

nitc :: ThunkFunction

Base class for all thunk-like function. A thunk is a function whose purpose

Descendants

class CustomizedThunkFunction

nitc :: CustomizedThunkFunction

Thunk implementation for global compiler.

Class definitions

nitc $ AbstractRuntimeFunction
# A C function associated to a Nit method
# This is the base class for all runtime representation of a nit method.
# It implements the Template Design Pattern whose steps are :
#       1. create the receiver `RuntimeVariable` (selfvar)
#       2. create a `StaticFrame`
#       3. resolve the return type.
#       4. write the function signature
#       5. Declare the function signature (for C header files)
#       6. writer the function body
#       7. post-compiler hook (optional)
# Each step is called in `AbstractRuntimeFunction::compile_to_c`. A default
# body is provided foreach step except for compilation hooks. Subclasses may
# redefine any of the above mentioned steps. However, it's not recommanded
# to override `compile_to_c` since there's an ordering of the compilation steps.
# Any information between steps must be saved in the visitor. Currently most
# of the future runtime info are stored in the `StaticFrame` of the visitor,
# e.g. the receiver (selfvar), the arguments, etc.
#
# Moreover, any subclass may redefine : the receiver type, the return type and
# the signature. This allow for a better customization for the final implementation.
# Because of customization, a given Nit method can be compile more that once.
abstract class AbstractRuntimeFunction

	type COMPILER: AbstractCompiler
	type VISITOR: AbstractCompilerVisitor

	# The associated Nit method
	var mmethoddef: MMethodDef

	protected var return_mtype: nullable MType = null

	# The mangled c name of the runtime_function
	# Subclasses should redefine `build_c_name` instead
	fun c_name: String
	do
		var res = self.c_name_cache
		if res != null then return res
		res = self.build_c_name
		self.c_name_cache = res
		return res
	end

	fun c_ref: String do return "&{c_name}"

	# Non cached version of `c_name`
	protected fun build_c_name: String is abstract

	protected var c_name_cache: nullable String = null is writable

	# Implements a call of the runtime_function
	# May inline the body or generate a C function call
	fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable is abstract

	# Returns `true` if the associated `mmethoddef`'s return type isn't null,
	# otherwise `false`.
	fun has_return: Bool
	do
		return mmethoddef.msignature.return_mtype != null
	end

	# The current msignature to use when compiling : `signature_to_c` and `body_to_c`.
	# This method is useful since most concrete implementation doesn't use the
	# mmethoddef's signature. By providing a definition in the abstract class,
	# subclasses can use any msignature.
	fun msignature: MSignature
	do
		return mmethoddef.msignature.as(not null)
	end

	# The current receiver type to compile : `signature_to_c` and `body_to_c`.
	# See `msignature` method for more information.
	protected fun recv_mtype: MType
	do
		return mmethoddef.mclassdef.bound_mtype
	end

	# Prepare the `self` runtime variable to be used by the rest of
	# compilation steps.
	# Step 1
	protected fun resolve_receiver(v: VISITOR): RuntimeVariable
	do
		var casttype = mmethoddef.mclassdef.bound_mtype
		return new RuntimeVariable("self", recv_mtype, casttype)
	end

	# Builds the static frame for current runtime method
	# Step 2
	protected fun build_frame(v: VISITOR, arguments: Array[RuntimeVariable]): StaticFrame
	do
		return new StaticFrame(v, mmethoddef, recv_mtype.as(MClassType), arguments)
	end

	# Step 3 : Returns the return type used by the runtime function.
	protected fun resolve_return_mtype(v: VISITOR)
	do
		return_mtype = msignature.return_mtype
	end

	# Fills the argument array inside v.frame.arguments, calling `resolve_ith_parameter`
	# for each parameter.
	private fun fill_parameters(v: VISITOR)
	do
		assert v.frame != null
		for i in [0..msignature.arity[ do
			var arg = resolve_ith_parameter(v, i)
			v.frame.arguments.add(arg)
		end
	end

	# Step 4 : Creates `RuntimeVariable` for each method argument.
	protected fun resolve_ith_parameter(v: VISITOR, i: Int): RuntimeVariable
	do
		var mp = msignature.mparameters[i]
		var mtype = mp.mtype
		if mp.is_vararg then
			mtype = v.mmodule.array_type(mtype)
		end
		return new RuntimeVariable("p{i}", mtype, mtype)
	end

	# Generate the code for the signature with an open curly brace
	#
	# Returns the generated signature without a semicolon and curly brace,
	# e.g `RES f(T0 p0, T1 p1, ..., TN pN)`
	# Step 5
	protected fun signature_to_c(v: VISITOR): String
	do
		assert v.frame != null
		var arguments = v.frame.arguments
		var comment = new FlatBuffer
		var selfvar = v.frame.selfvar
		var c_ret = "void"
		if has_return then
			c_ret = "{return_mtype.ctype}"
		end
		var sig = new FlatBuffer
		sig.append("{c_ret} {c_name}({recv_mtype.ctype} self")
		comment.append("({selfvar}: {selfvar.mtype}")

		for i in [0..arguments.length-1[ do
			# Skip the receiver
			var arg = arguments[i+1]
			comment.append(", {arg.mtype}")
			sig.append(", {arg.mtype.ctype} p{i}")
		end
		sig.append(")")
		comment.append(")")
		if has_return then
			comment.append(": {return_mtype.as(not null)}")
		end
		v.add_decl("/* method {self} for {comment} */")
		v.add_decl("{sig} \{")
		return sig.to_s
	end

	# How the concrete compiler will declare the method, e.g inside a global header file,
	# extern signature, etc.
	# Step 6
	protected fun declare_signature(v: VISITOR, signature: String) is abstract

	# Generate the code for the body without return statement at the end and
	# no curly brace.
	# Step 7
	protected fun body_to_c(v: VISITOR)
	do
		mmethoddef.compile_inside_to_c(v, v.frame.arguments)
	end

	# Hook called at the end of `compile_to_c` function. This function
	# is useful if you need to register any function compiled to c.
	# Step 8 (optional).
	protected fun end_compile_to_c(v: VISITOR)
	do
		# Nothing to do by default
	end

	# Generate the code
	fun compile_to_c(compiler: COMPILER)
	do
		var v = compiler.new_visitor
		var selfvar = resolve_receiver(v)
		var arguments = [selfvar]
		var frame = build_frame(v, arguments)
		v.frame = frame

		resolve_return_mtype(v)
		fill_parameters(v)

		# WARNING: the signature must be declared before creating
		# any returnlabel and returnvar (`StaticFrame`). Otherwise,
		# you could end up with variable outside the function.
		var sig = signature_to_c(v)
		declare_signature(v, sig)

		frame.returnlabel = v.get_name("RET_LABEL")
		if has_return then
			var ret_mtype = return_mtype
			assert ret_mtype != null
			frame.returnvar = v.new_var(ret_mtype)
		end

		body_to_c(v)
		v.add("{frame.returnlabel.as(not null)}:;")
		if has_return then
			v.add("return {frame.returnvar.as(not null)};")
		end
		v.add "\}"
		end_compile_to_c(v)
	end
end
src/compiler/abstract_compiler.nit:2055,1--2264,3