package org.simantics.scl.compiler.internal.interpreted; import java.util.Arrays; import org.simantics.scl.runtime.function.FunctionImpl1; import org.simantics.scl.runtime.function.FunctionImpl2; import org.simantics.scl.runtime.function.FunctionImpl3; import org.simantics.scl.runtime.function.FunctionImpl4; import org.simantics.scl.runtime.function.FunctionImplN; public class ILambda implements IExpression { private final class Arity1Func extends FunctionImpl1 { private final Object[] inheritedVariableBindings; private Arity1Func(Object[] inheritedVariableBindings) { this.inheritedVariableBindings = inheritedVariableBindings; } @Override public Object apply(Object param0) { Object[] newVariableBindings = new Object[variableBindingsLength]; int i = 0;; for(;i < inheritedVariableBindings.length;++i) newVariableBindings[i] = inheritedVariableBindings[i]; newVariableBindings[i] = param0; return body.execute(newVariableBindings); } @Override public String toString() { return ILambda.this.toString(inheritedVariableBindings); } @Override public int hashCode() { return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings); } private ILambda getParent() { return ILambda.this; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; Arity1Func other = (Arity1Func)obj; return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings); } } private final class Arity2Func extends FunctionImpl2 { private final Object[] inheritedVariableBindings; private Arity2Func(Object[] inheritedVariableBindings) { this.inheritedVariableBindings = inheritedVariableBindings; } @Override public Object apply(Object param0, Object param1) { Object[] newVariableBindings = new Object[variableBindingsLength]; int i = 0;; for(;i < inheritedVariableBindings.length;++i) newVariableBindings[i] = inheritedVariableBindings[i]; newVariableBindings[i++] = param0; newVariableBindings[i] = param1; return body.execute(newVariableBindings); } @Override public String toString() { return ILambda.this.toString(inheritedVariableBindings); } @Override public int hashCode() { return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings); } private ILambda getParent() { return ILambda.this; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; Arity2Func other = (Arity2Func)obj; return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings); } } private final class Arity3Func extends FunctionImpl3 { private final Object[] inheritedVariableBindings; private Arity3Func(Object[] inheritedVariableBindings) { this.inheritedVariableBindings = inheritedVariableBindings; } @Override public Object apply(Object param0, Object param1, Object param2) { Object[] newVariableBindings = new Object[variableBindingsLength]; int i = 0;; for(;i < inheritedVariableBindings.length;++i) newVariableBindings[i] = inheritedVariableBindings[i]; newVariableBindings[i++] = param0; newVariableBindings[i++] = param1; newVariableBindings[i] = param2; return body.execute(newVariableBindings); } @Override public String toString() { return ILambda.this.toString(inheritedVariableBindings); } @Override public int hashCode() { return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings); } private ILambda getParent() { return ILambda.this; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; Arity3Func other = (Arity3Func)obj; return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings); } } private final class Arity4Func extends FunctionImpl4 { private final Object[] inheritedVariableBindings; private Arity4Func(Object[] inheritedVariableBindings) { this.inheritedVariableBindings = inheritedVariableBindings; } @Override public Object apply(Object param0, Object param1, Object param2, Object param3) { Object[] newVariableBindings = new Object[variableBindingsLength]; int i = 0;; for(;i < inheritedVariableBindings.length;++i) newVariableBindings[i] = inheritedVariableBindings[i]; newVariableBindings[i++] = param0; newVariableBindings[i++] = param1; newVariableBindings[i++] = param2; newVariableBindings[i] = param3; return body.execute(newVariableBindings); } @Override public String toString() { return ILambda.this.toString(inheritedVariableBindings); } @Override public int hashCode() { return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings); } private ILambda getParent() { return ILambda.this; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; Arity4Func other = (Arity4Func)obj; return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings); } } private final class ArityNFunc extends FunctionImplN { private final Object[] inheritedVariableBindings; private ArityNFunc(Object[] inheritedVariableBindings) { super(arity); this.inheritedVariableBindings = inheritedVariableBindings; } @Override public Object doApply(Object... ps) { Object[] newVariableBindings = new Object[variableBindingsLength]; int i = 0;; for(;i < inheritedVariableBindings.length;++i) newVariableBindings[i] = inheritedVariableBindings[i]; for(Object p : ps) newVariableBindings[i++] = p; return body.execute(newVariableBindings); } @Override public String toString() { return ILambda.this.toString(inheritedVariableBindings); } @Override public int hashCode() { return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings); } private ILambda getParent() { return ILambda.this; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; ArityNFunc other = (ArityNFunc)obj; return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings); } } private final int[] inheritedVariableIds; private final int arity; private final int variableBindingsLength; private final IExpression body; public ILambda(int[] inheritedVariableIds, int arity, int variableBindingsLength, IExpression body) { this.inheritedVariableIds = inheritedVariableIds; this.arity = arity; this.variableBindingsLength = variableBindingsLength; this.body = body; } @Override public Object execute(Object[] variableBindings) { final Object[] inheritedVariableBindings = new Object[inheritedVariableIds.length]; for(int i=0;i "); b.append(body); b.append(')'); return b.toString(); } public String toString(Object[] variableBindings) { StringBuilder sb = new StringBuilder(); appendVariableBindings(sb, variableBindings); sb.append(this.toString()); return sb.toString(); } private static void appendVariableBindings(StringBuilder sb, Object[] variableBindings) { if (variableBindings.length > 0) { sb.append("(let {"); for(int i = 0; i < variableBindings.length; i++) { if (i > 0) sb.append("; "); sb.append("v").append(i).append("=").append(variableBindings[i].toString()); } sb.append("} in "); } } }