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.types.Type;
15 import org.simantics.scl.compiler.types.Types;
16 import org.simantics.scl.compiler.types.exceptions.MatchException;
17 import org.simantics.scl.compiler.types.exceptions.UnificationException;
18 import org.simantics.scl.compiler.types.kinds.Kinds;
20 public class EBind extends SimplifiableExpression {
22 public Expression pattern;
23 public Expression value;
25 public EVariable monadEvidence;
28 Type valueContentType;
31 public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in) {
33 this.blockType = blockType;
34 this.pattern = pattern;
39 public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in,
40 SCLValue bindFunction) {
42 this.blockType = blockType;
43 this.pattern = pattern;
49 protected void updateType() throws MatchException {
50 setType(in.getType());
54 public Expression checkBasicType(TypingContext context, Type requiredType) {
55 monadType = Types.metaVar(Kinds.STAR_TO_STAR);
56 inContentType = Types.metaVar(Kinds.STAR);
57 Type monadContent = Types.apply(monadType, inContentType);
59 Types.unify(requiredType, monadContent);
60 } catch (UnificationException e) {
61 context.typeError(location, requiredType, monadContent);
65 Variable variable = new Variable("monadEvidence");
66 variable.setType(Types.pred(blockType == BlockType.MonadE ? Types.MONAD_E : Types.MONAD, monadType));
67 monadEvidence = new EVariable(getLocation(), variable);
68 monadEvidence.setType(variable.getType());
69 context.addConstraintDemand(monadEvidence);
71 pattern = pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
72 valueContentType = pattern.getType();
73 value = value.checkType(context, Types.apply(monadType, valueContentType));
74 context.pushEffectUpperBound(location, blockType == BlockType.Monad ? Types.NO_EFFECTS : Types.metaVar(Kinds.EFFECT));
75 in = in.checkType(context, requiredType);
76 effect = context.popEffectUpperBound();
77 Type inType = in.getType();
83 public IVal toVal(CompilationContext context, CodeWriter w) {
84 throw new InternalCompilerError("EBind should be eliminated.");
91 public Expression simplify(SimplificationContext context) {
92 value = value.simplify(context);
93 in = in.simplify(context);
94 pattern = pattern.simplify(context);
96 long loc = getLocation();
97 monadType = Types.canonical(monadType);
98 valueContentType = Types.canonical(valueContentType);
99 effect = Types.canonical(effect);
100 inContentType = Types.canonical(inContentType);
101 Type[] types = blockType == BlockType.MonadE
102 ? new Type[] {monadType, valueContentType, effect, inContentType}
103 : new Type[] {monadType, valueContentType, inContentType};
104 Expression simplified = new EApply(loc,
105 new EConstant(loc, context.getValue(blockType == BlockType.MonadE ? Names.Prelude_bindE : Names.Prelude_bind), types),
108 new ELambda(loc, new Case[] {
109 new Case(new Expression[] { pattern }, in)
111 simplified.setType(getType());
113 return simplified.simplify(context);
117 public Expression resolve(TranslationContext context) {
118 value = value.resolve(context);
121 pattern = pattern.resolveAsPattern(context);
122 in = in.resolve(context);
129 public void setLocationDeep(long loc) {
130 if(location == Locations.NO_LOCATION) {
132 pattern.setLocationDeep(loc);
133 value.setLocationDeep(loc);
134 in.setLocationDeep(loc);
139 public void accept(ExpressionVisitor visitor) {
144 public Expression accept(ExpressionTransformer transformer) {
145 return transformer.transform(this);