1 package org.simantics.scl.compiler.constants;
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.simantics.scl.compiler.constants.componentaccess.ComponentAccess;
6 import org.simantics.scl.compiler.constants.componentaccess.FieldComponentAccess;
7 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
8 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
9 import org.simantics.scl.compiler.internal.codegen.references.IVal;
10 import org.simantics.scl.compiler.internal.codegen.references.Val;
11 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
12 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
13 import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
14 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
15 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
16 import org.simantics.scl.compiler.types.TVar;
17 import org.simantics.scl.compiler.types.Type;
18 import org.simantics.scl.compiler.types.Types;
20 public class SCLConstructor extends FunctionValue {
22 private static int MAX_FIELD_COUNT = Constants.MAX_TUPLE_LENGTH;
23 public static ComponentAccess[][] DEFAULT_FIELD_NAMES = new ComponentAccess[MAX_FIELD_COUNT+1][];
26 for(int i=0;i<=MAX_FIELD_COUNT;++i) {
27 ComponentAccess[] fieldNames = new ComponentAccess[i];
29 fieldNames[j] = new FieldComponentAccess("c" + j);
30 DEFAULT_FIELD_NAMES[i] = fieldNames;
34 private final String name; // For debugging
35 private final String className;
36 private final ComponentAccess[] componentAccesses;
37 boolean onlyConstructor;
38 private final int constructorTag;
40 public SCLConstructor(String name, String className, TVar[] typeParameters, int constructorTag,
41 Type returnType, ComponentAccess[] componentAccesses, Type... parameterTypes) {
42 super(typeParameters, Types.NO_EFFECTS, returnType, parameterTypes);
43 ClassBuilder.checkClassName(className);
45 this.className = className;
46 this.componentAccesses = componentAccesses;
47 this.constructorTag = constructorTag;
50 public SCLConstructor(String name, String className, TVar[] typeParameters, int constructorTag,
52 Type ... parameterTypes) {
53 this(name, className, typeParameters, constructorTag, returnType,
54 DEFAULT_FIELD_NAMES[parameterTypes.length], parameterTypes);
57 public void setOnlyConstructor(boolean onlyConstructor) {
58 this.onlyConstructor = onlyConstructor;
62 public Type applyExact(MethodBuilder mb, Val[] parameters) {
63 if(className == null) {
64 mb.push(parameters[0], parameterTypes[0]);
65 return getReturnType();
68 TypeDesc typeDesc = TypeDesc.forClass(className);
69 CodeBuilderUtils.constructRecord(typeDesc, mb,
70 parameterTypes, parameters);
71 return getReturnType();
76 public void deconstruct(MethodBuilder mb, IVal parameter, Cont success,
78 JavaTypeTranslator javaTypeTranslator = mb.getJavaTypeTranslator();
81 if(className == null) {
82 TypeDesc parameterDesc = javaTypeTranslator.getTypeDesc(parameter);
83 Type expectedType = success.getParameterType(0);
84 TypeDesc expectedDesc = javaTypeTranslator.toTypeDesc(expectedType);
85 if(parameterDesc.equals(expectedDesc))
86 mb.jump(success, parameter);
89 mb.unbox(expectedType);
90 BoundVar boundVar = new BoundVar(expectedType);
92 mb.jump(success, boundVar);
99 Label failureLabel = mb.createLabel();
101 TypeDesc constructorType = TypeDesc.forClass(className);
103 // Test if deconstructing is possible
104 mb.push(parameter, returnType);
105 if(failure != null) {
107 mb.instanceOf(constructorType);
108 mb.ifZeroComparisonBranch(failureLabel, "==");
113 mb.checkCast(constructorType);
114 Val[] parameters = new Val[parameterTypes.length];
115 for(int i=0;i<parameterTypes.length;++i) {
116 TypeDesc typeDesc = javaTypeTranslator.toTypeDesc(parameterTypes[i]);
117 Type contType = success.getParameterType(i);
119 if(!typeDesc.equals(TypeDesc.VOID)) {
121 componentAccesses[i].load(mb, MethodBuilder.getClassName(constructorType), typeDesc);
122 if(typeDesc == TypeDesc.OBJECT)
126 BoundVar boundVar = new BoundVar(contType);
128 parameters[i] = boundVar;
131 mb.jump(success, parameters);
134 if(failure != null) {
135 mb.setLocation(failureLabel);
140 public int constructorTag() {
141 return constructorTag;
145 public String toString() {