compiler: introduce and use `MType::is_c_primitive`
authorJean Privat <jean@pryen.org>
Mon, 23 Mar 2015 14:30:34 +0000 (21:30 +0700)
committerJean Privat <jean@pryen.org>
Mon, 23 Mar 2015 14:30:34 +0000 (21:30 +0700)
Thus remove all comparison to "val*" in the code, this is cleaner.

Signed-off-by: Jean Privat <jean@pryen.org>

src/compiler/abstract_compiler.nit
src/compiler/global_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit

index aa57850..5d5a4bc 100644 (file)
@@ -1395,7 +1395,7 @@ abstract class AbstractCompilerVisitor
                var recv
                var ctype = mtype.ctype
                assert mtype.mclass.name != "NativeArray"
-               if ctype == "val*" then
+               if not mtype.is_c_primitive then
                        recv = init_instance(mtype)
                else if ctype == "char*" then
                        recv = new_expr("NULL/*special!*/", mtype)
@@ -1754,12 +1754,16 @@ redef class MType
 
        # Short name of the `ctype` to use in unions
        fun ctypename: String do return "val"
+
+       # Is the associated C type a primitive one?
+       #
+       # ENSURE `result == (ctype != "val*")`
+       fun is_c_primitive: Bool do return false
 end
 
 redef class MClassType
 
-       redef fun ctype: String
-       do
+       redef var ctype is lazy do
                if mclass.name == "Int" then
                        return "long"
                else if mclass.name == "Bool" then
@@ -1777,6 +1781,8 @@ redef class MClassType
                end
        end
 
+       redef var is_c_primitive is lazy do return ctype != "val*"
+
        redef fun ctype_extern: String
        do
                if mclass.kind == extern_kind then
@@ -2266,7 +2272,7 @@ redef class AAttrPropdef
                        if is_lazy then
                                var set
                                var ret = self.mpropdef.static_mtype
-                               var useiset = ret.ctype == "val*" and not ret isa MNullableType
+                               var useiset = not ret.is_c_primitive and not ret isa MNullableType
                                var guard = self.mlazypropdef.mproperty
                                if useiset then
                                        set = v.isset_attribute(self.mpropdef.mproperty, recv)
@@ -2294,7 +2300,7 @@ redef class AAttrPropdef
                        v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
                        if is_lazy then
                                var ret = self.mpropdef.static_mtype
-                               var useiset = ret.ctype == "val*" and not ret isa MNullableType
+                               var useiset = not ret.is_c_primitive and not ret isa MNullableType
                                if not useiset then
                                        v.write_attribute(self.mlazypropdef.mproperty, arguments.first, v.new_expr("1", v.bool_type))
                                end
@@ -2803,7 +2809,7 @@ redef class AAsNotnullExpr
                var i = v.expr(self.n_expr, null)
                if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i
 
-               if i.mtype.ctype != "val*" then return i
+               if i.mtype.is_c_primitive then return i
 
                v.add("if (unlikely({i} == NULL)) \{")
                v.add_abort("Cast failed")
index 7a0f162..9130588 100644 (file)
@@ -86,7 +86,7 @@ class GlobalCompiler
                self.header = new CodeWriter(file)
                self.live_primitive_types = new Array[MClassType]
                for t in runtime_type_analysis.live_types do
-                       if t.ctype != "val*" or t.mclass.name == "Pointer" then
+                       if t.is_c_primitive or t.mclass.name == "Pointer" then
                                self.live_primitive_types.add(t)
                        end
                end
@@ -109,7 +109,7 @@ class GlobalCompiler
 
                # Init instance code (allocate and init-arguments)
                for t in runtime_type_analysis.live_types do
-                       if t.ctype == "val*" then
+                       if not t.is_c_primitive then
                                compiler.generate_init_instance(t)
                                if t.mclass.kind == extern_kind then
                                        compiler.generate_box_instance(t)
@@ -228,7 +228,7 @@ class GlobalCompiler
        fun generate_init_instance(mtype: MClassType)
        do
                assert self.runtime_type_analysis.live_types.has(mtype)
-               assert mtype.ctype == "val*"
+               assert not mtype.is_c_primitive
                var v = self.new_visitor
 
                var is_native_array = mtype.mclass.name == "NativeArray"
@@ -303,11 +303,11 @@ class GlobalCompilerVisitor
        do
                if value.mtype == mtype then
                        return value
-               else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive and not mtype.is_c_primitive then
                        return value
-               else if value.mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive then
                        return self.new_expr("((struct {mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
-               else if mtype.ctype == "val*" then
+               else if not mtype.is_c_primitive then
                        var valtype = value.mtype.as(MClassType)
                        var res = self.new_var(mtype)
                        if not compiler.runtime_type_analysis.live_types.has(valtype) then
@@ -426,7 +426,7 @@ class GlobalCompilerVisitor
                end
 
                self.add("/* send {m} on {args.first.inspect} */")
-               if args.first.mtype.ctype != "val*" then
+               if args.first.mtype.is_c_primitive then
                        var mclasstype = args.first.mtype.as(MClassType)
                        if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
                                self.add("/* skip, no method {m} */")
@@ -477,7 +477,7 @@ class GlobalCompilerVisitor
                var defaultpropdef: nullable MMethodDef = null
                for t in types do
                        var propdef = m.lookup_first_definition(self.compiler.mainmodule, t)
-                       if propdef.mclassdef.mclass.name == "Object" and t.ctype == "val*" then
+                       if propdef.mclassdef.mclass.name == "Object" and not t.is_c_primitive then
                                defaultpropdef = propdef
                                continue
                        end
@@ -552,7 +552,7 @@ class GlobalCompilerVisitor
                end
 
                self.add("/* super {m} on {args.first.inspect} */")
-               if args.first.mtype.ctype != "val*" then
+               if args.first.mtype.is_c_primitive then
                        var mclasstype = args.first.mtype.as(MClassType)
                        if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
                                self.add("/* skip, no method {m} */")
@@ -628,7 +628,7 @@ class GlobalCompilerVisitor
 
        fun bugtype(recv: RuntimeVariable)
        do
-               if recv.mtype.ctype != "val*" then return
+               if recv.mtype.is_c_primitive then return
                self.add("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
                self.add("show_backtrace(1);")
        end
@@ -659,7 +659,7 @@ class GlobalCompilerVisitor
                        ta = self.resolve_for(ta, recv2)
                        var attr = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
                        if not ta isa MNullableType then
-                               if ta.ctype == "val*" then
+                               if not ta.is_c_primitive then
                                        self.add("{res} = ({attr} != NULL);")
                                else
                                        self.add("{res} = 1; /*NOTYET isset on primitive attributes*/")
@@ -705,7 +705,7 @@ class GlobalCompilerVisitor
                        ta = self.resolve_for(ta, recv2)
                        var res2 = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
                        if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
-                               if ta.ctype == "val*" then
+                               if not ta.is_c_primitive then
                                        self.add("if ({res2} == NULL) \{")
                                        self.add_abort("Uninitialized attribute {a.name}")
                                        self.add("\}")
@@ -781,7 +781,7 @@ class GlobalCompilerVisitor
                var res = self.new_var(bool_type)
 
                self.add("/* isa {mtype} on {value.inspect} */")
-               if value.mtype.ctype != "val*" then
+               if value.mtype.is_c_primitive then
                        if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
                                self.add("{res} = 1;")
                        else
@@ -816,14 +816,14 @@ class GlobalCompilerVisitor
        redef fun is_same_type_test(value1, value2)
        do
                var res = self.new_var(bool_type)
-               if value2.mtype.ctype == "val*" then
-                       if value1.mtype.ctype == "val*" then
+               if not value2.mtype.is_c_primitive then
+                       if not value1.mtype.is_c_primitive then
                                self.add "{res} = {value1}->classid == {value2}->classid;"
                        else
                                self.add "{res} = {self.compiler.classid(value1.mtype.as(MClassType))} == {value2}->classid;"
                        end
                else
-                       if value1.mtype.ctype == "val*" then
+                       if not value1.mtype.is_c_primitive then
                                self.add "{res} = {value1}->classid == {self.compiler.classid(value2.mtype.as(MClassType))};"
                        else if value1.mcasttype == value2.mcasttype then
                                self.add "{res} = 1;"
@@ -838,7 +838,7 @@ class GlobalCompilerVisitor
        do
                var res = self.get_name("var_class_name")
                self.add_decl("const char* {res};")
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        self.add "{res} = class_names[{value}->classid];"
                else
                        self.add "{res} = class_names[{self.compiler.classid(value.mtype.as(MClassType))}];"
@@ -849,15 +849,15 @@ class GlobalCompilerVisitor
        redef fun equal_test(value1, value2)
        do
                var res = self.new_var(bool_type)
-               if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+               if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
                        var tmp = value1
                        value1 = value2
                        value2 = tmp
                end
-               if value1.mtype.ctype != "val*" then
+               if value1.mtype.is_c_primitive then
                        if value2.mtype == value1.mtype then
                                self.add("{res} = {value1} == {value2};")
-                       else if value2.mtype.ctype != "val*" then
+                       else if value2.mtype.is_c_primitive then
                                self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
                        else
                                var mtype1 = value1.mtype.as(MClassType)
index f62d733..af3cdd9 100644 (file)
@@ -777,7 +777,7 @@ class SeparateCompiler
                var v = new_visitor
 
                var rta = runtime_type_analysis
-               var is_dead = rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" and mclass.name != "Pointer"
+               var is_dead = rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" and mclass.name != "Pointer"
 
                v.add_decl("/* runtime class {c_name} */")
 
@@ -806,7 +806,7 @@ class SeparateCompiler
                        v.add_decl("\};")
                end
 
-               if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then
+               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
@@ -1136,9 +1136,9 @@ class SeparateCompilerVisitor
        do
                if value.mtype == mtype then
                        return value
-               else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive and not mtype.is_c_primitive then
                        return value
-               else if value.mtype.ctype == "val*" then
+               else if not value.mtype.is_c_primitive then
                        if mtype.is_tagged then
                                if mtype.name == "Int" then
                                        return self.new_expr("(long)({value})>>2", mtype)
@@ -1151,7 +1151,7 @@ class SeparateCompilerVisitor
                                end
                        end
                        return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
-               else if mtype.ctype == "val*" then
+               else if not mtype.is_c_primitive then
                        if value.mtype.is_tagged then
                                if value.mtype.name == "Int" then
                                        return self.new_expr("(val*)({value}<<2|1)", mtype)
@@ -1231,7 +1231,7 @@ class SeparateCompilerVisitor
        # Thus the expression can be used as a condition.
        fun extract_tag(value: RuntimeVariable): String
        do
-               assert value.mtype.ctype == "val*"
+               assert not value.mtype.is_c_primitive
                return "((long){value}&3)" # Get the two low bits
        end
 
@@ -1239,7 +1239,7 @@ class SeparateCompilerVisitor
        # The point of the method is to work also with primitive types.
        fun class_info(value: RuntimeVariable): String
        do
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        if can_be_primitive(value) and not compiler.modelbuilder.toolcontext.opt_no_tag_primitives.value then
                                var tag = extract_tag(value)
                                return "({tag}?class_info[{tag}]:{value}->class)"
@@ -1256,7 +1256,7 @@ class SeparateCompilerVisitor
        # The point of the method is to work also with primitive types.
        fun type_info(value: RuntimeVariable): String
        do
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        if can_be_primitive(value) and not compiler.modelbuilder.toolcontext.opt_no_tag_primitives.value then
                                var tag = extract_tag(value)
                                return "({tag}?type_info[{tag}]:{value}->type)"
@@ -1305,7 +1305,7 @@ class SeparateCompilerVisitor
        end
        redef fun send(mmethod, arguments)
        do
-               if arguments.first.mcasttype.ctype != "val*" then
+               if arguments.first.mcasttype.is_c_primitive then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # Howverr, because of performance (no flattening), we always work on the realmainmodule
                        var m = self.compiler.mainmodule
@@ -1512,7 +1512,7 @@ class SeparateCompilerVisitor
 
        redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
-               if arguments.first.mcasttype.ctype != "val*" then
+               if arguments.first.mcasttype.is_c_primitive then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # However, because of performance (no flattening), we always work on the realmainmodule
                        var main = self.compiler.mainmodule
@@ -1563,7 +1563,7 @@ class SeparateCompilerVisitor
                        self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/")
                else
 
-                       if mtype.ctype == "val*" then
+                       if not mtype.is_c_primitive then
                                self.add("{res} = {recv}->attrs[{a.const_color}].val != NULL; /* {a} on {recv.inspect} */")
                        else
                                self.add("{res} = 1; /* NOT YET IMPLEMENTED: isset of primitives: {a} on {recv.inspect} */")
@@ -1615,7 +1615,7 @@ class SeparateCompilerVisitor
                        self.add("{res} = {recv}->attrs[{a.const_color}].{ret.ctypename}; /* {a} on {recv.inspect} */")
 
                        # Check for Uninitialized attribute
-                       if ret.ctype == "val*" and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
+                       if not ret.is_c_primitive and not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
                                self.add("if (unlikely({res} == NULL)) \{")
                                self.add_abort("Uninitialized attribute {a.name}")
                                self.add("\}")
@@ -1644,7 +1644,7 @@ class SeparateCompilerVisitor
                self.require_declaration(a.const_color)
                if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
                        var attr = "{recv}->attrs[{a.const_color}]"
-                       if mtype.ctype != "val*" then
+                       if mtype.is_c_primitive then
                                assert mtype isa MClassType
                                # The attribute is primitive, thus we store it in a box
                                # The trick is to create the box the first time then resuse the box
@@ -1796,15 +1796,15 @@ class SeparateCompilerVisitor
        do
                var res = self.new_var(bool_type)
                # Swap values to be symetric
-               if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+               if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
                        var tmp = value1
                        value1 = value2
                        value2 = tmp
                end
-               if value1.mtype.ctype != "val*" then
+               if value1.mtype.is_c_primitive then
                        if value2.mtype == value1.mtype then
                                self.add("{res} = 1; /* is_same_type_test: compatible types {value1.mtype} vs. {value2.mtype} */")
-                       else if value2.mtype.ctype != "val*" then
+                       else if value2.mtype.is_c_primitive then
                                self.add("{res} = 0; /* is_same_type_test: incompatible types {value1.mtype} vs. {value2.mtype}*/")
                        else
                                var mtype1 = value1.mtype.as(MClassType)
@@ -1821,7 +1821,7 @@ class SeparateCompilerVisitor
        do
                var res = self.get_name("var_class_name")
                self.add_decl("const char* {res};")
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        self.add "{res} = {value} == NULL ? \"null\" : {type_info(value)}->name;"
                else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind and
                        value.mtype.as(MClassType).name != "NativeString" then
@@ -1836,15 +1836,15 @@ class SeparateCompilerVisitor
        redef fun equal_test(value1, value2)
        do
                var res = self.new_var(bool_type)
-               if value2.mtype.ctype != "val*" and value1.mtype.ctype == "val*" then
+               if value2.mtype.is_c_primitive and not value1.mtype.is_c_primitive then
                        var tmp = value1
                        value1 = value2
                        value2 = tmp
                end
-               if value1.mtype.ctype != "val*" then
+               if value1.mtype.is_c_primitive then
                        if value2.mtype == value1.mtype then
                                self.add("{res} = {value1} == {value2};")
-                       else if value2.mtype.ctype != "val*" then
+                       else if value2.mtype.is_c_primitive then
                                self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
                        else if value1.mtype.is_tagged then
                                self.add("{res} = ({value2} != NULL) && ({self.autobox(value2, value1.mtype)} == {value1});")
@@ -1877,11 +1877,11 @@ class SeparateCompilerVisitor
 
                var incompatible = false
                var primitive
-               if t1.ctype != "val*" then
+               if t1.is_c_primitive then
                        primitive = t1
                        if t1 == t2 then
                                # No need to compare class
-                       else if t2.ctype != "val*" then
+                       else if t2.is_c_primitive then
                                incompatible = true
                        else if can_be_primitive(value2) then
                                if t1.is_tagged then
@@ -1895,7 +1895,7 @@ class SeparateCompilerVisitor
                        else
                                incompatible = true
                        end
-               else if t2.ctype != "val*" then
+               else if t2.is_c_primitive then
                        primitive = t2
                        if can_be_primitive(value1) then
                                if t2.is_tagged then
@@ -1956,7 +1956,7 @@ class SeparateCompilerVisitor
                var t = value.mcasttype.as_notnullable
                if not t isa MClassType then return false
                var k = t.mclass.kind
-               return k == interface_kind or t.ctype != "val*"
+               return k == interface_kind or t.is_c_primitive
        end
 
        fun maybe_null(value: RuntimeVariable): Bool
@@ -2230,7 +2230,7 @@ class SeparateRuntimeFunction
                var selfvar = arguments.first
                var ret = called_signature.return_mtype
 
-               if mmethoddef.is_intro and recv.ctype == "val*" then
+               if mmethoddef.is_intro and not recv.is_c_primitive then
                        var m = mmethoddef.mproperty
                        var n2 = "CALL_" + m.const_color
                        compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
@@ -2247,7 +2247,7 @@ class SeparateRuntimeFunction
                        v2.add "\}"
 
                end
-               if mmethoddef.has_supercall and recv.ctype == "val*" then
+               if mmethoddef.has_supercall and not recv.is_c_primitive then
                        var m = mmethoddef
                        var n2 = "CALL_" + m.const_color
                        compiler.provide_declaration(n2, "{c_ret} {n2}{c_sig};")
index 6e0d2b6..004d361 100644 (file)
@@ -206,7 +206,7 @@ class SeparateErasureCompiler
 
                var rta = runtime_type_analysis
                var is_dead = false # mclass.kind == abstract_kind or mclass.kind == interface_kind
-               if not is_dead and rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" then
+               if not is_dead and rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" then
                        is_dead = true
                end
 
@@ -264,7 +264,7 @@ class SeparateErasureCompiler
                v.add_decl("\}")
                v.add_decl("\};")
 
-               if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then
+               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;")
@@ -529,7 +529,7 @@ class SeparateErasureCompilerVisitor
                end
 
                var class_ptr
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        class_ptr = "{value}->class->"
                else
                        var mclass = value.mtype.as(MClassType).mclass
@@ -548,7 +548,7 @@ class SeparateErasureCompilerVisitor
                else if mtype isa MVirtualType then
                        var recv = self.frame.arguments.first
                        var recv_ptr
-                       if recv.mtype.ctype == "val*" then
+                       if not recv.mtype.is_c_primitive then
                                recv_ptr = "{recv}->class->"
                        else
                                var mclass = recv.mtype.as(MClassType).mclass
@@ -632,7 +632,7 @@ class SeparateErasureCompilerVisitor
        do
                var res = self.get_name("var_class_name")
                self.add_decl("const char* {res};")
-               if value.mtype.ctype == "val*" then
+               if not value.mtype.is_c_primitive then
                        self.add "{res} = {value} == NULL ? \"null\" : {value}->class->name;"
                else
                        self.require_declaration("class_{value.mtype.c_name}")