In parallel, a new Gitlab Runner tagged "windows" was added. This new test only builds the project.
Pull-Request: #2776
Reviewed-by: Jean Privat <jean@pryen.org>
# ~~~
# assert 12.34.to_s == "12.34"
# assert (-0120.030).to_s == "-120.03"
+ # assert (-inf).to_s == "-inf"
+ # assert (nan).to_s == "nan"
# ~~~
#
# see `to_precision` for a custom precision.
redef fun to_s do
var str = to_precision(3)
- if is_inf != 0 or is_nan then return str
- var len = str.length
+ return adapt_number_of_decimal(str, false)
+ end
+
+ # Return the representation of `self`, with scientific notation
+ #
+ # Adpat the number of decimals as needed from 1 to a maximum of 6
+ # ~~~
+ # assert 12.34.to_sci == "1.234e+01"
+ # assert 123.45.to_sci.to_f.to_sci == "1.2345e+02"
+ # assert 0.001234.to_sci == "1.234e-03"
+ # assert (inf).to_sci == "inf"
+ # assert (nan).to_sci == "nan"
+ # ~~~
+ fun to_sci: String
+ do
+ var is_inf_or_nan = check_inf_or_nan
+ if is_inf_or_nan != null then return is_inf_or_nan
+ return adapt_number_of_decimal(return_from_specific_format("%e".to_cstring), true)
+ end
+
+ # Return the `string_number` with the adapted number of decimal (i.e the fonction remove the useless `0`)
+ # `is_expo` it's here to specifi if the given `string_number` is in scientific notation
+ private fun adapt_number_of_decimal(string_number: String, is_expo: Bool): String
+ do
+ # check if `self` does not need an adaptation of the decimal
+ if is_inf != 0 or is_nan then return string_number
+ var len = string_number.length
+ var expo_value = ""
+ var numeric_value = ""
for i in [0..len-1] do
- var j = len-1-i
- var c = str.chars[j]
- if c == '0' then
- continue
- else if c == '.' then
- return str.substring( 0, j+2 )
- else
- return str.substring( 0, j+1 )
+ var j = len - 1 - i
+ var c = string_number.chars[j]
+ if not is_expo then
+ if c == '0' then
+ continue
+ else if c == '.' then
+ numeric_value = string_number.substring( 0, j + 2)
+ break
+ else
+ numeric_value = string_number.substring( 0, j + 1)
+ break
+ end
+ else if c == 'e' then
+ expo_value = string_number.substring( j, len - 1 )
+ is_expo = false
end
end
- return str
+ return numeric_value + expo_value
+ end
+
+ # Return a string representation of `self` in fonction if it is not a number or infinity.
+ # Return `null` if `self` is not a not a number or an infinity
+ private fun check_inf_or_nan: nullable String
+ do
+ if is_nan then return "nan"
+
+ var isinf = self.is_inf
+ if isinf == 1 then
+ return "inf"
+ else if isinf == -1 then
+ return "-inf"
+ end
+ return null
end
# `String` representation of `self` with the given number of `decimals`
# ~~~
fun to_precision(decimals: Int): String
do
- if is_nan then return "nan"
-
- var isinf = self.is_inf
- if isinf == 1 then
- return "inf"
- else if isinf == -1 then
- return "-inf"
- end
-
- var size = to_precision_size(decimals)
- var cstr = new CString(size + 1)
- to_precision_fill(decimals, size + 1, cstr)
- return cstr.to_s_unsafe(byte_length = size, copy = false)
+ var is_inf_or_nan = check_inf_or_nan
+ if is_inf_or_nan != null then return is_inf_or_nan
+ return return_from_specific_format("%.{decimals}f".to_cstring)
end
# Returns the hexadecimal (`String`) representation of `self` in exponential notation
# ~~~
fun to_hexa_exponential_notation: String
do
- var size = to_precision_size_hexa
+ return return_from_specific_format("%a".to_cstring)
+ end
+
+ # Return the representation of `self`, with the specific given c `format`.
+ private fun return_from_specific_format(format: CString): String
+ do
+ var size = to_precision_size_with_format(format)
var cstr = new CString(size + 1)
- to_precision_fill_hexa(size + 1, cstr)
+ to_precision_fill_with_format(format, size + 1, cstr)
return cstr.to_s_unsafe(byte_length = size, copy = false)
end
- # Required string length to hold `self` with `nb` decimals
- #
- # The length does not include the terminating null byte.
- private fun to_precision_size(nb: Int): Int `{
- return snprintf(NULL, 0, "%.*f", (int)nb, self);
- `}
-
- # Fill `cstr` with `self` and `nb` decimals
- private fun to_precision_fill(nb, size: Int, cstr: CString) `{
- snprintf(cstr, size, "%.*f", (int)nb, self);
- `}
-
- # The lenght of `self` in exponential hexadecimal notation
- private fun to_precision_size_hexa: Int`{
- return snprintf(NULL, 0, "%a", self);
+ # The lenght of `self` in the specific given c `format`
+ private fun to_precision_size_with_format(format: CString): Int`{
+ return snprintf(NULL, 0, format, self);
`}
- # Fill `cstr` with `self` in exponential hexadecimal notation
- private fun to_precision_fill_hexa(size: Int, cstr: CString) `{
- snprintf(cstr, size, "%a", self);
+ # Fill `cstr` with `self` in the specific given c `format`
+ private fun to_precision_fill_with_format(format: CString, size: Int, cstr: CString) `{
+ snprintf(cstr, size, format, self);
`}
end
#
# var res = col.aggregate("""[
# { "$match": { "status": "A" } },
- # { "$group": { "_id": "$cust_id", "total": { "$sum": "$amount" } } }
+ # { "$group": { "_id": "$cust_id", "total": { "$sum": "$amount" } } },
+ # { "$sort" : { "_id": 1 } }
# ]""".parse_json.as(JsonArray))
#
- # assert res[0].to_json == """{"_id":"B212","total":200}"""
- # assert res[1].to_json == """{"_id":"A123","total":750}"""
+ # assert res[0].to_json == """{"_id":"A123","total":750}"""
+ # assert res[1].to_json == """{"_id":"B212","total":200}"""
# ~~~
fun aggregate(pipeline: JsonArray): Array[JsonObject] do
var q = new JsonObject
end
# A C function associated to a Nit method
-# Because of customization, a given Nit method can be compiler more that once
+# 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
# 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
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
# May inline the body or generate a C function call
fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable is abstract
- # Generate the code for the `AbstractRuntimeFunction`
- # Warning: compile more than once compilation makes CC unhappy
- fun compile_to_c(compiler: COMPILER) 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
+# 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
+
+
# A runtime variable hold a runtime value in C.
# Runtime variables are associated to Nit local variables and intermediate results in Nit expressions.
#
# The array comprehension currently filled, if any
private var comprehension: nullable RuntimeVariable = null
+
+ # Returns the first argument (the receiver) of a frame.
+ # REQUIRE: arguments.length >= 1
+ fun selfvar: RuntimeVariable
+ do
+ assert arguments.length >= 1
+ return arguments.first
+ end
end
redef class MType
end
end
-# A runtime function customized on a specific monomrph receiver type
+# A runtime function customized on a specific monomorph receiver type
private class CustomizedRuntimeFunction
super AbstractRuntimeFunction
end
end
- # compile the code customized for the reciever
- redef fun compile_to_c(compiler)
- do
- var recv = self.recv
- var mmethoddef = self.mmethoddef
- if not recv.is_subtype(compiler.mainmodule, null, mmethoddef.mclassdef.bound_mtype) then
- print("problem: why do we compile {self} for {recv}?")
- abort
- end
-
- var v = compiler.new_visitor
- var selfvar = new RuntimeVariable("self", recv, recv)
- if compiler.runtime_type_analysis.live_types.has(recv) then
- selfvar.is_exact = true
- end
- var arguments = new Array[RuntimeVariable]
- var frame = new StaticFrame(v, mmethoddef, recv, arguments)
- v.frame = frame
-
- var sig = new FlatBuffer
- var comment = new FlatBuffer
- var ret = mmethoddef.msignature.return_mtype
- if ret != null then
- ret = v.resolve_for(ret, selfvar)
- sig.append("{ret.ctype} ")
- else
- sig.append("void ")
- end
- sig.append(self.c_name)
- sig.append("({recv.ctype} {selfvar}")
- comment.append("(self: {recv}")
- arguments.add(selfvar)
- for i in [0..mmethoddef.msignature.arity[ do
- var mp = mmethoddef.msignature.mparameters[i]
- var mtype = mp.mtype
- if mp.is_vararg then
- mtype = v.mmodule.array_type(mtype)
- end
- mtype = v.resolve_for(mtype, selfvar)
- comment.append(", {mtype}")
- sig.append(", {mtype.ctype} p{i}")
- var argvar = new RuntimeVariable("p{i}", mtype, mtype)
- arguments.add(argvar)
- end
- sig.append(")")
- comment.append(")")
- if ret != null then
- comment.append(": {ret}")
- end
- compiler.header.add_decl("{sig};")
+ redef fun recv_mtype
+ do
+ return recv
+ end
- v.add_decl("/* method {self} for {comment} */")
- v.add_decl("{sig} \{")
- #v.add("printf(\"method {self} for {comment}\\n\");")
- if ret != null then
- frame.returnvar = v.new_var(ret)
- end
- frame.returnlabel = v.get_name("RET_LABEL")
+ redef var return_mtype
- mmethoddef.compile_inside_to_c(v, arguments)
-
- v.add("{frame.returnlabel.as(not null)}:;")
- if ret != null then
- v.add("return {frame.returnvar.as(not null)};")
+ redef fun resolve_receiver(v)
+ do
+ var selfvar = new RuntimeVariable("self", recv, recv)
+ if v.compiler.runtime_type_analysis.live_types.has(recv) then
+ selfvar.is_exact = true
end
- v.add("\}")
- if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
- end
+ return selfvar
+ end
+
+ redef fun resolve_return_mtype(v)
+ do
+ var selfvar = v.frame.selfvar
+ if has_return then
+ var ret = msignature.return_mtype.as(not null)
+ return_mtype = v.resolve_for(ret, selfvar)
+ end
+ end
+ redef fun resolve_ith_parameter(v, i)
+ do
+ var selfvar = v.frame.selfvar
+ var mp = msignature.mparameters[i]
+ var mtype = mp.mtype
+ if mp.is_vararg then
+ mtype = v.mmodule.array_type(mtype)
+ end
+ mtype = v.resolve_for(mtype, selfvar)
+ return new RuntimeVariable("p{i}", mtype, mtype)
+ end
+
+ redef fun declare_signature(v, sig)
+ do
+ v.compiler.header.add_decl("{sig};")
+ end
+
+ redef fun end_compile_to_c(v)
+ do
+ if not self.c_name.has_substring("VIRTUAL", 0) then v.compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
+ end
redef fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
do
self.virtual_runtime_function_cache = res
return res
end
-
- res = new SeparateRuntimeFunction(self, recv, msignature, "VIRTUAL_{c_name}")
- self.virtual_runtime_function_cache = res
- res.is_thunk = true
+ res = new SeparateThunkFunction(self, recv, msignature, "VIRTUAL_{c_name}", mclassdef.bound_mtype)
end
return res
end
# The name on the compiled method
redef var build_c_name: String
- # Statically call the original body instead
- var is_thunk = false
-
redef fun to_s do return self.mmethoddef.to_s
+ redef fun msignature
+ do
+ return called_signature
+ end
+
+ redef fun recv_mtype
+ do
+ return called_recv
+ end
+
+ redef fun return_mtype
+ do
+ return called_signature.return_mtype
+ end
+
# The C return type (something or `void`)
var c_ret: String is lazy do
var ret = called_signature.return_mtype
# The C type for the function pointer.
var c_funptrtype: String is lazy do return "{c_ret}(*){c_sig}"
- redef fun compile_to_c(compiler)
- do
- var mmethoddef = self.mmethoddef
-
- var sig = "{c_ret} {c_name}{c_sig}"
- compiler.provide_declaration(self.c_name, "{sig};")
-
- var rta = compiler.as(SeparateCompiler).runtime_type_analysis
-
- var recv = self.mmethoddef.mclassdef.bound_mtype
- var v = compiler.new_visitor
- var selfvar = new RuntimeVariable("self", called_recv, recv)
- var arguments = new Array[RuntimeVariable]
- var frame = new StaticFrame(v, mmethoddef, recv, arguments)
- v.frame = frame
+ redef fun declare_signature(v, sig)
+ do
+ v.compiler.provide_declaration(c_name, "{sig};")
+ end
- var msignature = called_signature
- var ret = called_signature.return_mtype
-
- var comment = new FlatBuffer
- comment.append("({selfvar}: {selfvar.mtype}")
- arguments.add(selfvar)
- for i in [0..msignature.arity[ do
- var mp = msignature.mparameters[i]
- var mtype = mp.mtype
- if mp.is_vararg then
- mtype = v.mmodule.array_type(mtype)
- end
- comment.append(", {mtype}")
- var argvar = new RuntimeVariable("p{i}", mtype, mtype)
- arguments.add(argvar)
- end
- comment.append(")")
- if ret != null then
- comment.append(": {ret}")
- end
+ redef fun body_to_c(v)
+ do
+ var rta = v.compiler.as(SeparateCompiler).runtime_type_analysis
+ if rta != null and not rta.live_mmodules.has(mmethoddef.mclassdef.mmodule) then
+ v.add_abort("FATAL: Dead method executed.")
+ else
+ super
+ end
+ end
- v.add_decl("/* method {self} for {comment} */")
- v.add_decl("{sig} \{")
- if ret != null then
- frame.returnvar = v.new_var(ret)
- end
- frame.returnlabel = v.get_name("RET_LABEL")
- if is_thunk then
- var subret = v.call(mmethoddef, recv, arguments)
- if ret != null then
- assert subret != null
- v.assign(frame.returnvar.as(not null), subret)
- end
- else if rta != null and not rta.live_mmodules.has(mmethoddef.mclassdef.mmodule) then
- v.add_abort("FATAL: Dead method executed.")
- else
- mmethoddef.compile_inside_to_c(v, arguments)
- end
+ redef fun end_compile_to_c(v)
+ do
+ var compiler = v.compiler
+ compiler.names[self.c_name] = "{mmethoddef.full_name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
+ end
- v.add("{frame.returnlabel.as(not null)}:;")
- if ret != null then
- v.add("return {frame.returnvar.as(not null)};")
- end
- v.add("\}")
- compiler.names[self.c_name] = "{mmethoddef.full_name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
- end
+ redef fun build_frame(v, arguments)
+ do
+ var recv = mmethoddef.mclassdef.bound_mtype
+ return new StaticFrame(v, mmethoddef, recv, arguments)
+ end
# Compile the trampolines used to implement late-binding.
#
end
end
+class SeparateThunkFunction
+ super ThunkFunction
+ super SeparateRuntimeFunction
+ redef var target_recv
+end
+
redef class MType
# Are values of `self` tagged?
# If false, it means that the type is not primitive, or is boxed.