First NIT release and new clean mercurial repository
[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 # Module dependence hierarchy element
130 readable attr _mhe: PartialOrderElement[MMModule]
131
132 # All global classes of the module (defined and imported)
133 readable attr _global_classes: Array[MMGlobalClass] = new Array[MMGlobalClass]
134
135 # All local classes of the module (defined and imported)
136 readable attr _local_classes: Array[MMLocalClass] = new Array[MMLocalClass]
137
138 # Class specialization hierarchy of the module.
139 readable attr _class_specialization_hierarchy: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
140
141 # Modules intruded (directly or not)
142 attr _intrude_modules: Set[MMModule] = new HashSet[MMModule]
143
144 # Module publicly imported (directly or not)
145 attr _public_modules: Set[MMModule] = new HashSet[MMModule]
146
147 # Module privately imported (directly or not)
148 attr _private_modules: Set[MMModule] = new HashSet[MMModule]
149
150 # Explicit imported modules
151 readable attr _explicit_imported_modules: Set[MMModule] = new HashSet[MMModule]
152
153 # Association between local class and global classes
154 attr _local_class_by_global: Map[MMGlobalClass, MMLocalClass] = new HashMap[MMGlobalClass, MMLocalClass]
155
156 # Dictionary of global classes
157 attr _global_class_by_name: Map[Symbol, MMGlobalClass] = new HashMap[Symbol, MMGlobalClass]
158
159 protected init(name: Symbol, dir: MMDirectory, context: MMContext)
160 do
161 _name = name
162 _directory = dir
163 _context = context
164
165 if dir == null then
166 _full_name = name
167 else
168 _full_name = dir.full_name_for(name)
169 end
170 end
171
172 # Register that a module is imported with a visibility
173 # 0 -> intrude
174 # 1 -> public
175 # 3 -> private
176 meth add_super_module(m: MMModule, visibility_level: Int)
177 do
178 _explicit_imported_modules.add(m)
179 if visibility_level == 0 then
180 _intrude_modules.add(m)
181 _intrude_modules.add_all(m._intrude_modules)
182 _public_modules.add_all(m._public_modules)
183 _private_modules.add_all(m._private_modules)
184 else if visibility_level == 1 then
185 _public_modules.add(m)
186 _public_modules.add_all(m._intrude_modules)
187 _public_modules.add_all(m._public_modules)
188 else
189 _private_modules.add(m)
190 _private_modules.add_all(m._intrude_modules)
191 _private_modules.add_all(m._public_modules)
192 end
193
194 end
195
196 # Return the visibiliy level of a super-module
197 # 3 -> self or intruded => see all
198 # 2 -> public => see public and protected
199 # 1 -> private => see public and protected
200 # 0 -> nothing => see nothing
201 meth visibility_for(m: MMModule): Int
202 do
203 if m == self or _intrude_modules.has(m) then
204 return 3
205 else if _public_modules.has(m) then
206 return 2
207 else if _private_modules.has(m) then
208 return 1
209 else
210 return 0
211 end
212 end
213
214
215 # Get the local class associated with a global class
216 meth [](c: MMGlobalClass): MMLocalClass
217 do
218 assert _local_class_by_global != null
219 assert c != null
220 if _local_class_by_global.has_key(c) then
221 return _local_class_by_global[c]
222 else
223 return null
224 end
225 end
226
227 # Register a local class to the module
228 meth add_local_class(c: MMLocalClass)
229 do
230 c._module = self
231 _local_classes.add(c)
232 end
233
234 # Get a local class by its name
235 meth class_by_name(n: Symbol): MMLocalClass
236 do
237 return self[_global_class_by_name[n]]
238 end
239
240 # Is there a global class with this name
241 meth has_global_class_named(n: Symbol): Bool
242 do
243 return _global_class_by_name.has_key(n)
244 end
245
246 # Get a global class by its name.
247 # Return null if not class match this name
248 meth global_class_named(n: Symbol): MMGlobalClass
249 do
250 if _global_class_by_name.has_key(n) then
251 return _global_class_by_name[n]
252 else
253 return null
254 end
255 end
256
257 redef meth to_s do return name.to_s
258
259 # Assign super_classes for a local class
260 meth set_supers_class(c: MMLocalClass, supers: Array[MMLocalClass])
261 do
262 assert supers != null
263 var tab = _class_specialization_hierarchy.select_smallests(supers)
264 c._cshe = _class_specialization_hierarchy.add(c,tab)
265 var tab_all = c.crhe.direct_greaters.to_a
266 tab_all.add_all(tab)
267 context.add_local_class(c,tab_all)
268 end
269
270 # Register a local class and its global class in the module
271 private meth register_global_class(c: MMLocalClass)
272 do
273 assert c.global != null
274 _local_class_by_global[c.global] = c
275 end
276 end
277
278 class MMGlobalClass
279 # The introducing local class
280 readable attr _intro: MMLocalClass
281
282 # Class refinement hierarchy
283 # It is not the real hierarchy since non concrete classes can only be leaves
284 readable attr _class_refinement_hierarchy: PartialOrder[MMLocalClass] = new PartialOrder[MMLocalClass]
285
286 # Create a new global class introduced with a given local class
287 init(c: MMLocalClass)
288 do
289 _intro = c
290 c.context.add_global_class(self)
291 end
292
293 # The name of the global class
294 meth name: Symbol
295 do
296 return intro.name
297 end
298
299 # The module that introduces the global class
300 meth module: MMModule
301 do
302 return intro.module
303 end
304
305 redef meth to_s
306 do
307 return intro.to_s
308 end
309
310 # register a new Local class to local class hierarchy (set the crhe value)
311 private meth register_local_class(c: MMLocalClass)
312 do
313 assert c.module != null
314 assert c.crhe == null
315 var sup = new Array[MMLocalClass]
316 for s in class_refinement_hierarchy do
317 if c.module.mhe < s.module and s isa MMConcreteClass then
318 sup.add(s)
319 end
320 end
321 c._crhe = _class_refinement_hierarchy.add(c, sup)
322 end
323
324 # Is the global class an interface?
325 readable writable attr _is_interface: Bool
326
327 # Is the global class an abstract class?
328 readable writable attr _is_abstract: Bool
329
330 # Is the global class a universal class?
331 readable writable attr _is_universal: Bool
332
333 # Visibility of the global class
334 # 1 -> public
335 # 3 -> private
336 readable writable attr _visibility_level: Int
337 end
338
339 # Local classes are classes defined, refined or imported in a module
340 class MMLocalClass
341 # The name of the local class
342 readable attr _name: Symbol
343
344 # Arity of the local class (if generic)
345 # FIXME: How to move this into the generic module in a sane way?
346 readable attr _arity : Int
347
348 # The module of the local class
349 readable attr _module: MMModule
350
351 # Is the class abstract
352 readable writable attr _abstract: Bool
353
354 # The global class of the local class
355 readable attr _global: MMGlobalClass
356
357 # The local class refinement hierarchy element
358 readable attr _crhe: PartialOrderElement[MMLocalClass]
359
360 # The local class specialization hierarchy element
361 readable attr _cshe: PartialOrderElement[MMLocalClass]
362
363 # The local class full hierarchy element
364 readable attr _che: PartialOrderElement[MMLocalClass]
365
366 # Association between local properties and global properties
367 readable attr _local_property_by_global: Map[MMGlobalProperty, MMLocalProperty]
368
369 # All known global properties
370 readable attr _global_properties: Set[MMGlobalProperty]
371
372 # Dictionnary of global properties
373 readable attr _properties_by_name: Map[Symbol, Array[MMGlobalProperty]]
374
375 # Create a new class with a given name and arity
376 protected init(name: Symbol, arity: Int)
377 do
378 _name = name
379 _arity = arity
380 end
381
382 # The corresponding local class in another module
383 meth for_module(m: MMModule): MMLocalClass
384 do
385 return m[global]
386 end
387
388 # Introduce a new global class to a new global one and register to hierarchy with no refine
389 meth new_global
390 do
391 var g = new MMGlobalClass(self)
392 _module._global_classes.add(g)
393 _module._global_class_by_name[name] = g
394 set_global(g)
395 end
396
397 # Associate this local class to a global one and register to hierarchy
398 # the global class for this class
399 # refined classes for this class
400 meth set_global(g: MMGlobalClass)
401 do
402 assert g != null
403 _global = g
404 _global.register_local_class(self)
405 _module.register_global_class(self)
406 end
407
408 # Is there a global propery with a given name
409 # TODO: Will disapear when qualified names will be available
410 meth has_global_property_by_name(n: Symbol): Bool
411 do
412 var props = _properties_by_name[n]
413 return props != null
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 var props = _properties_by_name[n]
421 if props == null or props.length > 1 then
422 return null
423 end
424 return props.first
425 end
426
427 # Get a attribute by its name
428 # TODO: Will disapear when qualified names will be available
429 meth attribute(a: Symbol): MMGlobalProperty
430 do
431 return get_property_by_name(a)
432 end
433
434 # Get a method by its name
435 # TODO: Will disapear when qualified names will be available
436 meth method(na: Symbol): MMGlobalProperty
437 do
438 assert _properties_by_name != null
439 var props = _properties_by_name[na]
440 if props != null then
441 return props.first
442 end
443
444 return null
445 end
446
447 # Look in super-classes (by specialization) and return properties with name
448 # Beware, global property of results is not intended to be the same
449 meth super_methods_named(n: Symbol): Array[MMLocalProperty]
450 do
451 var classes = new Array[MMLocalClass]
452 for c in cshe.greaters do
453 var g = c.method(n)
454 if g == null then continue
455 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 meth register_local_property(p: MMLocalProperty)
469 do
470 assert p.global != null
471 # FIXME: Why a test?
472 if not _local_property_by_global.has_key(p.global) then
473 _local_property_by_global[p.global] = p
474 end
475 end
476
477 # Register a global property and associate it with its name
478 meth register_global_property(glob: MMGlobalProperty)
479 do
480 var prop = glob.intro
481 var name = prop.name
482 var props = _properties_by_name[name]
483 if props == null then
484 _properties_by_name[name] = [glob]
485 else
486 _properties_by_name[name].add(glob)
487 end
488 _global_properties.add(glob)
489 register_local_property(prop)
490 end
491
492 # Get a local proprty by its global property
493 meth [](glob: MMGlobalProperty): MMLocalProperty
494 do
495 assert _local_property_by_global != null
496 assert glob != null
497 if _local_property_by_global.has_key(glob) then
498 return _local_property_by_global[glob]
499 end
500 return null
501 end
502
503 # The current MMContext
504 meth context: MMContext do return module.context
505
506 redef meth to_s
507 do
508 return _name.to_s
509 end
510 end
511
512 # A global property gather local properties that correspond to a same message
513 class MMGlobalProperty
514 # The local property for each class that has the global property
515
516 # The introducing local property
517 readable attr _intro: MMConcreteProperty
518
519 # The local class that introduces the global property
520 meth local_class: MMLocalClass
521 do
522 return intro.local_class
523 end
524
525 # The concrete property redefinition hierarchy
526 readable attr _concrete_property_hierarchy: PartialOrder[MMConcreteProperty] = new PartialOrder[MMConcreteProperty]
527
528 # Create a new global property introduced by a local one
529 protected init(p: MMConcreteProperty)
530 do
531 assert p != null
532 assert p.concrete_property != null
533
534 _concrete_property_hierarchy = new PartialOrder[MMConcreteProperty]
535
536 _intro = p
537 add_concrete_property(p, new Array[MMConcreteProperty])
538 end
539
540 redef meth to_s do return intro.full_name
541
542 # Register a new concrete property
543 meth add_concrete_property(i: MMConcreteProperty, sup: Array[MMConcreteProperty])
544 do
545 assert i != null
546 assert sup != null
547 i._cprhe = _concrete_property_hierarchy.add(i,sup)
548 end
549
550 # Is the global property an attribute ?
551 meth is_attribute: Bool do return intro isa MMAttribute
552
553 # Is the global property a method (or a constructor)?
554 meth is_method: Bool do return intro isa MMMethod
555
556 # Is the global property a constructor (thus also a method)?
557 readable writable attr _is_init: Bool
558
559 # Visibility of the property
560 # 1 -> public
561 # 2 -> protected
562 # 3 -> private
563 readable writable attr _visibility_level: Int
564 end
565
566 # Local properties are adaptation of concrete local properties
567 # They can be adapted for inheritance (or importation) or for type variarion (genericity, etc.)
568 class MMLocalProperty
569 # The name of the property
570 readable attr _name: Symbol
571
572 # The local class who own the local property
573 readable attr _local_class: MMLocalClass
574
575 # The global property where belong the local property
576 readable attr _global: MMGlobalProperty
577
578 # The original property where self is derived
579 # May be null if self is an original one
580 readable attr _super_prop: MMLocalProperty
581
582 # The concrete property
583 # May be self if self is a concrete property
584 readable attr _concrete_property: MMConcreteProperty
585
586 # The module of the local property
587 meth module: MMModule do return _local_class.module
588
589 # Full expanded name with all qualifications
590 meth full_name: String
591 do
592 if global == null then
593 return "{local_class.module}::{local_class}::(?::{name})"
594 else if global.intro == self then
595 return "{local_class.module}::{local_class}::{name}"
596 else
597 return "{local_class.module}::{local_class}::({global.intro.full_name})"
598 end
599 end
600
601 # set the global property for this property
602 meth set_global(g: MMGlobalProperty)
603 do
604 assert g != null
605 _global = g
606 _local_class.register_local_property(self)
607 end
608
609 redef meth to_s do return name.to_s
610
611 protected init(n: Symbol, bc: MMLocalClass, i: MMConcreteProperty)
612 do
613 _name = n
614 _local_class = bc
615 _concrete_property = i
616 end
617 end
618
619 # Attribute local properties
620 class MMAttribute
621 special MMLocalProperty
622 end
623
624 # Method local properties
625 class MMMethod
626 special MMLocalProperty
627 end
628
629 # Concrete local classes
630 class MMConcreteClass
631 special MMLocalClass
632 end
633
634 # Concrete local properties
635 class MMConcreteProperty
636 special MMLocalProperty
637 # Redefinition hierarchy of the concrete property
638 readable attr _cprhe: PartialOrderElement[MMConcreteProperty]
639
640 # Is the concrete property contain a `super' in the body?
641 readable writable attr _need_super: Bool
642
643 # Introduce a new global property for this local one
644 meth new_global
645 do
646 assert _global == null
647 _global = new MMGlobalProperty(self)
648 _local_class.register_global_property(_global)
649 end
650 end
651