]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / java / ListConstructor.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/ListConstructor.java
new file mode 100644 (file)
index 0000000..0f3f8f2
--- /dev/null
@@ -0,0 +1,101 @@
+package org.simantics.scl.compiler.elaboration.java;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Label;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.FunctionValue;
+import org.simantics.scl.compiler.constants.LocalVariableConstant;
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
+import org.simantics.scl.compiler.internal.codegen.utils.Constants;
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+public class ListConstructor extends FunctionValue {
+
+    private static final TVar A = Types.var(Kinds.STAR);
+    
+    public final int arity;
+    
+    public ListConstructor(int arity) {
+        super(new TVar[] {A}, Types.NO_EFFECTS, Types.list(A), parameterList(arity));
+        this.arity = arity;
+    }
+
+    private static Type[] parameterList(int arity) {
+        Type[] parameters = new Type[arity];
+        for(int i=0;i<arity;++i)
+            parameters[i] = A;  
+        return parameters;
+    }
+
+
+    @Override
+    public Type applyExact(MethodBuilder mb, Val[] parameters) {
+        mb.loadConstant(arity);
+        mb.newObject(Constants.OBJECT_ARRAY, 1);
+        for(int i=0;i<arity;++i) {
+            mb.dup();
+            mb.loadConstant(i);
+            mb.pushBoxed(parameters[i]);
+            mb.storeToArray(TypeDesc.OBJECT);
+        }
+        mb.invokeStatic("java/util/Arrays", "asList", Constants.LIST, 
+                new TypeDesc[] {Constants.OBJECT_ARRAY});
+        return getReturnType();
+    }
+    
+    @Override
+    public void deconstruct(MethodBuilder mb, IVal parameter, Cont success,
+            Label failure) {
+        if(failure == null)
+            throw new InternalCompilerError("List deconstruction may always fail");
+        if(success.getArity() != arity)
+            throw new InternalCompilerError("Arity of the list constructor (" + arity +
+                    ") is different from the arity of the success continuation (" + success.getArity() + ").");
+        parameter.push(mb);
+        mb.invokeInterface(Constants.LIST, "size", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY);
+        mb.loadConstant(arity);
+        mb.ifComparisonBranch(failure, "!=", TypeDesc.INT);
+        
+        JavaTypeTranslator translator = mb.getJavaTypeTranslator();
+        IVal[] parameters = new IVal[arity];
+        for(int i=0;i<arity;++i) {
+            parameter.push(mb);
+            mb.loadConstant(i);
+            mb.invokeInterface(Constants.LIST, "get", TypeDesc.OBJECT, new TypeDesc[] {TypeDesc.INT});
+            try {
+                mb.unbox(Types.matchApply(Types.LIST,parameter.getType()));
+            } catch (MatchException e) {
+                throw new InternalCompilerError("Expected list type.");
+            }
+            
+            Type pType = success.getParameterType(i);
+            TypeDesc pTypeDesc = translator.toTypeDesc(pType);
+            LocalVariable lv = mb.createLocalVariable("temp", pTypeDesc);
+            mb.storeLocal(lv);
+            
+            parameters[i] = new LocalVariableConstant(pType, lv);
+        }
+        
+        mb.jump(success, parameters);
+    }
+    
+    @Override
+    public int constructorTag() {
+        return arity;
+    }
+    
+    @Override
+    public String toString() {
+        return "[...]";
+    }
+
+}