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.internal.codegen.continuations.Cont;
6 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
7 import org.simantics.scl.compiler.internal.codegen.references.IVal;
8 import org.simantics.scl.compiler.internal.codegen.references.Val;
9 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
10 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
11 import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
12 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
13 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
14 import org.simantics.scl.compiler.types.TVar;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
18 public class SCLConstructor extends FunctionValue {
20 private static int MAX_FIELD_COUNT = Constants.MAX_TUPLE_LENGTH;
21 public static String[][] DEFAULT_FIELD_NAMES = new String[MAX_FIELD_COUNT+1][];
24 for(int i=0;i<=MAX_FIELD_COUNT;++i) {
25 String[] fieldNames = new String[i];
27 fieldNames[j] = "c" + j;
28 DEFAULT_FIELD_NAMES[i] = fieldNames;
32 String name; // For debugging
35 boolean onlyConstructor;
37 public final String[] recordFieldNames;
39 public SCLConstructor(String name, String className, TVar[] typeParameters, int constructorTag,
40 Type returnType, String[] fieldNames, String[] recordFieldNames, Type... parameterTypes) {
41 super(typeParameters, Types.NO_EFFECTS, returnType, parameterTypes);
42 ClassBuilder.checkClassName(className);
44 this.className = className;
45 this.fieldNames = fieldNames;
46 this.constructorTag = constructorTag;
47 this.recordFieldNames = recordFieldNames;
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], null, 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 mb.loadField(MethodBuilder.getClassName(constructorType), fieldNames[i], 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() {