]> gerrit.simantics Code Review - simantics/platform.git/blob
13c75db78bed5fe0f24cb211009ffb7c04f61b80
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import java.util.ArrayList;
4 import java.util.Set;
5
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.compilation.CompilationContext;
8 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
11 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
12 import org.simantics.scl.compiler.errors.Locations;
13 import org.simantics.scl.compiler.internal.codegen.references.IVal;
14 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
15 import org.simantics.scl.compiler.internal.interpreted.IExpression;
16 import org.simantics.scl.compiler.internal.interpreted.ILambda;
17 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
18 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
19 import org.simantics.scl.compiler.types.Type;
20 import org.simantics.scl.compiler.types.Types;
21 import org.simantics.scl.compiler.types.exceptions.MatchException;
22 import org.simantics.scl.compiler.types.exceptions.UnificationException;
23 import org.simantics.scl.compiler.types.kinds.Kinds;
24 import org.simantics.scl.compiler.types.util.MultiFunction;
25
26 import gnu.trove.map.hash.TObjectIntHashMap;
27 import gnu.trove.set.hash.TIntHashSet;
28
29 public class ESimpleLambda extends Expression {
30     public Variable parameter;
31     public Expression value;
32     public Type effect = Types.NO_EFFECTS;
33     
34     public ESimpleLambda(Variable parameter, Expression value) {
35         this.parameter = parameter;
36         this.value = value;
37     }
38     
39     public ESimpleLambda(Type effect, Variable parameter, Expression value) {
40         this.parameter = parameter;
41         this.value = value;
42         this.effect = effect;
43     }
44
45     public ESimpleLambda(long loc, Variable parameter, Expression value) {
46         super(loc);
47         this.parameter = parameter;
48         this.value = value;
49     }
50     
51     public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
52         super(loc);
53         this.parameter = parameter;
54         this.value = value;
55         this.effect = effect;
56     }
57
58     @Override
59     public void collectVars(TObjectIntHashMap<Variable> allVars,
60             TIntHashSet vars) {
61         value.collectVars(allVars, vars);
62     }
63
64     public Expression decomposeMatching() {
65         value = value.decomposeMatching();
66         return this;
67     }
68
69     @Override
70     protected void updateType() throws MatchException {
71         setType(Types.functionE(Types.canonical(parameter.type),
72                 effect, value.getType()));
73     }
74
75     @Override
76     public IVal toVal(CompilationContext context, CodeWriter w) {
77         return lambdaToVal(context, w);
78     }
79
80     @Override
81     public Expression simplify(SimplificationContext context) {
82         value = value.simplify(context);
83         return this;
84     }
85
86     @Override
87     public Expression resolve(TranslationContext context) {
88         value = value.resolve(context);
89         return this;
90     }
91
92     @Override
93     public Expression replace(ReplaceContext context) {
94         Variable newParameter = parameter.copy();
95         context.varMap.put(parameter, new EVariable(newParameter));
96         ESimpleLambda result = new ESimpleLambda(getLocation(),
97                 newParameter, 
98                 effect.replace(context.tvarMap),
99                 value.replace(context));
100         // not absolutely needed, but maybe good for performance
101         context.varMap.remove(parameter); 
102         return result;
103     }
104         
105     public Type getLocalEffect() {
106         if(SCLCompilerConfiguration.DEBUG)
107             if(effect == null)
108                 throw new InternalCompilerError();
109         return effect;
110     }
111     
112     public void setEffect(Type effect) {
113         if(effect == null)
114             throw new InternalCompilerError();
115         this.effect = effect;
116     }
117     
118     @Override
119     public IExpression toIExpression(ExpressionInterpretationContext context) {
120         // Find parameters of the whole function definition
121         ArrayList<Variable> parameters = new ArrayList<Variable>(2);
122         parameters.add(parameter);
123         Expression cur = value;
124         while(true) {
125             if(cur instanceof ESimpleLambda) {
126                 ESimpleLambda lambda = (ESimpleLambda)cur;
127                 parameters.add(lambda.parameter);
128                 cur = lambda.value;
129             }
130             else if(cur instanceof ELambdaType) {
131                 cur = ((ELambdaType)cur).value;
132             }
133             else
134                 break;
135             
136         }
137         
138         // Free variables;
139         ExpressionInterpretationContext innerContext =  context.createNewContext();
140         Set<Variable> freeVariables = cur.getFreeVariables();
141         for(Variable parameter : parameters)
142             freeVariables.remove(parameter);
143         int i=0;
144         int[] inheritedVariableIds = new int[freeVariables.size()];
145         for(Variable var : freeVariables) {
146             innerContext.push(var);
147             inheritedVariableIds[i++] = context.getVariableId(var);
148         }
149         
150         // Parameters
151         for(Variable parameter : parameters)
152             innerContext.push(parameter);
153         
154         // Construct lambda
155         IExpression body = cur.toIExpression(innerContext); 
156         return new ILambda(inheritedVariableIds,
157                 parameters.size(),
158                 innerContext.getMaxVariableId(),
159                 body);
160     }
161     
162     public Expression checkBasicType(TypingContext context, Type requiredType) {
163         MultiFunction mfun;
164         try {
165             mfun = Types.unifyFunction(requiredType, 1);
166         } catch (UnificationException e) {
167             context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
168             setType(Types.metaVar(Kinds.STAR));
169             return this;
170         }
171         
172         context.pushEffectUpperBound(location, mfun.effect);
173         parameter.setType(mfun.parameterTypes[0]);
174         value = value.checkType(context, mfun.returnType);
175         effect = context.popEffectUpperBound();
176         return this;
177     }
178     
179     @Override
180     public Expression inferType(TypingContext context) {
181         effect = Types.metaVar(Kinds.EFFECT);
182         context.pushEffectUpperBound(location, effect);
183         if(parameter.type == null)
184             parameter.setType(Types.metaVar(Kinds.STAR));
185         value = value.checkType(context, Types.metaVar(Kinds.STAR));
186         context.popEffectUpperBound();
187         return this;
188     }
189
190     @Override
191     public boolean isEffectful() {
192         return false;
193     }
194     
195     @Override
196     public void setLocationDeep(long loc) {
197         if(location == Locations.NO_LOCATION) {
198             location = loc;
199             value.setLocationDeep(loc);
200         }
201     }
202     
203     @Override
204     public void accept(ExpressionVisitor visitor) {
205         visitor.visit(this);
206     }
207     
208     public Expression getValue() {
209         return value;
210     }
211     
212     public Variable getParameter() {
213         return parameter;
214     }
215     
216     @Override
217     public Expression accept(ExpressionTransformer transformer) {
218         return transformer.transform(this);
219     }
220     
221     @Override
222     public int getSyntacticFunctionArity() {
223         return 1 + value.getSyntacticFunctionArity();
224     }
225
226 }