model: add basic closures
[nit.git] / src / model / model.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Object model of the Nit language
18 #
19 # This module define the entities of the Nit meta-model like modules,
20 # classes, types and properties
21 #
22 # It also provide an API to build and query models.
23 #
24 # All model classes starts with the M letter (MModule, MClass, etc.)
25 #
26 # TODO: better doc
27 #
28 # TODO: liearization, closures, extern stuff
29 # FIXME: better handling of the types
30 module model
31
32 import poset
33 import location
34 import model_base
35
36 redef class Model
37 # All known classes
38 var mclasses: Array[MClass] = new Array[MClass]
39
40 # All known properties
41 var mproperties: Array[MProperty] = new Array[MProperty]
42
43 # Hierarchy of class definition.
44 #
45 # Each classdef is associated with its super-classdefs in regard to
46 # its module of definition.
47 var mclassdef_hierarchy: POSet[MClassDef] = new POSet[MClassDef]
48
49 # Class-type hierarchy restricted to the introduction.
50 #
51 # The idea is that what is true on introduction is always true whatever
52 # the module considered.
53 # Therefore, this hierarchy is used for a fast positive subtype check.
54 #
55 # This poset will evolve in a monotonous way:
56 # * Two non connected nodes will remain unconnected
57 # * New nodes can appear with new edges
58 private var intro_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
59
60 # Global overlapped class-type hierarchy.
61 # The hierarchy when all modules are combined.
62 # Therefore, this hierarchy is used for a fast negative subtype check.
63 #
64 # This poset will evolve in an anarchic way. Loops can even be created.
65 #
66 # FIXME decide what to do on loops
67 private var full_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
68
69 # Collections of classes grouped by their short name
70 private var mclasses_by_name: MultiHashMap[String, MClass] = new MultiHashMap[String, MClass]
71
72 # Return all class named `name'.
73 #
74 # If such a class does not exist, null is returned
75 # (instead of an empty array)
76 #
77 # Visibility or modules are not considered
78 fun get_mclasses_by_name(name: String): nullable Array[MClass]
79 do
80 if mclasses_by_name.has_key(name) then
81 return mclasses_by_name[name]
82 else
83 return null
84 end
85 end
86
87 # Collections of properties grouped by their short name
88 private var mproperties_by_name: MultiHashMap[String, MProperty] = new MultiHashMap[String, MProperty]
89
90 # Return all properties named `name'.
91 #
92 # If such a property does not exist, null is returned
93 # (instead of an empty array)
94 #
95 # Visibility or modules are not considered
96 fun get_mproperties_by_name(name: String): nullable Array[MProperty]
97 do
98 if not mproperties_by_name.has_key(name) then
99 return null
100 else
101 return mproperties_by_name[name]
102 end
103 end
104
105 # The only null type
106 var null_type: MNullType = new MNullType(self)
107 end
108
109 redef class MModule
110 # All the classes introduced in the module
111 var intro_mclasses: Array[MClass] = new Array[MClass]
112
113 # All the class definitions of the module
114 # (introduction and refinement)
115 var mclassdefs: Array[MClassDef] = new Array[MClassDef]
116
117 # Does the current module has a given class `mclass'?
118 # Return true if the mmodule introduces, refines or imports a class.
119 # Visibility is not considered.
120 fun has_mclass(mclass: MClass): Bool
121 do
122 return self.in_importation <= mclass.intro_mmodule
123 end
124
125 # Full hierarchy of introduced ans imported classes.
126 #
127 # Create a new hierarchy got by flattening the classes for the module
128 # and its imported modules.
129 # Visibility is not considered.
130 #
131 # Note: this function is expensive and is usually used for the main
132 # module of a program only. Do not use it to do you own subtype
133 # functions.
134 fun flatten_mclass_hierarchy: POSet[MClass]
135 do
136 var res = self.flatten_mclass_hierarchy_cache
137 if res != null then return res
138 res = new POSet[MClass]
139 for m in self.in_importation.greaters do
140 for cd in m.mclassdefs do
141 var c = cd.mclass
142 for s in cd.supertypes do
143 res.add_edge(c, s.mclass)
144 end
145 end
146 end
147 self.flatten_mclass_hierarchy_cache = res
148 return res
149 end
150
151 private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null
152
153 # The primitive type Object, the root of the class hierarchy
154 fun object_type: MClassType
155 do
156 var res = self.object_type_cache
157 if res != null then return res
158 res = self.get_primitive_class("Object").mclass_type
159 self.object_type_cache = res
160 return res
161 end
162
163 private var object_type_cache: nullable MClassType
164
165 # The primitive type Bool
166 fun bool_type: MClassType
167 do
168 var res = self.bool_type_cache
169 if res != null then return res
170 res = self.get_primitive_class("Bool").mclass_type
171 self.bool_type_cache = res
172 return res
173 end
174
175 private var bool_type_cache: nullable MClassType
176
177 # The primitive type Sys, the main type of the program, if any
178 fun sys_type: nullable MClassType
179 do
180 var clas = self.model.get_mclasses_by_name("Sys")
181 if clas == null then return null
182 return get_primitive_class("Sys").mclass_type
183 end
184
185 # Force to get the primitive class named `name' or abort
186 fun get_primitive_class(name: String): MClass
187 do
188 var cla = self.model.get_mclasses_by_name(name)
189 if cla == null then
190 if name == "Bool" then
191 var c = new MClass(self, name, 0, enum_kind, public_visibility)
192 var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
193 return c
194 end
195 print("Fatal Error: no primitive class {name}")
196 abort
197 end
198 assert cla.length == 1 else print cla.join(", ")
199 return cla.first
200 end
201
202 # Try to get the primitive method named `name' on the type `recv'
203 fun try_get_primitive_method(name: String, recv: MType): nullable MMethod
204 do
205 var props = self.model.get_mproperties_by_name(name)
206 if props == null then return null
207 var res: nullable MMethod = null
208 for mprop in props do
209 assert mprop isa MMethod
210 if not recv.has_mproperty(self, mprop) then continue
211 if res == null then
212 res = mprop
213 else
214 print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
215 abort
216 end
217 end
218 return res
219 end
220
221 # Force to get the primitive method named `name' on the type `recv' or abort
222 fun force_get_primitive_method(name: String, recv: MType): MMethod
223 do
224 var res = try_get_primitive_method(name, recv)
225 if res == null then
226 print("Fatal Error: no primitive property {name} on {recv}")
227 abort
228 end
229 return res
230 end
231 end
232
233 # A named class
234 #
235 # MClass are global to the model; it means that a MClass is not bound to a
236 # specific `MModule`.
237 #
238 # This characteristic helps the reasoning about classes in a program since a
239 # single MClass object always denote the same class.
240 # However, because a MClass is global, it does not really have properties nor
241 # belong to a hierarchy since the property and the
242 # hierarchy of a class depends of a module.
243 class MClass
244 # The module that introduce the class
245 # While classes are not bound to a specific module,
246 # the introducing module is used for naming an visibility
247 var intro_mmodule: MModule
248
249 # The short name of the class
250 # In Nit, the name of a class cannot evolve in refinements
251 var name: String
252
253 # The canonical name of the class
254 # Example: "owner::module::MyClass"
255 fun full_name: String
256 do
257 return "{self.intro_mmodule.full_name}::{name}"
258 end
259
260 # The number of generic formal parameters
261 # 0 if the class is not generic
262 var arity: Int
263
264 # The kind of the class (interface, abstract class, etc.)
265 # In Nit, the kind of a class cannot evolve in refinements
266 var kind: MClassKind
267
268 # The visibility of the class
269 # In Nit, the visibility of a class cannot evolve in refinements
270 var visibility: MVisibility
271
272 init(intro_mmodule: MModule, name: String, arity: Int, kind: MClassKind, visibility: MVisibility)
273 do
274 self.intro_mmodule = intro_mmodule
275 self.name = name
276 self.arity = arity
277 self.kind = kind
278 self.visibility = visibility
279 intro_mmodule.intro_mclasses.add(self)
280 var model = intro_mmodule.model
281 model.mclasses_by_name.add_one(name, self)
282 model.mclasses.add(self)
283
284 # Create the formal parameter types
285 if arity > 0 then
286 var mparametertypes = new Array[MParameterType]
287 for i in [0..arity[ do
288 var mparametertype = new MParameterType(self, i)
289 mparametertypes.add(mparametertype)
290 end
291 var mclass_type = new MGenericType(self, mparametertypes)
292 self.mclass_type = mclass_type
293 self.get_mtype_cache.add(mclass_type)
294 else
295 self.mclass_type = new MClassType(self)
296 end
297 end
298
299 # All class definitions (introduction and refinements)
300 var mclassdefs: Array[MClassDef] = new Array[MClassDef]
301
302 # Alias for `name'
303 redef fun to_s do return self.name
304
305 # The definition that introduced the class
306 # Warning: the introduction is the first `MClassDef' object associated
307 # to self. If self is just created without having any associated
308 # definition, this method will abort
309 private fun intro: MClassDef
310 do
311 assert has_a_first_definition: not mclassdefs.is_empty
312 return mclassdefs.first
313 end
314
315 # The principal static type of the class.
316 #
317 # For non-generic class, mclass_type is the only MClassType based
318 # on self.
319 #
320 # For a generic class, the arguments are the formal parameters.
321 # i.e.: for the class `Array[E:Object]', the mtype is Array[E].
322 # If you want `Array[Object]' the see `MClassDef::bound_mtype'
323 #
324 # For generic classes, the mclass_type is also the way to get a formal
325 # generic parameter type.
326 #
327 # To get other types based on a generic class, see `get_mtype'.
328 #
329 # ENSURE: mclass_type.mclass == self
330 var mclass_type: MClassType
331
332 # Return a generic type based on the class
333 # Is the class is not generic, then the result is `mclass_type'
334 #
335 # REQUIRE: type_arguments.length == self.arity
336 fun get_mtype(mtype_arguments: Array[MType]): MClassType
337 do
338 assert mtype_arguments.length == self.arity
339 if self.arity == 0 then return self.mclass_type
340 for t in self.get_mtype_cache do
341 if t.arguments == mtype_arguments then
342 return t
343 end
344 end
345 var res = new MGenericType(self, mtype_arguments)
346 self.get_mtype_cache.add res
347 return res
348 end
349
350 private var get_mtype_cache: Array[MGenericType] = new Array[MGenericType]
351 end
352
353
354 # A definition (an introduction or a refinement) of a class in a module
355 #
356 # A MClassDef is associated with an explicit (or almost) definition of a
357 # class. Unlike MClass, a MClassDef is a local definition that belong to
358 # a specific module
359 class MClassDef
360 # The module where the definition is
361 var mmodule: MModule
362
363 # The associated MClass
364 var mclass: MClass
365
366 # The bounded type associated to the mclassdef
367 #
368 # For a non-generic class, `bound_mtype' and `mclass.mclass_type'
369 # are the same type.
370 #
371 # Example:
372 # For the classdef Array[E: Object], the bound_mtype is Array[Object].
373 # If you want Array[E], then see `mclass.mclass_type'
374 #
375 # ENSURE: bound_mtype.mclass = self.mclass
376 var bound_mtype: MClassType
377
378 # Name of each formal generic parameter (in order of declaration)
379 var parameter_names: Array[String]
380
381 # The origin of the definition
382 var location: Location
383
384 # Internal name combining the module and the class
385 # Example: "mymodule#MyClass"
386 redef fun to_s do return "{mmodule}#{mclass}"
387
388 init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
389 do
390 assert bound_mtype.mclass.arity == parameter_names.length
391 self.bound_mtype = bound_mtype
392 self.mmodule = mmodule
393 self.mclass = bound_mtype.mclass
394 self.location = location
395 mmodule.mclassdefs.add(self)
396 mclass.mclassdefs.add(self)
397 self.parameter_names = parameter_names
398 end
399
400 # All declared super-types
401 # FIXME: quite ugly but not better idea yet
402 var supertypes: Array[MClassType] = new Array[MClassType]
403
404 # Register the super-types for the class (ie "super SomeType")
405 # This function can only invoked once by class
406 fun set_supertypes(supertypes: Array[MClassType])
407 do
408 assert unique_invocation: self.in_hierarchy == null
409 var mmodule = self.mmodule
410 var model = mmodule.model
411 var res = model.mclassdef_hierarchy.add_node(self)
412 self.in_hierarchy = res
413 var mtype = self.bound_mtype
414
415 for supertype in supertypes do
416 self.supertypes.add(supertype)
417
418 # Register in full_type_specialization_hierarchy
419 model.full_mtype_specialization_hierarchy.add_edge(mtype, supertype)
420 # Register in intro_type_specialization_hierarchy
421 if mclass.intro_mmodule == mmodule and supertype.mclass.intro_mmodule == mmodule then
422 model.intro_mtype_specialization_hierarchy.add_edge(mtype, supertype)
423 end
424 end
425
426 for mclassdef in mtype.collect_mclassdefs(mmodule) do
427 res.poset.add_edge(self, mclassdef)
428 end
429 end
430
431 # The view of the class definition in `mclassdef_hierarchy'
432 var in_hierarchy: nullable POSetElement[MClassDef] = null
433
434 # Is the definition the one that introduced `mclass`?
435 fun is_intro: Bool do return mclass.intro == self
436
437 # All properties introduced by the classdef
438 var intro_mproperties: Array[MProperty] = new Array[MProperty]
439
440 # All property definitions in the class (introductions and redefinitions)
441 var mpropdefs: Array[MPropDef] = new Array[MPropDef]
442 end
443
444 # A global static type
445 #
446 # MType are global to the model; it means that a MType is not bound to a
447 # specific `MModule`.
448 # This characteristic helps the reasoning about static types in a program
449 # since a single MType object always denote the same type.
450 #
451 # However, because a MType is global, it does not really have properties
452 # nor have subtypes to a hierarchy since the property and the class hierarchy
453 # depends of a module.
454 # Moreover, virtual types an formal generic parameter types also depends on
455 # a receiver to have sense.
456 #
457 # Therefore, most method of the types require a module and an anchor.
458 # The module is used to know what are the classes and the specialization
459 # links.
460 # The anchor is used to know what is the bound of the virtual types and formal
461 # generic parameter types.
462 #
463 # MType are not directly usable to get properties. See the `anchor_to' method
464 # and the `MClassType' class.
465 #
466 # FIXME: the order of the parameters is not the best. We mus pick on from:
467 # * foo(mmodule, anchor, othertype)
468 # * foo(othertype, anchor, mmodule)
469 # * foo(anchor, mmodule, othertype)
470 # * foo(othertype, mmodule, anchor)
471 #
472 # FIXME: Add a 'is_valid_anchor' to improve imputability.
473 # Currently, anchors are used "as it" without check thus if the caller gives a
474 # bad anchor, then the method will likely crash (abort) in a bad case
475 #
476 # FIXME: maybe allways add an anchor with a nullable type (as in is_subtype)
477 abstract class MType
478
479 # The model of the type
480 fun model: Model is abstract
481
482 # Return true if `self' is an subtype of `sup'.
483 # The typing is done using the standard typing policy of Nit.
484 #
485 # REQUIRE: anchor == null implies not self.need_anchor and not sup.need_anchor
486 fun is_subtype(mmodule: MModule, anchor: nullable MClassType, sup: MType): Bool
487 do
488 var sub = self
489 if sub == sup then return true
490 if anchor == null then
491 assert not sub.need_anchor
492 assert not sup.need_anchor
493 end
494 # First, resolve the types
495 if sub isa MParameterType or sub isa MVirtualType then
496 assert anchor != null
497 sub = sub.resolve_for(anchor, anchor, mmodule, false)
498 end
499 if sup isa MParameterType or sup isa MVirtualType then
500 assert anchor != null
501 sup = sup.resolve_for(anchor, anchor, mmodule, false)
502 end
503
504 if sup isa MParameterType or sup isa MVirtualType or sup isa MNullType then
505 return sub == sup
506 end
507 if sub isa MParameterType or sub isa MVirtualType then
508 assert anchor != null
509 sub = sub.anchor_to(mmodule, anchor)
510 end
511 if sup isa MNullableType then
512 if sub isa MNullType then
513 return true
514 else if sub isa MNullableType then
515 return sub.mtype.is_subtype(mmodule, anchor, sup.mtype)
516 else if sub isa MClassType then
517 return sub.is_subtype(mmodule, anchor, sup.mtype)
518 else
519 abort
520 end
521 end
522
523 assert sup isa MClassType # It is the only remaining type
524 if sub isa MNullableType or sub isa MNullType then
525 return false
526 end
527
528 if sub == sup then return true
529
530 assert sub isa MClassType # It is the only remaining type
531 if anchor == null then anchor = sub # UGLY: any anchor will work
532 var resolved_sub = sub.anchor_to(mmodule, anchor)
533 var res = resolved_sub.collect_mclasses(mmodule).has(sup.mclass)
534 if res == false then return false
535 if not sup isa MGenericType then return true
536 var sub2 = sub.supertype_to(mmodule, anchor, sup.mclass)
537 assert sub2.mclass == sup.mclass
538 assert sub2 isa MGenericType
539 for i in [0..sup.mclass.arity[ do
540 var sub_arg = sub2.arguments[i]
541 var sup_arg = sup.arguments[i]
542 res = sub_arg.is_subtype(mmodule, anchor, sup_arg)
543 if res == false then return false
544 end
545 return true
546 end
547
548 # The base class type on which self is based
549 #
550 # This base type is used to get property (an internally to perform
551 # unsafe type comparison).
552 #
553 # Beware: some types (like null) are not based on a class thus this
554 # method will crash
555 #
556 # Basically, this function transform the virtual types and parameter
557 # types to their bounds.
558 #
559 # Example
560 # class G[T: A]
561 # type U: X
562 # end
563 # class H
564 # super G[C]
565 # redef type U: Y
566 # end
567 # Map[T,U] anchor_to H #-> Map[C,Y]
568 #
569 # Explanation of the example:
570 # In H, T is set to C, because "H super G[C]", and U is bound to Y,
571 # because "redef type U: Y". Therefore, Map[T, U] is bound to
572 # Map[C, Y]
573 #
574 # ENSURE: not self.need_anchor implies return == self
575 # ENSURE: not return.need_anchor
576 fun anchor_to(mmodule: MModule, anchor: MClassType): MType
577 do
578 if not need_anchor then return self
579 assert not anchor.need_anchor
580 # Just resolve to the anchor and clear all the virtual types
581 var res = self.resolve_for(anchor, anchor, mmodule, true)
582 assert not res.need_anchor
583 return res
584 end
585
586 # Does `self' contain a virtual type or a formal generic parameter type?
587 # In order to remove those types, you usually want to use `anchor_to'.
588 fun need_anchor: Bool do return true
589
590 # Return the supertype when adapted to a class.
591 #
592 # In Nit, for each super-class of a type, there is a equivalent super-type.
593 #
594 # Example:
595 # class G[T, U]
596 # class H[V] super G[V, Bool]
597 # H[Int] supertype_to G #-> G[Int, Bool]
598 #
599 # REQUIRE: `super_mclass' is a super-class of `self'
600 # ENSURE: return.mclass = mclass
601 fun supertype_to(mmodule: MModule, anchor: MClassType, super_mclass: MClass): MClassType
602 do
603 if super_mclass.arity == 0 then return super_mclass.mclass_type
604 if self isa MClassType and self.mclass == super_mclass then return self
605 var resolved_self = self.anchor_to(mmodule, anchor)
606 var supertypes = resolved_self.collect_mtypes(mmodule)
607 for supertype in supertypes do
608 if supertype.mclass == super_mclass then
609 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
610 return supertype.resolve_for(self, anchor, mmodule, false)
611 end
612 end
613 abort
614 end
615
616 # Replace formals generic types in self with resolved values in `mtype'
617 # If `cleanup_virtual' is true, then virtual types are also replaced
618 # with their bounds
619 #
620 # This function returns self if `need_anchor' is false.
621 #
622 # Example:
623 # class G[E]
624 # class H[F] super G[F]
625 # Array[E] resolve_for H[Int] #-> Array[Int]
626 #
627 # Explanation of the example:
628 # * Array[E].need_anchor is true because there is a formal generic
629 # parameter type E
630 # * E makes sense for H[Int] because E is a formal parameter of G
631 # and H specialize G
632 # * Since "H[F] super G[F]", E is in fact F for H
633 # * More specifically, in H[Int], E is Int
634 # * So, in H[Int], Array[E] is Array[Int]
635 #
636 # This function is mainly used to inherit a signature.
637 # Because, unlike `anchor_type', we do not want a full resolution of
638 # a type but only an adapted version of it.
639 #
640 # Example:
641 # class A[E]
642 # foo(e:E):E
643 # end
644 # class B super A[Int] end
645 #
646 # The signature on foo is (e: E): E
647 # If we resolve the signature for B, we get (e:Int):Int
648 #
649 # TODO: Explain the cleanup_virtual
650 #
651 # FIXME: the parameter `cleanup_virtual' is just a bad idea, but having
652 # two function instead of one seems also to be a bad idea.
653 #
654 # ENSURE: not self.need_anchor implies return == self
655 fun resolve_for(mtype: MType, anchor: MClassType, mmodule: MModule, cleanup_virtual: Bool): MType is abstract
656
657 # Return the nullable version of the type
658 # If the type is already nullable then self is returned
659 #
660 # FIXME: DO NOT WORK YET
661 fun as_nullable: MType
662 do
663 var res = self.as_nullable_cache
664 if res != null then return res
665 res = new MNullableType(self)
666 self.as_nullable_cache = res
667 return res
668 end
669
670 private var as_nullable_cache: nullable MType = null
671
672 # Compute all the classdefs inherited/imported.
673 # The returned set contains:
674 # * the class definitions from `mmodule` and its imported modules
675 # * the class definitions of this type and its super-types
676 #
677 # This function is used mainly internally.
678 #
679 # REQUIRE: not self.need_anchor
680 fun collect_mclassdefs(mmodule: MModule): Set[MClassDef] is abstract
681
682 # Compute all the super-classes.
683 # This function is used mainly internally.
684 #
685 # REQUIRE: not self.need_anchor
686 fun collect_mclasses(mmodule: MModule): Set[MClass] is abstract
687
688 # Compute all the declared super-types.
689 # Super-types are returned as declared in the classdefs (verbatim).
690 # This function is used mainly internally.
691 #
692 # REQUIRE: not self.need_anchor
693 fun collect_mtypes(mmodule: MModule): Set[MClassType] is abstract
694
695 # Is the property in self for a given module
696 # This method does not filter visibility or whatever
697 #
698 # REQUIRE: not self.need_anchor
699 fun has_mproperty(mmodule: MModule, mproperty: MProperty): Bool
700 do
701 assert not self.need_anchor
702 return self.collect_mclassdefs(mmodule).has(mproperty.intro_mclassdef)
703 end
704 end
705
706 # A type based on a class.
707 #
708 # MClassType have properties (see `has_property').
709 class MClassType
710 super MType
711
712 # The associated class
713 var mclass: MClass
714
715 redef fun model do return self.mclass.intro_mmodule.model
716
717 private init(mclass: MClass)
718 do
719 self.mclass = mclass
720 end
721
722 redef fun to_s do return mclass.to_s
723
724 redef fun need_anchor do return false
725
726 redef fun anchor_to(mmodule: MModule, anchor: MClassType): MClassType
727 do
728 return super.as(MClassType)
729 end
730
731 redef fun resolve_for(mtype: MType, anchor: MClassType, mmodule: MModule, cleanup_virtual: Bool): MClassType do return self
732
733 redef fun collect_mclassdefs(mmodule)
734 do
735 assert not self.need_anchor
736 var cache = self.collect_mclassdefs_cache
737 if not cache.has_key(mmodule) then
738 self.collect_things(mmodule)
739 end
740 return cache[mmodule]
741 end
742
743 redef fun collect_mclasses(mmodule)
744 do
745 assert not self.need_anchor
746 var cache = self.collect_mclasses_cache
747 if not cache.has_key(mmodule) then
748 self.collect_things(mmodule)
749 end
750 return cache[mmodule]
751 end
752
753 redef fun collect_mtypes(mmodule)
754 do
755 assert not self.need_anchor
756 var cache = self.collect_mtypes_cache
757 if not cache.has_key(mmodule) then
758 self.collect_things(mmodule)
759 end
760 return cache[mmodule]
761 end
762
763 # common implementation for `collect_mclassdefs', `collect_mclasses', and `collect_mtypes'.
764 private fun collect_things(mmodule: MModule)
765 do
766 var res = new HashSet[MClassDef]
767 var seen = new HashSet[MClass]
768 var types = new HashSet[MClassType]
769 seen.add(self.mclass)
770 var todo = [self.mclass]
771 while not todo.is_empty do
772 var mclass = todo.pop
773 #print "process {mclass}"
774 for mclassdef in mclass.mclassdefs do
775 if not mmodule.in_importation <= mclassdef.mmodule then continue
776 #print " process {mclassdef}"
777 res.add(mclassdef)
778 for supertype in mclassdef.supertypes do
779 types.add(supertype)
780 var superclass = supertype.mclass
781 if seen.has(superclass) then continue
782 #print " add {superclass}"
783 seen.add(superclass)
784 todo.add(superclass)
785 end
786 end
787 end
788 collect_mclassdefs_cache[mmodule] = res
789 collect_mclasses_cache[mmodule] = seen
790 collect_mtypes_cache[mmodule] = types
791 end
792
793 private var collect_mclassdefs_cache: HashMap[MModule, Set[MClassDef]] = new HashMap[MModule, Set[MClassDef]]
794 private var collect_mclasses_cache: HashMap[MModule, Set[MClass]] = new HashMap[MModule, Set[MClass]]
795 private var collect_mtypes_cache: HashMap[MModule, Set[MClassType]] = new HashMap[MModule, Set[MClassType]]
796
797 end
798
799 # A type based on a generic class.
800 # A generic type a just a class with additional formal generic arguments.
801 class MGenericType
802 super MClassType
803
804 private init(mclass: MClass, arguments: Array[MType])
805 do
806 super(mclass)
807 assert self.mclass.arity == arguments.length
808 self.arguments = arguments
809
810 self.need_anchor = false
811 for t in arguments do
812 if t.need_anchor then
813 self.need_anchor = true
814 break
815 end
816 end
817 end
818
819 # The formal arguments of the type
820 # ENSURE: return.length == self.mclass.arity
821 var arguments: Array[MType]
822
823 # Recursively print the type of the arguments within brackets.
824 # Example: "Map[String,List[Int]]"
825 redef fun to_s
826 do
827 return "{mclass}[{arguments.join(",")}]"
828 end
829
830 redef var need_anchor: Bool
831
832 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
833 do
834 if not need_anchor then return self
835 var types = new Array[MType]
836 for t in arguments do
837 types.add(t.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
838 end
839 return mclass.get_mtype(types)
840 end
841 end
842
843 # A virtual formal type.
844 class MVirtualType
845 super MType
846
847 # The property associated with the type.
848 # Its the definitions of this property that determine the bound or the virtual type.
849 var mproperty: MProperty
850
851 redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
852
853 # Lookup the bound for a given resolved_receiver
854 # The result may be a other virtual type (or a parameter type)
855 #
856 # The result is returned exactly as declared in the "type" property (verbatim).
857 #
858 # In case of conflict, the method aborts.
859 fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
860 do
861 assert not resolved_receiver.need_anchor
862 var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
863 if props.is_empty then
864 abort
865 else if props.length == 1 then
866 return props.first.as(MVirtualTypeDef).bound.as(not null)
867 end
868 var types = new ArraySet[MType]
869 for p in props do
870 types.add(p.as(MVirtualTypeDef).bound.as(not null))
871 end
872 if types.length == 1 then
873 return types.first
874 end
875 abort
876 end
877
878 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
879 do
880 if not cleanup_virtual then return self
881 # self is a virtual type declared (or inherited) in mtype
882 # The point of the function it to get the bound of the virtual type that make sense for mtype
883 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
884 #print "{class_name}: {self}/{mtype}/{anchor}?"
885 var resolved_reciever = mtype.resolve_for(anchor, anchor, mmodule, true)
886 # Now, we can get the bound
887 var verbatim_bound = lookup_bound(mmodule, resolved_reciever)
888 # The bound is exactly as declared in the "type" property, so we must resolve it again
889 var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, true)
890 #print "{class_name}: {self}/{mtype}/{anchor} -> {self}/{resolved_reciever}/{anchor} -> {verbatim_bound}/{mtype}/{anchor} -> {res}"
891 return res
892 end
893
894 redef fun to_s do return self.mproperty.to_s
895
896 init(mproperty: MProperty)
897 do
898 self.mproperty = mproperty
899 end
900 end
901
902 # The type associated the a formal parameter generic type of a class
903 #
904 # Each parameter type is associated to a specific class.
905 # It's mean that all refinements of a same class "share" the parameter type,
906 # but that a generic subclass has its on parameter types.
907 #
908 # However, in the sense of the meta-model, the a parameter type of a class is
909 # a valid types in a subclass. The "in the sense of the meta-model" is
910 # important because, in the Nit language, the programmer cannot refers
911 # directly to the parameter types of the super-classes.
912 #
913 # Example:
914 # class A[E]
915 # fun e: E is abstract
916 # end
917 # class B[F]
918 # super A[Array[F]]
919 # end
920 # In the class definition B[F], `F' is a valid type but `E' is not.
921 # However, `self.e' is a valid method call, and the signature of `e' is
922 # declared `e: E'.
923 #
924 # Note that parameter types are shared among class refinements.
925 # Therefore parameter only have an internal name (see `to_s' for details).
926 # TODO: Add a 'name_for' to get better messages.
927 class MParameterType
928 super MType
929
930 # The generic class where the parameter belong
931 var mclass: MClass
932
933 redef fun model do return self.mclass.intro_mmodule.model
934
935 # The position of the parameter (0 for the first parameter)
936 # FIXME: is `position' a better name?
937 var rank: Int
938
939 # Internal name of the parameter type
940 # Names of parameter types changes in each class definition
941 # Therefore, this method return an internal name.
942 # Example: return "G#1" for the second parameter of the class G
943 # FIXME: add a way to get the real name in a classdef
944 redef fun to_s do return "{mclass}#{rank}"
945
946 # Resolve the bound for a given resolved_receiver
947 # The result may be a other virtual type (or a parameter type)
948 fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
949 do
950 assert not resolved_receiver.need_anchor
951 var goalclass = self.mclass
952 var supertypes = resolved_receiver.collect_mtypes(mmodule)
953 for t in supertypes do
954 if t.mclass == goalclass then
955 # Yeah! c specialize goalclass with a "super `t'". So the question is what is the argument of f
956 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
957 assert t isa MGenericType
958 var res = t.arguments[self.rank]
959 return res
960 end
961 end
962 abort
963 end
964
965 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
966 do
967 #print "{class_name}: {self}/{mtype}/{anchor}?"
968
969 if mtype isa MGenericType and mtype.mclass == self.mclass then
970 return mtype.arguments[self.rank]
971 end
972
973 # self is a parameter type of mtype (or of a super-class of mtype)
974 # The point of the function it to get the bound of the virtual type that make sense for mtype
975 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
976 # FIXME: What happend here is far from clear. Thus this part must be validated and clarified
977 var resolved_receiver = mtype.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, true)
978 if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
979 if resolved_receiver isa MParameterType then
980 assert resolved_receiver.mclass == anchor.mclass
981 resolved_receiver = anchor.as(MGenericType).arguments[resolved_receiver.rank]
982 if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
983 end
984 assert resolved_receiver isa MClassType else print "{class_name}: {self}/{mtype}/{anchor}? {resolved_receiver}"
985
986 # Eh! The parameter is in the current class.
987 # So we return the corresponding argument, no mater what!
988 if resolved_receiver.mclass == self.mclass then
989 assert resolved_receiver isa MGenericType
990 var res = resolved_receiver.arguments[self.rank]
991 #print "{class_name}: {self}/{mtype}/{anchor} -> direct {res}"
992 return res
993 end
994
995 resolved_receiver = resolved_receiver.resolve_for(anchor, anchor, mmodule, false)
996 # Now, we can get the bound
997 var verbatim_bound = lookup_bound(mmodule, resolved_receiver)
998 # The bound is exactly as declared in the "type" property, so we must resolve it again
999 var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1000
1001 #print "{class_name}: {self}/{mtype}/{anchor} -> indirect {res}"
1002
1003 return res
1004 end
1005
1006 init(mclass: MClass, rank: Int)
1007 do
1008 self.mclass = mclass
1009 self.rank = rank
1010 end
1011 end
1012
1013 # A type prefixed with "nullable"
1014 # FIXME Stub implementation
1015 class MNullableType
1016 super MType
1017
1018 # The base type of the nullable type
1019 var mtype: MType
1020
1021 redef fun model do return self.mtype.model
1022
1023 init(mtype: MType)
1024 do
1025 self.mtype = mtype
1026 end
1027
1028 redef fun to_s do return "nullable {mtype}"
1029
1030 redef fun need_anchor do return mtype.need_anchor
1031 redef fun as_nullable do return self
1032 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1033 do
1034 var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1035 return res.as_nullable
1036 end
1037
1038 redef fun collect_mclassdefs(mmodule)
1039 do
1040 assert not self.need_anchor
1041 return self.mtype.collect_mclassdefs(mmodule)
1042 end
1043
1044 redef fun collect_mclasses(mmodule)
1045 do
1046 assert not self.need_anchor
1047 return self.mtype.collect_mclasses(mmodule)
1048 end
1049
1050 redef fun collect_mtypes(mmodule)
1051 do
1052 assert not self.need_anchor
1053 return self.mtype.collect_mtypes(mmodule)
1054 end
1055 end
1056
1057 # The type of the only value null
1058 #
1059 # The is only one null type per model, see `MModel::null_type'.
1060 class MNullType
1061 super MType
1062 redef var model: Model
1063 protected init(model: Model)
1064 do
1065 self.model = model
1066 end
1067 redef fun to_s do return "null"
1068 redef fun as_nullable do return self
1069 redef fun need_anchor do return false
1070 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
1071
1072 redef fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef]
1073
1074 redef fun collect_mclasses(mmodule) do return new HashSet[MClass]
1075
1076 redef fun collect_mtypes(mmodule) do return new HashSet[MClassType]
1077 end
1078
1079 # A signature of a method (or a closure)
1080 class MSignature
1081 super MType
1082
1083 # The each parameter (in order)
1084 var mparameters: Array[MParameter]
1085
1086 var mclosures = new Array[MParameter]
1087
1088 # The return type (null for a procedure)
1089 var return_mtype: nullable MType
1090
1091 # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
1092 init(mparameters: Array[MParameter], return_mtype: nullable MType)
1093 do
1094 var vararg_rank = -1
1095 for i in [0..mparameters.length[ do
1096 var parameter = mparameters[i]
1097 if parameter.is_vararg then
1098 assert vararg_rank == -1
1099 vararg_rank = i
1100 end
1101 end
1102 self.mparameters = mparameters
1103 self.return_mtype = return_mtype
1104 self.vararg_rank = vararg_rank
1105 end
1106
1107 # The rank of the ellipsis (...) for vararg (starting from 0).
1108 # value is -1 if there is no vararg.
1109 # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
1110 var vararg_rank: Int
1111
1112 # The number or parameters
1113 fun arity: Int do return mparameters.length
1114
1115 redef fun to_s
1116 do
1117 var b = new Buffer
1118 if not mparameters.is_empty then
1119 b.append("(")
1120 for i in [0..mparameters.length[ do
1121 var mparameter = mparameters[i]
1122 if i > 0 then b.append(", ")
1123 b.append(mparameter.name)
1124 b.append(": ")
1125 b.append(mparameter.mtype.to_s)
1126 if mparameter.is_vararg then
1127 b.append("...")
1128 end
1129 end
1130 b.append(")")
1131 end
1132 var ret = self.return_mtype
1133 if ret != null then
1134 b.append(": ")
1135 b.append(ret.to_s)
1136 end
1137 return b.to_s
1138 end
1139
1140 redef fun resolve_for(mtype: MType, anchor: MClassType, mmodule: MModule, cleanup_virtual: Bool): MSignature
1141 do
1142 var params = new Array[MParameter]
1143 for p in self.mparameters do
1144 params.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1145 end
1146 var ret = self.return_mtype
1147 if ret != null then
1148 ret = ret.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1149 end
1150 var res = new MSignature(params, ret)
1151 for p in self.mclosures do
1152 res.mclosures.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1153 end
1154 return res
1155 end
1156 end
1157
1158 # A parameter in a signature
1159 class MParameter
1160 # The name of the parameter
1161 var name: String
1162
1163 # The static type of the parameter
1164 var mtype: MType
1165
1166 # Is the parameter a vararg?
1167 var is_vararg: Bool
1168
1169 fun resolve_for(mtype: MType, anchor: MClassType, mmodule: MModule, cleanup_virtual: Bool): MParameter
1170 do
1171 if not self.mtype.need_anchor then return self
1172 var newtype = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1173 var res = new MParameter(self.name, newtype, self.is_vararg)
1174 return res
1175 end
1176 end
1177
1178 # A service (global property) that generalize method, attribute, etc.
1179 #
1180 # MProperty are global to the model; it means that a MProperty is not bound
1181 # to a specific `MModule` nor a specific `MClass`.
1182 #
1183 # A MProperty gather definitions (see `mpropdefs') ; one for the introduction
1184 # and the other in subclasses and in refinements.
1185 #
1186 # A MProperty is used to denotes services in polymorphic way (ie. independent
1187 # of any dynamic type).
1188 # For instance, a call site "x.foo" is associated to a MProperty.
1189 abstract class MProperty
1190 # The associated MPropDef subclass.
1191 # The two specialization hierarchy are symmetric.
1192 type MPROPDEF: MPropDef
1193
1194 # The classdef that introduce the property
1195 # While a property is not bound to a specific module, or class,
1196 # the introducing mclassdef is used for naming and visibility
1197 var intro_mclassdef: MClassDef
1198
1199 # The (short) name of the property
1200 var name: String
1201
1202 # The canonical name of the property
1203 # Example: "owner::my_module::MyClass::my_method"
1204 fun full_name: String
1205 do
1206 return "{self.intro_mclassdef.mmodule.full_name}::{self.intro_mclassdef.mclass.name}::{name}"
1207 end
1208
1209 # The visibility of the property
1210 var visibility: MVisibility
1211
1212 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1213 do
1214 self.intro_mclassdef = intro_mclassdef
1215 self.name = name
1216 self.visibility = visibility
1217 intro_mclassdef.intro_mproperties.add(self)
1218 var model = intro_mclassdef.mmodule.model
1219 model.mproperties_by_name.add_one(name, self)
1220 model.mproperties.add(self)
1221 end
1222
1223 # All definitions of the property.
1224 # The first is the introduction,
1225 # The other are redefinitions (in refinements and in subclasses)
1226 var mpropdefs: Array[MPROPDEF] = new Array[MPROPDEF]
1227
1228 # The definition that introduced the property
1229 # Warning: the introduction is the first `MPropDef' object
1230 # associated to self. If self is just created without having any
1231 # associated definition, this method will abort
1232 fun intro: MPROPDEF do return mpropdefs.first
1233
1234 # Alias for `name'
1235 redef fun to_s do return name
1236
1237 # Return the most specific property definitions defined or inherited by a type.
1238 # The selection knows that refinement is stronger than specialization;
1239 # however, in case of conflict more than one property are returned.
1240 # If mtype does not know mproperty then an empty array is returned.
1241 #
1242 # If you want the really most specific property, then look at `lookup_first_definition`
1243 fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
1244 do
1245 assert not mtype.need_anchor
1246 if mtype isa MNullableType then mtype = mtype.mtype
1247
1248 var cache = self.lookup_definitions_cache[mmodule, mtype]
1249 if cache != null then return cache
1250
1251 #print "select prop {mproperty} for {mtype} in {self}"
1252 # First, select all candidates
1253 var candidates = new Array[MPROPDEF]
1254 for mpropdef in self.mpropdefs do
1255 # If the definition is not imported by the module, then skip
1256 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1257 # If the definition is not inherited by the type, then skip
1258 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1259 # Else, we keep it
1260 candidates.add(mpropdef)
1261 end
1262 # Fast track for only one candidate
1263 if candidates.length <= 1 then
1264 self.lookup_definitions_cache[mmodule, mtype] = candidates
1265 return candidates
1266 end
1267
1268 # Second, filter the most specific ones
1269 var res = new Array[MPROPDEF]
1270 for pd1 in candidates do
1271 var cd1 = pd1.mclassdef
1272 var c1 = cd1.mclass
1273 var keep = true
1274 for pd2 in candidates do
1275 if pd2 == pd1 then continue # do not compare with self!
1276 var cd2 = pd2.mclassdef
1277 var c2 = cd2.mclass
1278 if c2.mclass_type == c1.mclass_type then
1279 if cd2.mmodule.in_importation <= cd1.mmodule then
1280 # cd2 refines cd1; therefore we skip pd1
1281 keep = false
1282 break
1283 end
1284 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1285 # cd2 < cd1; therefore we skip pd1
1286 keep = false
1287 break
1288 end
1289 end
1290 if keep then
1291 res.add(pd1)
1292 end
1293 end
1294 if res.is_empty then
1295 print "All lost! {candidates.join(", ")}"
1296 # FIXME: should be abort!
1297 end
1298 self.lookup_definitions_cache[mmodule, mtype] = res
1299 return res
1300 end
1301
1302 private var lookup_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
1303
1304 # Return the most specific property definitions inherited by a type.
1305 # The selection knows that refinement is stronger than specialization;
1306 # however, in case of conflict more than one property are returned.
1307 # If mtype does not know mproperty then an empty array is returned.
1308 #
1309 # If you want the really most specific property, then look at `lookup_next_definition`
1310 #
1311 # FIXME: Move to MPropDef?
1312 fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPropDef]
1313 do
1314 assert not mtype.need_anchor
1315 if mtype isa MNullableType then mtype = mtype.mtype
1316
1317 # First, select all candidates
1318 var candidates = new Array[MPropDef]
1319 for mpropdef in self.mpropdefs do
1320 # If the definition is not imported by the module, then skip
1321 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1322 # If the definition is not inherited by the type, then skip
1323 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1324 # If the definition is defined by the type, then skip (we want the super, so e skip the current)
1325 if mtype == mpropdef.mclassdef.bound_mtype and mmodule == mpropdef.mclassdef.mmodule then continue
1326 # Else, we keep it
1327 candidates.add(mpropdef)
1328 end
1329 # Fast track for only one candidate
1330 if candidates.length <= 1 then return candidates
1331
1332 # Second, filter the most specific ones
1333 var res = new Array[MPropDef]
1334 for pd1 in candidates do
1335 var cd1 = pd1.mclassdef
1336 var c1 = cd1.mclass
1337 var keep = true
1338 for pd2 in candidates do
1339 if pd2 == pd1 then continue # do not compare with self!
1340 var cd2 = pd2.mclassdef
1341 var c2 = cd2.mclass
1342 if c2.mclass_type == c1.mclass_type then
1343 if cd2.mmodule.in_importation <= cd1.mmodule then
1344 # cd2 refines cd1; therefore we skip pd1
1345 keep = false
1346 break
1347 end
1348 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1349 # cd2 < cd1; therefore we skip pd1
1350 keep = false
1351 break
1352 end
1353 end
1354 if keep then
1355 res.add(pd1)
1356 end
1357 end
1358 if res.is_empty then
1359 print "All lost! {candidates.join(", ")}"
1360 # FIXME: should be abort!
1361 end
1362 return res
1363 end
1364
1365 # Return the most specific definition in the linearization of `mtype`.
1366 # If mtype does not know mproperty then null is returned.
1367 #
1368 # If you want to know the next properties in the linearization,
1369 # look at `MPropDef::lookup_next_definition`.
1370 #
1371 # FIXME: NOT YET IMPLEMENTED
1372 #
1373 # REQUIRE: not mtype.need_anchor
1374 fun lookup_first_definition(mmodule: MModule, mtype: MType): nullable MPROPDEF
1375 do
1376 assert not mtype.need_anchor
1377 return null
1378 end
1379 end
1380
1381 # A global method
1382 class MMethod
1383 super MProperty
1384
1385 redef type MPROPDEF: MMethodDef
1386
1387 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1388 do
1389 super
1390 end
1391
1392 # Is the property a constructor?
1393 # Warning, this property can be inherited by subclasses with or without being a constructor
1394 # therefore, you should use `is_init_for' the verify if the property is a legal constructor for a given class
1395 var is_init: Bool writable = false
1396
1397 # The the property a 'new' contructor?
1398 var is_new: Bool writable = false
1399
1400 # Is the property a legal constructor for a given class?
1401 # As usual, visibility is not considered.
1402 # FIXME not implemented
1403 fun is_init_for(mclass: MClass): Bool
1404 do
1405 return self.is_init
1406 end
1407 end
1408
1409 # A global attribute
1410 class MAttribute
1411 super MProperty
1412
1413 redef type MPROPDEF: MAttributeDef
1414
1415 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1416 do
1417 super
1418 end
1419 end
1420
1421 # A global virtual type
1422 class MVirtualTypeProp
1423 super MProperty
1424
1425 redef type MPROPDEF: MVirtualTypeDef
1426
1427 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1428 do
1429 super
1430 end
1431
1432 # The formal type associated to the virtual type property
1433 var mvirtualtype: MVirtualType = new MVirtualType(self)
1434 end
1435
1436 # A definition of a property (local property)
1437 #
1438 # Unlike MProperty, a MPropDef is a local definition that belong to a
1439 # specific class definition (which belong to a specific module)
1440 abstract class MPropDef
1441
1442 # The associated MProperty subclass.
1443 # the two specialization hierarchy are symmetric
1444 type MPROPERTY: MProperty
1445
1446 # Self class
1447 type MPROPDEF: MPropDef
1448
1449 # The origin of the definition
1450 var location: Location
1451
1452 # The class definition where the property definition is
1453 var mclassdef: MClassDef
1454
1455 # The associated global property
1456 var mproperty: MPROPERTY
1457
1458 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1459 do
1460 self.mclassdef = mclassdef
1461 self.mproperty = mproperty
1462 self.location = location
1463 mclassdef.mpropdefs.add(self)
1464 mproperty.mpropdefs.add(self)
1465 end
1466
1467 # Internal name combining the module, the class and the property
1468 # Example: "mymodule#MyClass#mymethod"
1469 redef fun to_s
1470 do
1471 return "{mclassdef}#{mproperty}"
1472 end
1473
1474 # Is self the definition that introduce the property?
1475 fun is_intro: Bool do return mproperty.intro == self
1476
1477 # Return the next definition in linearization of `mtype`.
1478 # If there is no next method then null is returned.
1479 #
1480 # This method is used to determine what method is called by a super.
1481 #
1482 # FIXME: NOT YET IMPLEMENTED
1483 #
1484 # REQUIRE: not mtype.need_anchor
1485 fun lookup_next_definition(mmodule: MModule, mtype: MType): nullable MPROPDEF
1486 do
1487 assert not mtype.need_anchor
1488 return null
1489 end
1490 end
1491
1492 # A local definition of a method
1493 class MMethodDef
1494 super MPropDef
1495
1496 redef type MPROPERTY: MMethod
1497 redef type MPROPDEF: MMethodDef
1498
1499 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1500 do
1501 super
1502 end
1503
1504 # The signature attached to the property definition
1505 var msignature: nullable MSignature writable = null
1506 end
1507
1508 # A local definition of an attribute
1509 class MAttributeDef
1510 super MPropDef
1511
1512 redef type MPROPERTY: MAttribute
1513 redef type MPROPDEF: MAttributeDef
1514
1515 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1516 do
1517 super
1518 end
1519
1520 # The static type of the attribute
1521 var static_mtype: nullable MType writable = null
1522 end
1523
1524 # A local definition of a virtual type
1525 class MVirtualTypeDef
1526 super MPropDef
1527
1528 redef type MPROPERTY: MVirtualTypeProp
1529 redef type MPROPDEF: MVirtualTypeDef
1530
1531 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1532 do
1533 super
1534 end
1535
1536 # The bound of the virtual type
1537 var bound: nullable MType writable = null
1538 end
1539
1540 # A kind of class.
1541 #
1542 # * abstract_kind
1543 # * concrete_kind
1544 # * interface_kind
1545 # * enum_kind
1546 # * extern_kind
1547 #
1548 # Note this class is basically an enum.
1549 # FIXME: use a real enum once user-defined enums are available
1550 class MClassKind
1551 redef var to_s: String
1552
1553 # Is a constructor required?
1554 var need_init: Bool
1555 private init(s: String, need_init: Bool)
1556 do
1557 self.to_s = s
1558 self.need_init = need_init
1559 end
1560 end
1561
1562 fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true)
1563 fun concrete_kind: MClassKind do return once new MClassKind("class", true)
1564 fun interface_kind: MClassKind do return once new MClassKind("interface", false)
1565 fun enum_kind: MClassKind do return once new MClassKind("enum", false)
1566 fun extern_kind: MClassKind do return once new MClassKind("extern", false)