Merge remote-tracking branch 'alexandre/at/sep' into wip
authorJean Privat <jean@pryen.org>
Sat, 24 Nov 2012 05:28:02 +0000 (00:28 -0500)
committerJean Privat <jean@pryen.org>
Sat, 24 Nov 2012 05:28:02 +0000 (00:28 -0500)
1  2 
src/global_compiler.nit
src/separate_compiler.nit

diff --combined src/global_compiler.nit
@@@ -509,7 -509,7 +509,7 @@@ redef class MTyp
        # Return the name of the C structure associated to a Nit live type
        # FIXME: move to GlobalCompiler so we can check that self is a live type
        fun c_name: String is abstract
-       private var c_name_cache: nullable String
+       protected var c_name_cache: nullable String protected writable
  end
  
  redef class MClassType
@@@ -1461,14 -1461,6 +1461,14 @@@ class GlobalCompilerVisito
                var res = self.new_var(bool_type)
  
                self.add("/* isa {mtype} on {value.inspect} */")
 +              if value.mtype.ctype != "val*" then
 +                      if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
 +                              self.add("{res} = 1;")
 +                      else
 +                              self.add("{res} = 0;")
 +                      end
 +                      return res
 +              end
                if value.mcasttype isa MNullableType then
                        self.add("if ({value} == NULL) \{")
                        if mtype isa MNullableType then
@@@ -58,7 -58,7 +58,7 @@@ redef class ModelBuilde
                # Class abstract representation
                v.add_decl("struct class \{ nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */")
                # Type abstract representation
-               v.add_decl("struct type \{ int id; int color; struct fts_table *fts_table; int type_table[1]; \}; /* general C type representing a Nit type. */")
+               v.add_decl("struct type \{ int id; int color; struct fts_table *fts_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */")
                v.add_decl("struct fts_table \{ struct type *fts[1]; \}; /* fts list of a C type representation. */")
                # Instance abstract representation
                v.add_decl("typedef struct \{ struct type *type; struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */")
@@@ -358,6 -358,7 +358,7 @@@ class SeparateCompile
                self.header.add_decl("int id;")
                self.header.add_decl("int color;")
                self.header.add_decl("const struct fts_table_{c_name} *fts_table;")
+               self.header.add_decl("int table_size;")
                self.header.add_decl("int type_table[{self.type_tables[mtype].length}];")
                self.header.add_decl("\};")
  
                v.add_decl("{self.typeids[mtype]},")
                v.add_decl("{self.type_colors[mtype]},")
                v.add_decl("&fts_table_{c_name},")
+               v.add_decl("{self.type_tables[mtype].length},")
                v.add_decl("\{")
                for stype in self.type_tables[mtype] do
                        if stype == null then
@@@ -864,22 -866,9 +866,22 @@@ class SeparateCompilerVisito
                return res
        end
  
 +      # Add a check and an abort for a null reciever is needed
 +      fun check_recv_notnull(recv: RuntimeVariable)
 +      do
 +              var maybenull = recv.mcasttype isa MNullableType
 +              if maybenull then
 +                      self.add("if ({recv} == NULL) \{")
 +                      self.add_abort("Reciever is null")
 +                      self.add("\}")
 +              end
 +      end
 +
 +
        redef fun isset_attribute(a, recv)
        do
                # FIXME: Here we inconditionally return boxed primitive attributes
 +              self.check_recv_notnull(recv)
                var res = self.new_var(bool_type)
                self.add("{res} = {recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}] != NULL; /* {a} on {recv.inspect}*/")
                return res
                var cret = self.object_type.as_nullable
                var res = self.new_var(cret)
                res.mcasttype = ret
 +
 +              self.check_recv_notnull(recv)
 +
                self.add("{res} = {recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}]; /* {a} on {recv.inspect} */")
                if not ret isa MNullableType then
                        self.add("if ({res} == NULL) \{")
        redef fun write_attribute(a, recv, value)
        do
                # FIXME: Here we inconditionally box primitive attributes
 +              self.check_recv_notnull(recv)
                value = self.autobox(value, self.object_type.as_nullable)
                self.add("{recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}] = {value}; /* {a} on {recv.inspect} */")
        end
  
+       # Build livetype structure retrieving
+       #ENSURE: mtype.need_anchor
+       fun retrieve_anchored_livetype(mtype: MGenericType, buffer: Buffer) do
+               assert mtype.need_anchor
+               var compiler = self.compiler.as(SeparateCompiler)
+               for ft in mtype.arguments do
+                       if ft isa MParameterType then
+                               var ftcolor = compiler.ft_colors[ft]
+                               buffer.append("[self->type->fts_table->fts[{ftcolor}]->id]")
+                       else if ft isa MGenericType and ft.need_anchor then
+                               var bbuff = new Buffer
+                               retrieve_anchored_livetype(ft, bbuff)
+                               buffer.append("[livetypes_{ft.mclass.c_name}{bbuff.to_s}->id]")
+                       else if ft isa MClassType then
+                               var typecolor = compiler.type_colors[ft]
+                               buffer.append("[{typecolor}]")
+                       else
+                               self.add("printf(\"NOT YET IMPLEMENTED: init_instance(%s, {mtype}).\\n\", \"{ft.inspect}\"); exit(1);")
+                       end
+               end
+       end
        redef fun init_instance(mtype)
        do
                var compiler = self.compiler.as(SeparateCompiler)
                if mtype isa MGenericType and mtype.need_anchor then
                        var buff = new Buffer
-                       var rank = 0
-                       for ft in mtype.arguments do
-                               if ft isa MParameterType then
-                                       var ftcolor = compiler.ft_colors[ft]
-                                       buff.append("[self->type->fts_table->fts[{ftcolor}]->id]")
-                               else if ft isa MGenericType and ft.need_anchor then
-                                       var ft_decl = mtype.mclass.mclass_type.arguments[rank]
-                                       var ftcolor = compiler.ft_colors[ft_decl.as(MParameterType)]
-                                       buff.append("[self->type->fts_table->fts[{ftcolor}]->id]")
-                               else
-                                       var typecolor = compiler.type_colors[ft.as(MClassType)]
-                                       buff.append("[{typecolor}]")
-                               end
-                               rank += 1
-                       end
+                       retrieve_anchored_livetype(mtype, buff)
                        mtype = self.anchor(mtype).as(MClassType)
                        return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) livetypes_{mtype.mclass.c_name}{buff.to_s})", mtype)
                end
        do
                var compiler = self.compiler.as(SeparateCompiler)
                var res = self.new_var(bool_type)
+               var cltype = self.get_name("cltype")
+               self.add_decl("short int {cltype};")
+               var idtype = self.get_name("idtype")
+               self.add_decl("short int {idtype};")
                var buff = new Buffer
+               var boxed = self.autobox(value, self.object_type)
  
                var s: String
                if mtype isa MNullableType then
                        mtype = mtype.mtype
-                       s = "{value} == NULL ||"
+                       s = "{boxed} == NULL ||"
                else
-                       s = "{value} != NULL &&"
+                       s = "{boxed} != NULL &&"
                end
-               if mtype isa MGenericType and mtype.need_anchor then
+               if mtype isa MParameterType then
+                       var ftcolor = compiler.ft_colors[mtype]
+                       self.add("{cltype} = self->type->fts_table->fts[{ftcolor}]->color;")
+                       self.add("{idtype} = self->type->fts_table->fts[{ftcolor}]->id;")
+               else if mtype isa MGenericType and mtype.need_anchor then
                        for ft in mtype.mclass.mclass_type.arguments do
                                var ftcolor = compiler.ft_colors[ft.as(MParameterType)]
                                buff.append("[self->type->fts_table->fts[{ftcolor}]->id]")
                        end
-                       self.add("{res} = {s} {value}->type->type_table[livetypes_{mtype.mclass.c_name}{buff.to_s}->color] == livetypes_{mtype.mclass.c_name}{buff.to_s}->id;")
+                       self.add("{cltype} = livetypes_{mtype.mclass.c_name}{buff.to_s}->color;")
+                       self.add("{idtype} = livetypes_{mtype.mclass.c_name}{buff.to_s}->id;")
                else if mtype isa MClassType then
                        compiler.undead_types.add(mtype)
-                       self.add("{res} = {s} {value}->type->type_table[type_{mtype.c_name}.color] == type_{mtype.c_name}.id;")
-               else if mtype isa MParameterType then
-                       var ftcolor = compiler.ft_colors[mtype]
-                       self.add("{res} = {s} {value}->type->type_table[self->type->fts_table->fts[{ftcolor}]->color] == self->type->fts_table->fts[{ftcolor}]->id;")
+                       self.add("{cltype} = type_{mtype.c_name}.color;")
+                       self.add("{idtype} = type_{mtype.c_name}.id;")
                else
-                       add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); exit(1);")
+                       self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{boxed.inspect}\"); exit(1);")
                end
  
+               # check color is in table
+               self.add("if({boxed} != NULL && {cltype} >= {boxed}->type->table_size) \{")
+               self.add("{res} = 0;")
+               self.add("\} else \{")
+               self.add("{res} = {s} {boxed}->type->type_table[{cltype}] == {idtype};")
+               self.add("\}")
                return res
        end