]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/interpreted/ILambda.java
Merge branch 'feature/funcwrite'
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / interpreted / ILambda.java
1 package org.simantics.scl.compiler.internal.interpreted;
2
3 import java.util.Arrays;
4
5 import org.simantics.scl.runtime.function.FunctionImpl1;
6 import org.simantics.scl.runtime.function.FunctionImpl2;
7 import org.simantics.scl.runtime.function.FunctionImpl3;
8 import org.simantics.scl.runtime.function.FunctionImpl4;
9 import org.simantics.scl.runtime.function.FunctionImplN;
10
11 public class ILambda implements IExpression {
12     private final class Arity1Func extends FunctionImpl1 {
13         private final Object[] inheritedVariableBindings;
14
15         private Arity1Func(Object[] inheritedVariableBindings) {
16             this.inheritedVariableBindings = inheritedVariableBindings;
17         }
18
19         @Override
20         public Object apply(Object param0) {
21             Object[] newVariableBindings = new Object[variableBindingsLength];
22             int i = 0;;
23             for(;i < inheritedVariableBindings.length;++i)
24                 newVariableBindings[i] = inheritedVariableBindings[i];
25             newVariableBindings[i] = param0;
26             return body.execute(newVariableBindings);
27         }
28
29         @Override
30         public String toString() {
31             return ILambda.this.toString(inheritedVariableBindings);
32         }
33
34         @Override
35         public int hashCode() {
36             return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
37         }
38
39         private ILambda getParent() {
40             return ILambda.this;
41         }
42         
43         @Override
44         public boolean equals(Object obj) {
45             if(obj == this)
46                 return true;
47             if(obj == null || obj.getClass() != getClass())
48                 return false;
49             Arity1Func other = (Arity1Func)obj;
50             return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
51         }
52     }
53
54     private final class Arity2Func extends FunctionImpl2 {
55         private final Object[] inheritedVariableBindings;
56
57         private Arity2Func(Object[] inheritedVariableBindings) {
58             this.inheritedVariableBindings = inheritedVariableBindings;
59         }
60
61         @Override
62         public Object apply(Object param0, Object param1) {
63             Object[] newVariableBindings = new Object[variableBindingsLength];
64             int i = 0;;
65             for(;i < inheritedVariableBindings.length;++i)
66                 newVariableBindings[i] = inheritedVariableBindings[i];
67             newVariableBindings[i++] = param0;
68             newVariableBindings[i] = param1;
69             return body.execute(newVariableBindings);
70         }
71
72         @Override
73         public String toString() {
74             return ILambda.this.toString(inheritedVariableBindings);
75         }
76         
77         @Override
78         public int hashCode() {
79             return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
80         }
81
82         private ILambda getParent() {
83             return ILambda.this;
84         }
85         
86         @Override
87         public boolean equals(Object obj) {
88             if(obj == this)
89                 return true;
90             if(obj == null || obj.getClass() != getClass())
91                 return false;
92             Arity2Func other = (Arity2Func)obj;
93             return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
94         }
95     }
96
97     private final class Arity3Func extends FunctionImpl3 {
98         private final Object[] inheritedVariableBindings;
99
100         private Arity3Func(Object[] inheritedVariableBindings) {
101             this.inheritedVariableBindings = inheritedVariableBindings;
102         }
103
104         @Override
105         public Object apply(Object param0, Object param1, Object param2) {
106             Object[] newVariableBindings = new Object[variableBindingsLength];
107             int i = 0;;
108             for(;i < inheritedVariableBindings.length;++i)
109                 newVariableBindings[i] = inheritedVariableBindings[i];
110             newVariableBindings[i++] = param0;
111             newVariableBindings[i++] = param1;
112             newVariableBindings[i] = param2;
113             return body.execute(newVariableBindings);
114         }
115
116         @Override
117         public String toString() {
118             return ILambda.this.toString(inheritedVariableBindings);
119         }
120         
121         @Override
122         public int hashCode() {
123             return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
124         }
125
126         private ILambda getParent() {
127             return ILambda.this;
128         }
129         
130         @Override
131         public boolean equals(Object obj) {
132             if(obj == this)
133                 return true;
134             if(obj == null || obj.getClass() != getClass())
135                 return false;
136             Arity3Func other = (Arity3Func)obj;
137             return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
138         }
139     }
140
141     private final class Arity4Func extends FunctionImpl4 {
142         private final Object[] inheritedVariableBindings;
143
144         private Arity4Func(Object[] inheritedVariableBindings) {
145             this.inheritedVariableBindings = inheritedVariableBindings;
146         }
147
148         @Override
149         public Object apply(Object param0, Object param1, Object param2, Object param3) {
150             Object[] newVariableBindings = new Object[variableBindingsLength];
151             int i = 0;;
152             for(;i < inheritedVariableBindings.length;++i)
153                 newVariableBindings[i] = inheritedVariableBindings[i];
154             newVariableBindings[i++] = param0;
155             newVariableBindings[i++] = param1;
156             newVariableBindings[i++] = param2;
157             newVariableBindings[i] = param3;
158             return body.execute(newVariableBindings);
159         }
160
161         @Override
162         public String toString() {
163             return ILambda.this.toString(inheritedVariableBindings);
164         }
165
166         @Override
167         public int hashCode() {
168             return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
169         }
170
171         private ILambda getParent() {
172             return ILambda.this;
173         }
174         
175         @Override
176         public boolean equals(Object obj) {
177             if(obj == this)
178                 return true;
179             if(obj == null || obj.getClass() != getClass())
180                 return false;
181             Arity4Func other = (Arity4Func)obj;
182             return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
183         }
184     }
185
186     private final class ArityNFunc extends FunctionImplN {
187         private final Object[] inheritedVariableBindings;
188
189         private ArityNFunc(Object[] inheritedVariableBindings) {
190             super(arity);
191             this.inheritedVariableBindings = inheritedVariableBindings;
192         }
193
194         @Override
195         public Object doApply(Object... ps) {
196             Object[] newVariableBindings = new Object[variableBindingsLength];
197             int i = 0;;
198             for(;i < inheritedVariableBindings.length;++i)
199                 newVariableBindings[i] = inheritedVariableBindings[i];
200             for(Object p : ps)
201                 newVariableBindings[i++] = p;
202             return body.execute(newVariableBindings);
203         }
204
205         @Override
206         public String toString() {
207             return ILambda.this.toString(inheritedVariableBindings);
208         }
209
210         @Override
211         public int hashCode() {
212             return ILambda.this.hashCode() + 31*Arrays.hashCode(inheritedVariableBindings);
213         }
214
215         private ILambda getParent() {
216             return ILambda.this;
217         }
218         
219         @Override
220         public boolean equals(Object obj) {
221             if(obj == this)
222                 return true;
223             if(obj == null || obj.getClass() != getClass())
224                 return false;
225             ArityNFunc other = (ArityNFunc)obj;
226             return ILambda.this == other.getParent() && Arrays.equals(inheritedVariableBindings, other.inheritedVariableBindings);
227         }
228     }
229
230     private final int[] inheritedVariableIds;
231     private final int arity;
232     private final int variableBindingsLength;
233     private final IExpression body;
234
235     public ILambda(int[] inheritedVariableIds, int arity,
236             int variableBindingsLength, IExpression body) {
237         this.inheritedVariableIds = inheritedVariableIds;
238         this.arity = arity;
239         this.variableBindingsLength = variableBindingsLength;
240         this.body = body;
241     }
242
243     @Override
244     public Object execute(Object[] variableBindings) {
245         final Object[] inheritedVariableBindings = new Object[inheritedVariableIds.length];
246         for(int i=0;i<inheritedVariableIds.length;++i)
247             inheritedVariableBindings[i] = variableBindings[inheritedVariableIds[i]];
248         switch(arity) {
249         case 1:
250             return new Arity1Func(inheritedVariableBindings);
251         case 2:
252             return new Arity2Func(inheritedVariableBindings);
253         case 3:
254             return new Arity3Func(inheritedVariableBindings);
255         case 4:
256             return new Arity4Func(inheritedVariableBindings);
257         default:
258             return new ArityNFunc(inheritedVariableBindings);
259         }
260     }
261
262     @Override
263     public String toString() {
264         StringBuilder b = new StringBuilder();
265         b.append("(\\");
266         for(int i=0;i<inheritedVariableIds.length;++i)
267             b.append('v').append(i)
268             .append("(v").append(inheritedVariableIds[i]).append(") ");
269         for(int i=0;i<arity;++i)
270             b.append('v').append(i+inheritedVariableIds.length).append(' ');
271         b.append("-> ");
272         b.append(body);
273         b.append(')');
274         return b.toString();
275     }
276
277     public String toString(Object[] variableBindings) {
278         StringBuilder sb = new StringBuilder();
279         appendVariableBindings(sb, variableBindings);
280         sb.append(this.toString());
281         return sb.toString();
282     }
283
284     private static void appendVariableBindings(StringBuilder sb, Object[] variableBindings) {
285         if (variableBindings.length > 0) {
286             sb.append("(let {");
287             for(int i = 0; i < variableBindings.length; i++) {
288                 if (i > 0) sb.append("; ");
289                 sb.append("v").append(i).append("=").append(variableBindings[i].toString());
290             }
291             sb.append("} in ");
292         }       
293     }
294 }