]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstructor.java
Minor refactorings related to SCL constructors
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / SCLConstructor.java
1 package org.simantics.scl.compiler.constants;
2
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;
19
20 public class SCLConstructor extends FunctionValue {
21     
22     private static int MAX_FIELD_COUNT = Constants.MAX_TUPLE_LENGTH;
23     public static ComponentAccess[][] DEFAULT_FIELD_NAMES = new ComponentAccess[MAX_FIELD_COUNT+1][];
24     
25     static {
26         for(int i=0;i<=MAX_FIELD_COUNT;++i) {
27                 ComponentAccess[] fieldNames = new ComponentAccess[i];
28             for(int j=0;j<i;++j)
29                 fieldNames[j] = new FieldComponentAccess("c" + j);
30             DEFAULT_FIELD_NAMES[i] = fieldNames;
31         }
32     }
33     
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;
39        
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);
44         this.name = name;
45         this.className = className;
46         this.componentAccesses = componentAccesses;
47         this.constructorTag = constructorTag;
48     }    
49     
50     public SCLConstructor(String name, String className, TVar[] typeParameters, int constructorTag,
51             Type returnType,
52             Type ... parameterTypes) {     
53         this(name, className, typeParameters, constructorTag, returnType,
54                 DEFAULT_FIELD_NAMES[parameterTypes.length], parameterTypes);
55     }
56     
57     public void setOnlyConstructor(boolean onlyConstructor) {
58         this.onlyConstructor = onlyConstructor;
59     }
60         
61     @Override
62     public Type applyExact(MethodBuilder mb, Val[] parameters) {
63         if(className == null) {
64             mb.push(parameters[0], parameterTypes[0]);
65             return getReturnType();
66         }
67         else {
68             TypeDesc typeDesc = TypeDesc.forClass(className);
69             CodeBuilderUtils.constructRecord(typeDesc, mb, 
70                     parameterTypes, parameters);
71             return getReturnType();
72         }
73     }
74     
75     @Override
76     public void deconstruct(MethodBuilder mb, IVal parameter, Cont success,
77             Label failure) {
78         JavaTypeTranslator javaTypeTranslator = mb.getJavaTypeTranslator();
79
80         if(onlyConstructor) {
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);
87                 else {
88                     parameter.push(mb);
89                     mb.unbox(expectedType);
90                     BoundVar boundVar = new BoundVar(expectedType);
91                     mb.store(boundVar);
92                     mb.jump(success, boundVar);
93                 }
94                 return;
95             }
96             failure = null;
97         }
98         
99         Label failureLabel = mb.createLabel();
100         
101         TypeDesc constructorType = TypeDesc.forClass(className);
102         
103         // Test if deconstructing is possible
104         mb.push(parameter, returnType);
105         if(failure != null) {
106             mb.dup();
107             mb.instanceOf(constructorType);
108             mb.ifZeroComparisonBranch(failureLabel, "==");
109         }
110         
111         // Success
112         if(!onlyConstructor)
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);
118             
119             if(!typeDesc.equals(TypeDesc.VOID)) {
120                 mb.dup();
121                 componentAccesses[i].load(mb, MethodBuilder.getClassName(constructorType), typeDesc);
122                 if(typeDesc == TypeDesc.OBJECT)
123                     mb.unbox(contType);      
124             }
125             
126             BoundVar boundVar = new BoundVar(contType);
127             mb.store(boundVar);            
128             parameters[i] = boundVar;
129         }
130         mb.pop();
131         mb.jump(success, parameters);
132         
133         // Failure
134         if(failure != null) {
135             mb.setLocation(failureLabel);
136             mb.pop();
137             mb.branch(failure);
138         }
139     }
140     public int constructorTag() {
141         return constructorTag;
142     }
143     
144     @Override
145     public String toString() {
146         return name;
147     }
148     
149 }