1 package org.simantics.scl.compiler.elaboration.expressions;
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.common.names.Names;
5 import org.simantics.scl.compiler.compilation.CompilationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
7 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
8 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
9 import org.simantics.scl.compiler.elaboration.expressions.block.BlockType;
10 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
11 import org.simantics.scl.compiler.errors.Locations;
12 import org.simantics.scl.compiler.internal.codegen.references.IVal;
13 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
14 import org.simantics.scl.compiler.internal.header.ModuleHeader;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
17 import org.simantics.scl.compiler.types.exceptions.MatchException;
18 import org.simantics.scl.compiler.types.exceptions.UnificationException;
19 import org.simantics.scl.compiler.types.kinds.Kinds;
21 public class EBind extends SimplifiableExpression {
23 public Expression pattern;
24 public Expression value;
26 public EVariable monadEvidence;
29 Type valueContentType;
32 public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in) {
34 this.blockType = blockType;
35 this.pattern = pattern;
40 public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in,
41 SCLValue bindFunction) {
43 this.blockType = blockType;
44 this.pattern = pattern;
50 protected void updateType() throws MatchException {
51 setType(in.getType());
55 public Expression checkBasicType(TypingContext context, Type requiredType) {
56 ModuleHeader header = context.getCompilationContext().header;
57 boolean edo = header != null && header.edo;
59 monadType = Types.metaVar(Kinds.STAR_TO_STAR);
61 inContentType = Types.metaVar(Kinds.STAR);
62 Type monadContent = Types.apply(monadType, inContentType);
64 Types.unify(requiredType, monadContent);
65 } catch (UnificationException e) {
66 context.typeError(location, requiredType, monadContent);
70 Variable variable = new Variable("monadEvidence");
71 variable.setType(Types.pred(blockType == BlockType.MonadE ? Types.MONAD_E : Types.MONAD, monadType));
72 monadEvidence = new EVariable(getLocation(), variable);
73 monadEvidence.setType(variable.getType());
74 context.addConstraintDemand(monadEvidence);
76 pattern = pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
77 valueContentType = pattern.getType();
78 value = value.checkType(context, Types.apply(monadType, valueContentType));
80 context.pushEffectUpperBound(location, blockType == BlockType.Monad ? Types.NO_EFFECTS : Types.metaVar(Kinds.EFFECT));
81 in = in.checkType(context, requiredType);
83 effect = context.popEffectUpperBound();
85 effect = Types.NO_EFFECTS;
86 Type inType = in.getType();
92 public IVal toVal(CompilationContext context, CodeWriter w) {
93 throw new InternalCompilerError("EBind should be eliminated.");
100 public Expression simplify(SimplificationContext context) {
101 long loc = getLocation();
102 monadType = Types.canonical(monadType);
103 valueContentType = Types.canonical(valueContentType);
104 effect = Types.canonical(effect);
105 inContentType = Types.canonical(inContentType);
106 Type[] types = blockType == BlockType.MonadE
107 ? new Type[] {monadType, valueContentType, effect, inContentType}
108 : new Type[] {monadType, valueContentType, inContentType};
109 Expression simplified = new EApply(loc, effect,
110 new EConstant(loc, context.getValue(blockType == BlockType.MonadE ? Names.Prelude_bindE : Names.Prelude_bind), types),
113 new ELambda(loc, effect, new Case[] {
114 new Case(new Expression[] { pattern }, in)
116 simplified.setType(getType());
118 return simplified.simplify(context);
122 public Expression resolve(TranslationContext context) {
123 value = value.resolve(context);
126 pattern = pattern.resolveAsPattern(context);
127 in = in.resolve(context);
134 public void setLocationDeep(long loc) {
135 if(location == Locations.NO_LOCATION) {
137 pattern.setLocationDeep(loc);
138 value.setLocationDeep(loc);
139 in.setLocationDeep(loc);
144 public void accept(ExpressionVisitor visitor) {
149 public Expression accept(ExpressionTransformer transformer) {
150 return transformer.transform(this);