package org.simantics.scl.compiler.internal.types.effects; import java.util.ArrayList; import java.util.Collection; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.TMetaVar; import org.simantics.scl.compiler.types.TUnion; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import gnu.trove.map.hash.TObjectIntHashMap; public class EffectIdMap { public static final int MIN = 0; public static final int MAX = 0xffffffff; private static final int FIRST_FREE_EFFECT_ID = 16; private static ArrayList effectCons = new ArrayList(); private static TObjectIntHashMap effectCodes = new TObjectIntHashMap(); private static void add(String module, String name, int code) { TCon con = Types.con(module, name); effectCodes.put(con, code); effectCons.add(con); } static { add("Simantics/DB", "WriteGraph", 12); add("Simantics/DB", "ReadGraph", 4); add(Types.BUILTIN, "Proc", 1); } private ArrayList localCons = new ArrayList(); private TObjectIntHashMap localCodes = new TObjectIntHashMap(); private int freshId = FIRST_FREE_EFFECT_ID; public int toId(Type type, Collection metaVars) { type = Types.canonical(type); if(type instanceof TUnion) { int id = 0; for(Type e : ((TUnion)type).effects) id |= toId(e, metaVars); return id; } else if(effectCodes.contains(type)) { return effectCodes.get(type); } else if(type instanceof TMetaVar) { metaVars.add((TMetaVar)type); return 0; } else if(localCodes.contains(type)) { return localCodes.get(type); } else { int id = freshId; localCons.add(type); localCodes.put(type, id); freshId *= 2; return id; } } public Type toType(int id) { if(id == 0) return Types.NO_EFFECTS; ArrayList components = new ArrayList(); for(TCon con : effectCons) { int conId = effectCodes.get(con); if((id&conId) == conId) { components.add(con); id ^= conId; } } for(Type con : localCons) { int conId = localCodes.get(con); if((id&conId) == conId) { components.add(con); id ^= conId; } } if(components.size() == 1) return components.get(0); else return Types.union(components); } }