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 # Method to redefine to handle the property conflicts
25 # FIXME: This is just a bad workaround because of a bad design
26 fun handle_property_conflict
(lc
: MMLocalClass, impls2
: Array[MMLocalProperty])
28 var glob
= impls2
.first
.global
29 stderr
.write
("Fatal error: inherit_local_property error\n")
30 print
("------- {lc.mmmodule}::{lc} {glob.intro.full_name}")
32 print
(" {i.full_name}")
34 print
("------- {glob.property_hierarchy.first}")
35 print
("------- {glob.property_hierarchy.to_dot}")
41 # The root of the class hierarchy
44 var c_name
= class_by_name
(once
("Object".to_symbol
))
45 return c_name
.get_type
48 # Root of then extern class hierarchy
49 fun type_any_extern
: MMType
51 var c_name
= class_by_name
(once
("Pointer".to_symbol
))
52 return c_name
.get_type
55 # Import global classes from supermodules
56 fun import_global_classes
58 var globals
= new HashMap[MMGlobalClass,HashSet[MMLocalClass]]
60 for mod
in mhe
.direct_greaters
do
61 for glob
in mod
.global_classes
do
62 if global_classes
.has
(glob
) then continue
63 _global_classes
.add
(glob
)
64 _global_class_by_name
[glob
.name
] = glob
70 # Create implicit local classes for global classes that are not refined
71 fun import_local_classes
73 for g
in _global_classes
do
74 if _local_class_by_global
.has_key
(g
) then continue
75 var impl
= new MMImplicitLocalClass(self, g
)
80 redef class MMLocalClass
82 var _direct_parents
: Array[MMAncestor] = new Array[MMAncestor]
84 # Is the class computing super.
85 # Used to detect specialization loops.
86 var _computing_super
: Bool = false
88 # Compute super classes of a class
89 fun compute_super_classes
91 if computed_super_classes
then
92 # do no recompute if allready done
94 else if _computing_super
then
95 stderr
.write
("Fatal error: Inheritance loop for class {self}\n")
98 _computing_super
= true
100 var supers
= new Array[MMLocalClass]
101 add_explicit_classes
(supers
)
102 add_super_classes
(supers
)
103 add_default_any_class
(supers
)
104 compute_super_parents
(supers
)
105 var set
= new HashSet[MMLocalClass]
108 mmmodule
.set_supers_class
(self,u
)
111 _computing_super
= false
114 # Compute ancestors for a class
115 fun compute_ancestors
117 assert computed_super_classes
118 if computed_ancestors
then return
120 var ancestors
= group_ancestors
(build_ancestors
)
121 _ancestors
= new HashMap[MMLocalClass, MMAncestor]
123 for set
in ancestors
.values
do
124 if set
.length
== 1 then
125 add_ancestor
(set
.first
)
127 var ma
= merge_ancestors
(set
)
128 add_ancestor
(merge_ancestors
(set
))
133 var _are_global_properties_inherited
: Bool = false
135 # Inherit global properties for a class
136 private fun inherit_global_properties
138 if _are_global_properties_inherited
then return
139 _are_global_properties_inherited
= true
141 var names
= _properties_by_name
142 var set
= _global_properties
143 for c
in che
.direct_greaters
do
144 for glob
in c
.global_properties
do
145 if set
.has
(glob
) then continue
147 set
.add
(glob
) # Add the global property
149 # Do not inherit constructors trough specialization
150 #print "{c.mmmodule}::{c} -> {mmmodule}::{self} for {glob.local_property.local_class.mmmodule}::{glob.local_property.local_class}::{glob.local_property} : {glob.is_init}"
151 if glob
.is_init
and glob
.intro
.local_class
.global
!= global
then
156 # Do not inherit new style attributes
157 if glob
.intro
.name
.to_s
[0] == '@' then continue
159 make_visible_an_inherited_global_property
(glob
)
164 redef fun global_properties
166 if _are_global_properties_inherited
then return _global_properties
167 assert computed_super_classes
168 inherit_global_properties
169 return _global_properties
172 redef fun has_global_property
(g
)
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 var set
= _global_properties
179 if set
.has
(g
) then return true
180 for c
in che
.direct_greaters
do
181 if c
.has_global_property
(g
) then
189 redef fun has_global_property_by_name
(n
)
191 # has_global_property can be called during the construction of the class
192 # hierarchy to check that a type "X" is not a formal type.
193 if not computed_super_classes
then return false
195 # Ensure that super-classes are constructed
196 compute_super_classes
198 if _properties_by_name
.has_key
(n
) then
199 return _properties_by_name
[n
].length
== 1
201 var set
= _global_properties
203 if _properties_by_name
.has_key
(n
) then
204 nset
= _properties_by_name
[n
]
206 nset
= new Array[MMGlobalProperty]
207 _properties_by_name
[n
] = nset
209 for c
in che
.direct_greaters
do
210 if c
.has_global_property_by_name
(n
) then
211 var g
= c
.get_property_by_name
(n
)
212 if not set
.has
(g
) then set
.add
(g
)
213 if g
.is_init
and g
.intro
.local_class
.global
!= global
then continue
214 if g
.intro
.name
.to_s
.first
== '@' then continue # inherited new style attibutes are invisible
215 if nset
.has
(g
) then continue
219 return nset
.length
== 1
222 # Make the name of a global property meaningful in the class
223 fun make_visible_an_inherited_global_property
(glob
: MMGlobalProperty)
225 var names
= _properties_by_name
226 var gname
= glob
.intro
.name
227 var conf_set
: Array[MMGlobalProperty]
228 if names
.has_key
(gname
) then
229 conf_set
= names
[gname
]
231 conf_set
= new Array[MMGlobalProperty]
232 names
[gname
] = conf_set
237 # Add super stype of this current local class
238 fun add_direct_parent
(p
: MMAncestor)
240 _direct_parents
.add
(p
)
243 # Are super-class already computed?
244 fun computed_super_classes
: Bool
246 return _crhe
!= null and _cshe
!= null
249 # Are ancestors already computed
250 fun computed_ancestors
: Bool
252 return _ancestors
!= null
255 # Get the ancestor for a given class
256 # TODO: is this useful?
257 private fun ancestor_for
(c
: MMLocalClass): MMAncestor
259 assert ancestors
!= null
261 if _ancestors
.has_key
(c
) then
264 var a
= c
.for_module
(mmmodule
)
267 if _ancestors
.has_key
(a
) then
269 else if c
.global
== _global
then
270 ra
= new MMRefineAncestor(self,c
)
272 ra
= new MMSpecAncestor(get_type
,c
.get_type
)
280 if _local_property_by_global
.has_key
(glob
) then
281 return _local_property_by_global
[glob
]
282 else if has_global_property
(glob
) then
283 return inherit_local_property
(glob
)
284 else if not computed_super_classes
then
285 compute_super_classes
287 inherit_global_properties
288 assert has_global_property
(glob
)
289 return inherit_local_property
(glob
)
295 # Add default super class in direct parent and in super classes if this is not the Object class
296 # Default super class is Pointer for extern types
297 private fun add_default_any_class
(supers
: Array[MMLocalClass])
299 if name
!= once
("Object".to_symbol
) then
300 var has_no_top
= false
301 if supers
.is_empty
then
303 else if global
.is_extern
then
306 if s
.global
.is_extern
then
315 if name
!= once
("Pointer".to_symbol
) and global
.is_extern
then
316 top_type
= mmmodule
.type_any_extern
318 top_type
= mmmodule
.type_any
320 supers
.add
(top_type
.local_class
)
321 var default
= new MMDefaultAncestor(self, top_type
)
322 add_direct_parent
(default
)
327 # Adding inherited class from previous refinement of self
328 private fun add_super_classes
(supers
: Array[MMLocalClass])
331 for ref
in _crhe
.direct_greaters
do
332 for sup
in ref
.cshe
.direct_greaters
do
333 var cla
= sup
.for_module
(_mmmodule
)
339 # Add self parents of this local class
340 private fun add_explicit_classes
(supers
: Array[MMLocalClass])
342 for p
in _direct_parents
do
343 supers
.add
(p
.local_class
)
347 # Ensure all super parents are computed
348 private fun compute_super_parents
(supers
: Array[MMLocalClass])
351 p
.compute_super_classes
355 # compute all ancestors for a class (multiple)
356 private fun build_ancestors
: Array[MMAncestor]
358 var all_ancestors
= new Array[MMAncestor]
359 # Refined classes are ancestors
361 for p
in _crhe
.direct_greaters
do
363 var anc
= new MMRefineAncestor(self, p
)
364 anc
.add_in
(all_ancestors
)
366 for anc
in _direct_parents
do
367 assert anc
.local_class
!= self
368 anc
.add_in
(all_ancestors
)
373 # Build an ancestor map indexed by LocalClass
374 private fun group_ancestors
(all
: Array[MMAncestor]): Map[MMLocalClass, Set[MMAncestor]]
376 #print "process {self}"
377 var map
= new HashMap[MMLocalClass, Set[MMAncestor]]
379 var c
= a
.local_class
382 var set
: Set[MMAncestor]
384 if map
.has_key
(c
) then
387 set
= new HashSet[MMAncestor]
395 # Remove duplicate ancestors and merge if compatible, in the other case do an error
396 private fun merge_ancestors
(set
: Set[MMAncestor]): MMAncestor
398 var marks
= new HashSet[MMAncestor]
399 var res
= new Array[MMAncestor]
401 var it
= set
.iterator
403 while it
.is_ok
and search
do
406 a
= marks
.has
(it
.item
)
407 a
= it
.item
.stype
< t
.stype
409 if not(t
== it
.item
or marks
.has
(it
.item
)) and
410 (it
.item
.stype
< t
.stype
) then
416 if not marks
.has
(t
) then
421 if res
.length
> 1 then
422 stderr
.write
("Fatal error: Incompatibles ancestors for {self.name}: {res.join(", ")}\n")
428 # Inherit a local property
430 # FIXME: dont crash lazily
431 private fun inherit_local_property
(glob
: MMGlobalProperty): MMLocalProperty
433 assert not _local_property_by_global
.has_key
(glob
)
435 var impl
: MMLocalProperty
437 var ghier
= glob
.property_hierarchy
438 var supers
= che
.direct_greaters
439 if ghier
.length
== 1 then
440 # Unredefined property
442 else if supers
.length
== 1 then
444 impl
= supers
.first
[glob
]
446 # Hard multiple inheritance
447 # First compute the set of bottom properties
448 var impls
= new ArraySet[MMLocalProperty]
450 if sc
.has_global_property
(glob
) then impls
.add
(sc
[glob
])
452 # Second, extract most specific
453 var impls2
= ghier
.select_smallests
(impls
)
454 # Conflict case (FIXME)
455 if impls2
.length
!= 1 then
456 self.mmmodule
.context
.handle_property_conflict
(self, impls2
)
461 # FIXME: Why these 3 lines ?
462 #var ac = ancestor_for(impl.local_class)
463 #ac.local_class.inherit_global_properties
465 #assert a.local_class != self
467 # Register the local property
468 _local_property_by_global
[glob
] = impl
474 redef class MMLocalProperty
475 # Attach self to a global property
476 fun inherit_global
(g
: MMGlobalProperty)
479 var impls
= new Array[MMLocalProperty]
480 for sc
in local_class
.che
.direct_greaters
do
481 if not sc
.has_global_property
(g
) then continue
484 g
.add_local_property
(self, impls
)
488 redef class MMAncestor
489 # Add this ancestor and it's super one in tab
490 private fun add_in
(tab
: Array[MMAncestor])
493 stype
.local_class
.compute_ancestors
494 for anc
in stype
.local_class
.ancestors
.values
do
495 var aaa
= anc
.stype
.for_module
(stype
.mmmodule
)
496 var a
= aaa
.adapt_to
(stype
).for_module
(inheriter
.mmmodule
)
497 if a
.local_class
!= inheriter
.local_class
then
498 var it
= tab
.iterator
500 while it
.is_ok
and b
do
501 b
= not ( it
.item
.inheriter
== inheriter
and it
.item
.stype
== a
)
505 tab
.add
(new MMSpecAncestor(inheriter
,a
))
512 ##########################################
514 # A local class that is a pure importation of an other local class
515 class MMImplicitLocalClass
517 init(mod
: MMModule, g
: MMGlobalClass)
520 super(mod
, cla
.name
, cla
.arity
)
525 class MMRefineAncestor
527 redef readable var _local_class
: MMLocalClass
529 init(b
: MMLocalClass, a
: MMLocalClass)
532 inheriter
= b
.get_type
533 stype
= _local_class
.get_type
540 redef fun local_class
do return stype
.local_class
542 init(inheriter
: MMType, stype
: MMType)
544 _inheriter
= inheriter
549 class MMDefaultAncestor
551 redef fun local_class
do return stype
.local_class
553 init(b
: MMLocalClass, anc
: MMType)
555 inheriter
= b
.get_type