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.
nitc :: AbstractRuntimeFunction :: _mmethoddef
The associated Nit methodnitc :: 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_functionnitc :: 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 :: 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,
nitc :: AbstractRuntimeFunction :: mmethoddef=
The associated Nit methodnitc :: AbstractRuntimeFunction :: msignature
The current msignature to use when compiling :signature_to_c
and body_to_c
.
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 $ AbstractRuntimeFunction :: SELF
Type of this instance, automatically specialized in every classnitc :: AbstractRuntimeFunction :: _mmethoddef
The associated Nit methodnitc :: 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,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 :: 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 :: CustomizedRuntimeFunction
A runtime function customized on a specific monomorph receiver typenitc :: SeparateRuntimeFunction
The C function associated to a methoddef separately compilednitc :: CustomizedThunkFunction
Thunk implementation for global compiler.
# 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