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 meth 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 meth import_local_classes
49 for g
in _global_classes
do
50 if self[g
] != null then continue
51 var impl
= new MMImplicitLocalClass(self, g
)
56 redef class MMLocalClass
58 attr _direct_parents
: Array[MMAncestor] = new Array[MMAncestor]
60 # Is the class computing super.
61 # Used to detect specialization loops.
62 attr _computing_super
: Bool
64 # Compute super classes of a class
65 meth 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 module.set_supers_class
(self,u
)
87 _computing_super
= false
90 # Compute ancestors for a class
91 meth compute_ancestors
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 # Inherit global properties for a class
110 meth inherit_global_properties
112 if _global_properties
!= null then return
114 _global_properties
= new HashSet[MMGlobalProperty]
115 _properties_by_name
= new HashMap[Symbol, Array[MMGlobalProperty]]
116 _local_property_by_global
= new HashMap[MMGlobalProperty, MMLocalProperty]
118 var names
= _properties_by_name
119 var set
= _global_properties
120 for c
in che
.direct_greaters
do
121 for glob
in c
.global_properties
do
122 if set
.has
(glob
) then continue
124 set
.add
(glob
) # Add the global property
126 # Do not inherit constructors trough specialization
127 #print "{c.module}::{c} -> {module}::{self} for {glob.local_property.local_class.module}::{glob.local_property.local_class}::{glob.local_property} : {glob.is_init}"
128 if glob
.is_init
and glob
.intro
.local_class
.global
!= global
then
133 var gname
= glob
.intro
.name
134 var conf_set
: Array[MMGlobalProperty]
135 if names
.has_key
(gname
) then
136 conf_set
= names
[gname
]
138 conf_set
= new Array[MMGlobalProperty]
139 names
[gname
] = conf_set
146 # Add super stype of this current local class
147 meth add_direct_parent
(p
: MMAncestor)
149 _direct_parents
.add
(p
)
152 # Are super-class already computed?
153 meth computed_super_classes
: Bool
155 return _crhe
!= null and _cshe
!= null
158 # Are ancestors already computed
159 meth computed_ancestors
: Bool
161 return _ancestors
!= null
164 # Get the ancestor for a given class
165 # TODO: is this useful?
166 private meth ancestor_for
(c
: MMLocalClass): MMAncestor
168 assert ancestors
!= null
170 if _ancestors
.has_key
(c
) then
173 var a
= c
.for_module
(module)
176 if _ancestors
.has_key
(a
) then
178 else if c
.global
== _global
then
179 ra
= new MMRefineAncestor(self,c
)
181 ra
= new MMSpecAncestor(get_type
,c
.get_type
)
189 var prop
= super(glob
)
190 if prop
== null and _global_properties
.has
(glob
) then
191 prop
= inherit_local_property
(glob
)
196 # Add default super class in direct parent and in super classes if this is not the Object class
197 private meth add_default_any_class
(supers
: Array[MMLocalClass])
199 if supers
.is_empty
and name
!= once
("Object".to_symbol
) then
200 var t_any
= module.type_any
201 supers
.add
(t_any
.local_class
)
202 var default
= new MMDefaultAncestor(self, t_any
)
203 add_direct_parent
(default
)
207 # Adding inherited class from previous refinement of self
208 private meth add_super_classes
(supers
: Array[MMLocalClass])
211 for ref
in _crhe
.direct_greaters
do
212 assert ref
.cshe
!= null
213 for sup
in ref
.cshe
.direct_greaters
do
214 var cla
= sup
.for_module
(_module
)
221 # Add self parents of this local class
222 private meth add_explicit_classes
(supers
: Array[MMLocalClass])
224 for p
in _direct_parents
do
225 supers
.add
(p
.local_class
)
229 # Ensure all super parents are computed
230 private meth compute_super_parents
(supers
: Array[MMLocalClass])
234 p
.compute_super_classes
238 # compute all ancestors for a class (multiple)
239 private meth build_ancestors
: Array[MMAncestor]
241 var all_ancestors
= new Array[MMAncestor]
242 # Refined classes are ancestors
244 for p
in _crhe
.direct_greaters
do
246 var anc
= new MMRefineAncestor(self, p
)
247 anc
.add_in
(all_ancestors
)
249 for anc
in _direct_parents
do
250 assert anc
.local_class
!= self
251 anc
.add_in
(all_ancestors
)
256 # Build an ancestor map indexed by LocalClass
257 private meth group_ancestors
(all
: Array[MMAncestor]): Map[MMLocalClass, Set[MMAncestor]]
259 #print "process {self}"
260 var map
= new HashMap[MMLocalClass, Set[MMAncestor]]
262 var c
= a
.local_class
265 var set
: Set[MMAncestor]
267 if map
.has_key
(c
) then
270 set
= new HashSet[MMAncestor]
278 # Remove duplicate ancestors and merge if compatible, in the other case do an error
279 private meth merge_ancestors
(set
: Set[MMAncestor]): MMAncestor
281 var marks
= new HashSet[MMAncestor]
282 var res
= new Array[MMAncestor]
284 var it
= set
.iterator
286 while it
.is_ok
and search
do
289 a
= marks
.has
(it
.item
)
290 a
= it
.item
.stype
< t
.stype
292 if not(t
== it
.item
or marks
.has
(it
.item
)) and
293 (it
.item
.stype
< t
.stype
) then
299 if not marks
.has
(t
) then
304 if res
.length
> 1 then
305 stderr
.write
("Fatal error: Incompatibles ancestors for {self.name}: {res.join(", ")}\n")
311 # Inherit a local property
313 # FIXME: dont crash lazily
314 private meth inherit_local_property
(glob
: MMGlobalProperty): MMLocalProperty
316 assert not _local_property_by_global
.has_key
(glob
)
319 var impls
= glob
.get_compatible_concrete_properties_for
(self)
320 if impls
.length
!= 1 then
321 stderr
.write
("Fatal error: inherit_local_property error\n")
322 print
("------- {module}::{self} {glob.intro.full_name}")
324 print
(" {i.full_name}")
326 print
("------- {glob.concrete_property_hierarchy.first}")
327 print
("------- {glob.concrete_property_hierarchy.to_dot}")
330 var impl
= impls
.first
331 var ac
= ancestor_for
(impl
.local_class
)
332 ac
.local_class
.inherit_global_properties
335 assert a
.local_class
!= self
336 var sup
= a
.select_property
(glob
) # Select super prop
338 var prop
= sup
.inherit_to
(get_type
) # special the new prop
343 redef class MMConcreteProperty
345 meth is_deferred
: Bool do return false
348 redef class MMGlobalProperty
349 # Get the most specific local properties defined in superclasses of c
350 private meth get_compatible_concrete_properties_for
(cla
: MMLocalClass): Array[MMConcreteProperty]
352 var impl_hier
= _concrete_property_hierarchy
353 if impl_hier
.length
== 1 then return [intro
]
354 var impls
= new ArraySet[MMConcreteProperty]
357 #print "{cla.module}::{cla} get glob {intro.local_class}::{intro.name}"
358 for sc
in cla
.che
.direct_greaters
do
359 #print " try {sc.module}::{sc} {sc.che != null} {sc.crhe != null} {sc.che != null}"
361 if p
== null then continue
362 var impl
= p
.concrete_property
366 for impl
in impl_hier
do
367 var bc
= impl
.local_class
373 return impl_hier
.select_smallests
(impls
)
377 redef class MMLocalProperty
378 # Attach self to a global property
379 meth inherit_global
(g
: MMGlobalProperty)
382 # What the next line used for?
383 g
.add_concrete_property
(concrete_property
, g
.get_compatible_concrete_properties_for
(local_class
))
386 # Create an adaptation of self to a different receiver
387 meth inherit_to
(t
: MMType): MMLocalProperty is abstract
390 protected meth inherit_from
(s
: MMLocalProperty, t
: MMType) # for the super bugs
392 assert _super_prop
== null
394 if _global
== null then
402 redef meth inherit_to
(t
) do
403 return new MMImplicitMethod(self, t
)
407 # A local property that is an adatation of an exiting one
408 class MMImplicitProperty
409 special MMLocalProperty
410 # Create a property from an existing property and a new receiver
411 init(prop
: MMLocalProperty, bt
: MMType)
413 super(prop
.name
, bt
.local_class
, prop
.concrete_property
)
414 inherit_from
(prop
, bt
)
418 class MMImplicitMethod
420 special MMImplicitProperty
424 redef class MMAttribute
425 redef meth inherit_to
(t
)
427 return new MMImplicitAttribute(self,t
)
431 class MMImplicitAttribute
433 special MMImplicitProperty
437 redef class MMAncestor
438 # Add this ancestor and it's super one in tab
439 private meth add_in
(tab
: Array[MMAncestor])
441 assert ancestor
: stype
!= null
442 assert local_class
: stype
.local_class
!= null
444 stype
.local_class
.compute_ancestors
445 for anc
in stype
.local_class
.ancestors
do
446 var aaa
= anc
.stype
.for_module
(stype
.module)
447 var a
= aaa
.adapt_to
(stype
).for_module
(inheriter
.module)
448 if a
.local_class
!= inheriter
.local_class
then
449 var it
= tab
.iterator
451 while it
.is_ok
and b
do
452 b
= not ( it
.item
.inheriter
== inheriter
and it
.item
.stype
== a
)
456 tab
.add
(new MMSpecAncestor(inheriter
,a
))
463 ##########################################
465 # A local class that is a pure importation of an other local class
466 class MMImplicitLocalClass
468 init(mod
: MMModule, g
: MMGlobalClass)
471 super(cla
.name
, cla
.arity
)
472 mod
.add_local_class
(self)
477 class MMRefineAncestor
479 redef readable attr _local_class
: MMLocalClass
481 init(b
: MMLocalClass, a
: MMLocalClass)
484 inheriter
= b
.get_type
485 stype
= _local_class
.get_type
492 redef meth local_class
do return stype
.local_class
494 init(inheriter
: MMType, stype
: MMType)
496 _inheriter
= inheriter
501 class MMDefaultAncestor
503 redef meth local_class
do return stype
.local_class
505 init(b
: MMLocalClass, anc
: MMType)
508 assert b
.module != null
510 inheriter
= b
.get_type