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 # Root of then extern class hierarchy
32 fun type_any_extern
: MMType
34 var c_name
= class_by_name
(once
("Pointer".to_symbol
))
35 return c_name
.get_type
38 # Import global classes from supermodules
39 fun import_global_classes
41 var globals
= new HashMap[MMGlobalClass,HashSet[MMLocalClass]]
43 for mod
in mhe
.direct_greaters
do
44 for glob
in mod
.global_classes
do
45 if global_classes
.has
(glob
) then continue
46 _global_classes
.add
(glob
)
47 _global_class_by_name
[glob
.name
] = glob
53 # Create implicit local classes for global classes that are not refined
54 fun import_local_classes
56 for g
in _global_classes
do
57 if _local_class_by_global
.has_key
(g
) then continue
58 var impl
= new MMImplicitLocalClass(self, g
)
63 redef class MMLocalClass
65 var _direct_parents
: Array[MMAncestor] = new Array[MMAncestor]
67 # Is the class computing super.
68 # Used to detect specialization loops.
69 var _computing_super
: Bool = false
71 # Compute super classes of a class
72 fun compute_super_classes
74 if computed_super_classes
then
75 # do no recompute if allready done
77 else if _computing_super
then
78 stderr
.write
("Fatal error: Inheritance loop for class {self}\n")
81 _computing_super
= true
83 var supers
= new Array[MMLocalClass]
84 add_explicit_classes
(supers
)
85 add_super_classes
(supers
)
86 add_default_any_class
(supers
)
87 compute_super_parents
(supers
)
88 var set
= new HashSet[MMLocalClass]
91 mmmodule
.set_supers_class
(self,u
)
94 _computing_super
= false
97 # Compute ancestors for a class
100 assert computed_super_classes
101 if computed_ancestors
then return
103 var ancestors
= group_ancestors
(build_ancestors
)
104 _ancestors
= new HashMap[MMLocalClass, MMAncestor]
106 for set
in ancestors
do
107 if set
.length
== 1 then
108 add_ancestor
(set
.first
)
110 var ma
= merge_ancestors
(set
)
111 add_ancestor
(merge_ancestors
(set
))
116 var _are_global_properties_inherited
: Bool = false
118 # Inherit global properties for a class
119 private fun inherit_global_properties
121 if _are_global_properties_inherited
then return
122 _are_global_properties_inherited
= true
124 var names
= _properties_by_name
125 var set
= _global_properties
126 for c
in che
.direct_greaters
do
127 for glob
in c
.global_properties
do
128 if set
.has
(glob
) then continue
130 set
.add
(glob
) # Add the global property
132 # Do not inherit constructors trough specialization
133 #print "{c.mmmodule}::{c} -> {mmmodule}::{self} for {glob.local_property.local_class.mmmodule}::{glob.local_property.local_class}::{glob.local_property} : {glob.is_init}"
134 if glob
.is_init
and glob
.intro
.local_class
.global
!= global
then
139 # Do not inherit new style attributes
140 if glob
.intro
.name
.to_s
[0] == '@' then continue
142 make_visible_an_inherited_global_property
(glob
)
147 redef fun global_properties
149 if _are_global_properties_inherited
then return _global_properties
150 assert computed_super_classes
151 inherit_global_properties
152 return _global_properties
155 redef fun has_global_property
(g
)
157 # has_global_property can be called during the construction of the class
158 # hierarchy to check that a type "X" is not a formal type.
159 if not computed_super_classes
then return false
161 var set
= _global_properties
162 if set
.has
(g
) then return true
163 for c
in che
.direct_greaters
do
164 if c
.has_global_property
(g
) then
172 redef fun has_global_property_by_name
(n
)
174 # has_global_property can be called during the construction of the class
175 # hierarchy to check that a type "X" is not a formal type.
176 if not computed_super_classes
then return false
178 # Ensure that super-classes are constructed
179 compute_super_classes
181 if _properties_by_name
.has_key
(n
) then
182 return _properties_by_name
[n
].length
== 1
184 var set
= _global_properties
186 if _properties_by_name
.has_key
(n
) then
187 nset
= _properties_by_name
[n
]
189 nset
= new Array[MMGlobalProperty]
190 _properties_by_name
[n
] = nset
192 for c
in che
.direct_greaters
do
193 if c
.has_global_property_by_name
(n
) then
194 var g
= c
.get_property_by_name
(n
)
195 if not set
.has
(g
) then set
.add
(g
)
196 if g
.is_init
and g
.intro
.local_class
.global
!= global
then continue
197 if g
.intro
.name
.to_s
.first
== '@' then continue # inherited new style attibutes are invisible
198 if nset
.has
(g
) then continue
202 return nset
.length
== 1
205 # Make the name of a global property meaningful in the class
206 fun make_visible_an_inherited_global_property
(glob
: MMGlobalProperty)
208 var names
= _properties_by_name
209 var gname
= glob
.intro
.name
210 var conf_set
: Array[MMGlobalProperty]
211 if names
.has_key
(gname
) then
212 conf_set
= names
[gname
]
214 conf_set
= new Array[MMGlobalProperty]
215 names
[gname
] = conf_set
220 # Add super stype of this current local class
221 fun add_direct_parent
(p
: MMAncestor)
223 _direct_parents
.add
(p
)
226 # Are super-class already computed?
227 fun computed_super_classes
: Bool
229 return _crhe
!= null and _cshe
!= null
232 # Are ancestors already computed
233 fun computed_ancestors
: Bool
235 return _ancestors
!= null
238 # Get the ancestor for a given class
239 # TODO: is this useful?
240 private fun ancestor_for
(c
: MMLocalClass): MMAncestor
242 assert ancestors
!= null
244 if _ancestors
.has_key
(c
) then
247 var a
= c
.for_module
(mmmodule
)
250 if _ancestors
.has_key
(a
) then
252 else if c
.global
== _global
then
253 ra
= new MMRefineAncestor(self,c
)
255 ra
= new MMSpecAncestor(get_type
,c
.get_type
)
263 if _local_property_by_global
.has_key
(glob
) then
264 return _local_property_by_global
[glob
]
265 else if has_global_property
(glob
) then
266 return inherit_local_property
(glob
)
272 # Add default super class in direct parent and in super classes if this is not the Object class
273 # Default super class is Pointer for extern types
274 private fun add_default_any_class
(supers
: Array[MMLocalClass])
276 if name
!= once
("Object".to_symbol
) then
277 var has_no_top
= false
278 if supers
.is_empty
then
280 else if global
.is_extern
then
283 if s
.global
.is_extern
then
292 if name
!= once
("Pointer".to_symbol
) and global
.is_extern
then
293 top_type
= mmmodule
.type_any_extern
295 top_type
= mmmodule
.type_any
297 supers
.add
(top_type
.local_class
)
298 var default
= new MMDefaultAncestor(self, top_type
)
299 add_direct_parent
(default
)
304 # Adding inherited class from previous refinement of self
305 private fun add_super_classes
(supers
: Array[MMLocalClass])
308 for ref
in _crhe
.direct_greaters
do
309 for sup
in ref
.cshe
.direct_greaters
do
310 var cla
= sup
.for_module
(_mmmodule
)
316 # Add self parents of this local class
317 private fun add_explicit_classes
(supers
: Array[MMLocalClass])
319 for p
in _direct_parents
do
320 supers
.add
(p
.local_class
)
324 # Ensure all super parents are computed
325 private fun compute_super_parents
(supers
: Array[MMLocalClass])
328 p
.compute_super_classes
332 # compute all ancestors for a class (multiple)
333 private fun build_ancestors
: Array[MMAncestor]
335 var all_ancestors
= new Array[MMAncestor]
336 # Refined classes are ancestors
338 for p
in _crhe
.direct_greaters
do
340 var anc
= new MMRefineAncestor(self, p
)
341 anc
.add_in
(all_ancestors
)
343 for anc
in _direct_parents
do
344 assert anc
.local_class
!= self
345 anc
.add_in
(all_ancestors
)
350 # Build an ancestor map indexed by LocalClass
351 private fun group_ancestors
(all
: Array[MMAncestor]): Map[MMLocalClass, Set[MMAncestor]]
353 #print "process {self}"
354 var map
= new HashMap[MMLocalClass, Set[MMAncestor]]
356 var c
= a
.local_class
359 var set
: Set[MMAncestor]
361 if map
.has_key
(c
) then
364 set
= new HashSet[MMAncestor]
372 # Remove duplicate ancestors and merge if compatible, in the other case do an error
373 private fun merge_ancestors
(set
: Set[MMAncestor]): MMAncestor
375 var marks
= new HashSet[MMAncestor]
376 var res
= new Array[MMAncestor]
378 var it
= set
.iterator
380 while it
.is_ok
and search
do
383 a
= marks
.has
(it
.item
)
384 a
= it
.item
.stype
< t
.stype
386 if not(t
== it
.item
or marks
.has
(it
.item
)) and
387 (it
.item
.stype
< t
.stype
) then
393 if not marks
.has
(t
) then
398 if res
.length
> 1 then
399 stderr
.write
("Fatal error: Incompatibles ancestors for {self.name}: {res.join(", ")}\n")
405 # Inherit a local property
407 # FIXME: dont crash lazily
408 private fun inherit_local_property
(glob
: MMGlobalProperty): MMLocalProperty
410 assert not _local_property_by_global
.has_key
(glob
)
412 var impl
: MMLocalProperty
414 var ghier
= glob
.property_hierarchy
415 var supers
= che
.direct_greaters
416 if ghier
.length
== 1 then
417 # Unredefined property
419 else if supers
.length
== 1 then
421 impl
= supers
.first
[glob
]
423 # Hard multiple inheritance
424 # First compute the set of bottom properties
425 var impls
= new ArraySet[MMLocalProperty]
427 if sc
.has_global_property
(glob
) then impls
.add
(sc
[glob
])
429 # Second, extract most specific
430 var impls2
= ghier
.select_smallests
(impls
)
431 # Conflict case (FIXME)
432 if impls2
.length
!= 1 then
433 stderr
.write
("Fatal error: inherit_local_property error\n")
434 print
("------- {mmmodule}::{self} {glob.intro.full_name}")
436 print
(" {i.full_name}")
438 print
("------- {glob.property_hierarchy.first}")
439 print
("------- {glob.property_hierarchy.to_dot}")
445 # FIXME: Why these 3 lines ?
446 #var ac = ancestor_for(impl.local_class)
447 #ac.local_class.inherit_global_properties
449 #assert a.local_class != self
451 # Register the local property
452 _local_property_by_global
[glob
] = impl
458 redef class MMLocalProperty
459 # Attach self to a global property
460 fun inherit_global
(g
: MMGlobalProperty)
463 var impls
= new Array[MMLocalProperty]
464 for sc
in local_class
.che
.direct_greaters
do
465 if not sc
.has_global_property
(g
) then continue
468 g
.add_local_property
(self, impls
)
472 redef class MMAncestor
473 # Add this ancestor and it's super one in tab
474 private fun add_in
(tab
: Array[MMAncestor])
477 stype
.local_class
.compute_ancestors
478 for anc
in stype
.local_class
.ancestors
.as(not null) do
479 var aaa
= anc
.stype
.for_module
(stype
.mmmodule
)
480 var a
= aaa
.adapt_to
(stype
).for_module
(inheriter
.mmmodule
)
481 if a
.local_class
!= inheriter
.local_class
then
482 var it
= tab
.iterator
484 while it
.is_ok
and b
do
485 b
= not ( it
.item
.inheriter
== inheriter
and it
.item
.stype
== a
)
489 tab
.add
(new MMSpecAncestor(inheriter
,a
))
496 ##########################################
498 # A local class that is a pure importation of an other local class
499 class MMImplicitLocalClass
501 init(mod
: MMModule, g
: MMGlobalClass)
504 super(mod
, cla
.name
, cla
.arity
)
509 class MMRefineAncestor
511 redef readable var _local_class
: MMLocalClass
513 init(b
: MMLocalClass, a
: MMLocalClass)
516 inheriter
= b
.get_type
517 stype
= _local_class
.get_type
524 redef fun local_class
do return stype
.local_class
526 init(inheriter
: MMType, stype
: MMType)
528 _inheriter
= inheriter
533 class MMDefaultAncestor
535 redef fun local_class
do return stype
.local_class
537 init(b
: MMLocalClass, anc
: MMType)
539 inheriter
= b
.get_type