modelize_class: adapt MClass and MClassDef creation to new mparameters
authorJean Privat <jean@pryen.org>
Fri, 26 Sep 2014 03:28:25 +0000 (23:28 -0400)
committerJean Privat <jean@pryen.org>
Fri, 26 Sep 2014 03:28:25 +0000 (23:28 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/model/model.nit
src/modelize/modelize_class.nit

index e0d941a..0174f93 100644 (file)
@@ -250,8 +250,8 @@ redef class MModule
                var cla = self.model.get_mclasses_by_name(name)
                if cla == null then
                        if name == "Bool" then
-                               var c = new MClass(self, name, 0, enum_kind, public_visibility)
-                               var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
+                               var c = new MClass(self, name, null, enum_kind, public_visibility)
+                               var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0))
                                return c
                        end
                        print("Fatal Error: no primitive class {name}")
@@ -360,6 +360,10 @@ class MClass
        # 0 if the class is not generic
        var arity: Int
 
+       # Each generic formal parameters in order.
+       # is empty if the class is not generic
+       var mparameters = new Array[MParameterType]
+
        # The kind of the class (interface, abstract class, etc.)
        # In Nit, the kind of a class cannot evolve in refinements
        var kind: MClassKind
@@ -368,11 +372,15 @@ class MClass
        # In Nit, the visibility of a class cannot evolve in refinements
        var visibility: MVisibility
 
-       init(intro_mmodule: MModule, name: String, arity: Int, kind: MClassKind, visibility: MVisibility)
+       init(intro_mmodule: MModule, name: String, parameter_names: nullable Array[String], kind: MClassKind, visibility: MVisibility)
        do
                self.intro_mmodule = intro_mmodule
                self.name = name
-               self.arity = arity
+               if parameter_names == null then
+                       self.arity = 0
+               else
+                       self.arity = parameter_names.length
+               end
                self.kind = kind
                self.visibility = visibility
                intro_mmodule.intro_mclasses.add(self)
@@ -382,11 +390,13 @@ class MClass
 
                # Create the formal parameter types
                if arity > 0 then
+                       assert parameter_names != null
                        var mparametertypes = new Array[MParameterType]
                        for i in [0..arity[ do
-                               var mparametertype = new MParameterType(self, i)
+                               var mparametertype = new MParameterType(self, i, parameter_names[i])
                                mparametertypes.add(mparametertype)
                        end
+                       self.mparameters = mparametertypes
                        var mclass_type = new MGenericType(self, mparametertypes)
                        self.mclass_type = mclass_type
                        self.get_mtype_cache.add(mclass_type)
@@ -494,9 +504,6 @@ class MClassDef
        # ENSURE: `bound_mtype.mclass == self.mclass`
        var bound_mtype: MClassType
 
-       # Name of each formal generic parameter (in order of declaration)
-       var parameter_names: Array[String]
-
        # The origin of the definition
        var location: Location
 
@@ -504,16 +511,14 @@ class MClassDef
        # Example: "mymodule#MyClass"
        redef var to_s: String
 
-       init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
+       init(mmodule: MModule, bound_mtype: MClassType, location: Location)
        do
-               assert bound_mtype.mclass.arity == parameter_names.length
                self.bound_mtype = bound_mtype
                self.mmodule = mmodule
                self.mclass = bound_mtype.mclass
                self.location = location
                mmodule.mclassdefs.add(self)
                mclass.mclassdefs.add(self)
-               self.parameter_names = parameter_names
                self.to_s = "{mmodule}#{mclass}"
        end
 
@@ -1279,12 +1284,9 @@ class MParameterType
        # FIXME: is `position` a better name?
        var rank: Int
 
-       # Internal name of the parameter type
-       # Names of parameter types changes in each class definition
-       # Therefore, this method return an internal name.
-       # Example: return "G#1" for the second parameter of the class G
-       # FIXME: add a way to get the real name in a classdef
-       redef fun to_s do return "{mclass}#{rank}"
+       redef var name
+
+       redef fun to_s do return name
 
        # Resolve the bound for a given resolved_receiver
        # The result may be a other virtual type (or a parameter type)
@@ -1369,10 +1371,11 @@ class MParameterType
                return mtype.collect_mclassdefs(mmodule).has(mclass.intro)
        end
 
-       init(mclass: MClass, rank: Int)
+       init(mclass: MClass, rank: Int, name: String)
        do
                self.mclass = mclass
                self.rank = rank
+               self.name = name
        end
 end
 
index 8bc6ef2..9fa812f 100644 (file)
@@ -44,6 +44,7 @@ redef class ModelBuilder
                var nvisibility: nullable AVisibility
                var mvisibility: nullable MVisibility
                var arity = 0
+               var names = new Array[String]
                if nclassdef isa AStdClassdef then
                        name = nclassdef.n_id.text
                        nkind = nclassdef.n_classkind
@@ -58,6 +59,21 @@ redef class ModelBuilder
                                error(nvisibility, "Error: intrude is not a legal visibility for classes.")
                                return
                        end
+                       # Collect formal parameter names
+                       for i in [0..arity[ do
+                               var nfd = nclassdef.n_formaldefs[i]
+                               var ptname = nfd.n_id.text
+                               if names.has(ptname) then
+                                       error(nfd, "Error: A formal parameter type `{ptname}' already exists")
+                                       return
+                               end
+                               for c in ptname.chars do if c >= 'a' and c<= 'z' then
+                                       warning(nfd, "formal-type-name", "Warning: lowercase in the formal parameter type {ptname}")
+                                       break
+                               end
+                               names.add(ptname)
+                       end
+
                else if nclassdef isa ATopClassdef then
                        name = "Object"
                        nkind = null
@@ -80,7 +96,7 @@ redef class ModelBuilder
                                error(nclassdef, "Redef error: No imported class {name} to refine.")
                                return
                        end
-                       mclass = new MClass(mmodule, name, arity, mkind, mvisibility)
+                       mclass = new MClass(mmodule, name, names, mkind, mvisibility)
                        #print "new class {mclass}"
                else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then
                        error(nclassdef, "Error: A class {name} is already defined at line {nmodule.mclass2nclassdef[mclass].location.line_start}.")
@@ -121,35 +137,23 @@ redef class ModelBuilder
                        return
                end
 
-               var names = new Array[String]
                var bounds = new Array[MType]
                if nclassdef isa AStdClassdef and mclass.arity > 0 then
-                       # Collect formal parameter names
+                       # Revolve bound for formal parameters
                        for i in [0..mclass.arity[ do
-                               var nfd = nclassdef.n_formaldefs[i]
-                               var ptname = nfd.n_id.text
-                               if names.has(ptname) then
-                                       error(nfd, "Error: A formal parameter type `{ptname}' already exists")
-                                       return
-                               end
-                               for c in ptname.chars do if c >= 'a' and c<= 'z' then
-                                       warning(nfd, "formal-type-name", "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
-                       for i in [0..mclass.arity[ do
                                var nfd = nclassdef.n_formaldefs[i]
+                               var pname = mclass.mparameters[i].name
+                               if nfd.n_id.text != pname then
+                                       error(nfd.n_id, "Error: Formal parameter type #{i} `{nfd.n_id.text}` must be named `{pname}' as in the original definition in module `{mclass.intro.mmodule}`.")
+                               end
                                var nfdt = nfd.n_type
                                if nfdt != null then
                                        var bound = resolve_mtype_unchecked(mmodule, null, nfdt, false)
                                        if bound == null then return # Forward error
                                        if bound.need_anchor then
                                                # No F-bounds!
-                                               error(nfd, "Error: Formal parameter type `{names[i]}' bounded with a formal parameter type")
+                                               error(nfd, "Error: Formal parameter type `{pname}' bounded with a formal parameter type")
                                        else
                                                bounds.add(bound)
                                                nfd.bound = bound
@@ -172,7 +176,7 @@ redef class ModelBuilder
                end
 
                var bound_mtype = mclass.get_mtype(bounds)
-               var mclassdef = new MClassDef(mmodule, bound_mtype, nclassdef.location, names)
+               var mclassdef = new MClassDef(mmodule, bound_mtype, nclassdef.location)
                nclassdef.mclassdef = mclassdef
                self.mclassdef2nclassdef[mclassdef] = nclassdef