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