--- /dev/null
+package org.simantics.scl.compiler.internal.interpreted;
+
+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 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;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Object execute(Object[] variableBindings) {
+ final Object[] inheritedVariableBindings = new Object[inheritedVariableIds.length];
+ for(int i=0;i<inheritedVariableIds.length;++i)
+ inheritedVariableBindings[i] = variableBindings[inheritedVariableIds[i]];
+ switch(arity) {
+ case 1:
+ return new FunctionImpl1() {
+ @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);
+ }
+ };
+ case 2:
+ return new FunctionImpl2() {
+ @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);
+ }
+ };
+ case 3:
+ return new FunctionImpl3() {
+ @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);
+ }
+ };
+ case 4:
+ return new FunctionImpl4() {
+ @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);
+ }
+ };
+ default:
+ return new FunctionImplN(arity) {
+ @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 String toString() {
+ StringBuilder b = new StringBuilder();
+ b.append("(\\");
+ for(int i=0;i<inheritedVariableIds.length;++i)
+ b.append('v').append(i)
+ .append("(v").append(inheritedVariableIds[i]).append(") ");
+ for(int i=0;i<arity;++i)
+ b.append('v').append(i+inheritedVariableIds.length).append(' ');
+ b.append("-> ");
+ 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 ");
+ }
+ }
+}