deccc95f893b6ecab783201080420c550d582809
[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 names of each parameter (in order)
1084 var parameter_names: Array[String]
1085
1086 # The types of each parameter (in order)
1087 var parameter_mtypes: Array[MType]
1088
1089 # The return type (null for a procedure)
1090 var return_mtype: nullable MType
1091
1092 init(parameter_names: Array[String], parameter_mtypes: Array[MType], return_mtype: nullable MType, vararg_rank: Int)
1093 do
1094 self.parameter_names = parameter_names
1095 self.parameter_mtypes = parameter_mtypes
1096 self.return_mtype = return_mtype
1097 self.vararg_rank = vararg_rank
1098 end
1099
1100 # The rank of the ellipsis (...) for vararg (starting from 0).
1101 # value is -1 if there is no vararg.
1102 # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
1103 var vararg_rank: Int
1104
1105 # The number or parameters
1106 fun arity: Int do return parameter_mtypes.length
1107
1108 redef fun to_s
1109 do
1110 var b = new Buffer
1111 if not parameter_names.is_empty then
1112 b.append("(")
1113 for i in [0..parameter_names.length[ do
1114 if i > 0 then b.append(", ")
1115 b.append(parameter_names[i])
1116 b.append(": ")
1117 b.append(parameter_mtypes[i].to_s)
1118 if i == self.vararg_rank then
1119 b.append("...")
1120 end
1121 end
1122 b.append(")")
1123 end
1124 var ret = self.return_mtype
1125 if ret != null then
1126 b.append(": ")
1127 b.append(ret.to_s)
1128 end
1129 return b.to_s
1130 end
1131
1132 redef fun resolve_for(mtype: MType, anchor: MClassType, mmodule: MModule, cleanup_virtual: Bool): MSignature
1133 do
1134 var params = new Array[MType]
1135 for t in self.parameter_mtypes do
1136 params.add(t.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1137 end
1138 var ret = self.return_mtype
1139 if ret != null then
1140 ret = ret.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1141 end
1142 var res = new MSignature(self.parameter_names, params, ret, self.vararg_rank)
1143 return res
1144 end
1145 end
1146
1147 # A service (global property) that generalize method, attribute, etc.
1148 #
1149 # MProperty are global to the model; it means that a MProperty is not bound
1150 # to a specific `MModule` nor a specific `MClass`.
1151 #
1152 # A MProperty gather definitions (see `mpropdefs') ; one for the introduction
1153 # and the other in subclasses and in refinements.
1154 #
1155 # A MProperty is used to denotes services in polymorphic way (ie. independent
1156 # of any dynamic type).
1157 # For instance, a call site "x.foo" is associated to a MProperty.
1158 abstract class MProperty
1159 # The associated MPropDef subclass.
1160 # The two specialization hierarchy are symmetric.
1161 type MPROPDEF: MPropDef
1162
1163 # The classdef that introduce the property
1164 # While a property is not bound to a specific module, or class,
1165 # the introducing mclassdef is used for naming and visibility
1166 var intro_mclassdef: MClassDef
1167
1168 # The (short) name of the property
1169 var name: String
1170
1171 # The canonical name of the property
1172 # Example: "owner::my_module::MyClass::my_method"
1173 fun full_name: String
1174 do
1175 return "{self.intro_mclassdef.mmodule.full_name}::{self.intro_mclassdef.mclass.name}::{name}"
1176 end
1177
1178 # The visibility of the property
1179 var visibility: MVisibility
1180
1181 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1182 do
1183 self.intro_mclassdef = intro_mclassdef
1184 self.name = name
1185 self.visibility = visibility
1186 intro_mclassdef.intro_mproperties.add(self)
1187 var model = intro_mclassdef.mmodule.model
1188 model.mproperties_by_name.add_one(name, self)
1189 model.mproperties.add(self)
1190 end
1191
1192 # All definitions of the property.
1193 # The first is the introduction,
1194 # The other are redefinitions (in refinements and in subclasses)
1195 var mpropdefs: Array[MPROPDEF] = new Array[MPROPDEF]
1196
1197 # The definition that introduced the property
1198 # Warning: the introduction is the first `MPropDef' object
1199 # associated to self. If self is just created without having any
1200 # associated definition, this method will abort
1201 fun intro: MPROPDEF do return mpropdefs.first
1202
1203 # Alias for `name'
1204 redef fun to_s do return name
1205
1206 # Return the most specific property definitions defined or inherited by a type.
1207 # The selection knows that refinement is stronger than specialization;
1208 # however, in case of conflict more than one property are returned.
1209 # If mtype does not know mproperty then an empty array is returned.
1210 #
1211 # If you want the really most specific property, then look at `lookup_first_definition`
1212 fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
1213 do
1214 assert not mtype.need_anchor
1215 if mtype isa MNullableType then mtype = mtype.mtype
1216
1217 var cache = self.lookup_definitions_cache[mmodule, mtype]
1218 if cache != null then return cache
1219
1220 #print "select prop {mproperty} for {mtype} in {self}"
1221 # First, select all candidates
1222 var candidates = new Array[MPROPDEF]
1223 for mpropdef in self.mpropdefs do
1224 # If the definition is not imported by the module, then skip
1225 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1226 # If the definition is not inherited by the type, then skip
1227 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1228 # Else, we keep it
1229 candidates.add(mpropdef)
1230 end
1231 # Fast track for only one candidate
1232 if candidates.length <= 1 then
1233 self.lookup_definitions_cache[mmodule, mtype] = candidates
1234 return candidates
1235 end
1236
1237 # Second, filter the most specific ones
1238 var res = new Array[MPROPDEF]
1239 for pd1 in candidates do
1240 var cd1 = pd1.mclassdef
1241 var c1 = cd1.mclass
1242 var keep = true
1243 for pd2 in candidates do
1244 if pd2 == pd1 then continue # do not compare with self!
1245 var cd2 = pd2.mclassdef
1246 var c2 = cd2.mclass
1247 if c2.mclass_type == c1.mclass_type then
1248 if cd2.mmodule.in_importation <= cd1.mmodule then
1249 # cd2 refines cd1; therefore we skip pd1
1250 keep = false
1251 break
1252 end
1253 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1254 # cd2 < cd1; therefore we skip pd1
1255 keep = false
1256 break
1257 end
1258 end
1259 if keep then
1260 res.add(pd1)
1261 end
1262 end
1263 if res.is_empty then
1264 print "All lost! {candidates.join(", ")}"
1265 # FIXME: should be abort!
1266 end
1267 self.lookup_definitions_cache[mmodule, mtype] = res
1268 return res
1269 end
1270
1271 private var lookup_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
1272
1273 # Return the most specific property definitions inherited by a type.
1274 # The selection knows that refinement is stronger than specialization;
1275 # however, in case of conflict more than one property are returned.
1276 # If mtype does not know mproperty then an empty array is returned.
1277 #
1278 # If you want the really most specific property, then look at `lookup_next_definition`
1279 #
1280 # FIXME: Move to MPropDef?
1281 fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPropDef]
1282 do
1283 assert not mtype.need_anchor
1284 if mtype isa MNullableType then mtype = mtype.mtype
1285
1286 # First, select all candidates
1287 var candidates = new Array[MPropDef]
1288 for mpropdef in self.mpropdefs do
1289 # If the definition is not imported by the module, then skip
1290 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1291 # If the definition is not inherited by the type, then skip
1292 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1293 # If the definition is defined by the type, then skip (we want the super, so e skip the current)
1294 if mtype == mpropdef.mclassdef.bound_mtype and mmodule == mpropdef.mclassdef.mmodule then continue
1295 # Else, we keep it
1296 candidates.add(mpropdef)
1297 end
1298 # Fast track for only one candidate
1299 if candidates.length <= 1 then return candidates
1300
1301 # Second, filter the most specific ones
1302 var res = new Array[MPropDef]
1303 for pd1 in candidates do
1304 var cd1 = pd1.mclassdef
1305 var c1 = cd1.mclass
1306 var keep = true
1307 for pd2 in candidates do
1308 if pd2 == pd1 then continue # do not compare with self!
1309 var cd2 = pd2.mclassdef
1310 var c2 = cd2.mclass
1311 if c2.mclass_type == c1.mclass_type then
1312 if cd2.mmodule.in_importation <= cd1.mmodule then
1313 # cd2 refines cd1; therefore we skip pd1
1314 keep = false
1315 break
1316 end
1317 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1318 # cd2 < cd1; therefore we skip pd1
1319 keep = false
1320 break
1321 end
1322 end
1323 if keep then
1324 res.add(pd1)
1325 end
1326 end
1327 if res.is_empty then
1328 print "All lost! {candidates.join(", ")}"
1329 # FIXME: should be abort!
1330 end
1331 return res
1332 end
1333
1334 # Return the most specific definition in the linearization of `mtype`.
1335 # If mtype does not know mproperty then null is returned.
1336 #
1337 # If you want to know the next properties in the linearization,
1338 # look at `MPropDef::lookup_next_definition`.
1339 #
1340 # FIXME: NOT YET IMPLEMENTED
1341 #
1342 # REQUIRE: not mtype.need_anchor
1343 fun lookup_first_definition(mmodule: MModule, mtype: MType): nullable MPROPDEF
1344 do
1345 assert not mtype.need_anchor
1346 return null
1347 end
1348 end
1349
1350 # A global method
1351 class MMethod
1352 super MProperty
1353
1354 redef type MPROPDEF: MMethodDef
1355
1356 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1357 do
1358 super
1359 end
1360
1361 # Is the property a constructor?
1362 # Warning, this property can be inherited by subclasses with or without being a constructor
1363 # therefore, you should use `is_init_for' the verify if the property is a legal constructor for a given class
1364 var is_init: Bool writable = false
1365
1366 # The the property a 'new' contructor?
1367 var is_new: Bool writable = false
1368
1369 # Is the property a legal constructor for a given class?
1370 # As usual, visibility is not considered.
1371 # FIXME not implemented
1372 fun is_init_for(mclass: MClass): Bool
1373 do
1374 return self.is_init
1375 end
1376 end
1377
1378 # A global attribute
1379 class MAttribute
1380 super MProperty
1381
1382 redef type MPROPDEF: MAttributeDef
1383
1384 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1385 do
1386 super
1387 end
1388 end
1389
1390 # A global virtual type
1391 class MVirtualTypeProp
1392 super MProperty
1393
1394 redef type MPROPDEF: MVirtualTypeDef
1395
1396 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1397 do
1398 super
1399 end
1400
1401 # The formal type associated to the virtual type property
1402 var mvirtualtype: MVirtualType = new MVirtualType(self)
1403 end
1404
1405 # A definition of a property (local property)
1406 #
1407 # Unlike MProperty, a MPropDef is a local definition that belong to a
1408 # specific class definition (which belong to a specific module)
1409 abstract class MPropDef
1410
1411 # The associated MProperty subclass.
1412 # the two specialization hierarchy are symmetric
1413 type MPROPERTY: MProperty
1414
1415 # Self class
1416 type MPROPDEF: MPropDef
1417
1418 # The origin of the definition
1419 var location: Location
1420
1421 # The class definition where the property definition is
1422 var mclassdef: MClassDef
1423
1424 # The associated global property
1425 var mproperty: MPROPERTY
1426
1427 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1428 do
1429 self.mclassdef = mclassdef
1430 self.mproperty = mproperty
1431 self.location = location
1432 mclassdef.mpropdefs.add(self)
1433 mproperty.mpropdefs.add(self)
1434 end
1435
1436 # Internal name combining the module, the class and the property
1437 # Example: "mymodule#MyClass#mymethod"
1438 redef fun to_s
1439 do
1440 return "{mclassdef}#{mproperty}"
1441 end
1442
1443 # Is self the definition that introduce the property?
1444 fun is_intro: Bool do return mproperty.intro == self
1445
1446 # Return the next definition in linearization of `mtype`.
1447 # If there is no next method then null is returned.
1448 #
1449 # This method is used to determine what method is called by a super.
1450 #
1451 # FIXME: NOT YET IMPLEMENTED
1452 #
1453 # REQUIRE: not mtype.need_anchor
1454 fun lookup_next_definition(mmodule: MModule, mtype: MType): nullable MPROPDEF
1455 do
1456 assert not mtype.need_anchor
1457 return null
1458 end
1459 end
1460
1461 # A local definition of a method
1462 class MMethodDef
1463 super MPropDef
1464
1465 redef type MPROPERTY: MMethod
1466 redef type MPROPDEF: MMethodDef
1467
1468 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1469 do
1470 super
1471 end
1472
1473 # The signature attached to the property definition
1474 var msignature: nullable MSignature writable = null
1475 end
1476
1477 # A local definition of an attribute
1478 class MAttributeDef
1479 super MPropDef
1480
1481 redef type MPROPERTY: MAttribute
1482 redef type MPROPDEF: MAttributeDef
1483
1484 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1485 do
1486 super
1487 end
1488
1489 # The static type of the attribute
1490 var static_mtype: nullable MType writable = null
1491 end
1492
1493 # A local definition of a virtual type
1494 class MVirtualTypeDef
1495 super MPropDef
1496
1497 redef type MPROPERTY: MVirtualTypeProp
1498 redef type MPROPDEF: MVirtualTypeDef
1499
1500 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1501 do
1502 super
1503 end
1504
1505 # The bound of the virtual type
1506 var bound: nullable MType writable = null
1507 end
1508
1509 # A kind of class.
1510 #
1511 # * abstract_kind
1512 # * concrete_kind
1513 # * interface_kind
1514 # * enum_kind
1515 # * extern_kind
1516 #
1517 # Note this class is basically an enum.
1518 # FIXME: use a real enum once user-defined enums are available
1519 class MClassKind
1520 redef var to_s: String
1521
1522 # Is a constructor required?
1523 var need_init: Bool
1524 private init(s: String, need_init: Bool)
1525 do
1526 self.to_s = s
1527 self.need_init = need_init
1528 end
1529 end
1530
1531 fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true)
1532 fun concrete_kind: MClassKind do return once new MClassKind("class", true)
1533 fun interface_kind: MClassKind do return once new MClassKind("interface", false)
1534 fun enum_kind: MClassKind do return once new MClassKind("enum", false)
1535 fun extern_kind: MClassKind do return once new MClassKind("extern", false)