nullable: convert lib, tools and tests
[nit.git] / src / metamodel / abstractmetamodel.nit
index 1a2eb86..8d53ece 100644 (file)
@@ -38,12 +38,10 @@ class MMContext
        # All known modules
        readable attr _modules: Array[MMModule] = new Array[MMModule]
 
-       # Register a new module with the modules it depends on 
+       # Register a new module with the modules it depends on
        meth add_module(module: MMModule, supers: Array[MMModule])
        do
-               assert supers != null
                _module_hierarchy.add(module, _module_hierarchy.select_smallests(supers))
-               assert module.name != null
                _modules.add(module)
                module._mhe = _module_hierarchy[module]
        end
@@ -54,7 +52,6 @@ class MMContext
        # Register a local class
        meth add_local_class(c: MMLocalClass, sup: Array[MMLocalClass])
        do
-               assert sup != null
                var csup = new Array[MMLocalClass]
                var csups = new Array[String]
                for s in sup do
@@ -82,10 +79,10 @@ class MMDirectory
 
        # Parent directory
        # null if none
-       readable attr _parent: MMDirectory
+       readable attr _parent: nullable MMDirectory
 
        # The module that introduces the directory if any
-       readable writable attr _owner: MMModule
+       readable writable attr _owner: nullable MMModule = null
 
        # Known modules in the directory
        readable attr _modules: Map[Symbol, MMModule] = new HashMap[Symbol, MMModule]
@@ -97,10 +94,7 @@ class MMDirectory
                _modules[module.name] = module
        end
 
-       # Directory hierarchy element
-       readable attr _dhe: PartialOrderElement[MMDirectory]
-
-       init(name: Symbol, path: String, parent: MMDirectory) do
+       init(name: Symbol, path: String, parent: nullable MMDirectory) do
                _name = name
                _path = path
                _parent = parent
@@ -126,8 +120,11 @@ class MMModule
        # The directory of the module
        readable attr _directory: MMDirectory
 
+       # The filename of the module
+       readable attr _filename: String
+
        # Module dependence hierarchy element
-       readable attr _mhe: PartialOrderElement[MMModule] 
+       readable attr _mhe: nullable PartialOrderElement[MMModule]
 
        # All global classes of the module (defined and imported)
        readable attr _global_classes: Array[MMGlobalClass] = new Array[MMGlobalClass]
@@ -156,17 +153,13 @@ class MMModule
        # Dictionary of global classes
        attr _global_class_by_name: Map[Symbol, MMGlobalClass] = new HashMap[Symbol, MMGlobalClass]
 
-       protected init(name: Symbol, dir: MMDirectory, context: MMContext)
+       protected init(name: Symbol, dir: MMDirectory, context: MMContext, filename: String)
        do
                _name = name
                _directory = dir
                _context = context
-
-               if dir == null then
-                       _full_name = name
-               else
-                       _full_name = dir.full_name_for(name)
-               end
+               _full_name = dir.full_name_for(name)
+               _filename = filename
        end
 
        # Register that a module is imported with a visibility
@@ -215,20 +208,7 @@ class MMModule
        # Get the local class associated with a global class 
        meth [](c: MMGlobalClass): MMLocalClass
        do
-               assert _local_class_by_global != null
-               assert c != null
-               if _local_class_by_global.has_key(c) then
-                       return _local_class_by_global[c]
-               else
-                       return null
-               end
-       end
-
-       # Register a local class to the module
-       meth add_local_class(c: MMLocalClass)
-       do
-               c._module = self
-               _local_classes.add(c)
+               return _local_class_by_global[c]
        end
 
        # Get a local class by its name
@@ -247,11 +227,7 @@ class MMModule
        # Return null if not class match this name
        meth global_class_named(n: Symbol): MMGlobalClass
        do
-               if _global_class_by_name.has_key(n) then
-                       return _global_class_by_name[n]
-               else
-                       return null
-               end
+               return _global_class_by_name[n]
        end
 
        redef meth to_s do return name.to_s
@@ -259,7 +235,6 @@ class MMModule
        # Assign super_classes for a local class
        meth set_supers_class(c: MMLocalClass, supers: Array[MMLocalClass])
        do
-               assert supers != null
                var tab = _class_specialization_hierarchy.select_smallests(supers)
                c._cshe = _class_specialization_hierarchy.add(c,tab)
                var tab_all = c.crhe.direct_greaters.to_a
@@ -270,7 +245,6 @@ class MMModule
        # Register a local class and its global class in the module
        private meth register_global_class(c: MMLocalClass)
        do
-               assert c.global != null
                _local_class_by_global[c.global] = c
        end
 end
@@ -310,9 +284,7 @@ class MMGlobalClass
        # register a new Local class to local class hierarchy (set the crhe value)
        private meth register_local_class(c: MMLocalClass)
        do
-               assert c.module != null
-               assert c.crhe == null
-               var sup = new  Array[MMLocalClass]
+               var sup = new Array[MMLocalClass]
                for s in class_refinement_hierarchy do
                        if c.module.mhe < s.module and s isa MMConcreteClass then
                                sup.add(s)
@@ -322,18 +294,31 @@ class MMGlobalClass
        end
 
        # Is the global class an interface?
-       readable writable attr _is_interface: Bool
+       readable writable attr _is_interface: Bool = false
 
        # Is the global class an abstract class?
-       readable writable attr _is_abstract: Bool
+       readable writable attr _is_abstract: Bool = false
 
        # Is the global class a universal class?
-       readable writable attr _is_universal: Bool
+       readable writable attr _is_universal: Bool = false
 
        # Visibility of the global class
        # 1 -> public
        # 3 -> private
-       readable writable attr _visibility_level: Int
+       readable writable attr _visibility_level: Int = 1 # FIXME: why this should be defined ?
+
+       # Is the global class a mixin class?
+       # A mixin class inherits all constructors from a superclass
+       meth is_mixin: Bool
+       do
+               return _mixin_of != self
+       end
+
+       # Indicate the superclass the class is a mixin of.
+       # If mixin_of == self then the class is not a mixin
+       # Is two classes have the same mixin_of value, then they both belong to the same mixing group
+       readable writable attr _mixin_of: MMGlobalClass = self
+
 end
 
 # Local classes are classes defined, refined or imported in a module
@@ -348,35 +333,38 @@ class MMLocalClass
        # The module of the local class
        readable attr _module: MMModule
 
-       # Is the class abstract
-       readable writable attr _abstract: Bool
-
        # The global class of the local class
-       readable attr _global: MMGlobalClass 
+       meth global: MMGlobalClass do return _global.as(not null)
+       attr _global: nullable MMGlobalClass
 
        # The local class refinement hierarchy element
-       readable attr _crhe: PartialOrderElement[MMLocalClass] 
+       meth crhe: PartialOrderElement[MMLocalClass] do return _crhe.as(not null)
+       attr _crhe: nullable PartialOrderElement[MMLocalClass]
 
        # The local class specialization hierarchy element
-       readable attr _cshe: PartialOrderElement[MMLocalClass] 
+       meth cshe: PartialOrderElement[MMLocalClass] do return _cshe.as(not null)
+       attr _cshe: nullable PartialOrderElement[MMLocalClass]
 
        # The local class full hierarchy element
-       readable attr _che: PartialOrderElement[MMLocalClass]
+       meth che: PartialOrderElement[MMLocalClass] do return _che.as(not null)
+       attr _che: nullable PartialOrderElement[MMLocalClass]
 
        # Association between local properties and global properties
-       readable attr _local_property_by_global: Map[MMGlobalProperty, MMLocalProperty] 
+       attr _local_property_by_global: Map[MMGlobalProperty, MMLocalProperty] = new HashMap[MMGlobalProperty, MMLocalProperty]
 
        # All known global properties
-       readable attr _global_properties: Set[MMGlobalProperty] 
+       readable attr _global_properties: Set[MMGlobalProperty] = new HashSet[MMGlobalProperty]
 
        # Dictionnary of global properties
-       readable attr _properties_by_name: Map[Symbol, Array[MMGlobalProperty]]
+       attr _properties_by_name: Map[Symbol, Array[MMGlobalProperty]] = new HashMap[Symbol, Array[MMGlobalProperty]]
 
        # Create a new class with a given name and arity
-       protected init(name: Symbol, arity: Int)
+       protected init(mod: MMModule, name: Symbol, arity: Int)
        do
+               _module = mod
                _name = name
                _arity = arity
+               mod._local_classes.add(self)
        end
 
        # The corresponding local class in another module
@@ -399,7 +387,6 @@ class MMLocalClass
        # refined classes for this class
        meth set_global(g: MMGlobalClass)
        do
-               assert g != null
                _global = g
                _global.register_local_class(self)
                _module.register_global_class(self)
@@ -409,18 +396,15 @@ class MMLocalClass
        # TODO: Will disapear when qualified names will be available
        meth has_global_property_by_name(n: Symbol): Bool
        do
-               var props = _properties_by_name[n]
-               return props != null
+               return _properties_by_name.has_key(n) and _properties_by_name[n].length == 1
        end
 
        # Get a global property by its name
        # TODO: Will disapear when qualified names will be available
        meth get_property_by_name(n: Symbol): MMGlobalProperty
        do
+               if not has_global_property_by_name(n) then abort
                var props = _properties_by_name[n]
-               if props == null or props.length > 1 then
-                       return null
-               end
                return props.first
        end
 
@@ -435,13 +419,27 @@ class MMLocalClass
        # TODO: Will disapear when qualified names will be available
        meth method(na: Symbol): MMGlobalProperty
        do
-               assert _properties_by_name != null
-               var props = _properties_by_name[na]
-               if props != null then
-                       return props.first
-               end
+               return _properties_by_name[na].first
+       end
 
-               return null
+       # Select a method from its name
+       # TODO: Will disapear when qualified names will be available
+       meth select_method(name: Symbol): MMMethod
+       do
+               var gp = method(name)
+               var res = self[gp]
+               assert res isa MMMethod
+               return res
+       end
+       
+       # Select an attribute from its name
+       # TODO: Will disapear when qualified names will be available
+       meth select_attribute(name: Symbol): MMAttribute
+       do
+               var gp = attribute(name)
+               var res = self[gp]
+               assert res isa MMAttribute
+               return res
        end
        
        # Look in super-classes (by specialization) and return properties with name
@@ -450,9 +448,7 @@ class MMLocalClass
        do
                var classes = new Array[MMLocalClass]
                for c in cshe.greaters do
-                       var g = c.method(n)
-                       if g == null then continue
-                       classes.add(c)
+                       if c.has_global_property_by_name(n) then classes.add(c)
                end
                classes = cshe.order.select_smallests(classes)
                var res = new Array[MMLocalProperty]
@@ -467,11 +463,7 @@ class MMLocalClass
        # Register a local property and associate it with its global property
        meth register_local_property(p: MMLocalProperty)
        do
-               assert p.global != null
-               # FIXME: Why a test?
-               if not _local_property_by_global.has_key(p.global) then
-                       _local_property_by_global[p.global] = p
-               end
+               _local_property_by_global[p.global] = p
        end
 
        # Register a global property and associate it with its name
@@ -479,25 +471,25 @@ class MMLocalClass
        do
                var prop = glob.intro
                var name = prop.name
-               var  props = _properties_by_name[name]
-               if props == null then
-                       _properties_by_name[name] = [glob]
-               else
+               if _properties_by_name.has_key(name) then
                        _properties_by_name[name].add(glob)
+               else
+                       _properties_by_name[name] = [glob]
                end
                _global_properties.add(glob)
                register_local_property(prop)
        end
 
+       # Does the global property belong to the class?
+       meth has_global_property(glob: MMGlobalProperty): Bool
+       do
+               return _global_properties.has(glob)
+       end
+
        # Get a local proprty by its global property
        meth [](glob: MMGlobalProperty): MMLocalProperty
        do
-               assert _local_property_by_global != null
-               assert glob != null
-               if _local_property_by_global.has_key(glob) then
-                       return _local_property_by_global[glob]
-               end
-               return null
+               return _local_property_by_global[glob]
        end
 
        # The current MMContext
@@ -514,37 +506,30 @@ class MMGlobalProperty
        # The local property for each class that has the global property
 
        # The introducing local property
-       readable attr _intro: MMConcreteProperty
+       readable attr _intro: MMLocalProperty
 
        # The local class that introduces the global property
-       meth local_class: MMLocalClass
-       do
-               return intro.local_class
-       end
+       meth local_class: MMLocalClass
+       do
+               return intro.local_class
+       end
 
-       # The concrete property redefinition hierarchy
-       readable attr _concrete_property_hierarchy: PartialOrder[MMConcreteProperty] = new PartialOrder[MMConcreteProperty]
+       # The property redefinition hierarchy
+       readable attr _property_hierarchy: PartialOrder[MMLocalProperty] = new PartialOrder[MMLocalProperty]
 
        # Create a new global property introduced by a local one
-       protected init(p: MMConcreteProperty)
+       protected init(p: MMLocalProperty)
        do
-               assert p != null
-               assert p.concrete_property != null
-
-               _concrete_property_hierarchy = new PartialOrder[MMConcreteProperty]
-       
                _intro = p
-               add_concrete_property(p, new Array[MMConcreteProperty])
+               add_local_property(p, new Array[MMLocalProperty])
        end
 
        redef meth to_s do return intro.full_name
 
-       # Register a new concrete property
-       meth add_concrete_property(i: MMConcreteProperty, sup: Array[MMConcreteProperty])
+       # Register a new local property
+       meth add_local_property(i: MMLocalProperty, sup: Array[MMLocalProperty])
        do
-               assert i != null
-               assert sup != null
-               i._cprhe = _concrete_property_hierarchy.add(i,sup)
+               i._prhe = _property_hierarchy.add(i,sup)
        end
 
        # Is the global property an attribute ?
@@ -554,17 +539,25 @@ class MMGlobalProperty
        meth is_method: Bool do return intro isa MMMethod
 
        # Is the global property a constructor (thus also a method)?
-       readable writable attr _is_init: Bool
+       readable writable attr _is_init: Bool = false
+
+       # Is the global property a constructor for a given class?
+       meth is_init_for(c: MMLocalClass): Bool
+       do
+               if not is_init then return false
+               var sc = intro.local_class
+               var res = c.che <= sc and c.global.mixin_of == sc.global.mixin_of
+               return res
+       end
 
        # Visibility of the property
        # 1 -> public
        # 2 -> protected
        # 3 -> private
-       readable writable attr _visibility_level: Int
+       readable writable attr _visibility_level: Int = 1 # FIXME: why this should be defined ?
 end
 
-# Local properties are adaptation of concrete local properties
-# They can be adapted for inheritance (or importation) or for type variarion (genericity, etc.)
+# Local properties are properties defined (explicitely or not) in a local class
 class MMLocalProperty
        # The name of the property
        readable attr _name: Symbol
@@ -573,11 +566,15 @@ class MMLocalProperty
        readable attr _local_class: MMLocalClass
 
        # The global property where belong the local property
-       readable attr _global: MMGlobalProperty
+       attr _global: nullable MMGlobalProperty
 
-       # The concrete property
-       # May be self if self is a concrete property
-       readable attr _concrete_property: MMConcreteProperty 
+       meth global: MMGlobalProperty do return _global.as(not null)
+       meth is_global_set: Bool do return _global != null
+
+       # Redefinition hierarchy of the local property
+       attr _prhe: nullable PartialOrderElement[MMLocalProperty]
+
+       meth prhe: PartialOrderElement[MMLocalProperty] do return _prhe.as(not null)
 
        # The module of the local property
        meth module: MMModule do return _local_class.module
@@ -585,7 +582,7 @@ class MMLocalProperty
        # Full expanded name with all qualifications
        meth full_name: String
        do
-               if global == null then
+               if _global == null then
                        return "{local_class.module}::{local_class}::(?::{name})"
                else if global.intro == self then
                        return "{local_class.module}::{local_class}::{name}"
@@ -597,18 +594,28 @@ class MMLocalProperty
        # set the global property for this property
        meth set_global(g: MMGlobalProperty)
        do
-               assert g != null
                _global = g
                _local_class.register_local_property(self)
        end
-       
+
+       # Introduce a new global property for this local one
+       meth new_global
+       do
+               assert _global == null
+               var global = new MMGlobalProperty(self)
+               _global = global
+               _local_class.register_global_property(global)
+       end
+
        redef meth to_s do return name.to_s
 
-       protected init(n: Symbol, bc: MMLocalClass, i: MMConcreteProperty)
+       # Is the concrete property contain a `super' in the body?
+       readable writable attr _need_super: Bool = false
+
+       protected init(n: Symbol, bc: MMLocalClass)
        do
                _name = n
                _local_class = bc
-               _concrete_property = i
        end
 end
 
@@ -627,21 +634,3 @@ class MMConcreteClass
 special MMLocalClass
 end
 
-# Concrete local properties
-class MMConcreteProperty
-special MMLocalProperty
-       # Redefinition hierarchy of the concrete property
-       readable attr _cprhe: PartialOrderElement[MMConcreteProperty]
-
-       # Is the concrete property contain a `super' in the body?
-       readable writable attr _need_super: Bool
-       # Introduce a new global property for this local one
-       meth new_global
-       do
-               assert _global == null
-               _global = new MMGlobalProperty(self)
-               _local_class.register_global_property(_global)
-       end
-end
-