package org.simantics.scl.compiler.constants.singletons; 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.GetPrimitiveConstant; import org.simantics.scl.compiler.constants.LocalVariableConstant; import org.simantics.scl.compiler.constants.NoRepConstant; 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.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 JustConstant extends FunctionValue { private static final TVar A = Types.var(Kinds.STAR); public static final JustConstant INSTANCE = new JustConstant(); private JustConstant() { super(new TVar[] {A}, Types.NO_EFFECTS, Types.apply(Types.MAYBE, A), A); } @Override public Type applyExact(MethodBuilder mb, Val[] parameters) { parameters[0].push(mb); mb.box(parameters[0].getType()); return getReturnType(); } @Override public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) { Type componentType; try { componentType = Types.matchApply(Types.MAYBE, parameter.getType()); } catch (MatchException e) { throw new InternalCompilerError(); } TypeDesc componentTypeDesc = mb.getJavaTypeTranslator().toTypeDesc(componentType); if(failure == null) { IVal val = componentTypeDesc.isPrimitive() ? new GetPrimitiveConstant(componentType, parameter, componentTypeDesc) : parameter; mb.jump(success, val); } else { Label failureLabel = mb.createLabel(); parameter.push(mb); mb.dup(); mb.ifNullBranch(failureLabel, true); if(componentTypeDesc.equals(TypeDesc.VOID)) { mb.pop(); mb.jump(success, new NoRepConstant(componentType)); } else { if(componentTypeDesc.isPrimitive()) mb.convert(JavaTypeTranslator.toObjectType(componentTypeDesc), componentTypeDesc); LocalVariable lv = mb.createLocalVariable("temp", componentTypeDesc); mb.storeLocal(lv); mb.jump(success, new LocalVariableConstant(componentType, lv)); } // mb.setLocation(failureLabel); mb.pop(); mb.branch(failure); } } public int constructorTag() { return 1; } @Override public String toString() { return "Just"; } }