1 package org.simantics.scl.runtime.generation;
4 import java.io.FileOutputStream;
5 import java.io.PrintStream;
8 public class GenerateFunctions {
10 public static final String PACKAGE = "org.simantics.scl.runtime.function";
11 public static final int MAX_ARITY = 8;
13 public static final String HEADER =
15 + " * This code is generated in " + GenerateFunctions.class.getName() + ".\r\n"
16 + " * Do not edit manually!\r\n"
20 public static void generateFunctionN(PrintStream p, int n) {
22 p.println("package " + PACKAGE + ";");
24 p.print("public interface Function"+n+"<");
26 p.print("P" + i + ",");
29 for(int i=0;i<n;++i) {
32 p.print("P"+i+" p" + i);
38 public static void generateFunctionN(PrintStream p) {
40 p.println("package " + PACKAGE + ";");
42 p.println("public interface FunctionN {");
43 p.println(" Object applyArray(Object ... ps);");
47 public static void generateFunction(PrintStream p) {
49 p.println("package " + PACKAGE + ";");
51 //p.println("@SuppressWarnings(\"all\")");
52 p.print("public interface Function<");
53 for(int k=0;k<MAX_ARITY;++k) {
56 for(int k=1;k<=MAX_ARITY;++k) {
61 p.println("> extends");
62 for(int k=1;k<=MAX_ARITY;++k) {
63 p.print(" Function" + k + "<");
64 for(int i=0;i<k;++i) {
67 p.println("R"+k+">,");
69 p.println(" FunctionN {");
73 public static void generateFunctionImplN(PrintStream p, int n) {
75 p.println("package " + PACKAGE + ";");
77 p.println("import java.util.Arrays;");
79 p.println("@SuppressWarnings(\"all\")");
80 p.print("public abstract class FunctionImpl" + n + "<");
82 p.print("P" + i + ",");
83 p.print("R> implements Function<");
85 p.print("P" + i + ",");
86 for(int i=n;i<MAX_ARITY;++i)
88 for(int i=1;i<=MAX_ARITY;++i) {
97 for(int k=1;k<Math.min(n, MAX_ARITY+1);++k) {
98 p.println(" @Override");
99 p.print(" public Object apply(");
100 for(int i=0;i<k;++i) {
103 p.print("Object p" + i);
106 p.print(" return new UnsaturatedFunction" + k + "(this");
115 p.println(" @Override");
116 p.print(" public abstract R apply(");
117 for(int i=0;i<n;++i) {
120 p.print("P"+i+" p" + i);
125 for(int k=n+1;k<=MAX_ARITY;++k) {
126 p.println(" @Override");
127 p.print(" public Object apply(");
128 for(int i=0;i<k;++i) {
131 p.print("Object p" + i);
135 p.print(" return ((Function)apply(");
136 for(int i=0;i<n;++i) {
139 p.print("(P"+i+")p" + i);
141 p.print(")).apply(");
142 for(int i=n;i<k;++i) {
148 p.println(" } catch(ClassCastException e) {");
149 p.println(" throw new CalledWithTooManyParameters();");
154 p.println(" @Override");
155 p.println(" public Object applyArray(Object ... ps) {");
156 p.println(" switch(ps.length) {");
157 for(int k=0;k<=MAX_ARITY+n;++k) {
158 p.println(" case " + k + ":");
160 p.println(" return this;");
162 p.print(" return new UnsaturatedFunction" + k + "(this");
164 p.print(", ps[" + i + "]");
168 p.print(" return apply(");
169 for(int i=0;i<k;++i) {
172 p.print("(P"+i+")ps[" + i + "]");
176 else if(k <= n + MAX_ARITY) {
178 p.print(" return ((Function)apply(");
179 for(int i=0;i<n;++i) {
182 p.print("(P"+i+")ps[" + i + "]");
184 p.print(")).apply(");
185 for(int i=n;i<k;++i) {
188 p.print("ps[" + i + "]");
191 p.println(" } catch(ClassCastException e) {");
192 p.println(" throw new CalledWithTooManyParameters();");
197 p.println(" default:");
199 p.print(" return ((Function)apply(");
200 for(int i=0;i<n;++i) {
203 p.print("(P"+i+")ps[" + i + "]");
205 p.println(")).apply(Arrays.copyOfRange(ps, "+n+", ps.length));");
206 p.println(" } catch(ClassCastException e) {");
207 p.println(" throw new CalledWithTooManyParameters();");
215 public static void generateFunctionImplN(PrintStream p) {
217 p.println("package " + PACKAGE + ";");
219 p.println("import java.util.Arrays;");
221 p.println("@SuppressWarnings(\"all\")");
222 p.println("public abstract class FunctionImplN implements Function {");
223 p.println(" int arity;");
225 p.println(" public FunctionImplN(int arity) {");
226 p.println(" if(arity < 1)");
227 p.println(" throw new IllegalArgumentException();");
228 p.println(" this.arity = arity;");
231 for(int k=1;k<=MAX_ARITY;++k) {
232 p.println(" @Override");
233 p.print(" public Object apply(");
234 for(int i=0;i<k;++i) {
237 p.print("Object p" + i);
241 p.println(" switch(arity) {");
242 for(int i=1;i<k;++i) {
243 p.print(" case " + i + ": return ((Function)doApply(");
244 for(int j=0;j<i;++j) {
249 p.print(")).apply(");
250 for(int j=i;j<k;++j) {
257 p.print(" case " + k + ": return doApply(");
258 for(int i=0;i<k;++i) {
264 p.print(" default: return new UnsaturatedFunction" + k + "(this");
269 p.println(" } catch(ClassCastException e) {");
270 p.println(" throw new CalledWithTooManyParameters();");
275 p.println(" public abstract Object doApply(Object ... ps);");
277 p.println(" @Override");
278 p.println(" public Object applyArray(Object ... ps) {");
279 p.println(" if(ps.length == arity)");
280 p.println(" return doApply(ps);");
281 p.println(" else if(ps.length < arity)");
282 p.println(" return new UnsaturatedFunctionN(this, ps);");
283 p.println(" else /* ps.length > arity */ {");
285 p.println(" return ((Function)doApply(Arrays.copyOf(ps, arity))).applyArray(Arrays.copyOfRange(ps, arity, ps.length));");
286 p.println(" } catch(ClassCastException e) {");
287 p.println(" throw new CalledWithTooManyParameters();");
294 public static void generateUnsaturatedFunctionN(PrintStream p, int n) {
296 p.println("package " + PACKAGE + ";");
298 p.println("@SuppressWarnings(\"all\")");
299 p.println("public class UnsaturatedFunction" + n + " implements Function {");
300 p.println(" private final Function f;");
302 p.println(" private final Object p" + i + ";");
304 p.print(" public UnsaturatedFunction" + n + "(Function f");
306 p.print(", Object p" + i);
308 p.println(" this.f = f;");
310 p.println(" this.p" + i + " = p" + i + ";");
313 for(int k=1;k<=MAX_ARITY;++k) {
314 p.println(" @Override");
315 p.print(" public Object apply(");
316 for(int i=0;i<k;++i) {
319 p.print("Object p" + (i + n));
322 if(n + k <= MAX_ARITY)
323 p.print(" return f.apply(");
325 p.print(" return f.applyArray(");
326 for(int i=0;i<k+n;++i) {
336 p.println(" @Override");
337 p.println(" public Object applyArray(Object ... ps) {");
338 p.println(" Object[] nps = new Object[ps.length + " + n + "];");
340 p.println(" nps[" + i + "] = p" + i + ";");
341 p.println(" for(int i=0;i<ps.length;++i)");
342 p.println(" nps[i + " + n + "] = ps[i];");
343 p.println(" return f.applyArray(nps);");
348 p.println(" @Override");
349 p.println(" public String toString() {");
350 p.println(" StringBuilder sb = new StringBuilder();");
351 p.println(" sb.append(\"(\").append(f);");
353 p.println(" sb.append(\" \").append(p"+i+");");
354 p.println(" sb.append(\")\");");
355 p.println(" return sb.toString();");
360 p.println(" @Override");
361 p.println(" public int hashCode() {");
362 p.println(" int result = f.hashCode();");
364 p.println(" result = 31 * result + (p"+i+" == null ? 0 : p"+i+".hashCode());");
365 p.println(" return result;");
370 p.println(" @Override");
371 p.println(" public boolean equals(Object obj) {");
372 p.println(" if (this == obj)");
373 p.println(" return true;");
374 p.println(" if (obj == null)");
375 p.println(" return false;");
376 p.println(" if (getClass() != obj.getClass())");
377 p.println(" return false;");
378 p.println(" UnsaturatedFunction"+n+" other = (UnsaturatedFunction"+n+") obj;");
379 p.println(" if(!f.equals(other.f))");
380 p.println(" return false;");
381 for(int i=0;i<n;++i) {
382 p.println(" if(p"+i+" == null) {");
383 p.println(" if (other.p"+i+" != null)");
384 p.println(" return false;");
385 p.println(" } else if (!p"+i+".equals(other.p"+i+"))");
386 p.println(" return false;");
388 p.println(" return true;");
395 public static void generateUnsaturatedFunctionN(PrintStream p) {
397 p.println("package " + PACKAGE + ";");
399 p.println("import java.util.Arrays;");
401 p.println("@SuppressWarnings(\"all\")");
402 p.println("public class UnsaturatedFunctionN implements Function {");
403 p.println(" private final Function f;");
404 p.println(" private final Object[] ps;");
406 p.println(" public UnsaturatedFunctionN(Function f, Object ... ps) {");
407 p.println(" this.f = f;");
408 p.println(" this.ps = ps;");
411 for(int k=1;k<=MAX_ARITY;++k) {
412 p.println(" @Override");
413 p.print(" public Object apply(");
414 for(int i=1;i<=k;++i) {
417 p.print("Object p" + i);
420 p.println(" Object[] nps = new Object[ps.length + " + k + "];");
421 p.println(" System.arraycopy(ps, 0, nps, 0, ps.length);");
422 for(int i=1;i<=k;++i)
423 p.println(" nps[ps.length+" + (i-1) + "] = p" + i+ ";");
424 p.println(" return f.applyArray(nps);");
429 p.println(" @Override");
430 p.println(" public Object applyArray(Object ... ops) {");
431 p.println(" Object[] nps = new Object[ps.length + ops.length];");
432 p.println(" System.arraycopy(ps, 0, nps, 0, ps.length);");
433 p.println(" System.arraycopy(ops, 0, nps, ps.length, ops.length);");
434 p.println(" return f.applyArray(nps);");
439 p.println(" @Override");
440 p.println(" public String toString() {");
441 p.println(" StringBuilder sb = new StringBuilder();");
442 p.println(" sb.append(\"(\").append(f);");
443 p.println(" for (Object p : ps)");
444 p.println(" sb.append(\" \").append(p);");
445 p.println(" sb.append(\")\");");
446 p.println(" return sb.toString();");
451 p.println(" @Override");
452 p.println(" public int hashCode() {");
453 p.println(" return f.hashCode() + 31 * Arrays.hashCode(ps);");
458 p.println(" @Override");
459 p.println(" public boolean equals(Object obj) {");
460 p.println(" if (this == obj)");
461 p.println(" return true;");
462 p.println(" if (obj == null)");
463 p.println(" return false;");
464 p.println(" if (getClass() != obj.getClass())");
465 p.println(" return false;");
466 p.println(" UnsaturatedFunctionN other = (UnsaturatedFunctionN) obj;");
467 p.println(" return f.equals(other.f) && Arrays.equals(ps, other.ps);");
474 public static void main(String[] args) throws Exception {
475 URL url = GenerateFunctions.class.getResource(".");
476 File dir = new File(url.getPath());
477 while(!new File(dir, "src").exists())
478 dir = dir.getParentFile();
479 dir = new File(dir, "src");
480 dir = new File(dir, PACKAGE.replace('.', '/'));
483 for(int n=1;n<=MAX_ARITY;++n) {
485 new PrintStream(new FileOutputStream(new File(dir, "Function"+n+".java")));
486 generateFunctionN(ps, n);
490 new PrintStream(new FileOutputStream(new File(dir, "FunctionN.java")));
491 generateFunctionN(ps);
495 new PrintStream(new FileOutputStream(new File(dir, "Function.java")));
496 generateFunction(ps);
499 for(int n=1;n<=MAX_ARITY;++n) {
501 new PrintStream(new FileOutputStream(new File(dir, "FunctionImpl"+n+".java")));
502 generateFunctionImplN(ps, n);
506 new PrintStream(new FileOutputStream(new File(dir, "FunctionImplN.java")));
507 generateFunctionImplN(ps);
509 for(int n=1;n<=MAX_ARITY;++n) {
511 new PrintStream(new FileOutputStream(new File(dir, "UnsaturatedFunction"+n+".java")));
512 generateUnsaturatedFunctionN(ps, n);
516 new PrintStream(new FileOutputStream(new File(dir, "UnsaturatedFunctionN.java")));
517 generateUnsaturatedFunctionN(ps);