1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Graph coloring tools
23 # Unic ids or each element
24 var ids
: Map[E
, Int] = new HashMap[E
, Int]
25 # Fixed positions of each element in all tables
26 var pos
: Map[E
, Int] = new HashMap[E
, Int]
29 class PHTypingLayout[E
]
31 # Masks used by hash function
32 var masks
: Map[E
, Int] = new HashMap[E
, Int]
33 # Positions of each element for each tables
34 var hashes
: Map[E
, Map[E
, Int]] = new HashMap[E
, Map[E
, Int]]
37 class PropertyLayout[E
]
38 # Fixed positions of each element in all tables
39 var pos
: Map[E
, Int] = new HashMap[E
, Int]
42 # Layout for resolution tables
43 class ResolutionLayout
44 # Unic ids for each resolved type
45 var ids
: Map[MType, Int] = new HashMap[MType, Int]
46 # Fixed positions of resolved type
47 var pos
: Map[MType, Int] = new HashMap[MType, Int]
50 class PHResolutionLayout
51 super ResolutionLayout
52 # Masks associated to each owner of a resolution table
53 var masks
: Map[MClassType, Int] = new HashMap[MClassType, Int]
54 # Positions of each resolvec type for resolution tables
55 var hashes
: Map[MClassType, Map[MType, Int]] = new HashMap[MClassType, Map[MType, Int]]
60 abstract class TypingLayoutBuilder[E
]
62 type LAYOUT: TypingLayout[E
]
64 private var mmodule
: MModule
65 init(mmodule
: MModule) do self.mmodule
= mmodule
67 # Compute elements ids and position
68 fun build_layout
(elements
: Set[E
]): LAYOUT is abstract
70 # Give each MType a unic id using a descending linearization of the `mtypes` set
71 private fun compute_ids
(elements
: Set[E
]): Map[E
, Int] do
72 var ids
= new HashMap[E
, Int]
73 var lin
= self.reverse_linearize
(elements
)
75 ids
[element
] = ids
.length
80 private fun reverse_linearize
(elements
: Set[E
]): Array[E
] is abstract
83 # Layout builder for MType using Binary Matrix (BM)
84 class BMTypeLayoutBuilder
85 super TypingLayoutBuilder[MType]
87 init(mmodule
: MModule) do super
89 # Compute mtypes ids and position using BM
90 redef fun build_layout
(mtypes
) do
91 var result
= new TypingLayout[MType]
92 result
.ids
= self.compute_ids
(mtypes
)
93 result
.pos
= result
.ids
97 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mtypes
(elements
)
100 # Layout builder for MType using Coloring (CL)
101 class CLTypeLayoutBuilder
102 super TypingLayoutBuilder[MType]
104 private var colorer
: MTypeColorer
106 init(mmodule
: MModule) do
108 self.colorer
= new MTypeColorer(mmodule
)
111 # Compute mtypes ids and position using BM
112 redef fun build_layout
(mtypes
) do
113 var result
= new TypingLayout[MType]
114 result
.ids
= self.compute_ids
(mtypes
)
115 result
.pos
= self.colorer
.colorize
(mtypes
)
119 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mtypes
(elements
)
122 # Layout builder for MType using Perfect Hashing (PH)
123 class PHTypeLayoutBuilder
124 super TypingLayoutBuilder[MType]
126 redef type LAYOUT: PHTypingLayout[MType]
128 private var hasher
: MTypeHasher
130 init(mmodule
: MModule, operator
: PHOperator) do
132 self.hasher
= new MTypeHasher(mmodule
, operator
)
135 # Compute mtypes ids and position using BM
136 redef fun build_layout
(mtypes
) do
137 var result
= new PHTypingLayout[MType]
138 result
.ids
= self.compute_ids
(mtypes
)
139 result
.masks
= self.hasher
.compute_masks
(mtypes
, result
.ids
)
140 result
.hashes
= self.hasher
.compute_hashes
(mtypes
, result
.ids
, result
.masks
)
144 # Ids start from 1 instead of 0
145 redef fun compute_ids
(mtypes
) do
146 var ids
= new HashMap[MType, Int]
147 var lin
= self.mmodule
.reverse_linearize_mtypes
(mtypes
)
149 ids
[mtype
] = ids
.length
+ 1
154 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mtypes
(elements
)
157 # Layout builder for MClass using Binary Matrix (BM)
158 class BMClassLayoutBuilder
159 super TypingLayoutBuilder[MClass]
161 init(mmodule
: MModule) do super
163 # Compute mclasses ids and position using BM
164 redef fun build_layout
(mclasses
) do
165 var result
= new TypingLayout[MClass]
166 result
.ids
= self.compute_ids
(mclasses
)
167 result
.pos
= result
.ids
171 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mclasses
(elements
)
174 # Layout builder for MClass using Coloring (CL)
175 class CLClassLayoutBuilder
176 super TypingLayoutBuilder[MClass]
178 private var colorer
: MClassColorer
180 init(mmodule
: MModule) do
182 self.colorer
= new MClassColorer(mmodule
)
185 # Compute mclasses ids and position using BM
186 redef fun build_layout
(mclasses
) do
187 var result
= new TypingLayout[MClass]
188 result
.ids
= self.compute_ids
(mclasses
)
189 result
.pos
= self.colorer
.colorize
(mclasses
)
193 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mclasses
(elements
)
196 # Layout builder for MClass using Perfect Hashing (PH)
197 class PHClassLayoutBuilder
198 super TypingLayoutBuilder[MClass]
200 redef type LAYOUT: PHTypingLayout[MClass]
202 private var hasher
: MClassHasher
204 init(mmodule
: MModule, operator
: PHOperator) do
206 self.hasher
= new MClassHasher(mmodule
, operator
)
209 # Compute mclasses ids and position using BM
210 redef fun build_layout
(mclasses
) do
211 var result
= new PHTypingLayout[MClass]
212 result
.ids
= self.compute_ids
(mclasses
)
213 result
.masks
= self.hasher
.compute_masks
(mclasses
, result
.ids
)
214 result
.hashes
= self.hasher
.compute_hashes
(mclasses
, result
.ids
, result
.masks
)
218 # Ids start from 1 instead of 0
219 redef fun compute_ids
(mclasses
) do
220 var ids
= new HashMap[MClass, Int]
221 var lin
= self.mmodule
.reverse_linearize_mclasses
(mclasses
)
223 ids
[mclass
] = ids
.length
+ 1
228 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mclasses
(elements
)
231 abstract class PropertyLayoutBuilder[E
: MProperty]
233 type LAYOUT: PropertyLayout[E
]
235 private var mmodule
: MModule
236 init(mmodule
: MModule) do self.mmodule
= mmodule
238 # Compute properties ids and position
239 fun build_layout
(mclasses
: Set[MClass]): LAYOUT is abstract
242 # Layout builder for MProperty using Coloring (CL)
243 class CLPropertyLayoutBuilder[E
: MProperty]
244 super PropertyLayoutBuilder[E
]
246 private var colorer
: MPropertyColorer[E
]
248 init(mmodule
: MModule) do
250 self.colorer
= new MPropertyColorer[E
](mmodule
)
253 # Compute mclasses ids and position using BM
254 redef fun build_layout
(mclasses
) do
255 var result
= new PropertyLayout[E
]
256 result
.pos
= self.colorer
.colorize
(mclasses
)
261 abstract class ResolutionLayoutBuilder
263 type LAYOUT: ResolutionLayout
267 fun build_layout
(elements
: Map[MClassType, Set[MType]]): LAYOUT is abstract
269 fun compute_ids
(elements
: Map[MClassType, Set[MType]]): Map[MType, Int] do
270 var ids
= new HashMap[MType, Int]
272 for mclasstype
, mclasstypes
in elements
do
273 for element
in mclasstypes
do
274 if ids
.has_key
(element
) then continue
283 # Layout builder for MClass using Binary Matrix (BM)
284 class BMResolutionLayoutBuilder
285 super ResolutionLayoutBuilder
289 # Compute resolved types position using BM
290 redef fun build_layout
(elements
) do
291 var result
= new ResolutionLayout
292 result
.ids
= self.compute_ids
(elements
)
293 result
.pos
= result
.ids
298 # Layout builder for resolution tables using Coloring (CL)
299 class CLResolutionLayoutBuilder
300 super ResolutionLayoutBuilder
302 private var colorer
: ResolutionColorer = new ResolutionColorer
306 # Compute resolved types colors
307 redef fun build_layout
(elements
) do
308 var result
= new ResolutionLayout
309 result
.ids
= self.compute_ids
(elements
)
310 result
.pos
= self.colorer
.colorize
(elements
)
315 # Layout builder for resolution table using Perfect Hashing (PH)
316 class PHResolutionLayoutBuilder
317 super ResolutionLayoutBuilder
319 redef type LAYOUT: PHResolutionLayout
321 private var hasher
: ResolutionHasher
323 init(operator
: PHOperator) do self.hasher
= new ResolutionHasher(operator
)
325 # Compute resolved types masks and hashes
326 redef fun build_layout
(elements
) do
327 var result
= new PHResolutionLayout
328 result
.ids
= self.compute_ids
(elements
)
329 result
.pos
= result
.ids
330 result
.masks
= self.hasher
.compute_masks
(elements
, result
.ids
)
331 result
.hashes
= self.hasher
.compute_hashes
(elements
, result
.ids
, result
.masks
)
335 redef fun compute_ids
(elements
) do
336 var ids
= new HashMap[MType, Int]
338 for mclasstype
, mclasstypes
in elements
do
339 for element
in mclasstypes
do
340 if ids
.has_key
(element
) then continue
351 abstract class AbstractColorer[E
: Object]
353 private var core
: Set[E
] = new HashSet[E
]
354 private var crown
: Set[E
] = new HashSet[E
]
355 private var border
: Set[E
] = new HashSet[E
]
357 private var coloration_result
: Map[E
, Int] = new HashMap[E
, Int]
361 fun colorize
(elements
: Set[E
]): Map[E
, Int] do
362 tag_elements
(elements
)
363 build_conflicts_graph
(elements
)
364 colorize_elements
(core
)
365 colorize_elements
(border
)
366 colorize_elements
(crown
)
367 return coloration_result
370 # Colorize a collection of elements
371 private fun colorize_elements
(elements
: Set[E
]) do
374 var lin
= reverse_linearize
(elements
)
375 for element
in lin
do
376 var color
= min_color
377 while not self.is_color_free
(element
, elements
, color
) do
380 coloration_result
[element
] = color
385 # Check if a related element to the element already use the color
386 private fun is_color_free
(element
: E
, elements
: Set[E
], color
: Int): Bool do
387 if conflicts_graph
.has_key
(element
) then
388 for st
in conflicts_graph
[element
] do
389 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
392 for st
in self.super_elements
(element
, elements
) do
393 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
398 # Tag elements as core, crown or border
399 private fun tag_elements
(elements
: Set[E
]) do
400 for element
in elements
do
401 # Check if sub elements are all in single inheritance
402 var all_subelements_si
= true
403 for subelem
in self.sub_elements
(element
, elements
) do
404 if self.is_element_mi
(subelem
, elements
) then
405 all_subelements_si
= false
410 # Tag as core, crown or border
411 if self.is_element_mi
(element
, elements
) then
412 core
.add_all
(self.super_elements
(element
, elements
))
414 if all_subelements_si
then
417 else if not all_subelements_si
then
418 core
.add_all
(self.super_elements
(element
, elements
))
426 # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
427 private fun build_conflicts_graph
(elements
: Set[E
]) do
428 self.conflicts_graph
= new HashMap[E
, HashSet[E
]]
429 var core
= reverse_linearize
(self.core
)
431 for i
in self.linear_extension
(t
, elements
) do
432 if t
== i
then continue
434 var lin_i
= self.linear_extension
(i
, elements
)
436 for j
in self.linear_extension
(t
, elements
) do
437 if i
== j
or j
== t
then continue
438 var lin_j
= self.linear_extension
(j
, elements
)
440 var d_ij
= lin_i
- lin_j
441 var d_ji
= lin_j
- lin_i
444 if not conflicts_graph
.has_key
(ed1
) then conflicts_graph
[ed1
] = new HashSet[E
]
445 # add ed1 x ed2 to conflicts graph
446 for ed2
in d_ji
do conflicts_graph
[ed1
].add
(ed2
)
449 if not conflicts_graph
.has_key
(ed1
) then conflicts_graph
[ed1
] = new HashSet[E
]
450 # add ed1 x ed2 to conflicts graph
451 for ed2
in d_ji
do conflicts_graph
[ed1
].add
(ed2
)
458 private var conflicts_graph
: nullable HashMap[E
, Set[E
]]
460 # cache for linear_extensions
461 private var linear_extensions_cache
: Map[E
, Array[E
]] = new HashMap[E
, Array[E
]]
463 # Return a linear_extension of super_elements of the element
464 private fun linear_extension
(element
: E
, elements
: Set[E
]): Array[E
] do
465 if not self.linear_extensions_cache
.has_key
(element
) then
466 var supers
= new HashSet[E
]
468 supers
.add_all
(self.super_elements
(element
, elements
))
469 self.linear_extensions_cache
[element
] = self.linearize
(supers
)
471 return self.linear_extensions_cache
[element
]
474 private fun super_elements
(element
: E
, elements
: Set[E
]): Set[E
] is abstract
475 private fun sub_elements
(element
: E
, elements
: Set[E
]): Set[E
] is abstract
476 private fun is_element_mi
(element
: E
, elements
: Set[E
]): Bool is abstract
477 private fun linearize
(elements
: Set[E
]): Array[E
] is abstract
478 private fun reverse_linearize
(elements
: Set[E
]): Array[E
] is abstract
482 private class MTypeColorer
483 super AbstractColorer[MType]
487 init(mmodule
: MModule) do self.mmodule
= mmodule
489 redef fun super_elements
(element
, elements
) do return self.mmodule
.super_mtypes
(element
, elements
)
490 redef fun is_element_mi
(element
, elements
) do return self.super_elements
(element
, elements
).length
> 1
491 redef fun sub_elements
(element
, elements
) do do return self.mmodule
.sub_mtypes
(element
, elements
)
492 redef fun linearize
(elements
) do return self.mmodule
.linearize_mtypes
(elements
)
493 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mtypes
(elements
)
497 private class MClassColorer
498 super AbstractColorer[MClass]
500 private var mmodule
: MModule
502 init(mmodule
: MModule) do self.mmodule
= mmodule
504 redef fun super_elements
(element
, elements
) do return self.mmodule
.super_mclasses
(element
)
505 fun parent_elements
(element
: MClass): Set[MClass] do return self.mmodule
.parent_mclasses
(element
)
506 redef fun is_element_mi
(element
, elements
) do return self.parent_elements
(element
).length
> 1
507 redef fun sub_elements
(element
, elements
) do do return self.mmodule
.sub_mclasses
(element
)
508 redef fun linearize
(elements
) do return self.mmodule
.linearize_mclasses
(elements
)
509 redef fun reverse_linearize
(elements
) do return self.mmodule
.reverse_linearize_mclasses
(elements
)
513 private class MPropertyColorer[E
: MProperty]
515 private var mmodule
: MModule
516 private var class_colorer
: MClassColorer
517 private var coloration_result
: Map[E
, Int] = new HashMap[E
, Int]
519 init(mmodule
: MModule) do
520 self.mmodule
= mmodule
521 self.class_colorer
= new MClassColorer(mmodule
)
524 fun colorize
(mclasses
: Set[MClass]): Map[E
, Int] do
525 self.class_colorer
.tag_elements
(mclasses
)
526 self.class_colorer
.build_conflicts_graph
(mclasses
)
527 self.colorize_core
(self.class_colorer
.core
)
528 self.colorize_crown
(self.class_colorer
.crown
)
529 return self.coloration_result
532 # Colorize properties of the core hierarchy
533 private fun colorize_core
(mclasses
: Set[MClass]) do
535 for mclass
in mclasses
do
536 var color
= min_color
538 # if the class is root, get the minimal color
539 if self.mmodule
.parent_mclasses
(mclass
).length
== 0 then
540 colorize_elements
(self.properties
(mclass
), color
)
542 # check last color used by parents
543 color
= max_color
(color
, self.mmodule
.parent_mclasses
(mclass
))
544 # check max color used in conflicts
545 if self.class_colorer
.conflicts_graph
.has_key
(mclass
) then
546 color
= max_color
(color
, self.class_colorer
.conflicts_graph
[mclass
])
548 colorize_elements
(self.properties
(mclass
), color
)
553 # Colorize properties of the crown hierarchy
554 private fun colorize_crown
(mclasses
: Set[MClass]) do
555 for mclass
in mclasses
do
556 colorize_elements
(self.properties
(mclass
), max_color
(0, self.mmodule
.parent_mclasses
(mclass
)))
560 # Colorize a collection of mproperties given a starting color
561 private fun colorize_elements
(elements
: Collection[E
], start_color
: Int) do
562 for element
in elements
do
563 if self.coloration_result
.has_key
(element
) then continue
564 self.coloration_result
[element
] = start_color
569 private fun max_color
(min_color
: Int, mclasses
: Collection[MClass]): Int do
570 var max_color
= min_color
572 for mclass
in mclasses
do
573 for mproperty
in self.properties
(mclass
) do
574 var color
= min_color
575 if self.coloration_result
.has_key
(mproperty
) then
576 color
= self.coloration_result
[mproperty
]
577 if color
>= max_color
then max_color
= color
+ 1
585 private fun properties
(mclass
: MClass): Set[E
] do
586 var properties
= new HashSet[E
]
587 for mprop
in self.mmodule
.properties
(mclass
) do
588 if mprop
isa E
then properties
.add
(mprop
)
594 # Colorer for type resolution table
595 class ResolutionColorer
597 private var coloration_result
: Map[MType, Int] = new HashMap[MType, Int]
601 fun colorize
(elements
: Map[MClassType, Set[MType]]): Map[MType, Int] do
602 self.build_conflicts_graph
(elements
)
603 self.colorize_elements
(elements
)
604 return coloration_result
607 # Colorize a collection of elements
608 fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
610 for mclasstype
, mclasstypes
in elements
do
611 for element
in mclasstypes
do
612 if self.coloration_result
.has_key
(element
) then continue
613 var color
= min_color
614 while not self.is_color_free
(element
, color
) do
617 coloration_result
[element
] = color
623 # Check if a related element to the element already use the color
624 private fun is_color_free
(element
: MType, color
: Int): Bool do
625 if conflicts_graph
.has_key
(element
) then
626 for st
in conflicts_graph
[element
] do
627 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
633 # look for unanchored types generated by the same type
634 private fun build_conflicts_graph
(elements
: Map[MClassType, Set[MType]]) do
635 for mclasstype
, mtypes
in elements
do
636 for mtype
in mtypes
do
637 for otype
in mtypes
do
638 if otype
== mtype
then continue
639 self.add_conflict
(mtype
, otype
)
645 private var conflicts_graph
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
647 private fun add_conflict
(mtype
: MType, otype
: MType) do
648 if mtype
== otype
then return
649 if not self.conflicts_graph
.has_key
(mtype
) then self.conflicts_graph
[mtype
] = new HashSet[MType]
650 self.conflicts_graph
[mtype
].add
(otype
)
651 if not self.conflicts_graph
.has_key
(otype
) then self.conflicts_graph
[otype
] = new HashSet[MType]
652 self.conflicts_graph
[otype
].add
(mtype
)
658 # Abstract Perfect Hashing
659 private abstract class AbstractHasher[E
: Object]
661 var operator
: PHOperator
663 init(operator
: PHOperator) do self.operator
= operator
665 fun compute_masks
(elements
: Set[E
], ids
: Map[E
, Int]): Map[E
, Int] do
666 var masks
= new HashMap[E
, Int]
667 for element
in elements
do
668 var supers
= new HashSet[E
]
669 supers
.add_all
(self.super_elements
(element
, elements
))
671 masks
[element
] = compute_mask
(supers
, ids
)
676 fun compute_mask
(supers
: Set[E
], ids
: Map[E
, Int]): Int do
679 var used
= new List[Int]
681 var res
= operator
.op
(mask
, ids
[sup
])
682 if used
.has
(res
) then
688 if used
.length
== supers
.length
then break
694 fun compute_hashes
(elements
: Set[E
], ids
: Map[E
, Int], masks
: Map[E
, Int]): Map[E
, Map[E
, Int]] do
695 var hashes
= new HashMap[E
, Map[E
, Int]]
696 for element
in elements
do
697 var supers
= new HashSet[E
]
698 supers
.add_all
(self.super_elements
(element
, elements
))
700 var inhashes
= new HashMap[E
, Int]
701 var mask
= masks
[element
]
703 inhashes
[sup
] = operator
.op
(mask
, ids
[sup
])
705 hashes
[element
] = inhashes
710 fun super_elements
(element
: E
, elements
: Set[E
]): Set[E
] is abstract
713 # Abstract operator used for perfect hashing
714 abstract class PHOperator
715 fun op
(mask
: Int, id
:Int): Int is abstract
718 # Hashing using modulo (MOD) operator
723 redef fun op
(mask
, id
) do return mask
% id
726 # Hashing using binary and (AND) operator
731 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
734 # MType Perfect Hashing
735 private class MTypeHasher
736 super AbstractHasher[MType]
740 init(mmodule
: MModule, operator
: PHOperator) do
742 self.mmodule
= mmodule
745 redef fun super_elements
(element
, elements
) do return self.mmodule
.super_mtypes
(element
, elements
)
748 # MClass Perfect Hashing
749 private class MClassHasher
750 super AbstractHasher[MClass]
752 private var mmodule
: MModule
754 init(mmodule
: MModule, operator
: PHOperator) do
756 self.mmodule
= mmodule
759 redef fun super_elements
(element
, elements
) do return self.mmodule
.super_mclasses
(element
)
762 # Resolution tables Perfect Hashing (PH)
763 private class ResolutionHasher
765 var operator
: PHOperator
767 init(operator
: PHOperator) do self.operator
= operator
769 fun compute_masks
(elements
: Map[MClassType, Set[MType]], ids
: Map[MType, Int]): Map[MClassType, Int] do
770 var masks
= new HashMap[MClassType, Int]
771 for mclasstype
, mtypes
in elements
do
772 masks
[mclasstype
] = compute_mask
(mtypes
, ids
)
777 private fun compute_mask
(mtypes
: Set[MType], ids
: Map[MType, Int]): Int do
780 var used
= new List[Int]
781 for mtype
in mtypes
do
782 var res
= operator
.op
(mask
, ids
[mtype
])
783 if used
.has
(res
) then
789 if used
.length
== mtypes
.length
then break
795 fun compute_hashes
(elements
: Map[MClassType, Set[MType]], ids
: Map[MType, Int], masks
: Map[MClassType, Int]): Map[MClassType, Map[MType, Int]] do
796 var hashes
= new HashMap[MClassType, Map[MType, Int]]
797 for mclasstype
, mtypes
in elements
do
798 var mask
= masks
[mclasstype
]
799 var inhashes
= new HashMap[MType, Int]
800 for mtype
in mtypes
do
801 inhashes
[mtype
] = operator
.op
(mask
, ids
[mtype
])
803 hashes
[mclasstype
] = inhashes
809 # live unanchored coloring
810 class UnanchoredTypeColoring
812 private var coloration_result
: Map[MType, Int] = new HashMap[MType, Int]
813 private var conflicts_graph
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
817 fun colorize
(elements
: Map[MClassType, Set[MType]]): Map[MType, Int] do
818 build_conflicts_graph
(elements
)
819 colorize_elements
(elements
)
820 return coloration_result
823 # Colorize a collection of elements
824 fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
826 for mclasstype
, mclasstypes
in elements
do
827 for element
in mclasstypes
do
828 if self.coloration_result
.has_key
(element
) then continue
829 var color
= min_color
830 while not self.is_color_free
(element
, color
) do
833 coloration_result
[element
] = color
839 # Check if a related element to the element already use the color
840 private fun is_color_free
(element
: MType, color
: Int): Bool do
841 if conflicts_graph
.has_key
(element
) then
842 for st
in conflicts_graph
[element
] do
843 if coloration_result
.has_key
(st
) and coloration_result
[st
] == color
then return false
849 # look for unanchored types generated by the same type
850 private fun build_conflicts_graph
(elements
: Map[MClassType, Set[MType]]) do
851 for mclasstype
, mtypes
in elements
do
852 for mtype
in mtypes
do
853 for otype
in mtypes
do
854 if otype
== mtype
then continue
855 self.add_conflict
(mtype
, otype
)
861 private fun add_conflict
(mtype
: MType, otype
: MType) do
862 if mtype
== otype
then return
863 if not self.conflicts_graph
.has_key
(mtype
) then self.conflicts_graph
[mtype
] = new HashSet[MType]
864 self.conflicts_graph
[mtype
].add
(otype
)
865 if not self.conflicts_graph
.has_key
(otype
) then self.conflicts_graph
[otype
] = new HashSet[MType]
866 self.conflicts_graph
[otype
].add
(mtype
)
870 class NaiveUnanchoredTypeColoring
871 super UnanchoredTypeColoring
875 redef fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
877 for mclasstype
, mclasstypes
in elements
do
878 for element
in mclasstypes
do
879 coloration_result
[element
] = color
886 abstract class UnanchoredTypePerfectHashing
887 super NaiveUnanchoredTypeColoring
889 private var masks
: Map[MClassType, Int] = new HashMap[MClassType, Int]
893 redef fun colorize_elements
(elements
: Map[MClassType, Set[MType]]) do
895 for mclasstype
, mclasstypes
in elements
do
896 for element
in mclasstypes
do
897 coloration_result
[element
] = color
903 fun compute_masks
(elements
: Map[MClassType, Set[MType]]): Map[MClassType, Int] do
904 for mclasstype
, mtypes
in elements
do
905 self.masks
[mclasstype
] = compute_mask
(mtypes
)
910 private fun compute_mask
(mtypes
: Set[MType]): Int do
913 var used
= new List[Int]
914 for mtype
in mtypes
do
915 var res
= op
(mask
, self.coloration_result
[mtype
])
916 if used
.has
(res
) then
922 if used
.length
== mtypes
.length
then break
928 private fun op
(mask
: Int, id
:Int): Int is abstract
929 private fun phash
(id
: Int, mask
: Int): Int do return op
(mask
, id
)
932 class UnanchoredTypeModPerfectHashing
933 super UnanchoredTypePerfectHashing
935 redef fun op
(mask
, id
) do return mask
% id
938 class UnanchoredTypeAndPerfectHashing
939 super UnanchoredTypePerfectHashing
941 redef fun op
(mask
, id
) do return mask
.bin_and
(id
)
947 redef class HashSet[E
]
948 init from
(elements
: Collection[E
]) do
950 self.add_all
(elements
)
955 init from
(elements
: Collection[E
]) do
957 self.add_all
(elements
)
960 # Return a new Array with the elements only contened in 'self' and not in 'o'
961 fun -(o
: Array[E
]): Array[E
] do
962 var res
= new Array[E
]
963 for e
in self do if not o
.has
(e
) then res
.add
(e
)
970 # Return a linearization of a set of mtypes
971 private fun linearize_mtypes
(mtypes
: Set[MType]): Array[MType] do
972 var lin
= new Array[MType].from
(mtypes
)
973 var sorter
= new TypeSorter(self)
978 # Return a reverse linearization of a set of mtypes
979 private fun reverse_linearize_mtypes
(mtypes
: Set[MType]): Array[MType] do
980 var lin
= new Array[MType].from
(mtypes
)
981 var sorter
= new ReverseTypeSorter(self)
986 # Return super types of a `mtype` in `self`
987 private fun super_mtypes
(mtype
: MType, mtypes
: Set[MType]): Set[MType] do
988 if not self.super_mtypes_cache
.has_key
(mtype
) then
989 var supers
= new HashSet[MType]
990 for otype
in mtypes
do
991 if otype
== mtype
then continue
992 if mtype
.is_subtype
(self, null, otype
) then
996 self.super_mtypes_cache
[mtype
] = supers
998 return self.super_mtypes_cache
[mtype
]
1001 private var super_mtypes_cache
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
1003 # Return all sub mtypes (directs and indirects) of a `mtype` in `self`
1004 private fun sub_mtypes
(mtype
: MType, mtypes
: Set[MType]): Set[MType] do
1005 if not self.sub_mtypes_cache
.has_key
(mtype
) then
1006 var subs
= new HashSet[MType]
1007 for otype
in mtypes
do
1008 if otype
== mtype
then continue
1009 if otype
.is_subtype
(self, null, mtype
) then
1013 self.sub_mtypes_cache
[mtype
] = subs
1015 return self.sub_mtypes_cache
[mtype
]
1018 private var sub_mtypes_cache
: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
1020 # Return a linearization of a set of mclasses
1021 private fun linearize_mclasses
(mclasses
: Set[MClass]): Array[MClass] do
1022 var lin
= new Array[MClass].from
(mclasses
)
1023 var sorter
= new ClassSorter(self)
1028 # Return a reverse linearization of a set of mtypes
1029 private fun reverse_linearize_mclasses
(mclasses
: Set[MClass]): Array[MClass] do
1030 var lin
= new Array[MClass].from
(mclasses
)
1031 var sorter
= new ReverseClassSorter(self)
1036 # Return all super mclasses (directs and indirects) of a `mclass` in `self`
1037 private fun super_mclasses
(mclass
: MClass): Set[MClass] do
1038 if not self.super_mclasses_cache
.has_key
(mclass
) then
1039 var supers
= new HashSet[MClass]
1040 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1041 for sup
in self.flatten_mclass_hierarchy
[mclass
].greaters
do
1042 if sup
== mclass
then continue
1046 self.super_mclasses_cache
[mclass
] = supers
1048 return self.super_mclasses_cache
[mclass
]
1051 private var super_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1053 # Return all parents of a `mclass` in `self`
1054 private fun parent_mclasses
(mclass
: MClass): Set[MClass] do
1055 if not self.parent_mclasses_cache
.has_key
(mclass
) then
1056 var parents
= new HashSet[MClass]
1057 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1058 for sup
in self.flatten_mclass_hierarchy
[mclass
].direct_greaters
do
1059 if sup
== mclass
then continue
1063 self.parent_mclasses_cache
[mclass
] = parents
1065 return self.parent_mclasses_cache
[mclass
]
1068 private var parent_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1070 # Return all sub mclasses (directs and indirects) of a `mclass` in `self`
1071 private fun sub_mclasses
(mclass
: MClass): Set[MClass] do
1072 if not self.sub_mclasses_cache
.has_key
(mclass
) then
1073 var subs
= new HashSet[MClass]
1074 if self.flatten_mclass_hierarchy
.has
(mclass
) then
1075 for sub
in self.flatten_mclass_hierarchy
[mclass
].smallers
do
1076 if sub
== mclass
then continue
1080 self.sub_mclasses_cache
[mclass
] = subs
1082 return self.sub_mclasses_cache
[mclass
]
1085 private var sub_mclasses_cache
: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
1087 # All 'mproperties' associated to all 'mclassdefs' of `mclass`
1088 private fun properties
(mclass
: MClass): Set[MProperty] do
1089 if not self.properties_cache
.has_key
(mclass
) then
1090 var properties
= new HashSet[MProperty]
1091 var parents
= self.super_mclasses
(mclass
)
1092 for parent
in parents
do
1093 properties
.add_all
(self.properties
(parent
))
1096 for mclassdef
in mclass
.mclassdefs
do
1097 for mpropdef
in mclassdef
.mpropdefs
do
1098 properties
.add
(mpropdef
.mproperty
)
1101 self.properties_cache
[mclass
] = properties
1103 return properties_cache
[mclass
]
1106 private var properties_cache
: Map[MClass, Set[MProperty]] = new HashMap[MClass, Set[MProperty]]
1109 # A sorter for linearize list of types
1111 super AbstractSorter[MType]
1113 private var mmodule
: MModule
1115 init(mmodule
: MModule) do self.mmodule
= mmodule
1117 redef fun compare
(a
, b
) do
1120 else if a
.is_subtype
(self.mmodule
, null, b
) then
1127 # A sorter for reverse linearization
1128 class ReverseTypeSorter
1131 init(mmodule
: MModule) do end
1133 redef fun compare
(a
, b
) do
1136 else if a
.is_subtype
(self.mmodule
, null, b
) then
1143 # A sorter for linearize list of classes
1144 private class ClassSorter
1145 super AbstractSorter[MClass]
1147 var mmodule
: MModule
1149 redef fun compare
(a
, b
) do
1152 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then
1159 # A sorter for reverse linearization
1160 private class ReverseClassSorter
1161 super AbstractSorter[MClass]
1163 var mmodule
: MModule
1165 redef fun compare
(a
, b
) do
1168 else if self.mmodule
.flatten_mclass_hierarchy
.has
(a
) and self.mmodule
.flatten_mclass_hierarchy
[a
].greaters
.has
(b
) then