Compile an extern factory

Return true if the compilation was successful, false if a fall-back is needed

Property definitions

nitc :: abstract_compiler $ AMethPropdef :: compile_externinit_to_c
	# Compile an extern factory
	# Return `true` if the compilation was successful, `false` if a fall-back is needed
	fun compile_externinit_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool
	do
		var externname
		var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
		if at != null then
			externname = at.arg_as_string(v.compiler.modelbuilder)
			if externname == null then return false
		else
			return false
		end
		v.add_extern(mpropdef.mclassdef.mmodule)
		v.adapt_signature(mpropdef, arguments)
		v.unbox_signature_extern(mpropdef, arguments)
		var ret = arguments.first.mtype
		var res = v.new_var_extern(ret)

		arguments.shift

		v.add("{res} = {externname}({arguments.join(", ")});")
		res = v.box_extern(res, ret)
		v.ret(res)
		return true
	end
src/compiler/abstract_compiler.nit:3535,2--3559,4

nitc :: light $ AMethPropdef :: compile_externinit_to_c
	redef fun compile_externinit_to_c(v, mpropdef, arguments)
	do
		# if using the old native interface fallback on previous implementation
		if n_extern_code_block == null then return super

		if not accept_externmeth then return false

		var mmodule = mpropdef.mclassdef.mmodule
		mmodule.uses_ffi = true

		var mclass_type = mpropdef.mclassdef.bound_mtype

		var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
		var return_mtype = arguments.first.mtype
		var recv_var = v.new_var(return_mtype)

		v.adapt_signature(mpropdef, arguments)
		v.unbox_signature_extern(mpropdef, arguments)

		arguments.shift

		var arguments_for_c = new Array[String]
		for a in [0..arguments.length[ do
			var arg = arguments[a]
			var param_mtype: MType
			param_mtype = mpropdef.msignature.mparameters[a].mtype
			param_mtype = param_mtype.anchor_to(mmodule, mclass_type)

			if param_mtype.is_cprimitive then
				arguments_for_c.add(arg.name)
			else
				v.add("struct nitni_instance* var_for_c_{a};")
				v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));")
				v.add("var_for_c_{a}->value = {arg.name};")
				arguments_for_c.add("var_for_c_{a}")
			end
		end

		if return_mtype.is_cprimitive then
			v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
		else
			v.add("struct nitni_instance* ret_var;")
			v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
			v.add("{recv_var} = ret_var->value;")
		end
		recv_var = v.box_extern(recv_var, return_mtype)
		v.ret(recv_var)

		compile_ffi_support_to_c(v)
		return true
	end
src/compiler/compiler_ffi/light.nit:170,2--220,4