rta: store real types in live_cast_type
[nit.git] / src / modelize_class.nit
index 90eb70d..e8a207b 100644 (file)
@@ -33,7 +33,7 @@ private class ModelizeClassPhase
 end
 
 redef class ModelBuilder
-       # Visit the AST and create the MClass objects
+       # Visit the AST and create the `MClass` objects
        private fun build_a_mclass(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
@@ -76,6 +76,10 @@ redef class ModelBuilder
 
                var mclass = try_get_mclass_by_name(nclassdef, mmodule, name)
                if mclass == null then
+                       if nclassdef isa AStdClassdef and nclassdef.n_kwredef != null then
+                               error(nclassdef, "Redef error: No imported class {name} to refine.")
+                               return
+                       end
                        mclass = new MClass(mmodule, name, arity, mkind, mvisibility)
                        #print "new class {mclass}"
                else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then
@@ -96,7 +100,7 @@ redef class ModelBuilder
                nmodule.mclass2nclassdef[mclass] = nclassdef
        end
 
-       # Visit the AST and create the MClassDef objects
+       # Visit the AST and create the `MClassDef` objects
        private fun build_a_mclassdef(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
@@ -116,7 +120,12 @@ redef class ModelBuilder
                                        error(nfd, "Error: A formal parameter type `{ptname}' already exists")
                                        return
                                end
+                               for c in ptname do if c >= 'a' and c<= 'z' then
+                                       warning(nfd, "Warning: lowercase in the formal parameter type {ptname}")
+                                       break
+                               end
                                names.add(ptname)
+                               nfd.mtype = mclass.mclass_type.arguments[i].as(MParameterType)
                        end
 
                        # Revolve bound for formal parameter names
@@ -131,13 +140,18 @@ redef class ModelBuilder
                                                error(nfd, "Error: Formal parameter type `{names[i]}' bounded with a formal parameter type")
                                        else
                                                bounds.add(bound)
+                                               nfd.bound = bound
                                        end
                                else if mclass.mclassdefs.is_empty then
                                        # No bound, then implicitely bound by nullable Object
-                                       bounds.add(objectclass.mclass_type.as_nullable)
+                                       var bound = objectclass.mclass_type.as_nullable
+                                       bounds.add(bound)
+                                       nfd.bound = bound
                                else
                                        # Inherit the bound
-                                       bounds.add(mclass.intro.bound_mtype.arguments[i])
+                                       var bound = mclass.intro.bound_mtype.arguments[i]
+                                       bounds.add(bound)
+                                       nfd.bound = bound
                                end
                        end
                end
@@ -154,11 +168,12 @@ redef class ModelBuilder
                end
        end
 
-       # Visit the AST and set the super-types of the MClassdef objects
+       # Visit the AST and set the super-types of the `MClassDef` objects
        private fun collect_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
                var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
+               var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")
                var mclass = nclassdef.mclass.as(not null)
                var mclassdef = nclassdef.mclassdef.as(not null)
 
@@ -178,8 +193,16 @@ redef class ModelBuilder
                                #print "new super : {mclass} < {mtype}"
                        end
                end
-               if specobject and mclass.name != "Object" and objectclass != null and mclassdef.is_intro then
-                       supertypes.add objectclass.mclass_type
+               if specobject and mclassdef.is_intro then
+                       if mclass.kind == extern_kind then
+                               if mclass.name == "Pointer" then
+                                       supertypes.add objectclass.mclass_type
+                               else
+                                       supertypes.add pointerclass.mclass_type
+                               end
+                       else if mclass.name != "Object" and objectclass != null then
+                               supertypes.add objectclass.mclass_type
+                       end
                end
 
                mclassdef.set_supertypes(supertypes)
@@ -201,8 +224,8 @@ redef class ModelBuilder
                end
        end
 
-       # Build the classes of the module `nmodule'.
-       # REQUIRE: classes of imported modules are already build. (let `phase' do the job)
+       # Build the classes of the module `nmodule`.
+       # REQUIRE: classes of imported modules are already build. (let `phase` do the job)
        private fun build_classes(nmodule: AModule)
        do
                var errcount = toolcontext.error_count
@@ -337,13 +360,13 @@ redef class ModelBuilder
        end
 
        # Register the nclassdef associated to each mclassdef
-       # FIXME: why not refine the MClassDef class with a nullable attribute?
+       # FIXME: why not refine the `MClassDef` class with a nullable attribute?
        var mclassdef2nclassdef: HashMap[MClassDef, AClassdef] = new HashMap[MClassDef, AClassdef]
 
-       # Return the static type associated to the node `ntype'.
-       # `classdef' is the context where the call is made (used to understand formal types)
-       # The mmodule used as context is `nclassdef.mmodule'
-       # In case of problem, an error is displayed on `ntype' and null is returned.
+       # Return the static type associated to the node `ntype`.
+       # `nclassdef` is the context where the call is made (used to understand formal types)
+       # The mmodule used as context is `nclassdef.mmodule`
+       # In case of problem, an error is displayed on `ntype` and null is returned.
        # FIXME: the name "resolve_mtype" is awful
        fun resolve_mtype_unchecked(nclassdef: AClassdef, ntype: AType, with_virtual: Bool): nullable MType
        do
@@ -420,10 +443,10 @@ redef class ModelBuilder
                return null
        end
 
-       # Return the static type associated to the node `ntype'.
-       # `classdef' is the context where the call is made (used to understand formal types)
-       # The mmodule used as context is `nclassdef.mmodule'
-       # In case of problem, an error is displayed on `ntype' and null is returned.
+       # Return the static type associated to the node `ntype`.
+       # `nclassdef` is the context where the call is made (used to understand formal types)
+       # The mmodule used as context is `nclassdef.mmodule`
+       # In case of problem, an error is displayed on `ntype` and null is returned.
        # FIXME: the name "resolve_mtype" is awful
        fun resolve_mtype(nclassdef: AClassdef, ntype: AType): nullable MType
        do
@@ -456,15 +479,15 @@ end
 redef class AModule
        # Flag that indicate if the class building is already completed
        var build_classes_is_done: Bool = false
-       # What is the AClassdef associated to a MClass?
+       # What is the AClassdef associated to a `MClass`?
        # Used to check multiple definition of a class.
        var mclass2nclassdef: Map[MClass, AClassdef] = new HashMap[MClass, AClassdef]
 end
 
 redef class AClassdef
-       # The associated MClass once build by a `ModelBuilder'
+       # The associated MClass once build by a `ModelBuilder`
        var mclass: nullable MClass
-       # The associated MClassDef once build by a `ModelBuilder'
+       # The associated MClassDef once build by a `ModelBuilder`
        var mclassdef: nullable MClassDef
 end
 
@@ -488,6 +511,14 @@ redef class AExternClasskind
        redef fun mkind do return extern_kind
 end
 
+redef class AFormaldef
+       # The associated parameter type
+       var mtype: nullable MParameterType = null
+
+       # The associated bound
+       var bound: nullable MType = null
+end
+
 redef class AType
        # The mtype associated to the node
        var mtype: nullable MType = null