--- /dev/null
+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 "[...]";
+ }
+
+}