+ private var virtual_runtime_function_cache: nullable VirtualRuntimeFunction
+end
+
+# The C function associated to a methoddef separately compiled
+class SeparateRuntimeFunction
+ super AbstractRuntimeFunction
+
+ redef fun build_c_name: String do return "{mmethoddef.c_name}"
+
+ redef fun to_s do return self.mmethoddef.to_s
+
+ redef fun compile_to_c(compiler)
+ do
+ var mmethoddef = self.mmethoddef
+
+ var recv = self.mmethoddef.mclassdef.bound_mtype
+ var v = compiler.new_visitor
+ var selfvar = new RuntimeVariable("self", recv, recv)
+ var arguments = new Array[RuntimeVariable]
+ var frame = new Frame(v, mmethoddef, recv, arguments)
+ v.frame = frame
+
+ var msignature = mmethoddef.msignature.resolve_for(mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.mmodule, true)
+
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
+ var ret = msignature.return_mtype
+ if ret != null then
+ sig.append("{ret.ctype} ")
+ else if mmethoddef.mproperty.is_new then
+ ret = recv
+ sig.append("{ret.ctype} ")
+ else
+ sig.append("void ")
+ end
+ sig.append(self.c_name)
+ sig.append("({selfvar.mtype.ctype} {selfvar}")
+ comment.append("({selfvar}: {selfvar.mtype}")
+ arguments.add(selfvar)
+ for i in [0..msignature.arity[ do
+ var mtype = msignature.mparameters[i].mtype
+ if i == msignature.vararg_rank then
+ mtype = v.get_class("Array").get_mtype([mtype])
+ end
+ 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.provide_declaration(self.c_name, "{sig};")
+
+ 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 recv != arguments.first.mtype then
+ #print "{self} {recv} {arguments.first}"
+ end
+ 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)};")
+ 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
+end
+
+# The C function associated to a methoddef on a primitive type, stored into a VFT of a class
+# The first parameter (the reciever) is always typed by val* in order to accept an object value
+class VirtualRuntimeFunction
+ super AbstractRuntimeFunction
+
+ redef fun build_c_name: String do return "VIRTUAL_{mmethoddef.c_name}"
+
+ redef fun to_s do return self.mmethoddef.to_s
+
+ redef fun compile_to_c(compiler)
+ do
+ var mmethoddef = self.mmethoddef
+
+ var recv = self.mmethoddef.mclassdef.bound_mtype
+ var v = compiler.new_visitor
+ var selfvar = new RuntimeVariable("self", v.object_type, recv)
+ var arguments = new Array[RuntimeVariable]
+ var frame = new Frame(v, mmethoddef, recv, arguments)
+ v.frame = frame
+
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
+
+ # Because the function is virtual, the signature must match the one of the original class
+ var intromclassdef = self.mmethoddef.mproperty.intro.mclassdef
+ var msignature = mmethoddef.mproperty.intro.msignature.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true)
+ var ret = msignature.return_mtype
+ if ret != null then
+ sig.append("{ret.ctype} ")
+ else if mmethoddef.mproperty.is_new then
+ ret = recv
+ sig.append("{ret.ctype} ")
+ else
+ sig.append("void ")
+ end
+ sig.append(self.c_name)
+ sig.append("({selfvar.mtype.ctype} {selfvar}")
+ comment.append("({selfvar}: {selfvar.mtype}")
+ arguments.add(selfvar)
+ for i in [0..msignature.arity[ do
+ var mtype = msignature.mparameters[i].mtype
+ if i == msignature.vararg_rank then
+ mtype = v.get_class("Array").get_mtype([mtype])
+ end
+ 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.provide_declaration(self.c_name, "{sig};")
+
+ 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")
+
+ var subret = v.call(mmethoddef, recv, arguments)
+ if ret != null then
+ assert subret != null
+ v.assign(frame.returnvar.as(not null), subret)
+ end
+
+ v.add("{frame.returnlabel.as(not null)}:;")
+ if ret != null then
+ v.add("return {frame.returnvar.as(not null)};")
+ 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
+
+ # TODO ?
+ redef fun call(v, arguments) do abort
+end
+
+redef class MType
+ fun const_color: String do return "COLOR_{c_name}"
+
+ # C name of the instance type to use
+ fun c_instance_name: String do return c_name
+end
+
+redef class MClassType
+ redef fun c_instance_name do return mclass.c_instance_name
+end
+
+redef class MClass
+ # Extern classes use the C instance of kernel::Pointer
+ fun c_instance_name: String
+ do
+ if kind == extern_kind then
+ return "kernel__Pointer"
+ else return c_name
+ end
+end
+
+redef class MProperty
+ fun const_color: String do return "COLOR_{c_name}"
+end
+
+redef class MPropDef
+ fun const_color: String do return "COLOR_{c_name}"