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