package org.simantics.scl.compiler.elaboration.java; import org.cojen.classfile.TypeDesc; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.constants.FunctionValue; import org.simantics.scl.compiler.internal.codegen.references.Val; import org.simantics.scl.compiler.internal.codegen.utils.Constants; 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 CreateMVectorProto extends FunctionValue { private static final TVar A = Types.var(Kinds.STAR); public static final CreateMVectorProto INSTANCE = new CreateMVectorProto(); private CreateMVectorProto() { super(new TVar[] {A}, Types.PROC, Types.mvector(A), Types.vector(A), Types.INTEGER); } @Override public Type applyExact(MethodBuilder mb, Val[] parameters) { Val prototypeVar = parameters[0]; Val lengthVar = parameters[1]; try { Type elementType = Types.canonical( Types.matchApply(Types.VECTOR, prototypeVar.getType())); if(elementType instanceof TVar) { prototypeVar.push(mb); mb.invokeVirtual("java/lang/Object", "getClass", Constants.CLASS, Constants.EMPTY_TYPEDESC_ARRAY); mb.invokeVirtual("java/lang/Class", "getComponentType", Constants.CLASS, Constants.EMPTY_TYPEDESC_ARRAY); lengthVar.push(mb); mb.invokeStatic("java/lang/reflect/Array", "newInstance", TypeDesc.OBJECT, new TypeDesc[] {Constants.CLASS, TypeDesc.INT}); return Types.mvector(A); } else { TypeDesc desc = mb.getJavaTypeTranslator().toTypeDesc(elementType); TypeDesc arrayDesc = desc.toArrayType(); lengthVar.push(mb); mb.newObject(arrayDesc, 1); return Types.mvector(elementType); } } catch(MatchException e) { throw new InternalCompilerError(e); } } }