]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.runtime/generation/org/simantics/scl/runtime/generation/GenerateFunctions.java
(refs #7090) Generated Function objects implement equals and hashCode
[simantics/platform.git] / bundles / org.simantics.scl.runtime / generation / org / simantics / scl / runtime / generation / GenerateFunctions.java
1 package org.simantics.scl.runtime.generation;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.PrintStream;
6 import java.net.URL;
7
8 public class GenerateFunctions {
9     
10     public static final String PACKAGE = "org.simantics.scl.runtime.function";
11     public static final int MAX_ARITY = 8;
12     
13     public static final String HEADER =
14             "/**\r\n"
15           + " * This code is generated in " + GenerateFunctions.class.getName() + ".\r\n"
16           + " * Do not edit manually!\r\n"
17           + " */" 
18             ;
19     
20     public static void generateFunctionN(PrintStream p, int n) {
21         p.println(HEADER);
22         p.println("package " + PACKAGE + ";");
23         p.println();        
24         p.print("public interface Function"+n+"<");
25         for(int i=0;i<n;++i)
26             p.print("P" + i + ",");
27         p.println("R> {");
28         p.print("    R apply(");
29         for(int i=0;i<n;++i) {
30             if(i>0)
31                 p.print(", ");
32             p.print("P"+i+" p" + i);
33         }
34         p.println(");");
35         p.println("}");
36     }
37     
38     public static void generateFunctionN(PrintStream p) {
39         p.println(HEADER);
40         p.println("package " + PACKAGE + ";");
41         p.println();
42         p.println("public interface FunctionN {");
43         p.println("    Object applyArray(Object ... ps);");
44         p.println("}");
45     }
46     
47     public static void generateFunction(PrintStream p) {
48         p.println(HEADER);
49         p.println("package " + PACKAGE + ";");
50         p.println();
51         //p.println("@SuppressWarnings(\"all\")");
52         p.print("public interface Function<");
53         for(int k=0;k<MAX_ARITY;++k) {
54             p.print("P"+k+",");
55         }
56         for(int k=1;k<=MAX_ARITY;++k) {
57             p.print("R"+k);
58             if(k < MAX_ARITY)
59                 p.print(",");
60         }
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) {
65                 p.print("P"+i+",");
66             }
67             p.println("R"+k+">,");
68         }
69         p.println("    FunctionN {");
70         p.println("}");
71     }
72     
73     public static void generateFunctionImplN(PrintStream p, int n) {
74         p.println(HEADER);
75         p.println("package " + PACKAGE + ";");
76         p.println();
77         p.println("import java.util.Arrays;");
78         p.println();
79         p.println("@SuppressWarnings(\"all\")");
80         p.print("public abstract class FunctionImpl" + n + "<");
81         for(int i=0;i<n;++i)
82             p.print("P" + i + ",");
83         p.print("R> implements Function<");
84         for(int i=0;i<n;++i)
85             p.print("P" + i + ",");
86         for(int i=n;i<MAX_ARITY;++i)
87             p.print("Object,");
88         for(int i=1;i<=MAX_ARITY;++i) {
89             if(i == n)
90                 p.print("R");
91             else 
92                 p.print("Object");
93             if(i < MAX_ARITY)
94                 p.print(",");
95         }
96         p.println("> {");
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) {
101                 if(i>0)
102                     p.print(", ");
103                 p.print("Object p" + i);
104             }
105             p.println(") {");
106             p.print("        return new UnsaturatedFunction" + k + "(this");
107             for(int i=0;i<k;++i)
108                 p.print(", p" + i);
109             p.println(");");
110             p.println("    }");
111             p.println();
112         }
113         {
114             if(n <= MAX_ARITY)
115                 p.println("    @Override");
116             p.print("    public abstract R apply(");
117             for(int i=0;i<n;++i) {
118                 if(i>0)
119                     p.print(", ");
120                 p.print("P"+i+" p" + i);
121             }
122             p.println(");");
123             p.println();
124         }
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) {
129                 if(i>0)
130                     p.print(", ");
131                 p.print("Object p" + i);
132             }
133             p.println(") {");
134             p.println("        try {");
135             p.print("            return ((Function)apply(");
136             for(int i=0;i<n;++i) {
137                 if(i>0)
138                     p.print(", ");
139                 p.print("(P"+i+")p" + i);
140             }
141             p.print(")).apply(");
142             for(int i=n;i<k;++i) {
143                 if(i>n)
144                     p.print(", ");
145                 p.print("p" + i);
146             }
147             p.println(");");
148             p.println("        } catch(ClassCastException e) {");
149             p.println("            throw new CalledWithTooManyParameters();");
150             p.println("        }");
151             p.println("    }");
152             p.println();
153         }
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 + ":");
159             if(k==0)
160                 p.println("            return this;");
161             else if(k < n) {
162                 p.print("            return new UnsaturatedFunction" + k + "(this");
163                 for(int i=0;i<k;++i)
164                     p.print(", ps[" + i + "]");
165                 p.println(");");
166             }
167             else if(k == n) {
168                 p.print("            return apply(");
169                 for(int i=0;i<k;++i) {
170                     if(i > 0)
171                         p.print(", ");
172                     p.print("(P"+i+")ps[" + i + "]");
173                 }
174                 p.println(");");
175             }
176             else if(k <= n + MAX_ARITY) {
177                 p.println("            try {");
178                 p.print("                return ((Function)apply(");
179                 for(int i=0;i<n;++i) {
180                     if(i>0)
181                         p.print(", ");
182                     p.print("(P"+i+")ps[" + i + "]");
183                 }
184                 p.print(")).apply(");
185                 for(int i=n;i<k;++i) {
186                     if(i>n)
187                         p.print(", ");
188                     p.print("ps[" + i + "]");
189                 }
190                 p.println(");");
191                 p.println("            } catch(ClassCastException e) {");
192                 p.println("                throw new CalledWithTooManyParameters();");
193                 p.println("            }");
194             }
195         }
196         {
197             p.println("        default:");
198             p.println("            try {");
199             p.print("                return ((Function)apply(");
200             for(int i=0;i<n;++i) {
201                 if(i>0)
202                     p.print(", ");
203                 p.print("(P"+i+")ps[" + i + "]");
204             }
205             p.println(")).apply(Arrays.copyOfRange(ps, "+n+", ps.length));");
206             p.println("            } catch(ClassCastException e) {");
207             p.println("                throw new CalledWithTooManyParameters();");
208             p.println("            }");
209         }
210         p.println("        }");
211         p.println("    }");
212         p.println("}");
213     }
214     
215     public static void generateFunctionImplN(PrintStream p) {
216         p.println(HEADER);
217         p.println("package " + PACKAGE + ";");
218         p.println();
219         p.println("import java.util.Arrays;");
220         p.println();
221         p.println("@SuppressWarnings(\"all\")");
222         p.println("public abstract class FunctionImplN implements Function {");
223         p.println("    int arity;");
224         p.println();
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;");
229         p.println("    }");
230         p.println();
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) {
235                 if(i>0)
236                     p.print(", ");
237                 p.print("Object p" + i);
238             }
239             p.println(") {");
240             p.println("        try {");
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) {
245                     if(j>0)
246                         p.print(", ");
247                     p.print("p" + j);
248                 }
249                 p.print(")).apply(");
250                 for(int j=i;j<k;++j) {
251                     if(j>i)
252                         p.print(", ");
253                     p.print("p" + j);
254                 }
255                 p.println(");");
256             }
257             p.print("            case " + k + ": return doApply(");
258             for(int i=0;i<k;++i) {
259                 if(i>0)
260                     p.print(", ");
261                 p.print("p" + i);
262             }
263             p.println(");");
264             p.print("            default: return new UnsaturatedFunction" + k + "(this");
265             for(int i=0;i<k;++i)
266                 p.print(", p" + i);
267             p.println(");");
268             p.println("            }");
269             p.println("        } catch(ClassCastException e) {");
270             p.println("            throw new CalledWithTooManyParameters();");
271             p.println("        }");
272             p.println("    }");
273             p.println();
274         }
275         p.println("    public abstract Object doApply(Object ... ps);");
276         p.println();
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 */ {");
284         p.println("            try {");
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();");
288         p.println("            }");
289         p.println("        }");
290         p.println("    }");
291         p.println("}");
292     }
293     
294     public static void generateUnsaturatedFunctionN(PrintStream p, int n) {
295         p.println(HEADER);
296         p.println("package " + PACKAGE + ";");
297         p.println();
298         p.println("@SuppressWarnings(\"all\")");
299         p.println("public class UnsaturatedFunction" + n + " implements Function {");
300         p.println("    private final Function f;");
301         for(int i=0;i<n;++i)
302             p.println("    private final Object p" + i + ";");
303         p.println();
304         p.print("    public UnsaturatedFunction" + n + "(Function f");
305         for(int i=0;i<n;++i)
306             p.print(", Object p" + i);
307         p.println(") {");
308         p.println("        this.f = f;");
309         for(int i=0;i<n;++i)
310             p.println("        this.p" + i + " = p" + i + ";");
311         p.println("    }");
312         p.println();
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) {
317                 if(i>0)
318                     p.print(", ");
319                 p.print("Object p" + (i + n));
320             }
321             p.println(") {");
322             if(n + k <= MAX_ARITY)
323                 p.print("        return f.apply(");
324             else
325                 p.print("        return f.applyArray(");
326             for(int i=0;i<k+n;++i) {
327                 if(i>0)
328                     p.print(", ");
329                 p.print("p" + i);
330             }
331             p.println(");");
332             p.println("    }");
333             p.println();
334         }
335         {
336             p.println("    @Override");
337             p.println("    public Object applyArray(Object ... ps) {");         
338             p.println("        Object[] nps = new Object[ps.length + " + n + "];");
339             for(int i=0;i<n;++i)
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);");
344             p.println("    }");
345             p.println();
346         }
347         {
348             p.println("    @Override");
349             p.println("    public String toString() {");
350             p.println("        StringBuilder sb = new StringBuilder();");
351             p.println("        sb.append(\"(\").append(f);");
352             for(int i=0;i<n;++i)
353                 p.println("        sb.append(\" \").append(p"+i+");");
354             p.println("        sb.append(\")\");");
355             p.println("        return sb.toString();");
356             p.println("    }");
357             p.println();
358         }
359         {
360             p.println("    @Override");
361             p.println("    public int hashCode() {");
362             p.println("        int result = f.hashCode();");
363             for(int i=0;i<n;++i)
364                 p.println("        result = 31 * result + (p"+i+" == null ? 0 : p"+i+".hashCode());");
365             p.println("        return result;");
366             p.println("    }");
367             p.println();
368         }
369         {
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;");
387             }
388             p.println("        return true;");
389             p.println("    }");
390             p.println();
391         }
392         p.println("}");
393     }
394     
395     public static void generateUnsaturatedFunctionN(PrintStream p) {
396         p.println(HEADER);
397         p.println("package " + PACKAGE + ";");
398         p.println();
399         p.println("import java.util.Arrays;");
400         p.println();
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;");
405         p.println();
406         p.println("    public UnsaturatedFunctionN(Function f, Object ... ps) {");
407         p.println("        this.f = f;");
408         p.println("        this.ps = ps;");
409         p.println("    }");
410         p.println();
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) {
415                 if(i>1)
416                     p.print(", ");
417                 p.print("Object p" + i);
418             }
419             p.println(") {");
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);");
425             p.println("    }");
426             p.println();
427         }
428         {
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);");
435             p.println("    }");
436             p.println();
437         }
438         {
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();");
447             p.println("    }");
448             p.println();
449         }
450         {
451             p.println("    @Override");
452             p.println("    public int hashCode() {");
453             p.println("        return f.hashCode() + 31 * Arrays.hashCode(ps);");
454             p.println("    }");
455             p.println();
456         }
457         {
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);");
468             p.println("    }");
469             p.println();
470         }
471         p.println("}");
472     }
473     
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('.', '/'));
481         dir.mkdirs();
482         
483         for(int n=1;n<=MAX_ARITY;++n) {
484             PrintStream ps = 
485                 new PrintStream(new FileOutputStream(new File(dir, "Function"+n+".java")));
486             generateFunctionN(ps, n);
487         }
488         {
489             PrintStream ps = 
490                 new PrintStream(new FileOutputStream(new File(dir, "FunctionN.java")));
491             generateFunctionN(ps);
492         }
493         {
494             PrintStream ps = 
495                 new PrintStream(new FileOutputStream(new File(dir, "Function.java")));
496             generateFunction(ps);
497         }
498         
499         for(int n=1;n<=MAX_ARITY;++n) {
500             PrintStream ps = 
501                 new PrintStream(new FileOutputStream(new File(dir, "FunctionImpl"+n+".java")));
502             generateFunctionImplN(ps, n);
503         }
504         {
505             PrintStream ps = 
506                 new PrintStream(new FileOutputStream(new File(dir, "FunctionImplN.java")));
507             generateFunctionImplN(ps);
508         }
509         for(int n=1;n<=MAX_ARITY;++n) {
510             PrintStream ps = 
511                 new PrintStream(new FileOutputStream(new File(dir, "UnsaturatedFunction"+n+".java")));
512             generateUnsaturatedFunctionN(ps, n);
513         }
514         {
515             PrintStream ps = 
516                 new PrintStream(new FileOutputStream(new File(dir, "UnsaturatedFunctionN.java")));
517             generateUnsaturatedFunctionN(ps);
518         }
519     }    
520 }