package org.simantics.scl.compiler.internal.codegen.references; import java.util.ArrayList; import java.util.List; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction; import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder; import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext; import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder; 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.slf4j.Logger; import org.slf4j.LoggerFactory; public final class ValRef implements IVal { private static final Logger LOGGER = LoggerFactory.getLogger(ValRef.class); public static final ValRef[] EMPTY_ARRAY = new ValRef[0]; Val binding; ValRef prev; // FreeVars with the same binding form a linked list ValRef next; ValRefBinder parent; Type[] parameters; /** * Just for deserialization */ public ValRef(Type[] parameters) { this.parameters = parameters; } ValRef(Val binding, Type[] parameters) { //System.out.println("+ " + bindin g); this.parameters = parameters; setBinding(binding); } public void setBinding(Val binding) { this.binding = binding; ValRef head = binding.occurrence; binding.occurrence = this; this.next = head; this.prev = null; if(head != null) head.prev = this; } int removeModiId = -1; public void remove() { //System.out.println("- " + binding); if(prev == null) try { binding.occurrence = next; } catch(NullPointerException e) { LOGGER.error("removeModiId = " + removeModiId); LOGGER.error("current ModiId = " + SSASimplificationContext.modiId, e); throw new InternalCompilerError("The ValRef has already been removed."); } else prev.next = next; if(next != null) next.prev = prev; if(SCLCompilerConfiguration.DEBUG) { next = null; prev = null; binding = null; } removeModiId = SSASimplificationContext.modiId; } public Val getBinding() { return binding; } public ValRef getNext() { return next; } public static Val[] getBindings(ValRef[] refs) { Val[] result = new Val[refs.length]; for(int i=0;i ValRef[] createOccurrences(List vals) { ValRef[] result = new ValRef[vals.size()]; for(int i=0;i vars) { if(binding instanceof BoundVar) { BoundVar var = (BoundVar)binding; if(var.getFunctionParent() != function) vars.add(this); } } public void replaceBy(Val binding) { remove(); setBinding(binding); } @Override public Type apply(MethodBuilder mb, Type[] typeParameters, Val... parameters) { return binding.apply(mb, Types.concat(this.parameters, typeParameters), parameters); } /** * Replaces this reference with an application */ public void replaceByApply(Val function, Val ... parameters) { getParent().replaceByApply(this, function, this.parameters, parameters); } @Override public Object realizeValue(TransientClassBuilder classLoader) { return binding.realizeValue(classLoader); } @Override public void setLabel(String label) { } public void updateParentEffect() { if(parent instanceof LetApply) { LetApply apply = (LetApply)parent; if(apply.getFunction() == this) apply.updateEffect(); } } }