]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/JavaStaticMethod.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / JavaStaticMethod.java
1 package org.simantics.scl.compiler.constants;
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.types.JavaTypeTranslator;
7 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
8 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
9 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
10 import org.simantics.scl.compiler.types.TVar;
11 import org.simantics.scl.compiler.types.Type;
12 import org.simantics.scl.compiler.types.Types;
13
14 public class JavaStaticMethod extends FunctionValue {
15     
16     String className;
17     String methodName;
18     
19     TypeDesc returnTypeDesc;
20     TypeDesc[] parameterTypeDescs;
21     
22     public JavaStaticMethod(String className, String methodName, Type effect, TVar[] typeParameters, Type returnType, Type ... parameterTypes) {
23         super(typeParameters, effect, returnType, parameterTypes);
24         if(SCLCompilerConfiguration.DEBUG) {
25             if(className.contains("/"))
26                 throw new InternalCompilerError();
27         }
28         ClassBuilder.checkClassName(className);
29         this.className = className;
30         this.methodName = methodName;
31     }
32     
33     public JavaStaticMethod(String className, String methodName, Type effect, Type returnType, Type ... parameterTypes) {
34         super(Types.freeVarsArray(Types.functionE(parameterTypes, effect, returnType)), effect, returnType, parameterTypes);
35         if(SCLCompilerConfiguration.DEBUG) {
36             if(className.contains("/"))
37                 throw new InternalCompilerError();
38         }
39         ClassBuilder.checkClassName(className);
40         this.className = className;
41         this.methodName = methodName;
42     }
43    
44     public JavaStaticMethod(String className, String methodName, 
45             Type effect,
46             TypeDesc returnTypeDesc, TypeDesc[] parameterTypeDescs, 
47             Type returnType, Type ... parameterTypes) {
48         super(Types.freeVarsArray(Types.functionE(parameterTypes, effect, returnType)), effect, returnType, parameterTypes);
49         if(SCLCompilerConfiguration.DEBUG) {
50             if(className == null)
51                 throw new NullPointerException();
52             if(methodName == null)
53                 throw new NullPointerException();
54             if(parameterTypeDescs != null)
55                 for(TypeDesc td : parameterTypeDescs)
56                     if(td.equals(TypeDesc.VOID))
57                         throw new InternalCompilerError();
58         }
59         if( (returnTypeDesc == null) != (parameterTypeDescs == null) )
60             throw new IllegalArgumentException("Either specify both returnTypeDesc and parameterTypeDescs or neither");
61         ClassBuilder.checkClassName(className);
62         this.className = className;
63         this.methodName = methodName;
64         this.returnTypeDesc = returnTypeDesc;
65         this.parameterTypeDescs = parameterTypeDescs;
66     }
67     
68     public JavaStaticMethod(String className, String methodName, 
69             TypeDesc returnTypeDesc, TypeDesc[] parameterTypeDescs, 
70             Type returnType, Type ... parameterTypes) {
71         this(className, methodName, Types.NO_EFFECTS, 
72                 returnTypeDesc, parameterTypeDescs, 
73                 returnType, 
74                 parameterTypes);
75     }
76     
77     @Override
78     public Type applyExact(MethodBuilder mb, Val[] parameters) {
79         if(returnTypeDesc == null || parameterTypeDescs == null) {
80             // This method may be called from multiple threads at the same time when returnTypeDesc
81             // and parameterTypeDescs are uninitialized. Double initialization is OK in this case,
82             // but because there are two fields, we have to check that both are initialized.             
83             JavaTypeTranslator tt = mb.getJavaTypeTranslator();
84             returnTypeDesc = tt.toTypeDesc(returnType);
85             parameterTypeDescs = JavaTypeTranslator.filterVoid(
86                     tt.toTypeDescs(parameterTypes));
87         }
88         
89         mb.push(parameters, getParameterTypes());
90         mb.invokeStatic(className, methodName, 
91                 returnTypeDesc, 
92                 parameterTypeDescs);
93         
94         return getReturnType();
95     }
96     
97     @Override
98     public String toString() {
99         return className + "#" + methodName;
100     }
101
102 }