package org.simantics.scl.compiler.internal.codegen.references; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.internal.codegen.types.BTypes; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.top.SCLCompilerConfiguration; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; import gnu.trove.map.hash.THashMap; public abstract class Val implements IVal { public static final Val[] EMPTY_ARRAY = new Val[0]; transient ValRef occurrence; @Override public final ValRef createOccurrence() { return new ValRef(this, Type.EMPTY_ARRAY); } @Override public final ValRef createOccurrence(Type ... parameters) { return new ValRef(this, parameters); } @Override public IVal createSpecialization(Type... parameters) { return new ValSpecialization(this, parameters); } public final void replaceBy(ValRef other) { if(other.parameters.length == 0) replaceBy(other.binding); else replaceBy(other.binding, other.parameters); } public final ValRef getOccurrence() { return occurrence; } public void replaceBy(Val other) { ValRef cur = occurrence; if(cur != null) { while(true) { //System.out.println("+ " + other + " - " + cur.binding); if(SCLCompilerConfiguration.DEBUG) { if(cur.binding != this) throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + "."); } cur.binding = other; cur.updateParentEffect(); if(cur.next == null) break; else cur = cur.next; } cur.next = other.occurrence; if(other.occurrence != null) other.occurrence.prev = cur; other.occurrence = occurrence; occurrence = null; } } private void replaceBy(Val other, Type[] parameters) { if(other == this || other == null) throw new InternalCompilerError(); ValRef cur = occurrence; if(cur != null) { while(true) { //System.out.println("+ " + other + " - " + cur.binding); if(SCLCompilerConfiguration.DEBUG) { if(cur.binding != this) throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + "."); } cur.binding = other; cur.parameters = Types.concat(parameters, cur.parameters); cur.updateParentEffect(); if(cur.next == null) break; else cur = cur.next; } cur.next = other.occurrence; if(other.occurrence != null) other.occurrence.prev = cur; other.occurrence = occurrence; occurrence = null; } } public void replaceBy(Val other, TVar[] from, Type[] to) { if(other == this || other == null) throw new InternalCompilerError(); if(from.length == 0) replaceBy(other, to); else { ValRef cur = occurrence; if(cur != null) { while(true) { //System.out.println("+ " + other + " - " + cur.binding); if(SCLCompilerConfiguration.DEBUG) { if(cur.binding != this) throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + "."); } cur.binding = other; cur.parameters = Types.replace(to, from, cur.parameters); cur.updateParentEffect(); if(cur.next == null) break; else cur = cur.next; } cur.next = other.occurrence; if(other.occurrence != null) other.occurrence.prev = cur; other.occurrence = occurrence; occurrence = null; } } } public abstract Type getType(); /** * Returns the number of ValRefs of this Val. * @return */ public final int occurrenceCount() { int count = 0; for(ValRef ref = occurrence;ref != null;ref=ref.getNext()) ++count; return count; } public final boolean hasMoreThanOneOccurences() { return occurrence != null && occurrence.getNext() != null; } public final boolean hasNoOccurences() { return occurrence == null; } public abstract Val copy(THashMap tvarMap); public ValRef[] getOccurences() { int count = occurrenceCount(); if(count == 0) return ValRef.EMPTY_ARRAY; ValRef[] result = new ValRef[count]; ValRef cur = occurrence; for(int i=0;i