Property definitions

nitc :: compiler_ffi $ MExplicitCast :: compile_extern_callbacks
	private fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool)
	do
		var from = from
		var to = to

		#
		## check type
		#

		# In nitni files, declare internal function as extern
		var full_friendly_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
		ccu.header_decl.add("extern {full_friendly_csignature};\n")

		# In nitni files, #define friendly as extern
		ccu.header_decl.add "#ifndef {check_cname}\n"
		ccu.header_decl.add "#define {check_cname} {v.compiler.mainmodule.c_name}___{check_cname}\n"
		ccu.header_decl.add "#endif\n"

		if compile_implementation_too then
			# Internally, implement internal function
			var nitni_visitor = v.compiler.new_visitor
			nitni_visitor.frame = v.frame

			var full_internal_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"

			nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
			nitni_visitor.add_decl("{full_internal_csignature} \{")

			var from_var = nitni_visitor.var_from_c("from", from)
			from_var = nitni_visitor.box_extern(from_var, from)
			var recv_var = nitni_visitor.type_test(from_var, to, "isa")
			nitni_visitor.add("return {recv_var};")

			nitni_visitor.add("\}")
		end

		# special checks
		if from == to.as_nullable then
			# format A_is_null
			ccu.header_decl.add "#ifndef {from.mangled_cname}_is_null\n"
			ccu.header_decl.add "#define {from.mangled_cname}_is_null !{from.mangled_cname}_is_a_{to.mangled_cname}\n"
			ccu.header_decl.add "#endif\n"
		end

		#
		## cast
		#

		# In nitni files, declare internal function as extern
		full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
		ccu.header_decl.add("extern {full_friendly_csignature};\n")

		# In nitni files, #define friendly as extern
		ccu.header_decl.add "#ifndef {cast_cname}\n"
		ccu.header_decl.add "#define {cast_cname} {v.compiler.mainmodule.c_name}___{cast_cname}\n"
		ccu.header_decl.add "#endif\n"

		if compile_implementation_too then
			# Internally, implement internal function
			var nitni_visitor = v.compiler.new_visitor
			nitni_visitor.frame = v.frame

			var full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)"
			nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
			nitni_visitor.add_decl("{full_internal_csignature} \{")

			var from_var = nitni_visitor.var_from_c("from", from)
			from_var = nitni_visitor.box_extern(from_var, from)

			## test type
			var check = nitni_visitor.type_test(from_var, to, "as")
			nitni_visitor.add("if (!{check}) \{")
			nitni_visitor.add_abort("FFI cast failed")
			nitni_visitor.add("\}")

			## internal cast
			var recv_var = nitni_visitor.autobox(from_var, to)
			recv_var = nitni_visitor.unbox_extern(recv_var, to)

			nitni_visitor.ret_to_c(recv_var, to)

			nitni_visitor.add("\}")
		end

		# special casts
		if from.as_nullable == to then
			# format A_as_nullable
			ccu.header_decl.add "#ifndef {from.mangled_cname}_as_nullable\n"
			ccu.header_decl.add "#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
			ccu.header_decl.add "#endif\n"
		end

		if from == to.as_nullable then
			# format A_as_nullable
			ccu.header_decl.add "#ifndef {to.mangled_cname}_as_not_nullable\n"
			ccu.header_decl.add "#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n"
			ccu.header_decl.add "#endif\n"
		end
	end
src/compiler/compiler_ffi/compiler_ffi.nit:255,2--353,4