1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import java.util.ArrayList;
\r
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
6 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
\r
7 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
\r
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
\r
10 import org.simantics.scl.compiler.environment.Environment;
\r
11 import org.simantics.scl.compiler.errors.Locations;
\r
12 import org.simantics.scl.compiler.internal.codegen.references.IVal;
\r
13 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
\r
14 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
\r
15 import org.simantics.scl.compiler.internal.interpreted.IExpression;
\r
16 import org.simantics.scl.compiler.internal.interpreted.ILambda;
\r
17 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
\r
18 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
\r
19 import org.simantics.scl.compiler.types.Type;
\r
20 import org.simantics.scl.compiler.types.Types;
\r
21 import org.simantics.scl.compiler.types.exceptions.MatchException;
\r
22 import org.simantics.scl.compiler.types.exceptions.UnificationException;
\r
23 import org.simantics.scl.compiler.types.kinds.Kinds;
\r
24 import org.simantics.scl.compiler.types.util.MultiFunction;
\r
26 import gnu.trove.map.hash.TObjectIntHashMap;
\r
27 import gnu.trove.set.hash.THashSet;
\r
28 import gnu.trove.set.hash.TIntHashSet;
\r
30 public class ESimpleLambda extends Expression {
\r
31 public Variable parameter;
\r
32 public Expression value;
\r
33 public Type effect = Types.NO_EFFECTS;
\r
35 public ESimpleLambda(Variable parameter, Expression value) {
\r
36 this.parameter = parameter;
\r
40 public ESimpleLambda(Type effect, Variable parameter, Expression value) {
\r
41 this.parameter = parameter;
\r
43 this.effect = effect;
\r
46 public ESimpleLambda(long loc, Variable parameter, Expression value) {
\r
48 this.parameter = parameter;
\r
52 public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
\r
54 this.parameter = parameter;
\r
56 this.effect = effect;
\r
59 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
\r
60 value.collectRefs(allRefs, refs);
\r
64 public void collectVars(TObjectIntHashMap<Variable> allVars,
\r
66 value.collectVars(allVars, vars);
\r
69 public Expression decomposeMatching() {
\r
70 value = value.decomposeMatching();
\r
75 protected void updateType() throws MatchException {
\r
76 setType(Types.functionE(Types.canonical(parameter.type),
\r
77 effect, value.getType()));
\r
81 public IVal toVal(Environment env, CodeWriter w) {
\r
82 return lambdaToVal(env, w);
\r
86 public void collectFreeVariables(THashSet<Variable> vars) {
\r
87 value.collectFreeVariables(vars);
\r
88 vars.remove(parameter);
\r
92 public Expression simplify(SimplificationContext context) {
\r
93 value = value.simplify(context);
\r
98 public Expression resolve(TranslationContext context) {
\r
99 value = value.resolve(context);
\r
104 public Expression replace(ReplaceContext context) {
\r
105 Variable newParameter = parameter.copy();
\r
106 context.varMap.put(parameter, new EVariable(newParameter));
\r
107 ESimpleLambda result = new ESimpleLambda(getLocation(),
\r
109 effect.replace(context.tvarMap),
\r
110 value.replace(context));
\r
111 // not absolutely needed, but maybe good for performance
\r
112 context.varMap.remove(parameter);
\r
116 public Type getLocalEffect() {
\r
117 if(SCLCompilerConfiguration.DEBUG)
\r
119 throw new InternalCompilerError();
\r
123 public void setEffect(Type effect) {
\r
125 throw new InternalCompilerError();
\r
126 this.effect = effect;
\r
130 public IExpression toIExpression(ExpressionInterpretationContext context) {
\r
131 // Find parameters of the whole function definition
\r
132 ArrayList<Variable> parameters = new ArrayList<Variable>(2);
\r
133 parameters.add(parameter);
\r
134 Expression cur = value;
\r
136 if(cur instanceof ESimpleLambda) {
\r
137 ESimpleLambda lambda = (ESimpleLambda)cur;
\r
138 parameters.add(lambda.parameter);
\r
139 cur = lambda.value;
\r
141 else if(cur instanceof ELambdaType) {
\r
142 cur = ((ELambdaType)cur).value;
\r
150 ExpressionInterpretationContext innerContext = context.createNewContext();
\r
151 THashSet<Variable> freeVariables = cur.getFreeVariables();
\r
152 for(Variable parameter : parameters)
\r
153 freeVariables.remove(parameter);
\r
155 int[] inheritedVariableIds = new int[freeVariables.size()];
\r
156 for(Variable var : freeVariables) {
\r
157 innerContext.push(var);
\r
158 inheritedVariableIds[i++] = context.getVariableId(var);
\r
162 for(Variable parameter : parameters)
\r
163 innerContext.push(parameter);
\r
165 // Construct lambda
\r
166 IExpression body = cur.toIExpression(innerContext);
\r
167 return new ILambda(inheritedVariableIds,
\r
169 innerContext.getMaxVariableId(),
\r
173 public Expression checkBasicType(TypingContext context, Type requiredType) {
\r
174 MultiFunction mfun;
\r
176 mfun = Types.unifyFunction(requiredType, 1);
\r
177 } catch (UnificationException e) {
\r
178 context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
\r
179 setType(Types.metaVar(Kinds.STAR));
\r
183 effect = mfun.effect;
\r
184 context.pushEffectUpperBound(location, mfun.effect);
\r
185 parameter.setType(mfun.parameterTypes[0]);
\r
186 value = value.checkType(context, mfun.returnType);
\r
187 context.popEffectUpperBound();
\r
192 public Expression inferType(TypingContext context) {
\r
193 effect = Types.metaVar(Kinds.EFFECT);
\r
194 context.pushEffectUpperBound(location, effect);
\r
195 if(parameter.type == null)
\r
196 parameter.setType(Types.metaVar(Kinds.STAR));
\r
197 value = value.checkType(context, Types.metaVar(Kinds.STAR));
\r
198 context.popEffectUpperBound();
\r
203 public Expression decorate(ExpressionDecorator decorator) {
\r
204 if(decorator.decorateSubstructure(this))
\r
205 value = value.decorate(decorator);
\r
206 return decorator.decorate(this);
\r
210 public boolean isEffectful() {
\r
215 public void collectEffects(THashSet<Type> effects) {
\r
219 public void setLocationDeep(long loc) {
\r
220 if(location == Locations.NO_LOCATION) {
\r
222 value.setLocationDeep(loc);
\r
227 public void accept(ExpressionVisitor visitor) {
\r
228 visitor.visit(this);
\r
231 public Expression getValue() {
\r
235 public Variable getParameter() {
\r
240 public void forVariables(VariableProcedure procedure) {
\r
241 value.forVariables(procedure);
\r
245 public Expression accept(ExpressionTransformer transformer) {
\r
246 return transformer.transform(this);
\r