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