Updated release engineering instructions for 1.31.0 release.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EBind.java
1 package org.simantics.scl.compiler.elaboration.expressions;
2
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;
19
20 public class EBind extends SimplifiableExpression {
21     BlockType blockType;
22     public Expression pattern;
23     public Expression value;
24     public Expression in;
25     public EVariable monadEvidence;
26     Type monadType;
27     Type effect;
28     Type valueContentType;
29     Type inContentType;
30     
31     public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in) {
32         super(loc);
33         this.blockType = blockType;
34         this.pattern = pattern;
35         this.value = value;
36         this.in = in;
37     }
38
39     public EBind(long loc, BlockType blockType, Expression pattern, Expression value, Expression in,
40             SCLValue bindFunction) {
41         super(loc);
42         this.blockType = blockType;
43         this.pattern = pattern;
44         this.value = value;
45         this.in = in;
46     }
47     
48     @Override
49     protected void updateType() throws MatchException {
50         setType(in.getType());
51     }
52     
53     @Override
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);
58         try {
59             Types.unify(requiredType, monadContent);
60         } catch (UnificationException e) {
61             context.typeError(location, requiredType, monadContent);
62             return this;
63         }
64         
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);
70         
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();
78         setType(inType);
79         return this;
80     }
81
82     @Override
83     public IVal toVal(CompilationContext context, CodeWriter w) {
84         throw new InternalCompilerError("EBind should be eliminated.");
85     }
86
87     /**
88      * Splits let 
89      */
90     @Override
91     public Expression simplify(SimplificationContext context) {    
92         value = value.simplify(context);
93         in = in.simplify(context);
94         pattern = pattern.simplify(context);
95         
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),
106                 monadEvidence, 
107                 value,
108                 new ELambda(loc, new Case[] {
109                     new Case(new Expression[] { pattern }, in)
110                 }));
111         simplified.setType(getType());
112         
113         return simplified.simplify(context);
114     }
115
116     @Override
117     public Expression resolve(TranslationContext context) {
118         value = value.resolve(context);
119         
120         context.pushFrame();
121         pattern = pattern.resolveAsPattern(context);        
122         in = in.resolve(context);
123         context.popFrame();
124         
125         return this; 
126     }
127     
128     @Override
129     public void setLocationDeep(long loc) {
130         if(location == Locations.NO_LOCATION) {
131             location = loc;
132             pattern.setLocationDeep(loc);
133             value.setLocationDeep(loc);
134             in.setLocationDeep(loc);
135         }
136     }
137     
138     @Override
139     public void accept(ExpressionVisitor visitor) {
140         visitor.visit(this);
141     }
142     
143     @Override
144     public Expression accept(ExpressionTransformer transformer) {
145         return transformer.transform(this);
146     }
147
148 }