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 EFFECT_CONS = new ArrayList(); private static TObjectIntHashMap EFFECT_CODES = new TObjectIntHashMap(); private static void add(TCon con, int code) { EFFECT_CODES.put(con, code); EFFECT_CONS.add(con); } static { add(Types.WRITE_GRAPH, 0b11); add(Types.READ_GRAPH, 0b01); } 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(EFFECT_CODES.contains(type)) { return EFFECT_CODES.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 : EFFECT_CONS) { int conId = EFFECT_CODES.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); } }