(refs #7375) Replaced collectFreeVariables method by a visitor
[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.compilation.CompilationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
7 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
8 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
9 import org.simantics.scl.compiler.errors.Locations;
10 import org.simantics.scl.compiler.internal.codegen.references.IVal;
11 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
12 import org.simantics.scl.compiler.types.Type;
13 import org.simantics.scl.compiler.types.Types;
14 import org.simantics.scl.compiler.types.exceptions.MatchException;
15 import org.simantics.scl.compiler.types.exceptions.UnificationException;
16 import org.simantics.scl.compiler.types.kinds.Kinds;
17
18 import gnu.trove.map.hash.TObjectIntHashMap;
19 import gnu.trove.set.hash.TIntHashSet;
20
21 public class EBind extends SimplifiableExpression {
22     public Expression pattern;
23     public Expression value;
24     public Expression in;
25     public EVariable monadEvidence;
26     SCLValue bindFunction;
27     Type monadType;
28     Type valueContentType;
29     Type inContentType;
30     
31     public EBind(long loc, Expression pattern, Expression value, Expression in) {
32         super(loc);
33         this.pattern = pattern;
34         this.value = value;
35         this.in = in;
36     }
37
38     public EBind(long loc, Expression pattern, Expression value, Expression in,
39             SCLValue bindFunction) {
40         super(loc);
41         this.pattern = pattern;
42         this.value = value;
43         this.in = in;
44     }
45     
46     @Override
47     public void collectVars(TObjectIntHashMap<Variable> allVars,
48             TIntHashSet vars) {
49         value.collectVars(allVars, vars);
50         in.collectVars(allVars, vars);
51     }
52     
53     @Override
54     protected void updateType() throws MatchException {
55         setType(in.getType());
56     }
57     
58     @Override
59     public Expression checkBasicType(TypingContext context, Type requiredType) {
60         monadType = Types.metaVar(Kinds.STAR_TO_STAR);
61         inContentType = Types.metaVar(Kinds.STAR);
62         Type monadContent = Types.apply(monadType, inContentType);
63         try {
64             Types.unify(requiredType, monadContent);
65         } catch (UnificationException e) {
66             context.typeError(location, requiredType, monadContent);
67             return this;
68         }
69         
70         Variable variable = new Variable("monadEvidence");
71         variable.setType(Types.pred(Types.MONAD, monadType));
72         monadEvidence = new EVariable(getLocation(), variable);
73         monadEvidence.setType(variable.getType());
74         context.addConstraintDemand(monadEvidence);
75         
76         pattern = pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
77         valueContentType = pattern.getType();
78         value = value.checkType(context, Types.apply(monadType, valueContentType));
79         in = in.checkType(context, requiredType);
80         Type inType = in.getType();
81         setType(inType);
82         return this;
83     }
84
85     @Override
86     public IVal toVal(CompilationContext context, CodeWriter w) {
87         throw new InternalCompilerError("EBind should be eliminated.");
88     }
89
90     /**
91      * Splits let 
92      */
93     @Override
94     public Expression simplify(SimplificationContext context) {    
95         value = value.simplify(context);
96         in = in.simplify(context);
97         pattern = pattern.simplify(context);
98         
99         long loc = getLocation();
100         Expression simplified = new EApply(loc,
101                 new EConstant(loc, bindFunction, Types.canonical(monadType), Types.canonical(valueContentType), Types.canonical(inContentType)),
102                 monadEvidence, 
103                 value,
104                 new ELambda(loc, new Case[] {
105                     new Case(new Expression[] { pattern }, in)
106                 }));
107         simplified.setType(getType());
108         
109         return simplified.simplify(context);
110     }
111
112     @Override
113     public Expression resolve(TranslationContext context) {
114         value = value.resolve(context);
115         
116         context.pushFrame();
117         pattern = pattern.resolveAsPattern(context);        
118         in = in.resolve(context);
119         context.popFrame();
120         
121         bindFunction = context.getBindFunction();
122         
123         return this; 
124     }
125     
126     @Override
127     public void setLocationDeep(long loc) {
128         if(location == Locations.NO_LOCATION) {
129             location = loc;
130             pattern.setLocationDeep(loc);
131             value.setLocationDeep(loc);
132             in.setLocationDeep(loc);
133         }
134     }
135     
136     @Override
137     public void accept(ExpressionVisitor visitor) {
138         visitor.visit(this);
139     }
140     
141     @Override
142     public Expression accept(ExpressionTransformer transformer) {
143         return transformer.transform(this);
144     }
145
146 }