package org.simantics.scl.compiler.elaboration.java; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; 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.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.kinds.Kinds; /** * Dynamic :: a -> Dynamic */ public class DynamicConstructor extends FunctionValue { private static final TVar A = Types.var(Kinds.STAR); public static final DynamicConstructor INSTANCE = new DynamicConstructor(); private DynamicConstructor() { super(new TVar[] {A}, Types.NO_EFFECTS, Types.DYNAMIC, A); } @Override public Type applyExact(MethodBuilder mb, Val[] parameters) { mb.pushBoxed(parameters[0]); return Types.DYNAMIC; } @Override public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) { Type expectedType = success.getParameterType(0); TypeDesc expectedTypeDesc = mb.getJavaTypeTranslator().toTypeDesc(expectedType); TypeDesc expectedObjectTypeDesc = expectedTypeDesc.toObjectType(); LocalVariable cachedParameter = mb.cacheValue(parameter, Types.DYNAMIC); mb.loadLocal(cachedParameter); mb.instanceOf(expectedObjectTypeDesc); mb.ifZeroComparisonBranch(failure, "=="); mb.loadLocal(cachedParameter); mb.checkCast(expectedObjectTypeDesc); mb.unbox(expectedType); LocalVariable casted = mb.createLocalVariable("dynamicContent", expectedTypeDesc); mb.storeLocal(casted); mb.jump(success, new LocalVariableConstant(expectedType, casted)); } }