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