MClass
, if it's a universal class and if it needs to be handlespecifically 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.
# 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
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