1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2006-2008 Floréal Morandat <morandat@lirmm.fr>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # core NIT metamodel classes featuring the minimal and simpliest entities
19 module abstractmetamodel
25 # The main singleton which knows everything
26 abstract class MMContext
30 # The module dependence hierarchy
31 readable var _module_hierarchy
: PartialOrder[MMModule] = new PartialOrder[MMModule]
33 # The class refinement and specialization hierarchy
34 # It is not the real hierarchy since non concrete classes can only be leaves
35 readable var _class_hierarchy
: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
37 # All known global classes
38 var _global_classes
: Array[MMGlobalClass] = new Array[MMGlobalClass]
41 readable var _modules
: Array[MMModule] = new Array[MMModule]
43 # Register a new module with the modules it depends on
44 fun add_module
(mod
: MMModule, supers
: Array[MMModule])
46 _module_hierarchy
.add
(mod
, _module_hierarchy
.select_smallests
(supers
))
48 mod
._mhe
= _module_hierarchy
[mod
]
51 # Register a global class
52 private fun add_global_class
(c
: MMGlobalClass) do _global_classes
.add
(c
)
54 # Register a local class
55 fun add_local_class
(c
: MMLocalClass, sup
: Array[MMLocalClass])
57 var csup
= new Array[MMLocalClass]
59 if s
isa MMConcreteClass then
62 for ss
in s
.che
.direct_greaters
do
63 if csup
.has
(ss
) then continue
68 var che
= _class_hierarchy
.add
(c
, csup
)
73 # Directory of modules
75 # Full name of the directory
76 readable var _name
: Symbol
79 readable var _path
: String
83 readable var _parent
: nullable MMDirectory
85 # The module that introduces the directory if any
86 readable writable var _owner
: nullable MMModule = null
88 # Known modules in the directory
89 readable var _modules
: Map[Symbol, MMModule] = new HashMap[Symbol, MMModule]
91 # Register a new module
92 fun add_module
(mod
: MMModule)
94 assert not _modules
.has_key
(mod
.name
)
95 _modules
[mod
.name
] = mod
98 init(name
: Symbol, path
: String, parent
: nullable MMDirectory) do
104 # The fullname of a a potentiel module in the directory
105 fun full_name_for
(module_name
: Symbol): Symbol do
106 return "{name}/{module_name}".to_symbol
110 # A module is a Nit file
111 abstract class MMModule
113 readable var _context
: MMContext
115 # Short name of the module
116 readable var _name
: Symbol
118 # Full name of the module
119 readable var _full_name
: Symbol
121 # The directory of the module
122 readable var _directory
: MMDirectory
124 # Location of this module
125 readable var _location
: Location
127 # Module dependence hierarchy element
128 readable var _mhe
: nullable PartialOrderElement[MMModule]
130 # All global classes of the module (defined and imported)
131 readable var _global_classes
: Set[MMGlobalClass] = new HashSet[MMGlobalClass]
133 # All local classes of the module (defined and imported)
134 readable var _local_classes
: Set[MMLocalClass] = new HashSet[MMLocalClass]
136 # Class specialization hierarchy of the module.
137 readable var _class_specialization_hierarchy
: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
139 # Modules intruded (directly or not)
140 var _intrude_modules
: Set[MMModule] = new HashSet[MMModule]
142 # Module publicly imported (directly or not)
143 var _public_modules
: Set[MMModule] = new HashSet[MMModule]
145 # Module privately imported (directly or not)
146 var _private_modules
: Set[MMModule] = new HashSet[MMModule]
148 # Explicit imported modules
149 readable var _explicit_imported_modules
: Set[MMModule] = new HashSet[MMModule]
151 # Association between local class and global classes
152 var _local_class_by_global
: Map[MMGlobalClass, MMLocalClass] = new HashMap[MMGlobalClass, MMLocalClass]
154 # Dictionary of global classes
155 var _global_class_by_name
: Map[Symbol, MMGlobalClass] = new HashMap[Symbol, MMGlobalClass]
157 # Is a hybrid module partially implemented in extern code
158 # It is if it contains a new extern class or an
159 # extern class declaration
160 var is_extern_hybrid
: Bool writable = false
162 # Uses foreign function interface
163 fun uses_ffi
: Bool is abstract
165 protected init(name
: Symbol, dir
: MMDirectory, context
: MMContext, loc
: Location)
170 _full_name
= dir
.full_name_for
(name
)
174 # Register that a module is imported with a visibility
178 fun add_super_module
(m
: MMModule, visibility_level
: Int)
180 _explicit_imported_modules
.add
(m
)
181 if visibility_level
== 0 then
182 _intrude_modules
.add
(m
)
183 _intrude_modules
.add_all
(m
._intrude_modules
)
184 _public_modules
.add_all
(m
._public_modules
)
185 _private_modules
.add_all
(m
._private_modules
)
186 else if visibility_level
== 1 then
187 _public_modules
.add
(m
)
188 _public_modules
.add_all
(m
._intrude_modules
)
189 _public_modules
.add_all
(m
._public_modules
)
191 _private_modules
.add
(m
)
192 _private_modules
.add_all
(m
._intrude_modules
)
193 _private_modules
.add_all
(m
._public_modules
)
198 # Return the visibiliy level of a super-module
199 # 3 -> self or intruded => see all
200 # 2 -> public => see public and protected
201 # 1 -> private => see public and protected
202 # 0 -> nothing => see nothing
203 fun visibility_for
(m
: MMModule): Int
205 if m
== self or _intrude_modules
.has
(m
) then
207 else if _public_modules
.has
(m
) then
209 else if _private_modules
.has
(m
) then
217 # Get the local class associated with a global class
218 fun [](c
: MMGlobalClass): MMLocalClass
220 return _local_class_by_global
[c
]
223 # Get a local class by its name
224 fun class_by_name
(n
: Symbol): MMLocalClass
226 return self[_global_class_by_name
[n
]]
229 # Is there a global class with this name
230 fun has_global_class_named
(n
: Symbol): Bool
232 return _global_class_by_name
.has_key
(n
)
235 # Get a global class by its name.
236 # Return null if not class match this name
237 fun global_class_named
(n
: Symbol): MMGlobalClass
239 return _global_class_by_name
[n
]
242 redef fun to_s
do return name
.to_s
244 # Assign super_classes for a local class
245 fun set_supers_class
(c
: MMLocalClass, supers
: Array[MMLocalClass])
247 var tab
= _class_specialization_hierarchy
.select_smallests
(supers
)
248 c
._cshe
= _class_specialization_hierarchy
.add
(c
,tab
)
249 var tab_all
= c
.crhe
.direct_greaters
.to_a
251 context
.add_local_class
(c
,tab_all
)
254 # Register a local class and its global class in the module
255 private fun register_global_class
(c
: MMLocalClass)
257 _local_class_by_global
[c
.global
] = c
262 # The introducing local class
263 readable var _intro
: MMLocalClass
265 # Class refinement hierarchy
266 # It is not the real hierarchy since non concrete classes can only be leaves
267 readable var _class_refinement_hierarchy
: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
269 # Create a new global class introduced with a given local class
270 init(c
: MMLocalClass)
273 c
.context
.add_global_class
(self)
276 # The name of the global class
282 # The module that introduces the global class
283 fun mmmodule
: MMModule
285 return intro
.mmmodule
293 # register a new Local class to local class hierarchy (set the crhe value)
294 private fun register_local_class
(c
: MMLocalClass)
296 var sup
= new Array[MMLocalClass]
297 for s
in class_refinement_hierarchy
do
298 if c
.mmmodule
.mhe
< s
.mmmodule
and s
isa MMConcreteClass then
302 c
._crhe
= _class_refinement_hierarchy
.add
(c
, sup
)
305 # Is the global class an interface?
306 readable writable var _is_interface
: Bool = false
308 # Is the global class an abstract class?
309 readable writable var _is_abstract
: Bool = false
311 # Is the global class a enum class?
312 readable writable var _is_enum
: Bool = false
314 # Is the global class an extern class?
315 readable writable var _is_extern
: Bool = false
317 # Visibility of the global class
320 readable writable var _visibility_level
: Int = 1 # FIXME: why this should be defined ?
322 # Is the global class a mixin class?
323 # A mixin class inherits all constructors from a superclass
326 return _mixin_of
!= self
329 # Indicate the superclass the class is a mixin of.
330 # If mixin_of == self then the class is not a mixin
331 # Is two classes have the same mixin_of value, then they both belong to the same mixing group
332 readable writable var _mixin_of
: MMGlobalClass = self
336 # Local classes are classes defined, refined or imported in a module
337 abstract class MMLocalClass
338 # The name of the local class
339 readable var _name
: Symbol
341 # Arity of the local class (if generic)
342 # FIXME: How to move this into the generic module in a sane way?
343 readable var _arity
: Int
345 # The module of the local class
346 readable var _mmmodule
: MMModule
348 # The global class of the local class
349 fun global
: MMGlobalClass do return _global
.as(not null)
350 var _global
: nullable MMGlobalClass
352 # The local class refinement hierarchy element
353 fun crhe
: PartialOrderElement[MMLocalClass] do return _crhe
.as(not null)
354 var _crhe
: nullable PartialOrderElement[MMLocalClass]
356 # The local class specialization hierarchy element
357 fun cshe
: PartialOrderElement[MMLocalClass] do return _cshe
.as(not null)
358 var _cshe
: nullable PartialOrderElement[MMLocalClass]
360 # The local class full hierarchy element
361 fun che
: PartialOrderElement[MMLocalClass] do return _che
.as(not null)
362 var _che
: nullable PartialOrderElement[MMLocalClass]
364 # Association between local properties and global properties
365 var _local_property_by_global
: Map[MMGlobalProperty, MMLocalProperty] = new HashMap[MMGlobalProperty, MMLocalProperty]
367 # All known global properties
368 readable var _global_properties
: Set[MMGlobalProperty] = new HashSet[MMGlobalProperty]
370 # All locally defined local properties
371 readable var _local_local_properties
: Set[MMLocalProperty] = new HashSet[MMLocalProperty]
373 # Dictionnary of global properties
374 var _properties_by_name
: Map[Symbol, Array[MMGlobalProperty]] = new HashMap[Symbol, Array[MMGlobalProperty]]
376 # Create a new class with a given name and arity
377 protected init(mod
: MMModule, name
: Symbol, arity
: Int)
382 mod
._local_classes
.add
(self)
385 # The corresponding local class in another module
386 fun for_module
(m
: MMModule): MMLocalClass
391 # Introduce a new global class to a new global one and register to hierarchy with no refine
394 var g
= new MMGlobalClass(self)
395 _mmmodule
._global_classes
.add
(g
)
396 _mmmodule
._global_class_by_name
[name
] = g
400 # Associate this local class to a global one and register to hierarchy
401 # the global class for this class
402 # refined classes for this class
403 fun set_global
(g
: MMGlobalClass)
406 _global
.register_local_class
(self)
407 _mmmodule
.register_global_class
(self)
410 # Is there a global propery with a given name
411 # TODO: Will disapear when qualified names will be available
412 fun has_global_property_by_name
(n
: Symbol): Bool
414 return _properties_by_name
.has_key
(n
) and _properties_by_name
[n
].length
== 1
417 # Get a global property by its name
418 # TODO: Will disapear when qualified names will be available
419 fun get_property_by_name
(n
: Symbol): MMGlobalProperty
421 if not has_global_property_by_name
(n
) then abort
422 var props
= _properties_by_name
[n
]
426 # Get a attribute by its name
427 # TODO: Will disapear when qualified names will be available
428 fun attribute
(a
: Symbol): MMGlobalProperty
430 return get_property_by_name
(a
)
433 # Get a method by its name
434 # TODO: Will disapear when qualified names will be available
435 fun method
(na
: Symbol): MMGlobalProperty
437 return _properties_by_name
[na
].first
440 # Select a method from its name
441 # TODO: Will disapear when qualified names will be available
442 fun select_method
(name
: Symbol): MMMethod
444 var gp
= method
(name
)
446 assert res
isa MMMethod
450 # Select an attribute from its name
451 # TODO: Will disapear when qualified names will be available
452 fun select_attribute
(name
: Symbol): MMAttribute
454 var gp
= attribute
(name
)
456 assert res
isa MMAttribute
460 # Look in super-classes (by specialization) and return properties with name
461 # Beware, global property of results is not intended to be the same
462 fun super_methods_named
(n
: Symbol): Array[MMLocalProperty]
464 var classes
= new Array[MMLocalClass]
465 for c
in cshe
.greaters
do
466 if c
.has_global_property_by_name
(n
) then classes
.add
(c
)
468 classes
= cshe
.order
.select_smallests
(classes
)
469 var res
= new Array[MMLocalProperty]
472 #print "found {c[g].full_name}"
478 # Register a local property and associate it with its global property
479 fun register_local_property
(p
: MMLocalProperty)
481 _local_property_by_global
[p
.global
] = p
482 if p
.local_class
== self then
483 _local_local_properties
.add
(p
)
487 # Register a global property and associate it with its name
488 fun register_global_property
(glob
: MMGlobalProperty)
490 var prop
= glob
.intro
492 if _properties_by_name
.has_key
(name
) then
493 _properties_by_name
[name
].add
(glob
)
495 _properties_by_name
[name
] = [glob
]
497 _global_properties
.add
(glob
)
498 register_local_property
(prop
)
501 # Does the global property belong to the class?
502 fun has_global_property
(glob
: MMGlobalProperty): Bool
504 return _global_properties
.has
(glob
)
507 # Get a local property by its global property
508 fun [](glob
: MMGlobalProperty): MMLocalProperty
510 return _local_property_by_global
[glob
]
513 # The current MMContext
514 fun context
: MMContext do return mmmodule
.context
521 # Comparaison in a total order that superset the class refinement and the class specialisation relations
522 fun total_order_compare
(b
: MMLocalClass): Int
527 else if a
.mmmodule
.mhe
< b
.mmmodule
then
529 else if b
.mmmodule
.mhe
< a
.mmmodule
then
539 return b
.name
.to_s
<=> a
.name
.to_s
544 # A global property gather local properties that correspond to a same message
545 class MMGlobalProperty
546 # The local property for each class that has the global property
548 # The introducing local property
549 readable var _intro
: MMLocalProperty
551 # The local class that introduces the global property
552 fun local_class
: MMLocalClass
554 return intro
.local_class
557 # The property redefinition hierarchy
558 readable var _property_hierarchy
: PartialOrder[MMLocalProperty] = new PartialOrder[MMLocalProperty]
560 # Create a new global property introduced by a local one
561 protected init(p
: MMLocalProperty)
564 add_local_property
(p
, new Array[MMLocalProperty])
567 redef fun to_s
do return intro
.full_name
569 # Register a new local property
570 fun add_local_property
(i
: MMLocalProperty, sup
: Array[MMLocalProperty])
572 i
._prhe
= _property_hierarchy
.add
(i
,sup
)
575 # Is the global property an attribute ?
576 fun is_attribute
: Bool do return intro
isa MMAttribute
578 # Is the global property a method (or a constructor)?
579 fun is_method
: Bool do return intro
isa MMMethod
581 # Is the global property a constructor (thus also a method)?
582 readable writable var _is_init
: Bool = false
584 # Is the global property a constructor for a given class?
585 fun is_init_for
(c
: MMLocalClass): Bool
587 if not is_init
then return false
588 var sc
= intro
.local_class
589 var res
= c
.che
<= sc
and c
.global
.mixin_of
== sc
.global
.mixin_of
593 # Visibility of the property
597 readable writable var _visibility_level
: Int = 1 # FIXME: why this should be defined ?
600 # Local properties are properties defined (explicitely or not) in a local class
601 abstract class MMLocalProperty
602 # The name of the property
603 readable var _name
: Symbol
605 # The local class who own the local property
606 readable var _local_class
: MMLocalClass
608 # The global property where belong the local property
609 var _global
: nullable MMGlobalProperty
611 fun global
: MMGlobalProperty do return _global
.as(not null)
612 fun is_global_set
: Bool do return _global
!= null
614 # Redefinition hierarchy of the local property
615 var _prhe
: nullable PartialOrderElement[MMLocalProperty]
617 fun prhe
: PartialOrderElement[MMLocalProperty] do return _prhe
.as(not null)
619 # The module of the local property
620 fun mmmodule
: MMModule do return _local_class
.mmmodule
622 # Full expanded name with all qualifications
623 fun full_name
: String
625 if _global
== null then
626 return "{local_class.mmmodule}::{local_class}::(?::{name})"
627 else if global
.intro
== self then
628 return "{local_class.mmmodule}::{local_class}::{name}"
630 return "{local_class.mmmodule}::{local_class}::({global.intro.full_name})"
634 # set the global property for this property
635 fun set_global
(g
: MMGlobalProperty)
638 _local_class
.register_local_property
(self)
641 # Introduce a new global property for this local one
644 assert _global
== null
645 var global
= new MMGlobalProperty(self)
647 _local_class
.register_global_property
(global
)
650 redef fun to_s
do return name
.to_s
652 # Is the concrete property contain a `super' in the body?
653 readable writable var _need_super
: Bool = false
655 protected init(n
: Symbol, bc
: MMLocalClass)
662 # Attribute local properties
663 abstract class MMAttribute
664 super MMLocalProperty
667 class MMExplicitImport
668 var local_class
: MMLocalClass
669 var method
: MMMethod
672 # Method local properties
673 abstract class MMMethod
674 super MMLocalProperty
675 # Is the method defined with intern
676 fun is_intern
: Bool is abstract
678 # Is the method abstract
679 fun is_abstract
: Bool is abstract
681 # Is the method extern
682 fun is_extern
: Bool is abstract
684 # extern name when specified explicitly in nit code
685 fun extern_name
: nullable String is abstract
687 # properties explicitly exported to native code
688 fun explicit_imports
: Set[ MMExplicitImport ] is abstract
691 # Concrete local classes
692 abstract class MMConcreteClass