546b9fd1aa4bbf9e4d949be081732f0b7b541bc8
[nit.git] / src / metamodel / abstractmetamodel.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2006-2008 Floréal Morandat <morandat@lirmm.fr>
5 #
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
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
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.
17
18 # core NIT metamodel classes featuring the minimal and simpliest entities
19 package abstractmetamodel
20
21 import partial_order
22 import location
23
24 # The main singleton which knows everything
25 class MMContext
26
27 init do end
28
29 # The module dependence hierarchy
30 readable var _module_hierarchy: PartialOrder[MMModule] = new PartialOrder[MMModule]
31
32 # The class refinement and specialization hierarchy
33 # It is not the real hierarchy since non concrete classes can only be leaves
34 readable var _class_hierarchy: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
35
36 # All known global classes
37 var _global_classes: Array[MMGlobalClass] = new Array[MMGlobalClass]
38
39 # All known modules
40 readable var _modules: Array[MMModule] = new Array[MMModule]
41
42 # Register a new module with the modules it depends on
43 fun add_module(module: MMModule, supers: Array[MMModule])
44 do
45 _module_hierarchy.add(module, _module_hierarchy.select_smallests(supers))
46 _modules.add(module)
47 module._mhe = _module_hierarchy[module]
48 end
49
50 # Register a global class
51 private fun add_global_class(c: MMGlobalClass) do _global_classes.add(c)
52
53 # Register a local class
54 fun add_local_class(c: MMLocalClass, sup: Array[MMLocalClass])
55 do
56 var csup = new Array[MMLocalClass]
57 var csups = new Array[String]
58 for s in sup do
59 if s isa MMConcreteClass then
60 csup.add(s)
61 else
62 for ss in s.che.direct_greaters do
63 if csup.has(ss) then continue
64 csup.add(ss)
65 end
66 end
67 end
68 var che = _class_hierarchy.add(c, csup)
69 c._che = che
70 end
71 end
72
73 # Directory of modules
74 class MMDirectory
75 # Full name of the directory
76 readable var _name: Symbol
77
78 # Full path
79 readable var _path: String
80
81 # Parent directory
82 # null if none
83 readable var _parent: nullable MMDirectory
84
85 # The module that introduces the directory if any
86 readable writable var _owner: nullable MMModule = null
87
88 # Known modules in the directory
89 readable var _modules: Map[Symbol, MMModule] = new HashMap[Symbol, MMModule]
90
91 # Register a new module
92 fun add_module(module: MMModule)
93 do
94 assert not _modules.has_key(module.name)
95 _modules[module.name] = module
96 end
97
98 init(name: Symbol, path: String, parent: nullable MMDirectory) do
99 _name = name
100 _path = path
101 _parent = parent
102 end
103
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
107 end
108 end
109
110 # A module is a NIT package
111 class MMModule
112 # Global context
113 readable var _context: MMContext
114
115 # Short name of the module
116 readable var _name: Symbol
117
118 # Full name of the module
119 readable var _full_name: Symbol
120
121 # The directory of the module
122 readable var _directory: MMDirectory
123
124 # Location of this module
125 readable var _location: Location
126
127 # Module dependence hierarchy element
128 readable var _mhe: nullable PartialOrderElement[MMModule]
129
130 # All global classes of the module (defined and imported)
131 readable var _global_classes: Array[MMGlobalClass] = new Array[MMGlobalClass]
132
133 # All local classes of the module (defined and imported)
134 readable var _local_classes: Array[MMLocalClass] = new Array[MMLocalClass]
135
136 # Class specialization hierarchy of the module.
137 readable var _class_specialization_hierarchy: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
138
139 # Modules intruded (directly or not)
140 var _intrude_modules: Set[MMModule] = new HashSet[MMModule]
141
142 # Module publicly imported (directly or not)
143 var _public_modules: Set[MMModule] = new HashSet[MMModule]
144
145 # Module privately imported (directly or not)
146 var _private_modules: Set[MMModule] = new HashSet[MMModule]
147
148 # Explicit imported modules
149 readable var _explicit_imported_modules: Set[MMModule] = new HashSet[MMModule]
150
151 # Association between local class and global classes
152 var _local_class_by_global: Map[MMGlobalClass, MMLocalClass] = new HashMap[MMGlobalClass, MMLocalClass]
153
154 # Dictionary of global classes
155 var _global_class_by_name: Map[Symbol, MMGlobalClass] = new HashMap[Symbol, MMGlobalClass]
156
157 protected init(name: Symbol, dir: MMDirectory, context: MMContext, loc: Location)
158 do
159 _name = name
160 _directory = dir
161 _context = context
162 _full_name = dir.full_name_for(name)
163 _location = loc
164 end
165
166 # Register that a module is imported with a visibility
167 # 0 -> intrude
168 # 1 -> public
169 # 3 -> private
170 fun add_super_module(m: MMModule, visibility_level: Int)
171 do
172 _explicit_imported_modules.add(m)
173 if visibility_level == 0 then
174 _intrude_modules.add(m)
175 _intrude_modules.add_all(m._intrude_modules)
176 _public_modules.add_all(m._public_modules)
177 _private_modules.add_all(m._private_modules)
178 else if visibility_level == 1 then
179 _public_modules.add(m)
180 _public_modules.add_all(m._intrude_modules)
181 _public_modules.add_all(m._public_modules)
182 else
183 _private_modules.add(m)
184 _private_modules.add_all(m._intrude_modules)
185 _private_modules.add_all(m._public_modules)
186 end
187
188 end
189
190 # Return the visibiliy level of a super-module
191 # 3 -> self or intruded => see all
192 # 2 -> public => see public and protected
193 # 1 -> private => see public and protected
194 # 0 -> nothing => see nothing
195 fun visibility_for(m: MMModule): Int
196 do
197 if m == self or _intrude_modules.has(m) then
198 return 3
199 else if _public_modules.has(m) then
200 return 2
201 else if _private_modules.has(m) then
202 return 1
203 else
204 return 0
205 end
206 end
207
208
209 # Get the local class associated with a global class
210 fun [](c: MMGlobalClass): MMLocalClass
211 do
212 return _local_class_by_global[c]
213 end
214
215 # Get a local class by its name
216 fun class_by_name(n: Symbol): MMLocalClass
217 do
218 return self[_global_class_by_name[n]]
219 end
220
221 # Is there a global class with this name
222 fun has_global_class_named(n: Symbol): Bool
223 do
224 return _global_class_by_name.has_key(n)
225 end
226
227 # Get a global class by its name.
228 # Return null if not class match this name
229 fun global_class_named(n: Symbol): MMGlobalClass
230 do
231 return _global_class_by_name[n]
232 end
233
234 redef fun to_s do return name.to_s
235
236 # Assign super_classes for a local class
237 fun set_supers_class(c: MMLocalClass, supers: Array[MMLocalClass])
238 do
239 var tab = _class_specialization_hierarchy.select_smallests(supers)
240 c._cshe = _class_specialization_hierarchy.add(c,tab)
241 var tab_all = c.crhe.direct_greaters.to_a
242 tab_all.add_all(tab)
243 context.add_local_class(c,tab_all)
244 end
245
246 # Register a local class and its global class in the module
247 private fun register_global_class(c: MMLocalClass)
248 do
249 _local_class_by_global[c.global] = c
250 end
251 end
252
253 class MMGlobalClass
254 # The introducing local class
255 readable var _intro: MMLocalClass
256
257 # Class refinement hierarchy
258 # It is not the real hierarchy since non concrete classes can only be leaves
259 readable var _class_refinement_hierarchy: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
260
261 # Create a new global class introduced with a given local class
262 init(c: MMLocalClass)
263 do
264 _intro = c
265 c.context.add_global_class(self)
266 end
267
268 # The name of the global class
269 fun name: Symbol
270 do
271 return intro.name
272 end
273
274 # The module that introduces the global class
275 fun module: MMModule
276 do
277 return intro.module
278 end
279
280 redef fun to_s
281 do
282 return intro.to_s
283 end
284
285 # register a new Local class to local class hierarchy (set the crhe value)
286 private fun register_local_class(c: MMLocalClass)
287 do
288 var sup = new Array[MMLocalClass]
289 for s in class_refinement_hierarchy do
290 if c.module.mhe < s.module and s isa MMConcreteClass then
291 sup.add(s)
292 end
293 end
294 c._crhe = _class_refinement_hierarchy.add(c, sup)
295 end
296
297 # Is the global class an interface?
298 readable writable var _is_interface: Bool = false
299
300 # Is the global class an abstract class?
301 readable writable var _is_abstract: Bool = false
302
303 # Is the global class a universal class?
304 readable writable var _is_universal: Bool = false
305
306 # Visibility of the global class
307 # 1 -> public
308 # 3 -> private
309 readable writable var _visibility_level: Int = 1 # FIXME: why this should be defined ?
310
311 # Is the global class a mixin class?
312 # A mixin class inherits all constructors from a superclass
313 fun is_mixin: Bool
314 do
315 return _mixin_of != self
316 end
317
318 # Indicate the superclass the class is a mixin of.
319 # If mixin_of == self then the class is not a mixin
320 # Is two classes have the same mixin_of value, then they both belong to the same mixing group
321 readable writable var _mixin_of: MMGlobalClass = self
322
323 end
324
325 # Local classes are classes defined, refined or imported in a module
326 class MMLocalClass
327 # The name of the local class
328 readable var _name: Symbol
329
330 # Arity of the local class (if generic)
331 # FIXME: How to move this into the generic module in a sane way?
332 readable var _arity : Int
333
334 # The module of the local class
335 readable var _module: MMModule
336
337 # The global class of the local class
338 fun global: MMGlobalClass do return _global.as(not null)
339 var _global: nullable MMGlobalClass
340
341 # The local class refinement hierarchy element
342 fun crhe: PartialOrderElement[MMLocalClass] do return _crhe.as(not null)
343 var _crhe: nullable PartialOrderElement[MMLocalClass]
344
345 # The local class specialization hierarchy element
346 fun cshe: PartialOrderElement[MMLocalClass] do return _cshe.as(not null)
347 var _cshe: nullable PartialOrderElement[MMLocalClass]
348
349 # The local class full hierarchy element
350 fun che: PartialOrderElement[MMLocalClass] do return _che.as(not null)
351 var _che: nullable PartialOrderElement[MMLocalClass]
352
353 # Association between local properties and global properties
354 var _local_property_by_global: Map[MMGlobalProperty, MMLocalProperty] = new HashMap[MMGlobalProperty, MMLocalProperty]
355
356 # All known global properties
357 readable var _global_properties: Set[MMGlobalProperty] = new HashSet[MMGlobalProperty]
358
359 # All locally defined local properties
360 readable var _local_local_properties: Set[MMLocalProperty] = new HashSet[MMLocalProperty]
361
362 # Dictionnary of global properties
363 var _properties_by_name: Map[Symbol, Array[MMGlobalProperty]] = new HashMap[Symbol, Array[MMGlobalProperty]]
364
365 # Create a new class with a given name and arity
366 protected init(mod: MMModule, name: Symbol, arity: Int)
367 do
368 _module = mod
369 _name = name
370 _arity = arity
371 mod._local_classes.add(self)
372 end
373
374 # The corresponding local class in another module
375 fun for_module(m: MMModule): MMLocalClass
376 do
377 return m[global]
378 end
379
380 # Introduce a new global class to a new global one and register to hierarchy with no refine
381 fun new_global
382 do
383 var g = new MMGlobalClass(self)
384 _module._global_classes.add(g)
385 _module._global_class_by_name[name] = g
386 set_global(g)
387 end
388
389 # Associate this local class to a global one and register to hierarchy
390 # the global class for this class
391 # refined classes for this class
392 fun set_global(g: MMGlobalClass)
393 do
394 _global = g
395 _global.register_local_class(self)
396 _module.register_global_class(self)
397 end
398
399 # Is there a global propery with a given name
400 # TODO: Will disapear when qualified names will be available
401 fun has_global_property_by_name(n: Symbol): Bool
402 do
403 return _properties_by_name.has_key(n) and _properties_by_name[n].length == 1
404 end
405
406 # Get a global property by its name
407 # TODO: Will disapear when qualified names will be available
408 fun get_property_by_name(n: Symbol): MMGlobalProperty
409 do
410 if not has_global_property_by_name(n) then abort
411 var props = _properties_by_name[n]
412 return props.first
413 end
414
415 # Get a attribute by its name
416 # TODO: Will disapear when qualified names will be available
417 fun attribute(a: Symbol): MMGlobalProperty
418 do
419 return get_property_by_name(a)
420 end
421
422 # Get a method by its name
423 # TODO: Will disapear when qualified names will be available
424 fun method(na: Symbol): MMGlobalProperty
425 do
426 return _properties_by_name[na].first
427 end
428
429 # Select a method from its name
430 # TODO: Will disapear when qualified names will be available
431 fun select_method(name: Symbol): MMMethod
432 do
433 var gp = method(name)
434 var res = self[gp]
435 assert res isa MMMethod
436 return res
437 end
438
439 # Select an attribute from its name
440 # TODO: Will disapear when qualified names will be available
441 fun select_attribute(name: Symbol): MMAttribute
442 do
443 var gp = attribute(name)
444 var res = self[gp]
445 assert res isa MMAttribute
446 return res
447 end
448
449 # Look in super-classes (by specialization) and return properties with name
450 # Beware, global property of results is not intended to be the same
451 fun super_methods_named(n: Symbol): Array[MMLocalProperty]
452 do
453 var classes = new Array[MMLocalClass]
454 for c in cshe.greaters do
455 if c.has_global_property_by_name(n) then classes.add(c)
456 end
457 classes = cshe.order.select_smallests(classes)
458 var res = new Array[MMLocalProperty]
459 for c in classes do
460 var g = c.method(n)
461 #print "found {c[g].full_name}"
462 res.add(c[g])
463 end
464 return res
465 end
466
467 # Register a local property and associate it with its global property
468 fun register_local_property(p: MMLocalProperty)
469 do
470 _local_property_by_global[p.global] = p
471 if p.local_class == self then
472 _local_local_properties.add(p)
473 end
474 end
475
476 # Register a global property and associate it with its name
477 fun register_global_property(glob: MMGlobalProperty)
478 do
479 var prop = glob.intro
480 var name = prop.name
481 if _properties_by_name.has_key(name) then
482 _properties_by_name[name].add(glob)
483 else
484 _properties_by_name[name] = [glob]
485 end
486 _global_properties.add(glob)
487 register_local_property(prop)
488 end
489
490 # Does the global property belong to the class?
491 fun has_global_property(glob: MMGlobalProperty): Bool
492 do
493 return _global_properties.has(glob)
494 end
495
496 # Get a local proprty by its global property
497 fun [](glob: MMGlobalProperty): MMLocalProperty
498 do
499 return _local_property_by_global[glob]
500 end
501
502 # The current MMContext
503 fun context: MMContext do return module.context
504
505 redef fun to_s
506 do
507 return _name.to_s
508 end
509
510 # Comparaison in a total order that superset the class refinement and the class specialisation relations
511 fun total_order_compare(b: MMLocalClass): Int
512 do
513 var a = self
514 if a == b then
515 return 0
516 else if a.module.mhe < b.module then
517 return 1
518 else if b.module.mhe < a.module then
519 return -1
520 end
521 var ar = a.cshe.rank
522 var br = b.cshe.rank
523 if ar > br then
524 return 1
525 else if br > ar then
526 return -1
527 else
528 return b.name.to_s <=> a.name.to_s
529 end
530 end
531 end
532
533 # A global property gather local properties that correspond to a same message
534 class MMGlobalProperty
535 # The local property for each class that has the global property
536
537 # The introducing local property
538 readable var _intro: MMLocalProperty
539
540 # The local class that introduces the global property
541 fun local_class: MMLocalClass
542 do
543 return intro.local_class
544 end
545
546 # The property redefinition hierarchy
547 readable var _property_hierarchy: PartialOrder[MMLocalProperty] = new PartialOrder[MMLocalProperty]
548
549 # Create a new global property introduced by a local one
550 protected init(p: MMLocalProperty)
551 do
552 _intro = p
553 add_local_property(p, new Array[MMLocalProperty])
554 end
555
556 redef fun to_s do return intro.full_name
557
558 # Register a new local property
559 fun add_local_property(i: MMLocalProperty, sup: Array[MMLocalProperty])
560 do
561 i._prhe = _property_hierarchy.add(i,sup)
562 end
563
564 # Is the global property an attribute ?
565 fun is_attribute: Bool do return intro isa MMAttribute
566
567 # Is the global property a method (or a constructor)?
568 fun is_method: Bool do return intro isa MMMethod
569
570 # Is the global property a constructor (thus also a method)?
571 readable writable var _is_init: Bool = false
572
573 # Is the global property a constructor for a given class?
574 fun is_init_for(c: MMLocalClass): Bool
575 do
576 if not is_init then return false
577 var sc = intro.local_class
578 var res = c.che <= sc and c.global.mixin_of == sc.global.mixin_of
579 return res
580 end
581
582 # Visibility of the property
583 # 1 -> public
584 # 2 -> protected
585 # 3 -> private
586 readable writable var _visibility_level: Int = 1 # FIXME: why this should be defined ?
587 end
588
589 # Local properties are properties defined (explicitely or not) in a local class
590 class MMLocalProperty
591 # The name of the property
592 readable var _name: Symbol
593
594 # The local class who own the local property
595 readable var _local_class: MMLocalClass
596
597 # The global property where belong the local property
598 var _global: nullable MMGlobalProperty
599
600 fun global: MMGlobalProperty do return _global.as(not null)
601 fun is_global_set: Bool do return _global != null
602
603 # Redefinition hierarchy of the local property
604 var _prhe: nullable PartialOrderElement[MMLocalProperty]
605
606 fun prhe: PartialOrderElement[MMLocalProperty] do return _prhe.as(not null)
607
608 # The module of the local property
609 fun module: MMModule do return _local_class.module
610
611 # Full expanded name with all qualifications
612 fun full_name: String
613 do
614 if _global == null then
615 return "{local_class.module}::{local_class}::(?::{name})"
616 else if global.intro == self then
617 return "{local_class.module}::{local_class}::{name}"
618 else
619 return "{local_class.module}::{local_class}::({global.intro.full_name})"
620 end
621 end
622
623 # set the global property for this property
624 fun set_global(g: MMGlobalProperty)
625 do
626 _global = g
627 _local_class.register_local_property(self)
628 end
629
630 # Introduce a new global property for this local one
631 fun new_global
632 do
633 assert _global == null
634 var global = new MMGlobalProperty(self)
635 _global = global
636 _local_class.register_global_property(global)
637 end
638
639 redef fun to_s do return name.to_s
640
641 # Is the concrete property contain a `super' in the body?
642 readable writable var _need_super: Bool = false
643
644 protected init(n: Symbol, bc: MMLocalClass)
645 do
646 _name = n
647 _local_class = bc
648 end
649 end
650
651 # Attribute local properties
652 class MMAttribute
653 special MMLocalProperty
654 end
655
656 # Method local properties
657 class MMMethod
658 special MMLocalProperty
659 # Is the method defined with intern
660 fun is_intern: Bool is abstract
661
662 # Is the method abstract
663 fun is_abstract: Bool is abstract
664 end
665
666 # Concrete local classes
667 class MMConcreteClass
668 special MMLocalClass
669 end
670