1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2006-2008 Floréal Morandat <morandat@lirmm.fr>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # Compute importation of classes and inheritance of properties
21 intrude import static_type
24 # The root of the class hierarchy
27 var c_name
= class_by_name
(once
("Object".to_symbol
))
28 return c_name
.get_type
31 # Import global classes from supermodules
32 fun import_global_classes
34 var globals
= new HashMap[MMGlobalClass,HashSet[MMLocalClass]]
36 for mod
in mhe
.direct_greaters
do
37 for glob
in mod
.global_classes
do
38 if global_classes
.has
(glob
) then continue
39 _global_classes
.add
(glob
)
40 _global_class_by_name
[glob
.name
] = glob
46 # Create implicit local classes for global classes that are not refined
47 fun import_local_classes
49 for g
in _global_classes
do
50 if _local_class_by_global
.has_key
(g
) then continue
51 var impl
= new MMImplicitLocalClass(self, g
)
56 redef class MMLocalClass
58 var _direct_parents
: Array[MMAncestor] = new Array[MMAncestor]
60 # Is the class computing super.
61 # Used to detect specialization loops.
62 var _computing_super
: Bool = false
64 # Compute super classes of a class
65 fun compute_super_classes
67 if computed_super_classes
then
68 # do no recompute if allready done
70 else if _computing_super
then
71 stderr
.write
("Fatal error: Inheritance loop for class {self}\n")
74 _computing_super
= true
76 var supers
= new Array[MMLocalClass]
77 add_explicit_classes
(supers
)
78 add_super_classes
(supers
)
79 add_default_any_class
(supers
)
80 compute_super_parents
(supers
)
81 var set
= new HashSet[MMLocalClass]
84 mmmodule
.set_supers_class
(self,u
)
87 _computing_super
= false
90 # Compute ancestors for a class
93 assert computed_super_classes
94 if computed_ancestors
then return
96 var ancestors
= group_ancestors
(build_ancestors
)
97 _ancestors
= new HashMap[MMLocalClass, MMAncestor]
99 for set
in ancestors
do
100 if set
.length
== 1 then
101 add_ancestor
(set
.first
)
103 var ma
= merge_ancestors
(set
)
104 add_ancestor
(merge_ancestors
(set
))
109 var _are_global_properties_inherited
: Bool = false
111 # Inherit global properties for a class
112 private fun inherit_global_properties
114 if _are_global_properties_inherited
then return
115 _are_global_properties_inherited
= true
117 var names
= _properties_by_name
118 var set
= _global_properties
119 for c
in che
.direct_greaters
do
120 for glob
in c
.global_properties
do
121 if set
.has
(glob
) then continue
123 set
.add
(glob
) # Add the global property
125 # Do not inherit constructors trough specialization
126 #print "{c.mmmodule}::{c} -> {mmmodule}::{self} for {glob.local_property.local_class.mmmodule}::{glob.local_property.local_class}::{glob.local_property} : {glob.is_init}"
127 if glob
.is_init
and glob
.intro
.local_class
.global
!= global
then
132 # Do not inherit new style attributes
133 if glob
.intro
.name
.to_s
[0] == '@' then continue
135 make_visible_an_inherited_global_property
(glob
)
140 redef fun global_properties
142 if _are_global_properties_inherited
then return _global_properties
143 assert computed_super_classes
144 inherit_global_properties
145 return _global_properties
148 redef fun has_global_property
(g
)
150 # has_global_property can be called during the construction of the class
151 # hierarchy to check that a type "X" is not a formal type.
152 if not computed_super_classes
then return false
154 var set
= _global_properties
155 if set
.has
(g
) then return true
156 for c
in che
.direct_greaters
do
157 if c
.has_global_property
(g
) then
165 redef fun has_global_property_by_name
(n
)
167 # has_global_property can be called during the construction of the class
168 # hierarchy to check that a type "X" is not a formal type.
169 if not computed_super_classes
then return false
171 # Ensure that super-classes are constructed
172 compute_super_classes
174 if _properties_by_name
.has_key
(n
) then
175 return _properties_by_name
[n
].length
== 1
177 var set
= _global_properties
179 if _properties_by_name
.has_key
(n
) then
180 nset
= _properties_by_name
[n
]
182 nset
= new Array[MMGlobalProperty]
183 _properties_by_name
[n
] = nset
185 for c
in che
.direct_greaters
do
186 if c
.has_global_property_by_name
(n
) then
187 var g
= c
.get_property_by_name
(n
)
188 if not set
.has
(g
) then set
.add
(g
)
189 if g
.is_init
and g
.intro
.local_class
.global
!= global
then continue
190 if g
.intro
.name
.to_s
.first
== '@' then continue # inherited new style attibutes are invisible
191 if nset
.has
(g
) then continue
195 return nset
.length
== 1
198 # Make the name of a global property meaningful in the class
199 fun make_visible_an_inherited_global_property
(glob
: MMGlobalProperty)
201 var names
= _properties_by_name
202 var gname
= glob
.intro
.name
203 var conf_set
: Array[MMGlobalProperty]
204 if names
.has_key
(gname
) then
205 conf_set
= names
[gname
]
207 conf_set
= new Array[MMGlobalProperty]
208 names
[gname
] = conf_set
213 # Add super stype of this current local class
214 fun add_direct_parent
(p
: MMAncestor)
216 _direct_parents
.add
(p
)
219 # Are super-class already computed?
220 fun computed_super_classes
: Bool
222 return _crhe
!= null and _cshe
!= null
225 # Are ancestors already computed
226 fun computed_ancestors
: Bool
228 return _ancestors
!= null
231 # Get the ancestor for a given class
232 # TODO: is this useful?
233 private fun ancestor_for
(c
: MMLocalClass): MMAncestor
235 assert ancestors
!= null
237 if _ancestors
.has_key
(c
) then
240 var a
= c
.for_module
(mmmodule
)
243 if _ancestors
.has_key
(a
) then
245 else if c
.global
== _global
then
246 ra
= new MMRefineAncestor(self,c
)
248 ra
= new MMSpecAncestor(get_type
,c
.get_type
)
256 if _local_property_by_global
.has_key
(glob
) then
257 return _local_property_by_global
[glob
]
258 else if has_global_property
(glob
) then
259 return inherit_local_property
(glob
)
265 # Add default super class in direct parent and in super classes if this is not the Object class
266 private fun add_default_any_class
(supers
: Array[MMLocalClass])
268 if supers
.is_empty
and name
!= once
("Object".to_symbol
) then
269 var t_any
= mmmodule
.type_any
270 supers
.add
(t_any
.local_class
)
271 var default
= new MMDefaultAncestor(self, t_any
)
272 add_direct_parent
(default
)
276 # Adding inherited class from previous refinement of self
277 private fun add_super_classes
(supers
: Array[MMLocalClass])
280 for ref
in _crhe
.direct_greaters
do
281 for sup
in ref
.cshe
.direct_greaters
do
282 var cla
= sup
.for_module
(_mmmodule
)
288 # Add self parents of this local class
289 private fun add_explicit_classes
(supers
: Array[MMLocalClass])
291 for p
in _direct_parents
do
292 supers
.add
(p
.local_class
)
296 # Ensure all super parents are computed
297 private fun compute_super_parents
(supers
: Array[MMLocalClass])
300 p
.compute_super_classes
304 # compute all ancestors for a class (multiple)
305 private fun build_ancestors
: Array[MMAncestor]
307 var all_ancestors
= new Array[MMAncestor]
308 # Refined classes are ancestors
310 for p
in _crhe
.direct_greaters
do
312 var anc
= new MMRefineAncestor(self, p
)
313 anc
.add_in
(all_ancestors
)
315 for anc
in _direct_parents
do
316 assert anc
.local_class
!= self
317 anc
.add_in
(all_ancestors
)
322 # Build an ancestor map indexed by LocalClass
323 private fun group_ancestors
(all
: Array[MMAncestor]): Map[MMLocalClass, Set[MMAncestor]]
325 #print "process {self}"
326 var map
= new HashMap[MMLocalClass, Set[MMAncestor]]
328 var c
= a
.local_class
331 var set
: Set[MMAncestor]
333 if map
.has_key
(c
) then
336 set
= new HashSet[MMAncestor]
344 # Remove duplicate ancestors and merge if compatible, in the other case do an error
345 private fun merge_ancestors
(set
: Set[MMAncestor]): MMAncestor
347 var marks
= new HashSet[MMAncestor]
348 var res
= new Array[MMAncestor]
350 var it
= set
.iterator
352 while it
.is_ok
and search
do
355 a
= marks
.has
(it
.item
)
356 a
= it
.item
.stype
< t
.stype
358 if not(t
== it
.item
or marks
.has
(it
.item
)) and
359 (it
.item
.stype
< t
.stype
) then
365 if not marks
.has
(t
) then
370 if res
.length
> 1 then
371 stderr
.write
("Fatal error: Incompatibles ancestors for {self.name}: {res.join(", ")}\n")
377 # Inherit a local property
379 # FIXME: dont crash lazily
380 private fun inherit_local_property
(glob
: MMGlobalProperty): MMLocalProperty
382 assert not _local_property_by_global
.has_key
(glob
)
384 var impl
: MMLocalProperty
386 var ghier
= glob
.property_hierarchy
387 var supers
= che
.direct_greaters
388 if ghier
.length
== 1 then
389 # Unredefined property
391 else if supers
.length
== 1 then
393 impl
= supers
.first
[glob
]
395 # Hard multiple inheritance
396 # First compute the set of bottom properties
397 var impls
= new ArraySet[MMLocalProperty]
399 if sc
.has_global_property
(glob
) then impls
.add
(sc
[glob
])
401 # Second, extract most specific
402 var impls2
= ghier
.select_smallests
(impls
)
403 # Conflict case (FIXME)
404 if impls2
.length
!= 1 then
405 stderr
.write
("Fatal error: inherit_local_property error\n")
406 print
("------- {mmmodule}::{self} {glob.intro.full_name}")
408 print
(" {i.full_name}")
410 print
("------- {glob.property_hierarchy.first}")
411 print
("------- {glob.property_hierarchy.to_dot}")
417 # FIXME: Why these 3 lines ?
418 #var ac = ancestor_for(impl.local_class)
419 #ac.local_class.inherit_global_properties
421 #assert a.local_class != self
423 # Register the local property
424 _local_property_by_global
[glob
] = impl
430 redef class MMLocalProperty
431 # Attach self to a global property
432 fun inherit_global
(g
: MMGlobalProperty)
435 var impls
= new Array[MMLocalProperty]
436 for sc
in local_class
.che
.direct_greaters
do
437 if not sc
.has_global_property
(g
) then continue
440 g
.add_local_property
(self, impls
)
444 redef class MMAncestor
445 # Add this ancestor and it's super one in tab
446 private fun add_in
(tab
: Array[MMAncestor])
449 stype
.local_class
.compute_ancestors
450 for anc
in stype
.local_class
.ancestors
.as(not null) do
451 var aaa
= anc
.stype
.for_module
(stype
.mmmodule
)
452 var a
= aaa
.adapt_to
(stype
).for_module
(inheriter
.mmmodule
)
453 if a
.local_class
!= inheriter
.local_class
then
454 var it
= tab
.iterator
456 while it
.is_ok
and b
do
457 b
= not ( it
.item
.inheriter
== inheriter
and it
.item
.stype
== a
)
461 tab
.add
(new MMSpecAncestor(inheriter
,a
))
468 ##########################################
470 # A local class that is a pure importation of an other local class
471 class MMImplicitLocalClass
473 init(mod
: MMModule, g
: MMGlobalClass)
476 super(mod
, cla
.name
, cla
.arity
)
481 class MMRefineAncestor
483 redef readable var _local_class
: MMLocalClass
485 init(b
: MMLocalClass, a
: MMLocalClass)
488 inheriter
= b
.get_type
489 stype
= _local_class
.get_type
496 redef fun local_class
do return stype
.local_class
498 init(inheriter
: MMType, stype
: MMType)
500 _inheriter
= inheriter
505 class MMDefaultAncestor
507 redef fun local_class
do return stype
.local_class
509 init(b
: MMLocalClass, anc
: MMType)
511 inheriter
= b
.get_type