01fffc249bc8db24d74f4d054050277c44bd59d4
[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 module abstractmetamodel
20
21 import partial_order
22 import location
23 import symbol
24
25 # The main singleton which knows everything
26 abstract class MMContext
27
28 init do end
29
30 # The module dependence hierarchy
31 readable var _module_hierarchy: PartialOrder[MMModule] = new PartialOrder[MMModule]
32
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]
36
37 # All known global classes
38 var _global_classes: Array[MMGlobalClass] = new Array[MMGlobalClass]
39
40 # All known modules
41 readable var _modules: Array[MMModule] = new Array[MMModule]
42
43 # Register a new module with the modules it depends on
44 fun add_module(mod: MMModule, supers: Array[MMModule])
45 do
46 _module_hierarchy.add(mod, _module_hierarchy.select_smallests(supers))
47 _modules.add(mod)
48 mod._mhe = _module_hierarchy[mod]
49 end
50
51 # Register a global class
52 private fun add_global_class(c: MMGlobalClass) do _global_classes.add(c)
53
54 # Register a local class
55 fun add_local_class(c: MMLocalClass, sup: Array[MMLocalClass])
56 do
57 var csup = new Array[MMLocalClass]
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(mod: MMModule)
93 do
94 assert not _modules.has_key(mod.name)
95 _modules[mod.name] = mod
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 file
111 abstract 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: Set[MMGlobalClass] = new HashSet[MMGlobalClass]
132
133 # All local classes of the module (defined and imported)
134 readable var _local_classes: Set[MMLocalClass] = new HashSet[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 # 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
161
162 # Uses foreign function interface
163 fun uses_ffi : Bool is abstract
164
165 protected init(name: Symbol, dir: MMDirectory, context: MMContext, loc: Location)
166 do
167 _name = name
168 _directory = dir
169 _context = context
170 _full_name = dir.full_name_for(name)
171 _location = loc
172 end
173
174 # Register that a module is imported with a visibility
175 # 0 -> intrude
176 # 1 -> public
177 # 3 -> private
178 fun add_super_module(m: MMModule, visibility_level: Int)
179 do
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)
190 else
191 _private_modules.add(m)
192 _private_modules.add_all(m._intrude_modules)
193 _private_modules.add_all(m._public_modules)
194 end
195
196 end
197
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
204 do
205 if m == self or _intrude_modules.has(m) then
206 return 3
207 else if _public_modules.has(m) then
208 return 2
209 else if _private_modules.has(m) then
210 return 1
211 else
212 return 0
213 end
214 end
215
216
217 # Get the local class associated with a global class
218 fun [](c: MMGlobalClass): MMLocalClass
219 do
220 return _local_class_by_global[c]
221 end
222
223 # Get a local class by its name
224 fun class_by_name(n: Symbol): MMLocalClass
225 do
226 return self[_global_class_by_name[n]]
227 end
228
229 # Is there a global class with this name
230 fun has_global_class_named(n: Symbol): Bool
231 do
232 return _global_class_by_name.has_key(n)
233 end
234
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
238 do
239 return _global_class_by_name[n]
240 end
241
242 redef fun to_s do return name.to_s
243
244 # Assign super_classes for a local class
245 fun set_supers_class(c: MMLocalClass, supers: Array[MMLocalClass])
246 do
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
250 tab_all.add_all(tab)
251 context.add_local_class(c,tab_all)
252 end
253
254 # Register a local class and its global class in the module
255 private fun register_global_class(c: MMLocalClass)
256 do
257 _local_class_by_global[c.global] = c
258 end
259 end
260
261 class MMGlobalClass
262 # The introducing local class
263 readable var _intro: MMLocalClass
264
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]
268
269 # Create a new global class introduced with a given local class
270 init(c: MMLocalClass)
271 do
272 _intro = c
273 c.context.add_global_class(self)
274 end
275
276 # The name of the global class
277 fun name: Symbol
278 do
279 return intro.name
280 end
281
282 # The module that introduces the global class
283 fun mmmodule: MMModule
284 do
285 return intro.mmmodule
286 end
287
288 redef fun to_s
289 do
290 return intro.to_s
291 end
292
293 # register a new Local class to local class hierarchy (set the crhe value)
294 private fun register_local_class(c: MMLocalClass)
295 do
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
299 sup.add(s)
300 end
301 end
302 c._crhe = _class_refinement_hierarchy.add(c, sup)
303 end
304
305 # Is the global class an interface?
306 readable writable var _is_interface: Bool = false
307
308 # Is the global class an abstract class?
309 readable writable var _is_abstract: Bool = false
310
311 # Is the global class a enum class?
312 readable writable var _is_enum: Bool = false
313
314 # Is the global class an extern class?
315 readable writable var _is_extern: Bool = false
316
317 # Visibility of the global class
318 # 1 -> public
319 # 3 -> private
320 readable writable var _visibility_level: Int = 1 # FIXME: why this should be defined ?
321
322 # Is the global class a mixin class?
323 # A mixin class inherits all constructors from a superclass
324 fun is_mixin: Bool
325 do
326 return _mixin_of != self
327 end
328
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
333
334 end
335
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
340
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
344
345 # The module of the local class
346 readable var _mmmodule: MMModule
347
348 # The global class of the local class
349 fun global: MMGlobalClass do return _global.as(not null)
350 var _global: nullable MMGlobalClass
351
352 # The local class refinement hierarchy element
353 fun crhe: PartialOrderElement[MMLocalClass] do return _crhe.as(not null)
354 var _crhe: nullable PartialOrderElement[MMLocalClass]
355
356 # The local class specialization hierarchy element
357 fun cshe: PartialOrderElement[MMLocalClass] do return _cshe.as(not null)
358 var _cshe: nullable PartialOrderElement[MMLocalClass]
359
360 # The local class full hierarchy element
361 fun che: PartialOrderElement[MMLocalClass] do return _che.as(not null)
362 var _che: nullable PartialOrderElement[MMLocalClass]
363
364 # Association between local properties and global properties
365 var _local_property_by_global: Map[MMGlobalProperty, MMLocalProperty] = new HashMap[MMGlobalProperty, MMLocalProperty]
366
367 # All known global properties
368 readable var _global_properties: Set[MMGlobalProperty] = new HashSet[MMGlobalProperty]
369
370 # All locally defined local properties
371 readable var _local_local_properties: Set[MMLocalProperty] = new HashSet[MMLocalProperty]
372
373 # Dictionnary of global properties
374 var _properties_by_name: Map[Symbol, Array[MMGlobalProperty]] = new HashMap[Symbol, Array[MMGlobalProperty]]
375
376 # Create a new class with a given name and arity
377 protected init(mod: MMModule, name: Symbol, arity: Int)
378 do
379 _mmmodule = mod
380 _name = name
381 _arity = arity
382 mod._local_classes.add(self)
383 end
384
385 # The corresponding local class in another module
386 fun for_module(m: MMModule): MMLocalClass
387 do
388 return m[global]
389 end
390
391 # Introduce a new global class to a new global one and register to hierarchy with no refine
392 fun new_global
393 do
394 var g = new MMGlobalClass(self)
395 _mmmodule._global_classes.add(g)
396 _mmmodule._global_class_by_name[name] = g
397 set_global(g)
398 end
399
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)
404 do
405 _global = g
406 _global.register_local_class(self)
407 _mmmodule.register_global_class(self)
408 end
409
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
413 do
414 return _properties_by_name.has_key(n) and _properties_by_name[n].length == 1
415 end
416
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
420 do
421 if not has_global_property_by_name(n) then abort
422 var props = _properties_by_name[n]
423 return props.first
424 end
425
426 # Get a attribute by its name
427 # TODO: Will disapear when qualified names will be available
428 fun attribute(a: Symbol): MMGlobalProperty
429 do
430 return get_property_by_name(a)
431 end
432
433 # Get a method by its name
434 # TODO: Will disapear when qualified names will be available
435 fun method(na: Symbol): MMGlobalProperty
436 do
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 fun select_method(name: Symbol): MMMethod
443 do
444 var gp = method(name)
445 var res = self[gp]
446 assert res isa MMMethod
447 return res
448 end
449
450 # Select an attribute from its name
451 # TODO: Will disapear when qualified names will be available
452 fun select_attribute(name: Symbol): MMAttribute
453 do
454 var gp = attribute(name)
455 var res = self[gp]
456 assert res isa MMAttribute
457 return res
458 end
459
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]
463 do
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)
467 end
468 classes = cshe.order.select_smallests(classes)
469 var res = new Array[MMLocalProperty]
470 for c in classes do
471 var g = c.method(n)
472 #print "found {c[g].full_name}"
473 res.add(c[g])
474 end
475 return res
476 end
477
478 # Register a local property and associate it with its global property
479 fun register_local_property(p: MMLocalProperty)
480 do
481 _local_property_by_global[p.global] = p
482 if p.local_class == self then
483 _local_local_properties.add(p)
484 end
485 end
486
487 # Register a global property and associate it with its name
488 fun register_global_property(glob: MMGlobalProperty)
489 do
490 var prop = glob.intro
491 var name = prop.name
492 if _properties_by_name.has_key(name) then
493 _properties_by_name[name].add(glob)
494 else
495 _properties_by_name[name] = [glob]
496 end
497 _global_properties.add(glob)
498 register_local_property(prop)
499 end
500
501 # Does the global property belong to the class?
502 fun has_global_property(glob: MMGlobalProperty): Bool
503 do
504 return _global_properties.has(glob)
505 end
506
507 # Get a local property by its global property
508 fun [](glob: MMGlobalProperty): MMLocalProperty
509 do
510 return _local_property_by_global[glob]
511 end
512
513 # The current MMContext
514 fun context: MMContext do return mmmodule.context
515
516 redef fun to_s
517 do
518 return _name.to_s
519 end
520
521 # Comparaison in a total order that superset the class refinement and the class specialisation relations
522 fun total_order_compare(b: MMLocalClass): Int
523 do
524 var a = self
525 if a == b then
526 return 0
527 else if a.mmmodule.mhe < b.mmmodule then
528 return 1
529 else if b.mmmodule.mhe < a.mmmodule then
530 return -1
531 end
532 var ar = a.cshe.rank
533 var br = b.cshe.rank
534 if ar > br then
535 return 1
536 else if br > ar then
537 return -1
538 else
539 return b.name.to_s <=> a.name.to_s
540 end
541 end
542 end
543
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
547
548 # The introducing local property
549 readable var _intro: MMLocalProperty
550
551 # The local class that introduces the global property
552 fun local_class: MMLocalClass
553 do
554 return intro.local_class
555 end
556
557 # The property redefinition hierarchy
558 readable var _property_hierarchy: PartialOrder[MMLocalProperty] = new PartialOrder[MMLocalProperty]
559
560 # Create a new global property introduced by a local one
561 protected init(p: MMLocalProperty)
562 do
563 _intro = p
564 add_local_property(p, new Array[MMLocalProperty])
565 end
566
567 redef fun to_s do return intro.full_name
568
569 # Register a new local property
570 fun add_local_property(i: MMLocalProperty, sup: Array[MMLocalProperty])
571 do
572 i._prhe = _property_hierarchy.add(i,sup)
573 end
574
575 # Is the global property an attribute ?
576 fun is_attribute: Bool do return intro isa MMAttribute
577
578 # Is the global property a method (or a constructor)?
579 fun is_method: Bool do return intro isa MMMethod
580
581 # Is the global property a constructor (thus also a method)?
582 readable writable var _is_init: Bool = false
583
584 # Is the global property a constructor for a given class?
585 fun is_init_for(c: MMLocalClass): Bool
586 do
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
590 return res
591 end
592
593 # Visibility of the property
594 # 1 -> public
595 # 2 -> protected
596 # 3 -> private
597 readable writable var _visibility_level: Int = 1 # FIXME: why this should be defined ?
598 end
599
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
604
605 # The local class who own the local property
606 readable var _local_class: MMLocalClass
607
608 # The global property where belong the local property
609 var _global: nullable MMGlobalProperty
610
611 fun global: MMGlobalProperty do return _global.as(not null)
612 fun is_global_set: Bool do return _global != null
613
614 # Redefinition hierarchy of the local property
615 var _prhe: nullable PartialOrderElement[MMLocalProperty]
616
617 fun prhe: PartialOrderElement[MMLocalProperty] do return _prhe.as(not null)
618
619 # The module of the local property
620 fun mmmodule: MMModule do return _local_class.mmmodule
621
622 # Full expanded name with all qualifications
623 fun full_name: String
624 do
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}"
629 else
630 return "{local_class.mmmodule}::{local_class}::({global.intro.full_name})"
631 end
632 end
633
634 # set the global property for this property
635 fun set_global(g: MMGlobalProperty)
636 do
637 _global = g
638 _local_class.register_local_property(self)
639 end
640
641 # Introduce a new global property for this local one
642 fun new_global
643 do
644 assert _global == null
645 var global = new MMGlobalProperty(self)
646 _global = global
647 _local_class.register_global_property(global)
648 end
649
650 redef fun to_s do return name.to_s
651
652 # Is the concrete property contain a `super' in the body?
653 readable writable var _need_super: Bool = false
654
655 protected init(n: Symbol, bc: MMLocalClass)
656 do
657 _name = n
658 _local_class = bc
659 end
660 end
661
662 # Attribute local properties
663 abstract class MMAttribute
664 super MMLocalProperty
665 end
666
667 class MMExplicitImport
668 var local_class : MMLocalClass
669 var method : MMMethod
670 end
671
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
677
678 # Is the method abstract
679 fun is_abstract: Bool is abstract
680
681 # Is the method extern
682 fun is_extern: Bool is abstract
683
684 # extern name when specified explicitly in nit code
685 fun extern_name: nullable String is abstract
686
687 # properties explicitly exported to native code
688 fun explicit_imports : Set[ MMExplicitImport ] is abstract
689 end
690
691 # Concrete local classes
692 abstract class MMConcreteClass
693 super MMLocalClass
694 end
695