]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/generic/MethodRef.java
Merge commit '145a2884933f2ffdd48d6835729e58f1152d274e'
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / generic / MethodRef.java
1 package org.simantics.scl.compiler.constants.generic;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
5 import org.simantics.scl.compiler.internal.codegen.references.Val;
6 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
7 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
8 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
9
10 /**
11  * This interface represents a method for accessing the members of Java classes.
12  * This interface is implemented by <ul>
13  *      <li>{@link StaticMethodRef}</li> 
14  *      <li>{@link ObjectMethodRef}</li> 
15  *      <li>{@link ConstructorRef}</li> 
16  *      <li>{@link StaticFieldRef}</li> 
17  *      <li>{@link FieldRef}</li> 
18  *      <li>{@link SetStaticFieldRef}</li> 
19  *      <li>{@link SetFieldRef}</li>
20  * </ul>
21  * 
22  * It provides the method {@link #invoke(MethodBuilder, StackItem[], Val[])} for creating the Java byte code
23  * for calling the method or manipulating the field value.
24  * 
25  * Parameter and return value type can be accessed using {@link #getParameterTypes()} and {@link #getReturnType()}.
26  */
27 public interface MethodRef {
28
29         /**
30          * Build code for invoking the referenced function using a given MethodBuilder.
31          * @param mb  a method builder
32          * @param stackItems  a set of StackItem objects into which the call parameters are pushed
33          * @param parameters  the method call parameters 
34          */
35     void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters);
36
37     /**
38      * Get the parameter types for a method. For (non-static) object methods and field accessors, the first
39      * parameter represents the object itself, as passed in the {@code this} variable.
40      */
41     public TypeDesc[] getParameterTypes();
42     
43     /**
44      * Get the return type of the method.
45      */
46     public TypeDesc getReturnType();
47     
48     /**
49      * This class represents a static Java class method.
50      */
51     public static class StaticMethodRef implements MethodRef {
52         
53         String className;
54         String methodName;
55         TypeDesc ret;
56         TypeDesc[] params;
57         
58         public StaticMethodRef(String className, String methodName,
59                 TypeDesc ret, TypeDesc[] params) {
60             this.className = className;
61             this.methodName = methodName;
62             this.ret = ret;
63             this.params = params;
64         }
65         
66         @Override
67         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
68             if(SCLCompilerConfiguration.DEBUG)
69                 if(stackItems.length != params.length)
70                     throw new InternalCompilerError();
71             for(StackItem stackItem : stackItems)
72                 stackItem.push(mb, parameters);
73             mb.invokeStatic(className, methodName, ret, params);
74         }
75         
76         @Override
77         public TypeDesc[] getParameterTypes() {
78             return params;
79         }
80         
81         @Override
82         public TypeDesc getReturnType() {
83             return ret;
84         }
85         
86         @Override
87         public String toString() {
88             StringBuilder b = new StringBuilder();
89             b.append("public static ");
90             b.append(ret.getFullName());
91             b.append(" ");
92             b.append(methodName);
93             b.append("(");
94             boolean first = true;
95             for(TypeDesc param : params) {
96                 if(first)
97                     first = false;
98                 else
99                     b.append(", ");
100                 b.append(param.getFullName());
101             }
102             b.append(")");
103             return b.toString();
104         }
105     
106         @Override
107         public String getName() {
108             return className + "." + methodName;
109         }
110     }
111     
112     /**
113      * This class represents a (non-static) java object method.
114      */
115     public static class ObjectMethodRef implements MethodRef {        
116         
117         boolean isInterface;
118         String className;
119         String methodName;
120         TypeDesc ret;
121         TypeDesc[] params;
122         TypeDesc[] realParams;
123         
124         public ObjectMethodRef(boolean isInterface, String className, String methodName,
125                 TypeDesc ret, TypeDesc[] params) {
126             this.isInterface = isInterface;
127             ClassBuilder.checkClassName(className);
128             this.className = className;
129             this.methodName = methodName;
130             this.ret = ret;
131             this.params = params;
132             this.realParams = new TypeDesc[params.length+1];
133             realParams[0] = TypeDesc.forClass(className);            
134             for(int i=0;i<params.length;++i)
135                 realParams[i+1] = params[i];
136         }
137         
138         @Override
139         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
140             if(SCLCompilerConfiguration.DEBUG)
141                 if(stackItems.length != realParams.length)
142                     throw new InternalCompilerError();            
143             for(StackItem stackItem : stackItems)
144                 stackItem.push(mb, parameters);
145             if(isInterface)
146                 mb.invokeInterface(className, methodName, ret, params);
147             else
148                 mb.invokeVirtual(className, methodName, ret, params);                            
149         }
150         
151         @Override
152         public TypeDesc[] getParameterTypes() {
153             return realParams;
154         }
155         
156         @Override
157         public TypeDesc getReturnType() {
158             return ret;
159         }
160     
161         @Override
162         public String toString() {
163             StringBuilder b = new StringBuilder();
164             b.append("public ");
165             b.append(ret.getFullName());
166             b.append(" ");
167             b.append(methodName);
168             b.append("(");
169             boolean first = true;
170             for(TypeDesc param : params) {
171                 if(first)
172                     first = false;
173                 else
174                     b.append(", ");
175                 b.append(param.getFullName());
176             }
177             b.append(")");
178             return b.toString();
179         }
180         
181         @Override
182         public String getName() {
183             return className + "." + methodName;
184         }
185     }
186
187     /**
188      * This class represents a Java constructor. 
189      */
190     public static class ConstructorRef implements MethodRef {
191         
192         String className;
193         TypeDesc[] params;
194         TypeDesc ret;
195         
196         public ConstructorRef(String className, TypeDesc[] params) {
197             this.className = className;
198             this.params = params;
199             this.ret = TypeDesc.forClass(className);
200         }
201         
202         @Override
203         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
204             if(SCLCompilerConfiguration.DEBUG)
205                 if(stackItems.length != params.length)
206                     throw new InternalCompilerError();
207             mb.newObject(ret);
208             mb.dup();
209             for(StackItem stackItem : stackItems)
210                 stackItem.push(mb, parameters);
211             mb.invokeConstructor(className, params);
212         }
213         
214         @Override
215         public TypeDesc[] getParameterTypes() {
216             return params;
217         }
218         
219         @Override
220         public TypeDesc getReturnType() {
221             return ret;
222         }
223     
224         @Override
225         public String toString() {
226             StringBuilder b = new StringBuilder();
227             b.append("public ");
228             b.append(className);
229             b.append("(");
230             boolean first = true;
231             for(TypeDesc param : params) {
232                 if(first)
233                     first = false;
234                 else
235                     b.append(", ");
236                 b.append(param.getFullName());
237             }
238             b.append(")");
239             return b.toString();
240         }
241         
242         @Override
243         public String getName() {
244             return className + ".<init>";
245         }
246     }
247     
248     /**
249      * This class represents a read access to a static Java field, represented as a zero-arity {@link MethodRef}. 
250      */
251     public static class StaticFieldRef implements MethodRef {
252         
253         String className;
254         String fieldName;
255         TypeDesc ret;
256         
257         public StaticFieldRef(String className, String fieldName, TypeDesc ret) {
258             this.className = className;
259             this.fieldName = fieldName;
260             this.ret = ret;        
261         }
262         
263         @Override
264         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
265             if(SCLCompilerConfiguration.DEBUG)
266                 if(stackItems.length != 0)
267                     throw new InternalCompilerError();
268             mb.loadStaticField(className, fieldName, ret);
269         }
270         
271         @Override
272         public TypeDesc[] getParameterTypes() {
273             return ClassRef.NO_PARAMS;
274         }
275         
276         @Override
277         public TypeDesc getReturnType() {
278             return ret;
279         }
280     
281         @Override
282         public String toString() {
283             StringBuilder b = new StringBuilder();
284             b.append("public static ");
285             b.append(ret.getFullName());
286             b.append(" ");
287             b.append(fieldName);
288             return b.toString();
289         }
290         
291         @Override
292         public String getName() {
293             return className + "." + fieldName;
294         }
295     }
296     
297     /**
298      * This class represents read access to a Java (non-static) object field as a one-parameter {@link MethodRef}.
299      */
300     public static class FieldRef implements MethodRef {
301         
302         String className;
303         String fieldName;
304         TypeDesc[] params;
305         TypeDesc ret;
306         
307         public FieldRef(String className, String fieldName, TypeDesc ret) {
308             this.className = className;
309             this.fieldName = fieldName;
310             this.ret = ret;
311             this.params = new TypeDesc[] {TypeDesc.forClass(className)};            
312         }
313         
314         @Override
315         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
316             if(SCLCompilerConfiguration.DEBUG)
317                 if(stackItems.length != 1)
318                     throw new InternalCompilerError();
319             stackItems[0].push(mb, parameters);
320             mb.loadField(className, fieldName, ret);
321         }
322         
323         @Override
324         public TypeDesc[] getParameterTypes() {
325             return params;
326         }
327         
328         @Override
329         public TypeDesc getReturnType() {
330             return ret;
331         }
332         
333         @Override
334         public String toString() {
335             StringBuilder b = new StringBuilder();
336             b.append("public ");
337             b.append(ret.getFullName());
338             b.append(" ");
339             b.append(fieldName);
340             return b.toString();
341         }
342     
343         @Override
344         public String getName() {
345             return className + "." + fieldName;
346         }
347     }
348
349     /**
350      * This class represents a method for setting a static Java field value as a one-parameter {@link MethodRef}
351      */
352     public static class SetStaticFieldRef implements MethodRef {
353         
354         String className;
355         String fieldName;
356         TypeDesc ret;
357         TypeDesc[] params;
358         
359         public SetStaticFieldRef(String className, String fieldName, TypeDesc ret) {
360             this.className = className;
361             this.fieldName = fieldName;
362             this.ret = ret;
363             this.params = new TypeDesc[] {ret};
364         }
365         
366         @Override
367         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
368             if(SCLCompilerConfiguration.DEBUG)
369                 if(stackItems.length != 1)
370                     throw new InternalCompilerError();
371             stackItems[0].push(mb, parameters);
372             mb.storeStaticField(className, fieldName, ret);
373         }
374         
375         @Override
376         public TypeDesc[] getParameterTypes() {
377             return params;
378         }
379         
380         @Override
381         public TypeDesc getReturnType() {
382             return TypeDesc.VOID;
383         }
384     
385         @Override
386         public String toString() {
387             StringBuilder b = new StringBuilder();
388             b.append("public static ");
389             b.append(ret.getFullName());
390             b.append(" ");
391             b.append(fieldName);
392             return b.toString();
393         }
394         
395         @Override
396         public String getName() {
397             return className + ".<set>" + fieldName;
398         }
399     }
400     
401     /**
402      * This class represents a method for setting the value of a Java (non-static) object field as a two-parameter
403      * {@link MethodRef}. The first parameter is the object reference and the second parameter is the field value. 
404      */
405     public static class SetFieldRef implements MethodRef {
406         
407         String className;
408         String fieldName;
409         TypeDesc ret;
410         TypeDesc[] params;
411         
412         public SetFieldRef(String className, String fieldName, TypeDesc ret) {
413             this.className = className;
414             this.fieldName = fieldName;
415             this.ret = ret;
416             this.params = new TypeDesc[] {TypeDesc.forClass(className), ret};
417         }
418         
419         @Override
420         public void invoke(MethodBuilder mb, StackItem[] stackItems, Val[] parameters) {
421             if(SCLCompilerConfiguration.DEBUG)
422                 if(stackItems.length != 2)
423                     throw new InternalCompilerError();
424             stackItems[0].push(mb, parameters);
425             stackItems[1].push(mb, parameters);
426             mb.storeField(className, fieldName, ret);
427         }
428         
429         @Override
430         public TypeDesc[] getParameterTypes() {
431             return params;
432         }
433         
434         @Override
435         public TypeDesc getReturnType() {
436             return TypeDesc.VOID;
437         }
438     
439         @Override
440         public String toString() {
441             StringBuilder b = new StringBuilder();
442             b.append("public ");
443             b.append(ret.getFullName());
444             b.append(" ");
445             b.append(fieldName);
446             return b.toString();
447         }
448         
449         @Override
450         public String getName() {
451             return className + ".<set>" + fieldName;
452         }
453     }
454
455     public abstract String getName();
456 }