1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Object model of the Nit language
19 # This module define the entities of the Nit meta-model like modules,
20 # classes, types and properties
22 # It also provide an API to build and query models.
24 # All model classes starts with the M letter (MModule, MClass, etc.)
28 # TODO: liearization, closures, extern stuff
29 # FIXME: better handling of the types
38 var mclasses
: Array[MClass] = new Array[MClass]
40 # All known properties
41 var mproperties
: Array[MProperty] = new Array[MProperty]
43 # Hierarchy of class definition.
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]
49 # Class-type hierarchy restricted to the introduction.
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.
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]
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.
64 # This poset will evolve in an anarchic way. Loops can even be created.
66 # FIXME decide what to do on loops
67 private var full_mtype_specialization_hierarchy
: POSet[MClassType] = new POSet[MClassType]
69 # Collections of classes grouped by their short name
70 private var mclasses_by_name
: MultiHashMap[String, MClass] = new MultiHashMap[String, MClass]
72 # Return all class named `name'.
74 # If such a class does not exist, null is returned
75 # (instead of an empty array)
77 # Visibility or modules are not considered
78 fun get_mclasses_by_name
(name
: String): nullable Array[MClass]
80 if mclasses_by_name
.has_key
(name
) then
81 return mclasses_by_name
[name
]
87 # Collections of properties grouped by their short name
88 private var mproperties_by_name
: MultiHashMap[String, MProperty] = new MultiHashMap[String, MProperty]
90 # Return all properties named `name'.
92 # If such a property does not exist, null is returned
93 # (instead of an empty array)
95 # Visibility or modules are not considered
96 fun get_mproperties_by_name
(name
: String): nullable Array[MProperty]
98 if not mproperties_by_name
.has_key
(name
) then
101 return mproperties_by_name
[name
]
106 var null_type
: MNullType = new MNullType(self)
110 # All the classes introduced in the module
111 var intro_mclasses
: Array[MClass] = new Array[MClass]
113 # All the class definitions of the module
114 # (introduction and refinement)
115 var mclassdefs
: Array[MClassDef] = new Array[MClassDef]
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
122 return self.in_importation
<= mclass
.intro_mmodule
125 # Full hierarchy of introduced ans imported classes.
127 # Create a new hierarchy got by flattening the classes for the module
128 # and its imported modules.
129 # Visibility is not considered.
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
134 fun flatten_mclass_hierarchy
: POSet[MClass]
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
142 for s
in cd
.supertypes
do
143 res
.add_edge
(c
, s
.mclass
)
147 self.flatten_mclass_hierarchy_cache
= res
151 private var flatten_mclass_hierarchy_cache
: nullable POSet[MClass] = null
153 # The primitive type Object, the root of the class hierarchy
154 fun object_type
: MClassType
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
163 private var object_type_cache
: nullable MClassType
165 # The primitive type Bool
166 fun bool_type
: MClassType
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
175 private var bool_type_cache
: nullable MClassType
177 # The primitive type Sys, the main type of the program, if any
178 fun sys_type
: nullable MClassType
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
185 # Force to get the primitive class named `name' or abort
186 fun get_primitive_class
(name
: String): MClass
188 var cla
= self.model
.get_mclasses_by_name
(name
)
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])
195 print
("Fatal Error: no primitive class {name}")
198 assert cla
.length
== 1 else print cla
.join
(", ")
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
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
214 print
("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
224 # MClass are global to the model; it means that a MClass is not bound to a
225 # specific `MModule`.
227 # This characteristic helps the reasoning about classes in a program since a
228 # single MClass object always denote the same class.
229 # However, because a MClass is global, it does not really have properties nor
230 # belong to a hierarchy since the property and the
231 # hierarchy of a class depends of a module.
233 # The module that introduce the class
234 # While classes are not bound to a specific module,
235 # the introducing module is used for naming an visibility
236 var intro_mmodule
: MModule
238 # The short name of the class
239 # In Nit, the name of a class cannot evolve in refinements
242 # The canonical name of the class
243 # Example: "owner::module::MyClass"
244 fun full_name
: String
246 return "{self.intro_mmodule.full_name}::{name}"
249 # The number of generic formal parameters
250 # 0 if the class is not generic
253 # The kind of the class (interface, abstract class, etc.)
254 # In Nit, the kind of a class cannot evolve in refinements
257 # The visibility of the class
258 # In Nit, the visibility of a class cannot evolve in refinements
259 var visibility
: MVisibility
261 init(intro_mmodule
: MModule, name
: String, arity
: Int, kind
: MClassKind, visibility
: MVisibility)
263 self.intro_mmodule
= intro_mmodule
267 self.visibility
= visibility
268 intro_mmodule
.intro_mclasses
.add
(self)
269 var model
= intro_mmodule
.model
270 model
.mclasses_by_name
.add_one
(name
, self)
271 model
.mclasses
.add
(self)
273 # Create the formal parameter types
275 var mparametertypes
= new Array[MParameterType]
276 for i
in [0..arity
[ do
277 var mparametertype
= new MParameterType(self, i
)
278 mparametertypes
.add
(mparametertype
)
280 var mclass_type
= new MGenericType(self, mparametertypes
)
281 self.mclass_type
= mclass_type
282 self.get_mtype_cache
.add
(mclass_type
)
284 self.mclass_type
= new MClassType(self)
288 # All class definitions (introduction and refinements)
289 var mclassdefs
: Array[MClassDef] = new Array[MClassDef]
292 redef fun to_s
do return self.name
294 # The definition that introduced the class
295 # Warning: the introduction is the first `MClassDef' object associated
296 # to self. If self is just created without having any associated
297 # definition, this method will abort
300 assert has_a_first_definition
: not mclassdefs
.is_empty
301 return mclassdefs
.first
304 # Return the class `self' in the class hierarchy of the module `mmodule'.
306 # SEE: MModule::flatten_mclass_hierarchy
307 # REQUIRE: mmodule.has_mclass(self)
308 fun in_hierarchy
(mmodule
: MModule): POSetElement[MClass]
310 return mmodule
.flatten_mclass_hierarchy
[self]
313 # The principal static type of the class.
315 # For non-generic class, mclass_type is the only MClassType based
318 # For a generic class, the arguments are the formal parameters.
319 # i.e.: for the class `Array[E:Object]', the mtype is Array[E].
320 # If you want `Array[Object]' the see `MClassDef::bound_mtype'
322 # For generic classes, the mclass_type is also the way to get a formal
323 # generic parameter type.
325 # To get other types based on a generic class, see `get_mtype'.
327 # ENSURE: mclass_type.mclass == self
328 var mclass_type
: MClassType
330 # Return a generic type based on the class
331 # Is the class is not generic, then the result is `mclass_type'
333 # REQUIRE: type_arguments.length == self.arity
334 fun get_mtype
(mtype_arguments
: Array[MType]): MClassType
336 assert mtype_arguments
.length
== self.arity
337 if self.arity
== 0 then return self.mclass_type
338 for t
in self.get_mtype_cache
do
339 if t
.arguments
== mtype_arguments
then
343 var res
= new MGenericType(self, mtype_arguments
)
344 self.get_mtype_cache
.add res
348 private var get_mtype_cache
: Array[MGenericType] = new Array[MGenericType]
352 # A definition (an introduction or a refinement) of a class in a module
354 # A MClassDef is associated with an explicit (or almost) definition of a
355 # class. Unlike MClass, a MClassDef is a local definition that belong to
358 # The module where the definition is
361 # The associated MClass
364 # The bounded type associated to the mclassdef
366 # For a non-generic class, `bound_mtype' and `mclass.mclass_type'
370 # For the classdef Array[E: Object], the bound_mtype is Array[Object].
371 # If you want Array[E], then see `mclass.mclass_type'
373 # ENSURE: bound_mtype.mclass = self.mclass
374 var bound_mtype
: MClassType
376 # Name of each formal generic parameter (in order of declaration)
377 var parameter_names
: Array[String]
379 # The origin of the definition
380 var location
: Location
382 # Internal name combining the module and the class
383 # Example: "mymodule#MyClass"
384 redef fun to_s
do return "{mmodule}#{mclass}"
386 init(mmodule
: MModule, bound_mtype
: MClassType, location
: Location, parameter_names
: Array[String])
388 assert bound_mtype
.mclass
.arity
== parameter_names
.length
389 self.bound_mtype
= bound_mtype
390 self.mmodule
= mmodule
391 self.mclass
= bound_mtype
.mclass
392 self.location
= location
393 mmodule
.mclassdefs
.add
(self)
394 mclass
.mclassdefs
.add
(self)
395 self.parameter_names
= parameter_names
398 # All declared super-types
399 # FIXME: quite ugly but not better idea yet
400 var supertypes
: Array[MClassType] = new Array[MClassType]
402 # Register some super-types for the class (ie "super SomeType")
404 # The hierarchy must not already be set
405 # REQUIRE: self.in_hierarchy == null
406 fun set_supertypes
(supertypes
: Array[MClassType])
408 assert unique_invocation
: self.in_hierarchy
== null
409 var mmodule
= self.mmodule
410 var model
= mmodule
.model
411 var mtype
= self.bound_mtype
413 for supertype
in supertypes
do
414 self.supertypes
.add
(supertype
)
416 # Register in full_type_specialization_hierarchy
417 model
.full_mtype_specialization_hierarchy
.add_edge
(mtype
, supertype
)
418 # Register in intro_type_specialization_hierarchy
419 if mclass
.intro_mmodule
== mmodule
and supertype
.mclass
.intro_mmodule
== mmodule
then
420 model
.intro_mtype_specialization_hierarchy
.add_edge
(mtype
, supertype
)
426 # Collect the super-types (set by set_supertypes) to build the hierarchy
428 # This function can only invoked once by class
429 # REQUIRE: self.in_hierarchy == null
430 # ENSURE: self.in_hierarchy != null
433 assert unique_invocation
: self.in_hierarchy
== null
434 var model
= mmodule
.model
435 var res
= model
.mclassdef_hierarchy
.add_node
(self)
436 self.in_hierarchy
= res
437 var mtype
= self.bound_mtype
439 # Here we need to connect the mclassdef to its pairs in the mclassdef_hierarchy
440 # The simpliest way is to attach it to collect_mclassdefs
441 for mclassdef
in mtype
.collect_mclassdefs
(mmodule
) do
442 res
.poset
.add_edge
(self, mclassdef
)
446 # The view of the class definition in `mclassdef_hierarchy'
447 var in_hierarchy
: nullable POSetElement[MClassDef] = null
449 # Is the definition the one that introduced `mclass`?
450 fun is_intro
: Bool do return mclass
.intro
== self
452 # All properties introduced by the classdef
453 var intro_mproperties
: Array[MProperty] = new Array[MProperty]
455 # All property definitions in the class (introductions and redefinitions)
456 var mpropdefs
: Array[MPropDef] = new Array[MPropDef]
459 # A global static type
461 # MType are global to the model; it means that a MType is not bound to a
462 # specific `MModule`.
463 # This characteristic helps the reasoning about static types in a program
464 # since a single MType object always denote the same type.
466 # However, because a MType is global, it does not really have properties
467 # nor have subtypes to a hierarchy since the property and the class hierarchy
468 # depends of a module.
469 # Moreover, virtual types an formal generic parameter types also depends on
470 # a receiver to have sense.
472 # Therefore, most method of the types require a module and an anchor.
473 # The module is used to know what are the classes and the specialization
475 # The anchor is used to know what is the bound of the virtual types and formal
476 # generic parameter types.
478 # MType are not directly usable to get properties. See the `anchor_to' method
479 # and the `MClassType' class.
481 # FIXME: the order of the parameters is not the best. We mus pick on from:
482 # * foo(mmodule, anchor, othertype)
483 # * foo(othertype, anchor, mmodule)
484 # * foo(anchor, mmodule, othertype)
485 # * foo(othertype, mmodule, anchor)
487 # FIXME: Add a 'is_valid_anchor' to improve imputability.
488 # Currently, anchors are used "as it" without check thus if the caller gives a
489 # bad anchor, then the method will likely crash (abort) in a bad case
491 # FIXME: maybe allways add an anchor with a nullable type (as in is_subtype)
494 # The model of the type
495 fun model
: Model is abstract
497 # Return true if `self' is an subtype of `sup'.
498 # The typing is done using the standard typing policy of Nit.
500 # REQUIRE: anchor == null implies not self.need_anchor and not sup.need_anchor
501 fun is_subtype
(mmodule
: MModule, anchor
: nullable MClassType, sup
: MType): Bool
504 if sub
== sup
then return true
505 if anchor
== null then
506 assert not sub
.need_anchor
507 assert not sup
.need_anchor
510 # First, resolve the formal types to a common version in the receiver
511 # The trick here is that fixed formal type will be associed to the bound
512 # And unfixed formal types will be associed to a canonical formal type.
513 if sub
isa MParameterType or sub
isa MVirtualType then
514 assert anchor
!= null
515 sub
= sub
.resolve_for
(anchor
.mclass
.mclass_type
, anchor
, mmodule
, false)
517 if sup
isa MParameterType or sup
isa MVirtualType then
518 assert anchor
!= null
519 sup
= sup
.resolve_for
(anchor
.mclass
.mclass_type
, anchor
, mmodule
, false)
522 # Does `sup` accept null or not?
523 # Discard the nullable marker if it exists
524 var sup_accept_null
= false
525 if sup
isa MNullableType then
526 sup_accept_null
= true
528 else if sup
isa MNullType then
529 sup_accept_null
= true
532 # Can `sub` provide null or not?
533 # Thus we can match with `sup_accept_null`
534 # Also discard the nullable marker if it exists
535 if sub
isa MNullableType then
536 if not sup_accept_null
then return false
538 else if sub
isa MNullType then
539 return sup_accept_null
541 # Now the case of direct null and nullable is over.
543 # A unfixed formal type can only accept itself
544 if sup
isa MParameterType or sup
isa MVirtualType then
548 # If `sub` is a formal type, then it is accepted if its bound is accepted
549 if sub
isa MParameterType or sub
isa MVirtualType then
550 assert anchor
!= null
551 sub
= sub
.anchor_to
(mmodule
, anchor
)
553 # Manage the second layer of null/nullable
554 if sub
isa MNullableType then
555 if not sup_accept_null
then return false
557 else if sub
isa MNullType then
558 return sup_accept_null
562 assert sub
isa MClassType # It is the only remaining type
564 if sup
isa MNullType then
565 # `sup` accepts only null
569 assert sup
isa MClassType # It is the only remaining type
571 # Now both are MClassType, we need to dig
573 if sub
== sup
then return true
575 if anchor
== null then anchor
= sub
# UGLY: any anchor will work
576 var resolved_sub
= sub
.anchor_to
(mmodule
, anchor
)
577 var res
= resolved_sub
.collect_mclasses
(mmodule
).has
(sup
.mclass
)
578 if res
== false then return false
579 if not sup
isa MGenericType then return true
580 var sub2
= sub
.supertype_to
(mmodule
, anchor
, sup
.mclass
)
581 assert sub2
.mclass
== sup
.mclass
582 for i
in [0..sup
.mclass
.arity
[ do
583 var sub_arg
= sub2
.arguments
[i
]
584 var sup_arg
= sup
.arguments
[i
]
585 res
= sub_arg
.is_subtype
(mmodule
, anchor
, sup_arg
)
586 if res
== false then return false
591 # The base class type on which self is based
593 # This base type is used to get property (an internally to perform
594 # unsafe type comparison).
596 # Beware: some types (like null) are not based on a class thus this
599 # Basically, this function transform the virtual types and parameter
600 # types to their bounds.
610 # Map[T,U] anchor_to H #-> Map[C,Y]
612 # Explanation of the example:
613 # In H, T is set to C, because "H super G[C]", and U is bound to Y,
614 # because "redef type U: Y". Therefore, Map[T, U] is bound to
617 # ENSURE: not self.need_anchor implies return == self
618 # ENSURE: not return.need_anchor
619 fun anchor_to
(mmodule
: MModule, anchor
: MClassType): MType
621 if not need_anchor
then return self
622 assert not anchor
.need_anchor
623 # Just resolve to the anchor and clear all the virtual types
624 var res
= self.resolve_for
(anchor
, anchor
, mmodule
, true)
625 assert not res
.need_anchor
629 # Does `self' contain a virtual type or a formal generic parameter type?
630 # In order to remove those types, you usually want to use `anchor_to'.
631 fun need_anchor
: Bool do return true
633 # Return the supertype when adapted to a class.
635 # In Nit, for each super-class of a type, there is a equivalent super-type.
639 # class H[V] super G[V, Bool]
640 # H[Int] supertype_to G #-> G[Int, Bool]
642 # REQUIRE: `super_mclass' is a super-class of `self'
643 # ENSURE: return.mclass = mclass
644 fun supertype_to
(mmodule
: MModule, anchor
: MClassType, super_mclass
: MClass): MClassType
646 if super_mclass
.arity
== 0 then return super_mclass
.mclass_type
647 if self isa MClassType and self.mclass
== super_mclass
then return self
648 var resolved_self
= self.anchor_to
(mmodule
, anchor
)
649 var supertypes
= resolved_self
.collect_mtypes
(mmodule
)
650 for supertype
in supertypes
do
651 if supertype
.mclass
== super_mclass
then
652 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
653 return supertype
.resolve_for
(self, anchor
, mmodule
, false)
659 # Replace formals generic types in self with resolved values in `mtype'
660 # If `cleanup_virtual' is true, then virtual types are also replaced
663 # This function returns self if `need_anchor' is false.
667 # class H[F] super G[F]
668 # Array[E] resolve_for H[Int] #-> Array[Int]
670 # Explanation of the example:
671 # * Array[E].need_anchor is true because there is a formal generic
673 # * E makes sense for H[Int] because E is a formal parameter of G
675 # * Since "H[F] super G[F]", E is in fact F for H
676 # * More specifically, in H[Int], E is Int
677 # * So, in H[Int], Array[E] is Array[Int]
679 # This function is mainly used to inherit a signature.
680 # Because, unlike `anchor_type', we do not want a full resolution of
681 # a type but only an adapted version of it.
687 # class B super A[Int] end
689 # The signature on foo is (e: E): E
690 # If we resolve the signature for B, we get (e:Int):Int
692 # TODO: Explain the cleanup_virtual
694 # FIXME: the parameter `cleanup_virtual' is just a bad idea, but having
695 # two function instead of one seems also to be a bad idea.
697 # ENSURE: not self.need_anchor implies return == self
698 fun resolve_for
(mtype
: MType, anchor
: MClassType, mmodule
: MModule, cleanup_virtual
: Bool): MType is abstract
700 # Return the nullable version of the type
701 # If the type is already nullable then self is returned
703 # FIXME: DO NOT WORK YET
704 fun as_nullable
: MType
706 var res
= self.as_nullable_cache
707 if res
!= null then return res
708 res
= new MNullableType(self)
709 self.as_nullable_cache
= res
713 private var as_nullable_cache
: nullable MType = null
716 # The deph of the type seen as a tree.
723 # Formal types have a depth of 1.
729 # Compute all the classdefs inherited/imported.
730 # The returned set contains:
731 # * the class definitions from `mmodule` and its imported modules
732 # * the class definitions of this type and its super-types
734 # This function is used mainly internally.
736 # REQUIRE: not self.need_anchor
737 fun collect_mclassdefs
(mmodule
: MModule): Set[MClassDef] is abstract
739 # Compute all the super-classes.
740 # This function is used mainly internally.
742 # REQUIRE: not self.need_anchor
743 fun collect_mclasses
(mmodule
: MModule): Set[MClass] is abstract
745 # Compute all the declared super-types.
746 # Super-types are returned as declared in the classdefs (verbatim).
747 # This function is used mainly internally.
749 # REQUIRE: not self.need_anchor
750 fun collect_mtypes
(mmodule
: MModule): Set[MClassType] is abstract
752 # Is the property in self for a given module
753 # This method does not filter visibility or whatever
755 # REQUIRE: not self.need_anchor
756 fun has_mproperty
(mmodule
: MModule, mproperty
: MProperty): Bool
758 assert not self.need_anchor
759 return self.collect_mclassdefs
(mmodule
).has
(mproperty
.intro_mclassdef
)
763 # A type based on a class.
765 # MClassType have properties (see `has_property').
769 # The associated class
772 redef fun model
do return self.mclass
.intro_mmodule
.model
774 private init(mclass
: MClass)
779 # The formal arguments of the type
780 # ENSURE: return.length == self.mclass.arity
781 var arguments
: Array[MType] = new Array[MType]
783 redef fun to_s
do return mclass
.to_s
785 redef fun need_anchor
do return false
787 redef fun anchor_to
(mmodule
: MModule, anchor
: MClassType): MClassType
789 return super.as(MClassType)
792 redef fun resolve_for
(mtype
: MType, anchor
: MClassType, mmodule
: MModule, cleanup_virtual
: Bool): MClassType do return self
794 redef fun collect_mclassdefs
(mmodule
)
796 assert not self.need_anchor
797 var cache
= self.collect_mclassdefs_cache
798 if not cache
.has_key
(mmodule
) then
799 self.collect_things
(mmodule
)
801 return cache
[mmodule
]
804 redef fun collect_mclasses
(mmodule
)
806 assert not self.need_anchor
807 var cache
= self.collect_mclasses_cache
808 if not cache
.has_key
(mmodule
) then
809 self.collect_things
(mmodule
)
811 return cache
[mmodule
]
814 redef fun collect_mtypes
(mmodule
)
816 assert not self.need_anchor
817 var cache
= self.collect_mtypes_cache
818 if not cache
.has_key
(mmodule
) then
819 self.collect_things
(mmodule
)
821 return cache
[mmodule
]
824 # common implementation for `collect_mclassdefs', `collect_mclasses', and `collect_mtypes'.
825 private fun collect_things
(mmodule
: MModule)
827 var res
= new HashSet[MClassDef]
828 var seen
= new HashSet[MClass]
829 var types
= new HashSet[MClassType]
830 seen
.add
(self.mclass
)
831 var todo
= [self.mclass
]
832 while not todo
.is_empty
do
833 var mclass
= todo
.pop
834 #print "process {mclass}"
835 for mclassdef
in mclass
.mclassdefs
do
836 if not mmodule
.in_importation
<= mclassdef
.mmodule
then continue
837 #print " process {mclassdef}"
839 for supertype
in mclassdef
.supertypes
do
841 var superclass
= supertype
.mclass
842 if seen
.has
(superclass
) then continue
843 #print " add {superclass}"
849 collect_mclassdefs_cache
[mmodule
] = res
850 collect_mclasses_cache
[mmodule
] = seen
851 collect_mtypes_cache
[mmodule
] = types
854 private var collect_mclassdefs_cache
: HashMap[MModule, Set[MClassDef]] = new HashMap[MModule, Set[MClassDef]]
855 private var collect_mclasses_cache
: HashMap[MModule, Set[MClass]] = new HashMap[MModule, Set[MClass]]
856 private var collect_mtypes_cache
: HashMap[MModule, Set[MClassType]] = new HashMap[MModule, Set[MClassType]]
860 # A type based on a generic class.
861 # A generic type a just a class with additional formal generic arguments.
865 private init(mclass
: MClass, arguments
: Array[MType])
868 assert self.mclass
.arity
== arguments
.length
869 self.arguments
= arguments
871 self.need_anchor
= false
872 for t
in arguments
do
873 if t
.need_anchor
then
874 self.need_anchor
= true
880 # Recursively print the type of the arguments within brackets.
881 # Example: "Map[String, List[Int]]"
884 return "{mclass}[{arguments.join(", ")}]"
887 redef var need_anchor
: Bool
889 redef fun resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
891 if not need_anchor
then return self
892 var types
= new Array[MType]
893 for t
in arguments
do
894 types
.add
(t
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
))
896 return mclass
.get_mtype
(types
)
902 for a
in self.arguments
do
904 if d
> dmax
then dmax
= d
910 # A virtual formal type.
914 # The property associated with the type.
915 # Its the definitions of this property that determine the bound or the virtual type.
916 var mproperty
: MProperty
918 redef fun model
do return self.mproperty
.intro_mclassdef
.mmodule
.model
920 # Lookup the bound for a given resolved_receiver
921 # The result may be a other virtual type (or a parameter type)
923 # The result is returned exactly as declared in the "type" property (verbatim).
925 # In case of conflict, the method aborts.
926 fun lookup_bound
(mmodule
: MModule, resolved_receiver
: MType): MType
928 assert not resolved_receiver
.need_anchor
929 var props
= self.mproperty
.lookup_definitions
(mmodule
, resolved_receiver
)
930 if props
.is_empty
then
932 else if props
.length
== 1 then
933 return props
.first
.as(MVirtualTypeDef).bound
.as(not null)
935 var types
= new ArraySet[MType]
937 types
.add
(p
.as(MVirtualTypeDef).bound
.as(not null))
939 if types
.length
== 1 then
945 redef fun resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
947 # self is a virtual type declared (or inherited) in mtype
948 # The point of the function it to get the bound of the virtual type that make sense for mtype
949 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
950 #print "{class_name}: {self}/{mtype}/{anchor}?"
951 var resolved_reciever
= mtype
.resolve_for
(anchor
, anchor
, mmodule
, true)
952 # Now, we can get the bound
953 var verbatim_bound
= lookup_bound
(mmodule
, resolved_reciever
)
954 # The bound is exactly as declared in the "type" property, so we must resolve it again
955 var res
= verbatim_bound
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
956 #print "{class_name}: {self}/{mtype}/{anchor} -> {self}/{resolved_reciever}/{anchor} -> {verbatim_bound}/{mtype}/{anchor} -> {res}"
958 # What to return here? There is a bunch a special cases:
959 # If 'cleanup_virtual' we must return the resolved type, since we cannot return self
960 if cleanup_virtual
then return res
961 # If the reciever is a intern class, then the virtual type cannot be redefined since there is no possible subclass. self is just fixed. so simply return the resolution
962 if resolved_reciever
isa MNullableType then resolved_reciever
= resolved_reciever
.mtype
963 if resolved_reciever
.as(MClassType).mclass
.kind
== enum_kind
then return res
964 # If the resolved type isa MVirtualType, it means that self was bound to it, and cannot be unbound. self is just fixed. so return the resolution.
965 if res
isa MVirtualType then return res
966 # It the resolved type isa intern class, then there is no possible valid redefinition is any potentiel subclass. self is just fixed. so simply return the resolution
967 if res
isa MClassType and res
.mclass
.kind
== enum_kind
then return res
968 # TODO: Add 'fixed' virtual type in the specification.
969 # TODO: What if bound to a MParameterType?
970 # Note that Nullable types can always be redefined by the non nullable version, so there is no specific case on it.
972 # If anything apply, then `self' cannot be resolved, so return self
976 redef fun to_s
do return self.mproperty
.to_s
978 init(mproperty
: MProperty)
980 self.mproperty
= mproperty
984 # The type associated the a formal parameter generic type of a class
986 # Each parameter type is associated to a specific class.
987 # It's mean that all refinements of a same class "share" the parameter type,
988 # but that a generic subclass has its on parameter types.
990 # However, in the sense of the meta-model, the a parameter type of a class is
991 # a valid types in a subclass. The "in the sense of the meta-model" is
992 # important because, in the Nit language, the programmer cannot refers
993 # directly to the parameter types of the super-classes.
997 # fun e: E is abstract
1002 # In the class definition B[F], `F' is a valid type but `E' is not.
1003 # However, `self.e' is a valid method call, and the signature of `e' is
1006 # Note that parameter types are shared among class refinements.
1007 # Therefore parameter only have an internal name (see `to_s' for details).
1008 # TODO: Add a 'name_for' to get better messages.
1009 class MParameterType
1012 # The generic class where the parameter belong
1015 redef fun model
do return self.mclass
.intro_mmodule
.model
1017 # The position of the parameter (0 for the first parameter)
1018 # FIXME: is `position' a better name?
1021 # Internal name of the parameter type
1022 # Names of parameter types changes in each class definition
1023 # Therefore, this method return an internal name.
1024 # Example: return "G#1" for the second parameter of the class G
1025 # FIXME: add a way to get the real name in a classdef
1026 redef fun to_s
do return "{mclass}#{rank}"
1028 # Resolve the bound for a given resolved_receiver
1029 # The result may be a other virtual type (or a parameter type)
1030 fun lookup_bound
(mmodule
: MModule, resolved_receiver
: MType): MType
1032 assert not resolved_receiver
.need_anchor
1033 var goalclass
= self.mclass
1034 var supertypes
= resolved_receiver
.collect_mtypes
(mmodule
)
1035 for t
in supertypes
do
1036 if t
.mclass
== goalclass
then
1037 # Yeah! c specialize goalclass with a "super `t'". So the question is what is the argument of f
1038 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
1039 var res
= t
.arguments
[self.rank
]
1046 redef fun resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1048 #print "{class_name}: {self}/{mtype}/{anchor}?"
1050 if mtype
isa MGenericType and mtype
.mclass
== self.mclass
then
1051 return mtype
.arguments
[self.rank
]
1054 # self is a parameter type of mtype (or of a super-class of mtype)
1055 # The point of the function it to get the bound of the virtual type that make sense for mtype
1056 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
1057 # FIXME: What happend here is far from clear. Thus this part must be validated and clarified
1058 var resolved_receiver
= mtype
.resolve_for
(anchor
.mclass
.mclass_type
, anchor
, mmodule
, true)
1059 if resolved_receiver
isa MNullableType then resolved_receiver
= resolved_receiver
.mtype
1060 if resolved_receiver
isa MParameterType then
1061 assert resolved_receiver
.mclass
== anchor
.mclass
1062 resolved_receiver
= anchor
.arguments
[resolved_receiver
.rank
]
1063 if resolved_receiver
isa MNullableType then resolved_receiver
= resolved_receiver
.mtype
1065 assert resolved_receiver
isa MClassType else print
"{class_name}: {self}/{mtype}/{anchor}? {resolved_receiver}"
1067 # Eh! The parameter is in the current class.
1068 # So we return the corresponding argument, no mater what!
1069 if resolved_receiver
.mclass
== self.mclass
then
1070 var res
= resolved_receiver
.arguments
[self.rank
]
1071 #print "{class_name}: {self}/{mtype}/{anchor} -> direct {res}"
1075 resolved_receiver
= resolved_receiver
.resolve_for
(anchor
, anchor
, mmodule
, false)
1076 # Now, we can get the bound
1077 var verbatim_bound
= lookup_bound
(mmodule
, resolved_receiver
)
1078 # The bound is exactly as declared in the "type" property, so we must resolve it again
1079 var res
= verbatim_bound
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1081 #print "{class_name}: {self}/{mtype}/{anchor} -> indirect {res}"
1086 init(mclass
: MClass, rank
: Int)
1088 self.mclass
= mclass
1093 # A type prefixed with "nullable"
1094 # FIXME Stub implementation
1098 # The base type of the nullable type
1101 redef fun model
do return self.mtype
.model
1108 redef fun to_s
do return "nullable {mtype}"
1110 redef fun need_anchor
do return mtype
.need_anchor
1111 redef fun as_nullable
do return self
1112 redef fun resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1114 var res
= self.mtype
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1115 return res
.as_nullable
1118 redef fun depth
do return self.mtype
.depth
1120 redef fun collect_mclassdefs
(mmodule
)
1122 assert not self.need_anchor
1123 return self.mtype
.collect_mclassdefs
(mmodule
)
1126 redef fun collect_mclasses
(mmodule
)
1128 assert not self.need_anchor
1129 return self.mtype
.collect_mclasses
(mmodule
)
1132 redef fun collect_mtypes
(mmodule
)
1134 assert not self.need_anchor
1135 return self.mtype
.collect_mtypes
(mmodule
)
1139 # The type of the only value null
1141 # The is only one null type per model, see `MModel::null_type'.
1144 redef var model
: Model
1145 protected init(model
: Model)
1149 redef fun to_s
do return "null"
1150 redef fun as_nullable
do return self
1151 redef fun need_anchor
do return false
1152 redef fun resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
) do return self
1154 redef fun collect_mclassdefs
(mmodule
) do return new HashSet[MClassDef]
1156 redef fun collect_mclasses
(mmodule
) do return new HashSet[MClass]
1158 redef fun collect_mtypes
(mmodule
) do return new HashSet[MClassType]
1161 # A signature of a method (or a closure)
1165 # The each parameter (in order)
1166 var mparameters
: Array[MParameter]
1168 var mclosures
= new Array[MParameter]
1170 # The return type (null for a procedure)
1171 var return_mtype
: nullable MType
1176 var t
= self.return_mtype
1177 if t
!= null then dmax
= t
.depth
1178 for p
in mparameters
do
1179 var d
= p
.mtype
.depth
1180 if d
> dmax
then dmax
= d
1182 for p
in mclosures
do
1183 var d
= p
.mtype
.depth
1184 if d
> dmax
then dmax
= d
1189 # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
1190 init(mparameters
: Array[MParameter], return_mtype
: nullable MType)
1192 var vararg_rank
= -1
1193 for i
in [0..mparameters
.length
[ do
1194 var parameter
= mparameters
[i
]
1195 if parameter
.is_vararg
then
1196 assert vararg_rank
== -1
1200 self.mparameters
= mparameters
1201 self.return_mtype
= return_mtype
1202 self.vararg_rank
= vararg_rank
1205 # The rank of the ellipsis (...) for vararg (starting from 0).
1206 # value is -1 if there is no vararg.
1207 # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
1208 var vararg_rank
: Int
1210 # The number or parameters
1211 fun arity
: Int do return mparameters
.length
1216 if not mparameters
.is_empty
then
1218 for i
in [0..mparameters
.length
[ do
1219 var mparameter
= mparameters
[i
]
1220 if i
> 0 then b
.append
(", ")
1221 b
.append
(mparameter
.name
)
1223 b
.append
(mparameter
.mtype
.to_s
)
1224 if mparameter
.is_vararg
then
1230 var ret
= self.return_mtype
1238 redef fun resolve_for
(mtype
: MType, anchor
: MClassType, mmodule
: MModule, cleanup_virtual
: Bool): MSignature
1240 var params
= new Array[MParameter]
1241 for p
in self.mparameters
do
1242 params
.add
(p
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
))
1244 var ret
= self.return_mtype
1246 ret
= ret
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1248 var res
= new MSignature(params
, ret
)
1249 for p
in self.mclosures
do
1250 res
.mclosures
.add
(p
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
))
1256 # A parameter in a signature
1258 # The name of the parameter
1261 # The static type of the parameter
1264 # Is the parameter a vararg?
1267 fun resolve_for
(mtype
: MType, anchor
: MClassType, mmodule
: MModule, cleanup_virtual
: Bool): MParameter
1269 if not self.mtype
.need_anchor
then return self
1270 var newtype
= self.mtype
.resolve_for
(mtype
, anchor
, mmodule
, cleanup_virtual
)
1271 var res
= new MParameter(self.name
, newtype
, self.is_vararg
)
1276 # A service (global property) that generalize method, attribute, etc.
1278 # MProperty are global to the model; it means that a MProperty is not bound
1279 # to a specific `MModule` nor a specific `MClass`.
1281 # A MProperty gather definitions (see `mpropdefs') ; one for the introduction
1282 # and the other in subclasses and in refinements.
1284 # A MProperty is used to denotes services in polymorphic way (ie. independent
1285 # of any dynamic type).
1286 # For instance, a call site "x.foo" is associated to a MProperty.
1287 abstract class MProperty
1288 # The associated MPropDef subclass.
1289 # The two specialization hierarchy are symmetric.
1290 type MPROPDEF: MPropDef
1292 # The classdef that introduce the property
1293 # While a property is not bound to a specific module, or class,
1294 # the introducing mclassdef is used for naming and visibility
1295 var intro_mclassdef
: MClassDef
1297 # The (short) name of the property
1300 # The canonical name of the property
1301 # Example: "owner::my_module::MyClass::my_method"
1302 fun full_name
: String
1304 return "{self.intro_mclassdef.mmodule.full_name}::{self.intro_mclassdef.mclass.name}::{name}"
1307 # The visibility of the property
1308 var visibility
: MVisibility
1310 init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1312 self.intro_mclassdef
= intro_mclassdef
1314 self.visibility
= visibility
1315 intro_mclassdef
.intro_mproperties
.add
(self)
1316 var model
= intro_mclassdef
.mmodule
.model
1317 model
.mproperties_by_name
.add_one
(name
, self)
1318 model
.mproperties
.add
(self)
1321 # All definitions of the property.
1322 # The first is the introduction,
1323 # The other are redefinitions (in refinements and in subclasses)
1324 var mpropdefs
: Array[MPROPDEF] = new Array[MPROPDEF]
1326 # The definition that introduced the property
1327 # Warning: the introduction is the first `MPropDef' object
1328 # associated to self. If self is just created without having any
1329 # associated definition, this method will abort
1330 fun intro
: MPROPDEF do return mpropdefs
.first
1333 redef fun to_s
do return name
1335 # Return the most specific property definitions defined or inherited by a type.
1336 # The selection knows that refinement is stronger than specialization;
1337 # however, in case of conflict more than one property are returned.
1338 # If mtype does not know mproperty then an empty array is returned.
1340 # If you want the really most specific property, then look at `lookup_first_definition`
1341 fun lookup_definitions
(mmodule
: MModule, mtype
: MType): Array[MPROPDEF]
1343 assert not mtype
.need_anchor
1344 if mtype
isa MNullableType then mtype
= mtype
.mtype
1346 var cache
= self.lookup_definitions_cache
[mmodule
, mtype
]
1347 if cache
!= null then return cache
1349 #print "select prop {mproperty} for {mtype} in {self}"
1350 # First, select all candidates
1351 var candidates
= new Array[MPROPDEF]
1352 for mpropdef
in self.mpropdefs
do
1353 # If the definition is not imported by the module, then skip
1354 if not mmodule
.in_importation
<= mpropdef
.mclassdef
.mmodule
then continue
1355 # If the definition is not inherited by the type, then skip
1356 if not mtype
.is_subtype
(mmodule
, null, mpropdef
.mclassdef
.bound_mtype
) then continue
1358 candidates
.add
(mpropdef
)
1360 # Fast track for only one candidate
1361 if candidates
.length
<= 1 then
1362 self.lookup_definitions_cache
[mmodule
, mtype
] = candidates
1366 # Second, filter the most specific ones
1367 var res
= new Array[MPROPDEF]
1368 for pd1
in candidates
do
1369 var cd1
= pd1
.mclassdef
1372 for pd2
in candidates
do
1373 if pd2
== pd1
then continue # do not compare with self!
1374 var cd2
= pd2
.mclassdef
1376 if c2
.mclass_type
== c1
.mclass_type
then
1377 if cd2
.mmodule
.in_importation
<= cd1
.mmodule
then
1378 # cd2 refines cd1; therefore we skip pd1
1382 else if cd2
.bound_mtype
.is_subtype
(mmodule
, null, cd1
.bound_mtype
) then
1383 # cd2 < cd1; therefore we skip pd1
1392 if res
.is_empty
then
1393 print
"All lost! {candidates.join(", ")}"
1394 # FIXME: should be abort!
1396 self.lookup_definitions_cache
[mmodule
, mtype
] = res
1400 private var lookup_definitions_cache
: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
1402 # Return the most specific property definitions inherited by a type.
1403 # The selection knows that refinement is stronger than specialization;
1404 # however, in case of conflict more than one property are returned.
1405 # If mtype does not know mproperty then an empty array is returned.
1407 # If you want the really most specific property, then look at `lookup_next_definition`
1409 # FIXME: Move to MPropDef?
1410 fun lookup_super_definitions
(mmodule
: MModule, mtype
: MType): Array[MPropDef]
1412 assert not mtype
.need_anchor
1413 if mtype
isa MNullableType then mtype
= mtype
.mtype
1415 # First, select all candidates
1416 var candidates
= new Array[MPropDef]
1417 for mpropdef
in self.mpropdefs
do
1418 # If the definition is not imported by the module, then skip
1419 if not mmodule
.in_importation
<= mpropdef
.mclassdef
.mmodule
then continue
1420 # If the definition is not inherited by the type, then skip
1421 if not mtype
.is_subtype
(mmodule
, null, mpropdef
.mclassdef
.bound_mtype
) then continue
1422 # If the definition is defined by the type, then skip (we want the super, so e skip the current)
1423 if mtype
== mpropdef
.mclassdef
.bound_mtype
and mmodule
== mpropdef
.mclassdef
.mmodule
then continue
1425 candidates
.add
(mpropdef
)
1427 # Fast track for only one candidate
1428 if candidates
.length
<= 1 then return candidates
1430 # Second, filter the most specific ones
1431 var res
= new Array[MPropDef]
1432 for pd1
in candidates
do
1433 var cd1
= pd1
.mclassdef
1436 for pd2
in candidates
do
1437 if pd2
== pd1
then continue # do not compare with self!
1438 var cd2
= pd2
.mclassdef
1440 if c2
.mclass_type
== c1
.mclass_type
then
1441 if cd2
.mmodule
.in_importation
<= cd1
.mmodule
then
1442 # cd2 refines cd1; therefore we skip pd1
1446 else if cd2
.bound_mtype
.is_subtype
(mmodule
, null, cd1
.bound_mtype
) then
1447 # cd2 < cd1; therefore we skip pd1
1456 if res
.is_empty
then
1457 print
"All lost! {candidates.join(", ")}"
1458 # FIXME: should be abort!
1463 # Return the most specific definition in the linearization of `mtype`.
1464 # If mtype does not know mproperty then null is returned.
1466 # If you want to know the next properties in the linearization,
1467 # look at `MPropDef::lookup_next_definition`.
1469 # FIXME: NOT YET IMPLEMENTED
1471 # REQUIRE: not mtype.need_anchor
1472 fun lookup_first_definition
(mmodule
: MModule, mtype
: MType): nullable MPROPDEF
1474 assert not mtype
.need_anchor
1483 redef type MPROPDEF: MMethodDef
1485 init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1490 # Is the property a constructor?
1491 # Warning, this property can be inherited by subclasses with or without being a constructor
1492 # therefore, you should use `is_init_for' the verify if the property is a legal constructor for a given class
1493 var is_init
: Bool writable = false
1495 # The the property a 'new' contructor?
1496 var is_new
: Bool writable = false
1498 # Is the property a legal constructor for a given class?
1499 # As usual, visibility is not considered.
1500 # FIXME not implemented
1501 fun is_init_for
(mclass
: MClass): Bool
1507 # A global attribute
1511 redef type MPROPDEF: MAttributeDef
1513 init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1519 # A global virtual type
1520 class MVirtualTypeProp
1523 redef type MPROPDEF: MVirtualTypeDef
1525 init(intro_mclassdef
: MClassDef, name
: String, visibility
: MVisibility)
1530 # The formal type associated to the virtual type property
1531 var mvirtualtype
: MVirtualType = new MVirtualType(self)
1534 # A definition of a property (local property)
1536 # Unlike MProperty, a MPropDef is a local definition that belong to a
1537 # specific class definition (which belong to a specific module)
1538 abstract class MPropDef
1540 # The associated MProperty subclass.
1541 # the two specialization hierarchy are symmetric
1542 type MPROPERTY: MProperty
1545 type MPROPDEF: MPropDef
1547 # The origin of the definition
1548 var location
: Location
1550 # The class definition where the property definition is
1551 var mclassdef
: MClassDef
1553 # The associated global property
1554 var mproperty
: MPROPERTY
1556 init(mclassdef
: MClassDef, mproperty
: MPROPERTY, location
: Location)
1558 self.mclassdef
= mclassdef
1559 self.mproperty
= mproperty
1560 self.location
= location
1561 mclassdef
.mpropdefs
.add
(self)
1562 mproperty
.mpropdefs
.add
(self)
1565 # Internal name combining the module, the class and the property
1566 # Example: "mymodule#MyClass#mymethod"
1569 return "{mclassdef}#{mproperty}"
1572 # Is self the definition that introduce the property?
1573 fun is_intro
: Bool do return mproperty
.intro
== self
1575 # Return the next definition in linearization of `mtype`.
1576 # If there is no next method then null is returned.
1578 # This method is used to determine what method is called by a super.
1580 # FIXME: NOT YET IMPLEMENTED
1582 # REQUIRE: not mtype.need_anchor
1583 fun lookup_next_definition
(mmodule
: MModule, mtype
: MType): nullable MPROPDEF
1585 assert not mtype
.need_anchor
1590 # A local definition of a method
1594 redef type MPROPERTY: MMethod
1595 redef type MPROPDEF: MMethodDef
1597 init(mclassdef
: MClassDef, mproperty
: MPROPERTY, location
: Location)
1602 # The signature attached to the property definition
1603 var msignature
: nullable MSignature writable = null
1606 # A local definition of an attribute
1610 redef type MPROPERTY: MAttribute
1611 redef type MPROPDEF: MAttributeDef
1613 init(mclassdef
: MClassDef, mproperty
: MPROPERTY, location
: Location)
1618 # The static type of the attribute
1619 var static_mtype
: nullable MType writable = null
1622 # A local definition of a virtual type
1623 class MVirtualTypeDef
1626 redef type MPROPERTY: MVirtualTypeProp
1627 redef type MPROPDEF: MVirtualTypeDef
1629 init(mclassdef
: MClassDef, mproperty
: MPROPERTY, location
: Location)
1634 # The bound of the virtual type
1635 var bound
: nullable MType writable = null
1646 # Note this class is basically an enum.
1647 # FIXME: use a real enum once user-defined enums are available
1649 redef var to_s
: String
1651 # Is a constructor required?
1653 private init(s
: String, need_init
: Bool)
1656 self.need_init
= need_init
1660 fun abstract_kind
: MClassKind do return once
new MClassKind("abstract class", true)
1661 fun concrete_kind
: MClassKind do return once
new MClassKind("class", true)
1662 fun interface_kind
: MClassKind do return once
new MClassKind("interface", false)
1663 fun enum_kind
: MClassKind do return once
new MClassKind("enum", false)
1664 fun extern_kind
: MClassKind do return once
new MClassKind("extern", false)