1 package org.simantics.scl.compiler.internal.elaboration.constraints;
3 import java.util.ArrayList;
5 import org.simantics.scl.compiler.types.TApply;
6 import org.simantics.scl.compiler.types.TCon;
7 import org.simantics.scl.compiler.types.Type;
8 import org.simantics.scl.compiler.types.Types;
9 import org.simantics.scl.compiler.types.util.MultiApply;
11 import gnu.trove.map.hash.THashMap;
12 import gnu.trove.procedure.TObjectObjectProcedure;
14 public class InstanceTree<T> {
18 private static interface Node<T> {
19 T get(ArrayList<Type> types);
22 private static class SplitNode<T> implements Node<T> {
24 THashMap<TCon, Node<T>> map;
27 public SplitNode(int pId, THashMap<TCon, Node<T>> map, Node<T> alternative) {
30 this.alternative = alternative;
34 public T get(ArrayList<Type> types) {
35 MultiApply apply = Types.matchApply(types.get(pId));
36 Node<T> node = map.get(apply.constructor);
39 for(Type parameter : apply.parameters)
41 return node.get(types);
45 private static class Entry<T> {
50 private static boolean isIndexable(Type type) {
51 type = Types.canonical(type);
53 if(type instanceof TCon)
55 else if(type instanceof TApply)
56 type = Types.canonical(((TApply)type).function);
62 private static <T> int choosePId(ArrayList<Entry<T>> entries) {
63 int arity = entries.get(0).types.length;
66 int[] indexableCount = new int[arity];
67 for(Entry<T> entry : entries)
68 for(int i=0;i<arity;++i)
69 if(isIndexable(entry.types[i]))
71 int bestIndexableCount = indexableCount[0];
73 for(int i=1;i<arity;++i)
74 if(indexableCount[i] > bestIndexableCount) {
75 bestIndexableCount = indexableCount[i];
81 private static <T> Node<T> create(ArrayList<Entry<T>> entries) {
82 int pId = choosePId(entries);
83 THashMap<TCon, ArrayList<Entry<T>>> map1 = new THashMap<TCon, ArrayList<Entry<T>>>();
84 ArrayList<Entry<T>> otherEntries = new ArrayList<Entry<T>>();
85 for(Entry<T> entry : entries) {
86 Type[] types = entry.types;
87 Type type = types[pId];
88 MultiApply apply = Types.matchApply(type);
89 if(apply.constructor instanceof TCon) {
90 ArrayList<Entry<T>> l = map1.get((TCon)apply.constructor);
92 l = new ArrayList<Entry<T>>();
93 map1.put((TCon)apply.constructor, l);
95 Type[] newTypes = new Type[types.length-1+apply.parameters.length];
97 for(int i=0;i<pId;++i)
98 newTypes[j++] = types[i];
99 for(int i=0;i<apply.parameters.length;++i)
100 newTypes[j++] = apply.parameters[i];
101 for(int i=pId+1;i<types.length;++i)
102 newTypes[j++] = types[i];
103 entry.types = newTypes;
107 otherEntries.add(entry);
110 final THashMap<TCon, Node<T>> map = new THashMap<TCon, Node<T>>();
111 map1.forEachEntry(new TObjectObjectProcedure<TCon, ArrayList<Entry<T>>>() {
113 public boolean execute(TCon a, ArrayList<Entry<T>> b) {
114 map.put(a, create(b));
118 return new SplitNode<T>(pId, map, create(otherEntries));
121 public T get(ArrayList<Type> types) {
122 return root.get(types);