1 package org.simantics.scl.compiler.constants;
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;
14 public class JavaStaticMethod extends FunctionValue {
19 TypeDesc returnTypeDesc;
20 TypeDesc[] parameterTypeDescs;
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();
28 ClassBuilder.checkClassName(className);
29 this.className = className;
30 this.methodName = methodName;
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();
39 ClassBuilder.checkClassName(className);
40 this.className = className;
41 this.methodName = methodName;
44 public JavaStaticMethod(String className, String methodName,
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) {
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();
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;
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,
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));
89 mb.push(parameters, getParameterTypes());
90 mb.invokeStatic(className, methodName,
94 return getReturnType();
98 public String toString() {
99 return className + "#" + methodName;