package org.simantics.scl.compiler.internal.elaboration.constraints; import java.util.ArrayList; import org.simantics.scl.compiler.types.TApply; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.util.MultiApply; import gnu.trove.map.hash.THashMap; import gnu.trove.procedure.TObjectObjectProcedure; public class InstanceTree { Node root; private static interface Node { T get(ArrayList types); } private static class SplitNode implements Node { int pId; THashMap> map; Node alternative; public SplitNode(int pId, THashMap> map, Node alternative) { this.pId = pId; this.map = map; this.alternative = alternative; } @Override public T get(ArrayList types) { MultiApply apply = Types.matchApply(types.get(pId)); Node node = map.get(apply.constructor); if(node == null) return null; for(Type parameter : apply.parameters) types.add(parameter); return node.get(types); } } private static class Entry { Type[] types; T value; } private static boolean isIndexable(Type type) { type = Types.canonical(type); while(true) { if(type instanceof TCon) return true; else if(type instanceof TApply) type = Types.canonical(((TApply)type).function); else return false; } } private static int choosePId(ArrayList> entries) { int arity = entries.get(0).types.length; if(arity == 1) return 0; int[] indexableCount = new int[arity]; for(Entry entry : entries) for(int i=0;i bestIndexableCount) { bestIndexableCount = indexableCount[i]; bestPId = i; } return bestPId; } private static Node create(ArrayList> entries) { int pId = choosePId(entries); THashMap>> map1 = new THashMap>>(); ArrayList> otherEntries = new ArrayList>(); for(Entry entry : entries) { Type[] types = entry.types; Type type = types[pId]; MultiApply apply = Types.matchApply(type); if(apply.constructor instanceof TCon) { ArrayList> l = map1.get((TCon)apply.constructor); if(l == null) { l = new ArrayList>(); map1.put((TCon)apply.constructor, l); } Type[] newTypes = new Type[types.length-1+apply.parameters.length]; int j=0; for(int i=0;i> map = new THashMap>(); map1.forEachEntry(new TObjectObjectProcedure>>() { @Override public boolean execute(TCon a, ArrayList> b) { map.put(a, create(b)); return true; } }); return new SplitNode(pId, map, create(otherEntries)); } public T get(ArrayList types) { return root.get(types); } }