A visitor on the AST of property definition that generate the C code.

Introduced properties

private var _compiler: COMPILER

nitc :: AbstractCompilerVisitor :: _compiler

The associated compiler
private var _current_node: nullable ANode

nitc :: AbstractCompilerVisitor :: _current_node

The current visited AST node
private var _frame: nullable StaticFrame

nitc :: AbstractCompilerVisitor :: _frame

The current StaticFrame
private var _last: Int

nitc :: AbstractCompilerVisitor :: _last

abstract fun adapt_signature(m: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: adapt_signature

Adapt the arguments of a method according to targetted MMethodDef
fun add(s: String)

nitc :: AbstractCompilerVisitor :: add

Add a line in the main part of the generated C
fun add_abort(message: String)

nitc :: AbstractCompilerVisitor :: add_abort

Generate generic abort
fun add_cast(value: RuntimeVariable, mtype: MType, tag: String)

nitc :: AbstractCompilerVisitor :: add_cast

Add a dynamic cast
fun add_decl(s: String)

nitc :: AbstractCompilerVisitor :: add_decl

Add a line in the
fun add_escape_label(e: nullable EscapeMark)

nitc :: AbstractCompilerVisitor :: add_escape_label

Insert a C label for associated with an escapemark
fun add_extern(mmodule: MModule)

nitc :: AbstractCompilerVisitor :: add_extern

Look for a needed .h and .c file for a given module
fun add_raw_abort

nitc :: AbstractCompilerVisitor :: add_raw_abort

Generate abort without a message.
fun add_raw_throw

nitc :: AbstractCompilerVisitor :: add_raw_throw

Generate a long jump if there is a catch block.
fun anchor(mtype: MType): MType

nitc :: AbstractCompilerVisitor :: anchor

Anchor a type to the main module and the current receiver
abstract fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: array_instance

Generate an array value
fun assign(left: RuntimeVariable, right: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: assign

Correctly assign a left and a right value
fun autoadapt(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: autoadapt

Unsafely cast a value to a new type
abstract fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: autobox

Box or unbox a value to another type iff a C type conversion is needed
fun bool_instance(value: Bool): RuntimeVariable

nitc :: AbstractCompilerVisitor :: bool_instance

Generate an integer value
fun bool_type: MClassType

nitc :: AbstractCompilerVisitor :: bool_type

Alias for self.compiler.mainmodule.bool_type
abstract fun box_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: box_extern

Box extern classes to be used in the generated code
fun byte_instance(value: Byte): RuntimeVariable

nitc :: AbstractCompilerVisitor :: byte_instance

Generate a byte value
fun c_string_instance(ns: CString, len: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: c_string_instance

Generates a CString instance fully escaped in C-style \xHH fashion
abstract fun call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: call

Generate a static call on a method definition
fun char_instance(value: Char): RuntimeVariable

nitc :: AbstractCompilerVisitor :: char_instance

Generate a char value
fun check_recv_notnull(recv: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: check_recv_notnull

Add a check and an abort for a null receiver if needed
abstract fun class_name_string(value: RuntimeVariable): String

nitc :: AbstractCompilerVisitor :: class_name_string

Return a "const char*" variable associated to the classname of the dynamic type of an object
fun compiler: COMPILER

nitc :: AbstractCompilerVisitor :: compiler

The associated compiler
protected fun compiler=(compiler: COMPILER)

nitc :: AbstractCompilerVisitor :: compiler=

The associated compiler
fun current_node: nullable ANode

nitc :: AbstractCompilerVisitor :: current_node

The current visited AST node
fun current_node=(current_node: nullable ANode)

nitc :: AbstractCompilerVisitor :: current_node=

The current visited AST node
fun debug(message: String)

nitc :: AbstractCompilerVisitor :: debug

Safely show a debug message on the current node and repeat the message in the C code as a comment
fun declare_once(s: String)

nitc :: AbstractCompilerVisitor :: declare_once

Add a declaration in the local-header
abstract fun equal_test(value1: RuntimeVariable, value2: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: equal_test

Generate a Nit "is" for two runtime_variables
fun escapemark_name(e: nullable EscapeMark): String

nitc :: AbstractCompilerVisitor :: escapemark_name

Return an unique and stable identifier associated with an escapemark
fun expr(nexpr: AExpr, mtype: nullable MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: expr

Compile an expression an return its result
fun expr_bool(nexpr: AExpr): RuntimeVariable

nitc :: AbstractCompilerVisitor :: expr_bool

Alias for self.expr(nexpr, self.bool_type)
fun float_instance(value: Float): RuntimeVariable

nitc :: AbstractCompilerVisitor :: float_instance

Generate a float value
fun frame: nullable StaticFrame

nitc :: AbstractCompilerVisitor :: frame

The current StaticFrame
fun frame=(frame: nullable StaticFrame)

nitc :: AbstractCompilerVisitor :: frame=

The current StaticFrame
fun get_name(s: String): String

nitc :: AbstractCompilerVisitor :: get_name

Return a new name based on s and unique in the visitor
fun get_property(name: String, recv: MType): MMethod

nitc :: AbstractCompilerVisitor :: get_property

Force to get the primitive property named name in the instance recv or abort
abstract fun init_instance(mtype: MClassType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: init_instance

Generate a alloc-instance + init-attributes
fun init_instance_or_extern(mtype: MClassType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: init_instance_or_extern

Allocate and init attributes of an instance of a standard or extern class
fun int16_instance(value: Int16): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int16_instance

Generate an int16 value
fun int32_instance(value: Int32): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int32_instance

Generate an int32 value
fun int8_instance(value: Int8): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int8_instance

Generate an int8 value
fun int_instance(value: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int_instance

Generate an integer value
abstract fun is_same_type_test(value1: RuntimeVariable, value2: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: is_same_type_test

Generate the code required to dynamically check if 2 objects share the same runtime type
abstract fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: isset_attribute

Generate a polymorphic attribute is_set test
private fun last: Int

nitc :: AbstractCompilerVisitor :: last

private fun last=(last: Int)

nitc :: AbstractCompilerVisitor :: last=

fun maybe_null(value: RuntimeVariable): Bool

nitc :: AbstractCompilerVisitor :: maybe_null

Can value be null? (according to current knowledge)
fun mmodule: MModule

nitc :: AbstractCompilerVisitor :: mmodule

The currently processed module
fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: monomorphic_send

Generate a monomorphic send for the method m, the type t and the arguments args
fun monomorphic_super_send(m: MMethodDef, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: monomorphic_super_send

Generate a monomorphic super send from the method m, the type t and the arguments args
private fun names=(names: HashSet[String])

nitc :: AbstractCompilerVisitor :: names=

fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool

nitc :: AbstractCompilerVisitor :: native_array_def

abstract fun native_array_get(native_array: RuntimeVariable, index: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: native_array_get

Return an element of a native array.
abstract fun native_array_set(native_array: RuntimeVariable, index: Int, value: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: native_array_set

Store an element in a native array.
fun new_expr(cexpr: String, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_expr

Return a new local runtime_variable initialized with the C expression cexpr.
fun new_named_var(mtype: MType, name: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_named_var

Return a new uninitialized named runtime_variable
fun new_var(mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_var

Return a new uninitialized local runtime_variable
fun new_var_extern(mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_var_extern

The difference with new_var is the C static type of the local variable
fun nit_alloc(size: String, tag: nullable String): String

nitc :: AbstractCompilerVisitor :: nit_alloc

Allocate size bytes with the low_level nit_alloc C function
fun object_type: MClassType

nitc :: AbstractCompilerVisitor :: object_type

Alias for self.compiler.mainmodule.object_type
abstract fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: read_attribute

Generate a polymorphic attribute read
fun require_declaration(key: String)

nitc :: AbstractCompilerVisitor :: require_declaration

Request the presence of a global declaration
fun ret(s: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: ret

Generate a return with the value s
private fun ret_to_c(src: RuntimeVariable, mtype: MType)

nitc :: AbstractCompilerVisitor :: ret_to_c

Return a RuntimeVarible to C user code
abstract fun routine_ref_call(mmethoddef: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: routine_ref_call

Call the underlying referenced function
abstract fun routine_ref_instance(routine_mclass_type: MClassType, recv: RuntimeVariable, callsite: CallSite): RuntimeVariable

nitc :: AbstractCompilerVisitor :: routine_ref_instance

Instantiate a new routine pointer
abstract fun send(m: MMethod, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: send

Generate a polymorphic send for the method m and the arguments args
fun set_finalizer(recv: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: set_finalizer

Set a GC finalizer on recv, only if recv isa Finalizable
fun stmt(nexpr: nullable AExpr)

nitc :: AbstractCompilerVisitor :: stmt

Compile a statement (if any)
fun string_instance(string: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: string_instance

Generate a string value
abstract fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: supercall

Generate a super call from a method definition
abstract fun type_test(value: RuntimeVariable, mtype: MType, tag: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: type_test

Generate a polymorphic subtype test
abstract fun unbox_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: unbox_extern

Unbox extern classes to be used in extern code (legacy NI and FFI)
abstract fun unbox_signature_extern(m: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: unbox_signature_extern

Unbox all the arguments of a method when implemented extern or intern
private fun var_from_c(name: String, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: var_from_c

Create a RuntimeVariable for this C variable originating from C user code
abstract fun vararg_instance(mpropdef: MPropDef, recv: RuntimeVariable, varargs: Array[RuntimeVariable], elttype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: vararg_instance

Get an instance of a array for a vararg
fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]

nitc :: AbstractCompilerVisitor :: varargize

Evaluate args as expressions in the call of mpropdef on recv.
fun variable(variable: Variable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: variable

Return the local runtime_variable associated to a Nit local variable
abstract fun write_attribute(a: MAttribute, recv: RuntimeVariable, value: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: write_attribute

Generate a polymorphic attribute write
protected fun writer=(writer: CodeWriter)

nitc :: AbstractCompilerVisitor :: writer=

Redefined properties

redef type SELF: AbstractCompilerVisitor

nitc $ AbstractCompilerVisitor :: SELF

Type of this instance, automatically specialized in every class
redef fun nit_alloc(size: String, tag: nullable String): String

nitc :: memory_logger $ AbstractCompilerVisitor :: nit_alloc

Allocate size bytes with the low_level nit_alloc C function

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 _compiler: COMPILER

nitc :: AbstractCompilerVisitor :: _compiler

The associated compiler
private var _current_node: nullable ANode

nitc :: AbstractCompilerVisitor :: _current_node

The current visited AST node
private var _frame: nullable StaticFrame

nitc :: AbstractCompilerVisitor :: _frame

The current StaticFrame
private var _last: Int

nitc :: AbstractCompilerVisitor :: _last

abstract fun adapt_signature(m: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: adapt_signature

Adapt the arguments of a method according to targetted MMethodDef
fun add(s: String)

nitc :: AbstractCompilerVisitor :: add

Add a line in the main part of the generated C
fun add_abort(message: String)

nitc :: AbstractCompilerVisitor :: add_abort

Generate generic abort
fun add_cast(value: RuntimeVariable, mtype: MType, tag: String)

nitc :: AbstractCompilerVisitor :: add_cast

Add a dynamic cast
fun add_decl(s: String)

nitc :: AbstractCompilerVisitor :: add_decl

Add a line in the
fun add_escape_label(e: nullable EscapeMark)

nitc :: AbstractCompilerVisitor :: add_escape_label

Insert a C label for associated with an escapemark
fun add_extern(mmodule: MModule)

nitc :: AbstractCompilerVisitor :: add_extern

Look for a needed .h and .c file for a given module
fun add_raw_abort

nitc :: AbstractCompilerVisitor :: add_raw_abort

Generate abort without a message.
fun add_raw_throw

nitc :: AbstractCompilerVisitor :: add_raw_throw

Generate a long jump if there is a catch block.
fun anchor(mtype: MType): MType

nitc :: AbstractCompilerVisitor :: anchor

Anchor a type to the main module and the current receiver
abstract fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: array_instance

Generate an array value
fun assign(left: RuntimeVariable, right: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: assign

Correctly assign a left and a right value
fun autoadapt(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: autoadapt

Unsafely cast a value to a new type
abstract fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: autobox

Box or unbox a value to another type iff a C type conversion is needed
fun bool_instance(value: Bool): RuntimeVariable

nitc :: AbstractCompilerVisitor :: bool_instance

Generate an integer value
fun bool_type: MClassType

nitc :: AbstractCompilerVisitor :: bool_type

Alias for self.compiler.mainmodule.bool_type
abstract fun box_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: box_extern

Box extern classes to be used in the generated code
fun byte_instance(value: Byte): RuntimeVariable

nitc :: AbstractCompilerVisitor :: byte_instance

Generate a byte value
fun c_string_instance(ns: CString, len: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: c_string_instance

Generates a CString instance fully escaped in C-style \xHH fashion
abstract fun call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: call

Generate a static call on a method definition
fun char_instance(value: Char): RuntimeVariable

nitc :: AbstractCompilerVisitor :: char_instance

Generate a char value
fun check_recv_notnull(recv: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: check_recv_notnull

Add a check and an abort for a null receiver if needed
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.
abstract fun class_name_string(value: RuntimeVariable): String

nitc :: AbstractCompilerVisitor :: class_name_string

Return a "const char*" variable associated to the classname of the dynamic type of an object
fun compiler: COMPILER

nitc :: AbstractCompilerVisitor :: compiler

The associated compiler
protected fun compiler=(compiler: COMPILER)

nitc :: AbstractCompilerVisitor :: compiler=

The associated compiler
fun current_node: nullable ANode

nitc :: AbstractCompilerVisitor :: current_node

The current visited AST node
fun current_node=(current_node: nullable ANode)

nitc :: AbstractCompilerVisitor :: current_node=

The current visited AST node
fun debug(message: String)

nitc :: AbstractCompilerVisitor :: debug

Safely show a debug message on the current node and repeat the message in the C code as a comment
fun declare_once(s: String)

nitc :: AbstractCompilerVisitor :: declare_once

Add a declaration in the local-header
abstract fun equal_test(value1: RuntimeVariable, value2: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: equal_test

Generate a Nit "is" for two runtime_variables
fun escapemark_name(e: nullable EscapeMark): String

nitc :: AbstractCompilerVisitor :: escapemark_name

Return an unique and stable identifier associated with an escapemark
fun expr(nexpr: AExpr, mtype: nullable MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: expr

Compile an expression an return its result
fun expr_bool(nexpr: AExpr): RuntimeVariable

nitc :: AbstractCompilerVisitor :: expr_bool

Alias for self.expr(nexpr, self.bool_type)
fun float_instance(value: Float): RuntimeVariable

nitc :: AbstractCompilerVisitor :: float_instance

Generate a float value
fun frame: nullable StaticFrame

nitc :: AbstractCompilerVisitor :: frame

The current StaticFrame
fun frame=(frame: nullable StaticFrame)

nitc :: AbstractCompilerVisitor :: frame=

The current StaticFrame
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun get_name(s: String): String

nitc :: AbstractCompilerVisitor :: get_name

Return a new name based on s and unique in the visitor
fun get_property(name: String, recv: MType): MMethod

nitc :: AbstractCompilerVisitor :: get_property

Force to get the primitive property named name in the instance recv or abort
fun hash: Int

core :: Object :: hash

The hash code of the object.
init init

core :: Object :: init

abstract fun init_instance(mtype: MClassType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: init_instance

Generate a alloc-instance + init-attributes
fun init_instance_or_extern(mtype: MClassType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: init_instance_or_extern

Allocate and init attributes of an instance of a standard or extern class
fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
fun int16_instance(value: Int16): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int16_instance

Generate an int16 value
fun int32_instance(value: Int32): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int32_instance

Generate an int32 value
fun int8_instance(value: Int8): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int8_instance

Generate an int8 value
fun int_instance(value: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: int_instance

Generate an integer value
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.
abstract fun is_same_type_test(value1: RuntimeVariable, value2: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: is_same_type_test

Generate the code required to dynamically check if 2 objects share the same runtime type
abstract fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: isset_attribute

Generate a polymorphic attribute is_set test
private fun last: Int

nitc :: AbstractCompilerVisitor :: last

private fun last=(last: Int)

nitc :: AbstractCompilerVisitor :: last=

fun maybe_null(value: RuntimeVariable): Bool

nitc :: AbstractCompilerVisitor :: maybe_null

Can value be null? (according to current knowledge)
fun mmodule: MModule

nitc :: AbstractCompilerVisitor :: mmodule

The currently processed module
fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: monomorphic_send

Generate a monomorphic send for the method m, the type t and the arguments args
fun monomorphic_super_send(m: MMethodDef, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: monomorphic_super_send

Generate a monomorphic super send from the method m, the type t and the arguments args
private fun names=(names: HashSet[String])

nitc :: AbstractCompilerVisitor :: names=

fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool

nitc :: AbstractCompilerVisitor :: native_array_def

abstract fun native_array_get(native_array: RuntimeVariable, index: Int): RuntimeVariable

nitc :: AbstractCompilerVisitor :: native_array_get

Return an element of a native array.
abstract fun native_array_set(native_array: RuntimeVariable, index: Int, value: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: native_array_set

Store an element in a native array.
private intern fun native_class_name: CString

core :: Object :: native_class_name

The class name of the object in CString format.
fun new_expr(cexpr: String, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_expr

Return a new local runtime_variable initialized with the C expression cexpr.
fun new_named_var(mtype: MType, name: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_named_var

Return a new uninitialized named runtime_variable
fun new_var(mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_var

Return a new uninitialized local runtime_variable
fun new_var_extern(mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: new_var_extern

The difference with new_var is the C static type of the local variable
fun nit_alloc(size: String, tag: nullable String): String

nitc :: AbstractCompilerVisitor :: nit_alloc

Allocate size bytes with the low_level nit_alloc C function
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun object_type: MClassType

nitc :: AbstractCompilerVisitor :: object_type

Alias for self.compiler.mainmodule.object_type
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).
abstract fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: read_attribute

Generate a polymorphic attribute read
fun require_declaration(key: String)

nitc :: AbstractCompilerVisitor :: require_declaration

Request the presence of a global declaration
fun ret(s: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: ret

Generate a return with the value s
private fun ret_to_c(src: RuntimeVariable, mtype: MType)

nitc :: AbstractCompilerVisitor :: ret_to_c

Return a RuntimeVarible to C user code
abstract fun routine_ref_call(mmethoddef: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: routine_ref_call

Call the underlying referenced function
abstract fun routine_ref_instance(routine_mclass_type: MClassType, recv: RuntimeVariable, callsite: CallSite): RuntimeVariable

nitc :: AbstractCompilerVisitor :: routine_ref_instance

Instantiate a new routine pointer
abstract fun send(m: MMethod, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: send

Generate a polymorphic send for the method m and the arguments args
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
fun set_finalizer(recv: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: set_finalizer

Set a GC finalizer on recv, only if recv isa Finalizable
fun stmt(nexpr: nullable AExpr)

nitc :: AbstractCompilerVisitor :: stmt

Compile a statement (if any)
fun string_instance(string: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: string_instance

Generate a string value
abstract fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable

nitc :: AbstractCompilerVisitor :: supercall

Generate a super call from a method definition
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.
abstract fun type_test(value: RuntimeVariable, mtype: MType, tag: String): RuntimeVariable

nitc :: AbstractCompilerVisitor :: type_test

Generate a polymorphic subtype test
abstract fun unbox_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: unbox_extern

Unbox extern classes to be used in extern code (legacy NI and FFI)
abstract fun unbox_signature_extern(m: MMethodDef, args: Array[RuntimeVariable])

nitc :: AbstractCompilerVisitor :: unbox_signature_extern

Unbox all the arguments of a method when implemented extern or intern
private fun var_from_c(name: String, mtype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: var_from_c

Create a RuntimeVariable for this C variable originating from C user code
abstract fun vararg_instance(mpropdef: MPropDef, recv: RuntimeVariable, varargs: Array[RuntimeVariable], elttype: MType): RuntimeVariable

nitc :: AbstractCompilerVisitor :: vararg_instance

Get an instance of a array for a vararg
fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]

nitc :: AbstractCompilerVisitor :: varargize

Evaluate args as expressions in the call of mpropdef on recv.
fun variable(variable: Variable): RuntimeVariable

nitc :: AbstractCompilerVisitor :: variable

Return the local runtime_variable associated to a Nit local variable
abstract fun write_attribute(a: MAttribute, recv: RuntimeVariable, value: RuntimeVariable)

nitc :: AbstractCompilerVisitor :: write_attribute

Generate a polymorphic attribute write
protected fun writer=(writer: CodeWriter)

nitc :: AbstractCompilerVisitor :: writer=

package_diagram nitc::AbstractCompilerVisitor AbstractCompilerVisitor core::Object Object nitc::AbstractCompilerVisitor->core::Object nitc::SeparateCompilerVisitor SeparateCompilerVisitor nitc::SeparateCompilerVisitor->nitc::AbstractCompilerVisitor nitc::GlobalCompilerVisitor GlobalCompilerVisitor nitc::GlobalCompilerVisitor->nitc::AbstractCompilerVisitor nitc::SeparateErasureCompilerVisitor SeparateErasureCompilerVisitor nitc::SeparateErasureCompilerVisitor->nitc::SeparateCompilerVisitor nitc::SeparateErasureCompilerVisitor... ... nitc::SeparateErasureCompilerVisitor...->nitc::SeparateErasureCompilerVisitor

Parents

interface Object

core :: Object

The root of the class hierarchy.

Children

class GlobalCompilerVisitor

nitc :: GlobalCompilerVisitor

A visitor on the AST of property definition that generate the C code.
class SeparateCompilerVisitor

nitc :: SeparateCompilerVisitor

A visitor on the AST of property definition that generate the C code of a separate compilation process.

Descendants

Class definitions

nitc $ AbstractCompilerVisitor
# A visitor on the AST of property definition that generate the C code.
abstract class AbstractCompilerVisitor

	type COMPILER: AbstractCompiler

	# The associated compiler
	var compiler: COMPILER

	# The current visited AST node
	var current_node: nullable ANode = null is writable

	# The current `StaticFrame`
	var frame: nullable StaticFrame = null is writable

	# Alias for self.compiler.mainmodule.object_type
	fun object_type: MClassType do return self.compiler.mainmodule.object_type

	# Alias for self.compiler.mainmodule.bool_type
	fun bool_type: MClassType do return self.compiler.mainmodule.bool_type

	var writer: CodeWriter is noinit

	init
	do
		self.writer = new CodeWriter(compiler.files.last)
	end

	# Force to get the primitive property named `name` in the instance `recv` or abort
	fun get_property(name: String, recv: MType): MMethod
	do
		assert recv isa MClassType
		return self.compiler.modelbuilder.force_get_primitive_method(self.current_node, name, recv.mclass, self.compiler.mainmodule)
	end

	fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
	do
		if callsite.is_broken then return null
		return self.send(callsite.mproperty, arguments)
	end

	fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable is abstract

	fun native_array_def(pname: String, ret_type: nullable MType, arguments: Array[RuntimeVariable]): Bool do return false

	# Return an element of a native array.
	# The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
	fun native_array_get(native_array: RuntimeVariable, index: Int): RuntimeVariable is abstract

	# Store an element in a native array.
	# The method is unsafe and is just a direct wrapper for the specific implementation of native arrays
	fun native_array_set(native_array: RuntimeVariable, index: Int, value: RuntimeVariable) is abstract

	# Instantiate a new routine pointer
	fun routine_ref_instance(routine_mclass_type: MClassType, recv: RuntimeVariable, callsite: CallSite): RuntimeVariable is abstract

	# Call the underlying referenced function
	fun routine_ref_call(mmethoddef: MMethodDef, args: Array[RuntimeVariable]) is abstract

	# Allocate `size` bytes with the low_level `nit_alloc` C function
	#
	# This method can be redefined to inject statistic or tracing code.
	#
	# `tag` if any, is used to mark the class of the allocated object.
	fun nit_alloc(size: String, tag: nullable String): String
	do
		return "nit_alloc({size})"
	end

	# Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
	# This method is used to manage varargs in signatures and returns the real array
	# of runtime variables to use in the call.
	fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
	do
		var msignature = mpropdef.msignature.as(not null)
		var res = new Array[RuntimeVariable]
		res.add(recv)

		if msignature.arity == 0 then return res

		if map == null then
			assert args.length == msignature.arity
			for ne in args do
				res.add self.expr(ne, null)
			end
			return res
		end

		# Eval in order of arguments, not parameters
		var exprs = new Array[RuntimeVariable].with_capacity(args.length)
		for ne in args do
			exprs.add self.expr(ne, null)
		end

		# Fill `res` with the result of the evaluation according to the mapping
		for i in [0..msignature.arity[ do
			var param = msignature.mparameters[i]
			var j = map.map.get_or_null(i)
			if j == null then
				# default value
				res.add(null_instance)
				continue
			end
			if param.is_vararg and args[i].vararg_decl > 0 then
				var vararg = exprs.sub(j, args[i].vararg_decl)
				var elttype = param.mtype
				var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
				res.add(arg)
				continue
			end
			res.add exprs[j]
		end
		return res
	end

	# Type handling

	# Anchor a type to the main module and the current receiver
	fun anchor(mtype: MType): MType
	do
		if not mtype.need_anchor then return mtype
		return mtype.anchor_to(self.compiler.mainmodule, self.frame.receiver)
	end

	fun resolve_for(mtype: MType, recv: RuntimeVariable): MType
	do
		if not mtype.need_anchor then return mtype
		return mtype.resolve_for(recv.mcasttype, self.frame.receiver, self.compiler.mainmodule, true)
	end

	# Unsafely cast a value to a new type
	# ie the result share the same C variable but my have a different mcasttype
	# NOTE: if the adaptation is useless then `value` is returned as it.
	# ENSURE: `result.name == value.name`
	fun autoadapt(value: RuntimeVariable, mtype: MType): RuntimeVariable
	do
		mtype = self.anchor(mtype)
		var valmtype = value.mcasttype

		# CPrimitive is the best you can do
		if valmtype.is_c_primitive then
			return value
		end

		# Do nothing if useless autocast
		if valmtype.is_subtype(self.compiler.mainmodule, null, mtype) then
			return value
		end

		# Just as_not_null if the target is not nullable.
		#
		# eg `nullable PreciseType` adapted to `Object` gives precisetype.
		if valmtype isa MNullableType and valmtype.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
			mtype = valmtype.mtype
		end

		var res = new RuntimeVariable(value.name, value.mtype, mtype)
		return res
	end

	# Generate a super call from a method definition
	fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable is abstract

	# Adapt the arguments of a method according to targetted `MMethodDef`
	fun adapt_signature(m: MMethodDef, args: Array[RuntimeVariable]) is abstract

	# Unbox all the arguments of a method when implemented `extern` or `intern`
	fun unbox_signature_extern(m: MMethodDef, args: Array[RuntimeVariable]) is abstract

	# Box or unbox a value to another type iff a C type conversion is needed
	# ENSURE: `result.mtype.ctype == mtype.ctype`
	fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract

	# Box extern classes to be used in the generated code
	fun box_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract

	# Unbox extern classes to be used in extern code (legacy NI and FFI)
	fun unbox_extern(value: RuntimeVariable, mtype: MType): RuntimeVariable is abstract

	#  Generate a polymorphic subtype test
	fun type_test(value: RuntimeVariable, mtype: MType, tag: String): RuntimeVariable is abstract

	#  Generate the code required to dynamically check if 2 objects share the same runtime type
	fun is_same_type_test(value1, value2: RuntimeVariable): RuntimeVariable is abstract

	#  Generate a Nit "is" for two runtime_variables
	fun equal_test(value1, value2: RuntimeVariable): RuntimeVariable is abstract

	# Sends

	#  Generate a static call on a method definition
	fun call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable is abstract

	#  Generate a polymorphic send for the method `m` and the arguments `args`
	fun send(m: MMethod, args: Array[RuntimeVariable]): nullable RuntimeVariable is abstract

	# Generate a monomorphic send for the method `m`, the type `t` and the arguments `args`
	fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable
	do
		assert t isa MClassType
		var propdef = m.lookup_first_definition(self.compiler.mainmodule, t)
		return self.call(propdef, t, args)
	end

	# Generate a monomorphic super send from the method `m`, the type `t` and the arguments `args`
	fun monomorphic_super_send(m: MMethodDef, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable
	do
		assert t isa MClassType
		m = m.lookup_next_definition(self.compiler.mainmodule, t)
		return self.call(m, t, args)
	end

	# Attributes handling

	# Generate a polymorphic attribute is_set test
	fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable is abstract

	# Generate a polymorphic attribute read
	fun read_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable is abstract

	# Generate a polymorphic attribute write
	fun write_attribute(a: MAttribute, recv: RuntimeVariable, value: RuntimeVariable) is abstract

	# Checks

	# Can value be null? (according to current knowledge)
	fun maybe_null(value: RuntimeVariable): Bool
	do
		return value.mcasttype isa MNullableType or value.mcasttype isa MNullType
	end

	# Add a check and an abort for a null receiver if needed
	fun check_recv_notnull(recv: RuntimeVariable)
	do
		if self.compiler.modelbuilder.toolcontext.opt_no_check_null.value then return

		if maybe_null(recv) then
			self.add("if (unlikely({recv} == NULL)) \{")
			self.add_abort("Receiver is null")
			self.add("\}")
		end
	end

	# Names handling

	private var names = new HashSet[String]
	private var last: Int = 0

	# Return a new name based on `s` and unique in the visitor
	fun get_name(s: String): String
	do
		if not self.names.has(s) then
			self.names.add(s)
			return s
		end
		var i = self.last + 1
		loop
			var s2 = s + i.to_s
			if not self.names.has(s2) then
				self.last = i
				self.names.add(s2)
				return s2
			end
			i = i + 1
		end
	end

	# Return an unique and stable identifier associated with an escapemark
	fun escapemark_name(e: nullable EscapeMark): String
	do
		assert e != null
		if frame.escapemark_names.has_key(e) then return frame.escapemark_names[e]
		var name = e.name
		if name == null then name = "label"
		name = get_name(name)
		frame.escapemark_names[e] = name
		return name
	end

	# Insert a C label for associated with an escapemark
	fun add_escape_label(e: nullable EscapeMark)
	do
		if e == null then return
		if e.escapes.is_empty then return
		add("BREAK_{escapemark_name(e)}: (void)0;")
	end

	# Return a "const char*" variable associated to the classname of the dynamic type of an object
	# NOTE: we do not return a `RuntimeVariable` "CString" as the class may not exist in the module/program
	fun class_name_string(value: RuntimeVariable): String is abstract

	# Variables handling

	protected var variables = new HashMap[Variable, RuntimeVariable]

	# Return the local runtime_variable associated to a Nit local variable
	fun variable(variable: Variable): RuntimeVariable
	do
		if self.variables.has_key(variable) then
			return self.variables[variable]
		else
			var name = self.get_name("var_{variable.name}")
			var mtype = variable.declared_type.as(not null)
			mtype = self.anchor(mtype)
			var res = new RuntimeVariable(name, mtype, mtype)
			self.add_decl("{mtype.ctype} {name} /* var {variable}: {mtype} */;")
			self.variables[variable] = res
			return res
		end
	end

	# Return a new uninitialized local runtime_variable
	fun new_var(mtype: MType): RuntimeVariable
	do
		mtype = self.anchor(mtype)
		var name = self.get_name("var")
		var res = new RuntimeVariable(name, mtype, mtype)
		self.add_decl("{mtype.ctype} {name} /* : {mtype} */;")
		return res
	end

	# The difference with `new_var` is the C static type of the local variable
	fun new_var_extern(mtype: MType): RuntimeVariable
	do
		mtype = self.anchor(mtype)
		var name = self.get_name("var")
		var res = new RuntimeVariable(name, mtype, mtype)
		self.add_decl("{mtype.ctype_extern} {name} /* : {mtype} for extern */;")
		return res
	end

	# Return a new uninitialized named runtime_variable
	fun new_named_var(mtype: MType, name: String): RuntimeVariable
	do
		mtype = self.anchor(mtype)
		var res = new RuntimeVariable(name, mtype, mtype)
		self.add_decl("{mtype.ctype} {name} /* : {mtype} */;")
		return res
	end

	# Correctly assign a left and a right value
	# Boxing and unboxing is performed if required
	fun assign(left, right: RuntimeVariable)
	do
		right = self.autobox(right, left.mtype)
		self.add("{left} = {right};")
	end

	# Generate instances

	# Generate a alloc-instance + init-attributes
	fun init_instance(mtype: MClassType): RuntimeVariable is abstract

	# Allocate and init attributes of an instance of a standard or extern class
	#
	# Does not support universals and the pseudo-internal `NativeArray` class.
	fun init_instance_or_extern(mtype: MClassType): RuntimeVariable
	do
		var recv
		var ctype = mtype.ctype
		assert mtype.mclass.name != "NativeArray"
		if not mtype.is_c_primitive then
			recv = init_instance(mtype)
		else if ctype == "char*" then
			recv = new_expr("NULL/*special!*/", mtype)
		else
			recv = new_expr("({ctype})0/*special!*/", mtype)
		end
		return recv
	end

	# Set a GC finalizer on `recv`, only if `recv` isa Finalizable
	fun set_finalizer(recv: RuntimeVariable)
	do
		var mtype = recv.mtype
		var finalizable_type = compiler.mainmodule.finalizable_type
		if finalizable_type != null and not mtype.need_anchor and
				mtype.is_subtype(compiler.mainmodule, null, finalizable_type) then
			add "gc_register_finalizer({recv});"
		end
	end

	# The currently processed module
	#
	# alias for `compiler.mainmodule`
	fun mmodule: MModule do return compiler.mainmodule

	# Generate an integer value
	fun int_instance(value: Int): RuntimeVariable
	do
		var t = mmodule.int_type
		var res = new RuntimeVariable("{value.to_s}l", t, t)
		return res
	end

	# Generate a byte value
	fun byte_instance(value: Byte): RuntimeVariable
	do
		var t = mmodule.byte_type
		var res = new RuntimeVariable("((unsigned char){value.to_s})", t, t)
		return res
	end

	# Generate an int8 value
	fun int8_instance(value: Int8): RuntimeVariable
	do
		var t = mmodule.int8_type
		var res = new RuntimeVariable("INT8_C({value.to_s})", t, t)
		return res
	end

	# Generate an int16 value
	fun int16_instance(value: Int16): RuntimeVariable
	do
		var t = mmodule.int16_type
		var res = new RuntimeVariable("INT16_C({value.to_s})", t, t)
		return res
	end

	# Generate a uint16 value
	fun uint16_instance(value: UInt16): RuntimeVariable
	do
		var t = mmodule.uint16_type
		var res = new RuntimeVariable("UINT16_C({value.to_s})", t, t)
		return res
	end

	# Generate an int32 value
	fun int32_instance(value: Int32): RuntimeVariable
	do
		var t = mmodule.int32_type
		var res = new RuntimeVariable("INT32_C({value.to_s})", t, t)
		return res
	end

	# Generate a uint32 value
	fun uint32_instance(value: UInt32): RuntimeVariable
	do
		var t = mmodule.uint32_type
		var res = new RuntimeVariable("UINT32_C({value.to_s})", t, t)
		return res
	end

	# Generate a char value
	fun char_instance(value: Char): RuntimeVariable
	do
		var t = mmodule.char_type

		if value.code_point < 128 then
			return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
		else
			return new RuntimeVariable("{value.code_point}", t, t)
		end
	end

	# Generate a float value
	#
	# FIXME pass a Float, not a string
	fun float_instance(value: Float): RuntimeVariable
	do
		var t = mmodule.float_type
		var res = new RuntimeVariable("{value.to_hexa_exponential_notation}", t, t)
		return res
	end

	# Generate an integer value
	fun bool_instance(value: Bool): RuntimeVariable
	do
		var s = if value then "1" else "0"
		var res = new RuntimeVariable(s, bool_type, bool_type)
		return res
	end

	# Generate the `null` value
	fun null_instance: RuntimeVariable
	do
		var t = compiler.mainmodule.model.null_type
		var res = new RuntimeVariable("((val*)NULL)", t, t)
		return res
	end

	# Generates a CString instance fully escaped in C-style \xHH fashion
	fun c_string_instance(ns: CString, len: Int): RuntimeVariable do
		var mtype = mmodule.c_string_type
		var nat = new_var(mtype)
		var byte_esc = new Buffer.with_cap(len * 4)
		for i in [0 .. len[ do
			byte_esc.append("\\x{ns[i].to_hex}")
		end
		self.add("{nat} = \"{byte_esc}\";")
		return nat
	end

	# Generate a string value
	fun string_instance(string: String): RuntimeVariable
	do
		var mtype = mmodule.string_type
		var name = self.get_name("varonce")
		self.add_decl("static {mtype.ctype} {name};")
		var res = self.new_var(mtype)
		self.add("if (likely({name}!=NULL)) \{")
		self.add("{res} = {name};")
		self.add("\} else \{")
		var native_mtype = mmodule.c_string_type
		var nat = self.new_var(native_mtype)
		self.add("{nat} = \"{string.escape_to_c}\";")
		var byte_length = self.int_instance(string.byte_length)
		var unilen = self.int_instance(string.length)
		self.add("{res} = {self.send(self.get_property("to_s_unsafe", native_mtype), [nat, byte_length, unilen, value_instance(false), value_instance(false)]).as(not null)};")
		self.add("{name} = {res};")
		self.add("\}")
		return res
	end

	fun value_instance(object: Object): RuntimeVariable
	do
		if object isa Int then
			return int_instance(object)
		else if object isa Bool then
			return bool_instance(object)
		else if object isa String then
			return string_instance(object)
		else
			abort
		end
	end

	# Generate an array value
	fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable is abstract

	# Get an instance of a array for a vararg
	fun vararg_instance(mpropdef: MPropDef, recv: RuntimeVariable, varargs: Array[RuntimeVariable], elttype: MType): RuntimeVariable is abstract

	# Code generation

	# Add a line in the main part of the generated C
	fun add(s: String) do self.writer.lines.add(s)

	# Add a line in the
	# (used for local or global declaration)
	fun add_decl(s: String) do self.writer.decl_lines.add(s)

	# Request the presence of a global declaration
	fun require_declaration(key: String)
	do
		var reqs = self.writer.file.required_declarations
		if reqs.has(key) then return
		reqs.add(key)
		var node = current_node
		if node != null then compiler.requirers_of_declarations[key] = node
	end

	# Add a declaration in the local-header
	# The declaration is ensured to be present once
	fun declare_once(s: String)
	do
		self.compiler.provide_declaration(s, s)
		self.require_declaration(s)
	end

	# Look for a needed .h and .c file for a given module
	# This is used for the legacy FFI
	fun add_extern(mmodule: MModule)
	do
		var file = mmodule.filepath
		file = file.strip_extension(".nit")
		var tryfile = file + ".nit.h"
		if tryfile.file_exists then
			self.declare_once("#include \"{tryfile.basename}\"")
			self.compiler.files_to_copy.add(tryfile)
		end
		tryfile = file + "_nit.h"
		if tryfile.file_exists then
			self.declare_once("#include \"{tryfile.basename}\"")
			self.compiler.files_to_copy.add(tryfile)
		end

		if self.compiler.seen_extern.has(file) then return
		self.compiler.seen_extern.add(file)
		tryfile = file + ".nit.c"
		if not tryfile.file_exists then
			tryfile = file + "_nit.c"
			if not tryfile.file_exists then return
		end
		var f = new ExternCFile(tryfile.basename, "")
		self.compiler.extern_bodies.add(f)
		self.compiler.files_to_copy.add(tryfile)
	end

	# Return a new local runtime_variable initialized with the C expression `cexpr`.
	fun new_expr(cexpr: String, mtype: MType): RuntimeVariable
	do
		var res = new_var(mtype)
		self.add("{res} = {cexpr};")
		return res
	end

	# Generate generic abort
	# used by aborts, asserts, casts, etc.
	fun add_abort(message: String)
	do
		add_raw_throw
		self.add("PRINT_ERROR(\"Runtime error: %s\", \"{message.escape_to_c}\");")
		add_raw_abort
	end

	# Generate a long jump if there is a catch block.
	#
	# This method should be called before the error messages and before a `add_raw_abort`.
	fun add_raw_throw
	do
		self.add("\{")
		self.add("struct catch_stack_t *catchStack = getCatchStack();")
		self.add("if(catchStack->cursor >= 0)\{")
		self.add("	longjmp(catchStack->envs[catchStack->cursor], 1);")
		self.add("\}")
		self.add("\}")
	end

	# Generate abort without a message.
	#
	# Used when one need a more complex message.
	# Do not forget to call `add_raw_abort` before the display of a custom user message.
	fun add_raw_abort
	do
		var current_node = self.current_node
		if current_node != null and current_node.location.file != null and
				current_node.location.file.mmodule != null then
			var f = "FILE_{self.current_node.location.file.mmodule.c_name}"
			self.require_declaration(f)
			self.add("PRINT_ERROR(\" (%s:%d)\\n\", {f}, {current_node.location.line_start});")
		else
			self.add("PRINT_ERROR(\"\\n\");")
		end
		self.add("fatal_exit(1);")
	end

	# Add a dynamic cast
	fun add_cast(value: RuntimeVariable, mtype: MType, tag: String)
	do
		var res = self.type_test(value, mtype, tag)
		self.add("if (unlikely(!{res})) \{")
		self.add_raw_throw
		var cn = self.class_name_string(value)
		self.add("PRINT_ERROR(\"Runtime error: Cast failed. Expected `%s`, got `%s`\", \"{mtype.to_s.escape_to_c}\", {cn});")
		self.add_raw_abort
		self.add("\}")
	end

	# Generate a return with the value `s`
	fun ret(s: RuntimeVariable)
	do
		self.assign(self.frame.returnvar.as(not null), s)
		self.add("goto {self.frame.returnlabel.as(not null)};")
	end

	# Compile a statement (if any)
	fun stmt(nexpr: nullable AExpr)
	do
		if nexpr == null then return
		if nexpr.is_broken then
			# Untyped expression.
			# Might mean dead code or invalid code
			# so aborts
			add_abort("FATAL: bad statement executed.")
			return
		end

		var narray = nexpr.comprehension
		if narray != null then
			var recv = frame.comprehension.as(not null)
			var val = expr(nexpr, narray.element_mtype)
			compile_callsite(narray.push_callsite.as(not null), [recv, val])
			return
		end

		var old = self.current_node
		self.current_node = nexpr
		nexpr.stmt(self)
		self.current_node = old
	end

	# Compile an expression an return its result
	# `mtype` is the expected return type, pass null if no specific type is expected.
	fun expr(nexpr: AExpr, mtype: nullable MType): RuntimeVariable
	do
		var old = self.current_node
		self.current_node = nexpr

		var res = null
		if nexpr.mtype != null then
			res = nexpr.expr(self)
		end

		if res == null then
			# Untyped expression.
			# Might mean dead code or invalid code.
			# so aborts
			add_abort("FATAL: bad expression executed.")
			# and return a placebo result to please the C compiler
			if mtype == null then mtype = compiler.mainmodule.object_type
			res = new_var(mtype)

			self.current_node = old
			return res
		end

		if mtype != null then
			mtype = self.anchor(mtype)
			res = self.autobox(res, mtype)
		end
		res = autoadapt(res, nexpr.mtype.as(not null))
		var implicit_cast_to = nexpr.implicit_cast_to
		if implicit_cast_to != null and not self.compiler.modelbuilder.toolcontext.opt_no_check_autocast.value then
			add_cast(res, implicit_cast_to, "auto")
			res = autoadapt(res, implicit_cast_to)
		end
		self.current_node = old
		return res
	end

	# Alias for `self.expr(nexpr, self.bool_type)`
	fun expr_bool(nexpr: AExpr): RuntimeVariable do return expr(nexpr, bool_type)

	# Safely show a debug message on the current node and repeat the message in the C code as a comment
	fun debug(message: String)
	do
		var node = self.current_node
		if node == null then
			print "?: {message}"
		else
			node.debug(message)
		end
		self.add("/* DEBUG: {message} */")
	end
end
src/compiler/abstract_compiler.nit:1320,1--2054,3

nitc :: light $ AbstractCompilerVisitor
redef class AbstractCompilerVisitor
	# Create a `RuntimeVariable` for this C variable originating from C user code
	private fun var_from_c(name: String, mtype: MType): RuntimeVariable
	do
		if mtype.is_cprimitive then
			return new RuntimeVariable(name, mtype, mtype)
		else
			return new RuntimeVariable("{name}->value", mtype, mtype)
		end
	end

	# Return a `RuntimeVarible` to C user code
	private fun ret_to_c(src: RuntimeVariable, mtype: MType)
	do
		if mtype.is_cprimitive then
			add("return {src};")
		else
			add("struct nitni_instance* ret_for_c;")
			add("ret_for_c = nit_alloc(sizeof(struct nitni_instance));")
			add("ret_for_c->value = {src};")
			add("return ret_for_c;")
		end
	end
end
src/compiler/compiler_ffi/light.nit:246,1--269,3