1 package org.simantics.scl.compiler.constants;
3 import java.util.Arrays;
5 import org.cojen.classfile.TypeDesc;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.internal.codegen.references.Val;
8 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
9 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
10 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
11 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
12 import org.simantics.scl.compiler.types.Type;
13 import org.simantics.scl.compiler.types.Types;
15 public class JavaMethod extends FunctionValue {
20 TypeDesc returnTypeDesc;
21 TypeDesc[] parameterTypeDescs;
25 public JavaMethod(boolean virtual, String className, String methodName,
27 TypeDesc returnTypeDesc, TypeDesc[] parameterTypeDescs,
28 Type returnType, Type ... parameterTypes) {
29 super(Types.freeVarsArray(
30 Types.functionE(parameterTypes, effect, returnType)),
32 returnType, parameterTypes);
33 if(SCLCompilerConfiguration.DEBUG) {
35 throw new NullPointerException();
36 if(methodName == null)
37 throw new NullPointerException();
38 if(parameterTypeDescs != null)
39 for(TypeDesc td : parameterTypeDescs)
40 if(td.equals(TypeDesc.VOID))
41 throw new InternalCompilerError();
43 ClassBuilder.checkClassName(className);
44 this.virtual = virtual;
45 this.className = className;
46 this.methodName = methodName;
47 this.returnTypeDesc = returnTypeDesc;
48 this.parameterTypeDescs = parameterTypeDescs;
51 public JavaMethod(boolean virtual, String className, String methodName, Type effect,
52 Type returnType, Type ... parameterTypes) {
53 this(virtual, className, methodName, effect, null, null, returnType, parameterTypes);
57 public Type applyExact(MethodBuilder mb, Val[] parameters) {
58 if(returnTypeDesc == null || parameterTypeDescs == null) {
59 // This method may be called from multiple threads at the same time when returnTypeDesc
60 // and parameterTypeDescs are uninitialized. Double initialization is OK in this case,
61 // but because there are two fields, we have to check that both are initialized.
62 JavaTypeTranslator tt = mb.getJavaTypeTranslator();
63 returnTypeDesc = tt.toTypeDesc(returnType);
64 parameterTypeDescs = JavaTypeTranslator.filterVoid(
65 tt.toTypeDescs(Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length)));
68 mb.push(parameters, parameterTypes);
70 mb.invokeVirtual(className, methodName, returnTypeDesc, parameterTypeDescs);
72 mb.invokeInterface(className, methodName, returnTypeDesc, parameterTypeDescs);
74 return getReturnType();
78 public String toString() {
79 return className + "." + methodName;