Given a MClass, if it's a universal class and if it needs to be handle

specifically by the compiler, this function will compile it and return true. Otherwise, no C code will be written in the visitor and the value false will be returned.

Property definitions

nitc $ SeparateCompiler :: compile_class_if_universal
	# Given a `MClass`, if it's a universal class and if it needs to be handle
	# specifically by the compiler, this function will compile it and return
	# true. Otherwise, no C code will be written in the visitor and the value
	# false will be returned.
	fun compile_class_if_universal(ccinfo: ClassCompilationInfo, v: SeparateCompilerVisitor): Bool
	do
		var mclass = ccinfo.mclass
		var mtype = ccinfo.mtype
		var c_name = ccinfo.mclass.c_name
		var is_dead = ccinfo.is_dead
		var need_corpse = ccinfo.need_corpse

		if mtype.is_c_primitive or mtype.mclass.name == "Pointer" then
			# Is a primitive type or the Pointer class, not any other extern class

			if mtype.is_tagged then return true

			#Build instance struct
			self.header.add_decl("struct instance_{c_name} \{")
			self.header.add_decl("const struct type *type;")
			self.header.add_decl("const struct class *class;")
			self.header.add_decl("{mtype.ctype_extern} value;")
			self.header.add_decl("\};")

			# Pointer is needed by extern types, live or not
			if is_dead and mtype.mclass.name != "Pointer" then return true

			#Build BOX
			self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype_extern} value) \{")
			var alloc = v.nit_alloc("sizeof(struct instance_{c_name})", mclass.full_name)
			v.add("struct instance_{c_name}*res = {alloc};")
			v.compiler.undead_types.add(mtype)
			v.require_declaration("type_{c_name}")
			v.add("res->type = &type_{c_name};")
			v.require_declaration("class_{c_name}")
			v.add("res->class = &class_{c_name};")
			v.add("res->value = value;")
			v.add("return (val*)res;")
			v.add("\}")

			# A Pointer class also need its constructor
			if mtype.mclass.name != "Pointer" then return true

			v = new_visitor
			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
			if is_dead then
				v.add_abort("{mclass} is DEAD")
			else
				var res = v.new_named_var(mtype, "self")
				res.is_exact = true
				alloc = v.nit_alloc("sizeof(struct instance_{mtype.c_name})", mclass.full_name)
				v.add("{res} = {alloc};")
				v.add("{res}->type = type;")
				hardening_live_type(v, "type")
				v.require_declaration("class_{c_name}")
				v.add("{res}->class = &class_{c_name};")
				v.add("((struct instance_{mtype.c_name}*){res})->value = NULL;")
				v.add("return {res};")
			end
			v.add("\}")
			return true
		else if mclass.name == "NativeArray" then
			#Build instance struct
			self.header.add_decl("struct instance_{c_name} \{")
			self.header.add_decl("const struct type *type;")
			self.header.add_decl("const struct class *class;")
			# NativeArrays are just a instance header followed by a length and an array of values
			self.header.add_decl("int length;")
			self.header.add_decl("val* values[0];")
			self.header.add_decl("\};")

			#Build NEW
			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(int length, const struct type* type);")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}(int length, const struct type* type) \{")
			var res = v.get_name("self")
			v.add_decl("struct instance_{c_name} *{res};")
			var mtype_elt = mtype.arguments.first
			var alloc = v.nit_alloc("sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype})", mclass.full_name)
			v.add("{res} = {alloc};")
			v.add("{res}->type = type;")
			hardening_live_type(v, "type")
			v.require_declaration("class_{c_name}")
			v.add("{res}->class = &class_{c_name};")
			v.add("{res}->length = length;")
			v.add("return (val*){res};")
			v.add("\}")
			return true
		else if mclass.name == "RoutineRef" then
			self.header.add_decl("struct instance_{c_name} \{")
			self.header.add_decl("const struct type *type;")
			self.header.add_decl("const struct class *class;")
			self.header.add_decl("val* recv;")
			self.header.add_decl("nitmethod_t method;")
			self.header.add_decl("\};")

			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(val* recv, nitmethod_t method, const struct class* class, const struct type* type);")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}(val* recv, nitmethod_t method, const struct class* class, const struct type* type)\{")
			var res = v.get_name("self")
			v.add_decl("struct instance_{c_name} *{res};")
			var alloc = v.nit_alloc("sizeof(struct instance_{c_name})", mclass.full_name)
			v.add("{res} = {alloc};")
			v.add("{res}->type = type;")
			hardening_live_type(v, "type")
			v.add("{res}->class = class;")
			v.add("{res}->recv = recv;")
			v.add("{res}->method = method;")
			v.add("return (val*){res};")
			v.add("\}")
			return true
		else if mtype.mclass.kind == extern_kind and mtype.mclass.name != "CString" then
			# Is an extern class (other than Pointer and CString)
			# Pointer is caught in a previous `if`, and CString is internal

			var pointer_type = mainmodule.pointer_type

			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);")
			v.add_decl("/* allocate extern {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
			if is_dead then
				v.add_abort("{mclass} is DEAD")
			else
				var res = v.new_named_var(mtype, "self")
				res.is_exact = true
				var alloc = v.nit_alloc("sizeof(struct instance_{pointer_type.c_name})", mclass.full_name)
				v.add("{res} = {alloc};")
				v.add("{res}->type = type;")
				hardening_live_type(v, "type")
				v.require_declaration("class_{c_name}")
				v.add("{res}->class = &class_{c_name};")
				v.add("((struct instance_{pointer_type.c_name}*){res})->value = NULL;")
				v.add("return {res};")
			end
			v.add("\}")
			return true
		end
		return false
	end
src/compiler/separate_compiler.nit:869,2--1011,4

nitc $ SeparateErasureCompiler :: compile_class_if_universal
	redef fun compile_class_if_universal(ccinfo, v)
	do
		var mclass = ccinfo.mclass
		var mtype = ccinfo.mtype
		var c_name = mclass.c_name
		var is_dead = ccinfo.is_dead

		if mtype.is_c_primitive or mtype.mclass.name == "Pointer" then
			#Build instance struct
			self.header.add_decl("struct instance_{c_name} \{")
			self.header.add_decl("const struct class *class;")
			self.header.add_decl("{mtype.ctype} value;")
			self.header.add_decl("\};")

			#Build BOX
			self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype_extern} value) \{")
			v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));")
			v.require_declaration("class_{c_name}")
			v.add("res->class = &class_{c_name};")
			v.add("res->value = value;")
			v.add("return (val*)res;")
			v.add("\}")

			if mtype.mclass.name != "Pointer" then return true

			v = new_visitor
			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}();")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}() \{")
			if is_dead then
				v.add_abort("{mclass} is DEAD")
			else
				var res = v.new_named_var(mtype, "self")
				res.is_exact = true
				v.add("{res} = nit_alloc(sizeof(struct instance_{mtype.c_name}));")
				v.require_declaration("class_{c_name}")
				v.add("{res}->class = &class_{c_name};")
				v.add("((struct instance_{mtype.c_name}*){res})->value = NULL;")
				v.add("return {res};")
			end
			v.add("\}")
			return true
		else if mclass.name == "NativeArray" then
			#Build instance struct
			self.header.add_decl("struct instance_{c_name} \{")
			self.header.add_decl("const struct class *class;")
			self.header.add_decl("int length;")
			self.header.add_decl("val* values[];")
			self.header.add_decl("\};")

			#Build NEW
			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(int length);")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}(int length) \{")
			var res = v.get_name("self")
			v.add_decl("struct instance_{c_name} *{res};")
			var mtype_elt = mtype.arguments.first
			v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
			v.require_declaration("class_{c_name}")
			v.add("{res}->class = &class_{c_name};")
			v.add("{res}->length = length;")
			v.add("return (val*){res};")
			v.add("\}")
			return true
                else if mclass.name == "RoutineRef" then
                        self.header.add_decl("struct instance_{c_name} \{")
                        self.header.add_decl("const struct class *class;")
                        self.header.add_decl("val* recv;")
                        self.header.add_decl("nitmethod_t method;")
                        self.header.add_decl("\};")

                        self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(val* recv, nitmethod_t method, const struct class* class);")
                        v.add_decl("/* allocate {mtype} */")
                        v.add_decl("{mtype.ctype} NEW_{c_name}(val* recv, nitmethod_t method, const struct class* class)\{")
                        var res = v.get_name("self")
                        v.add_decl("struct instance_{c_name} *{res};")
                        var alloc = v.nit_alloc("sizeof(struct instance_{c_name})", mclass.full_name)
                        v.add("{res} = {alloc};")
                        v.add("{res}->class = class;")
                        v.add("{res}->recv = recv;")
                        v.add("{res}->method = method;")
                        v.add("return (val*){res};")
                        v.add("\}")
                        return true
		else if mtype.mclass.kind == extern_kind and mtype.mclass.name != "CString" then
			var pointer_type = mainmodule.pointer_type

			self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}();")
			v.add_decl("/* allocate {mtype} */")
			v.add_decl("{mtype.ctype} NEW_{c_name}() \{")
			if is_dead then
				v.add_abort("{mclass} is DEAD")
			else
				var res = v.new_named_var(mtype, "self")
				res.is_exact = true
				v.add("{res} = nit_alloc(sizeof(struct instance_{pointer_type.c_name}));")
				#v.add("{res}->type = type;")
				v.require_declaration("class_{c_name}")
				v.add("{res}->class = &class_{c_name};")
				v.add("((struct instance_{pointer_type.c_name}*){res})->value = NULL;")
				v.add("return {res};")
			end
			v.add("\}")
			return true
		end
		return false
	end
src/compiler/separate_erasure_compiler.nit:197,2--305,4