1 package org.simantics.scl.compiler.elaboration.expressions;
3 import java.util.ArrayList;
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
6 import org.simantics.scl.compiler.compilation.CompilationContext;
7 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
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.interpreted.IExpression;
15 import org.simantics.scl.compiler.internal.interpreted.ILambda;
16 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
17 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
18 import org.simantics.scl.compiler.types.Type;
19 import org.simantics.scl.compiler.types.Types;
20 import org.simantics.scl.compiler.types.exceptions.MatchException;
21 import org.simantics.scl.compiler.types.exceptions.UnificationException;
22 import org.simantics.scl.compiler.types.kinds.Kinds;
23 import org.simantics.scl.compiler.types.util.MultiFunction;
25 import gnu.trove.map.hash.TObjectIntHashMap;
26 import gnu.trove.set.hash.THashSet;
27 import gnu.trove.set.hash.TIntHashSet;
29 public class ESimpleLambda extends Expression {
30 public Variable parameter;
31 public Expression value;
32 public Type effect = Types.NO_EFFECTS;
34 public ESimpleLambda(Variable parameter, Expression value) {
35 this.parameter = parameter;
39 public ESimpleLambda(Type effect, Variable parameter, Expression value) {
40 this.parameter = parameter;
45 public ESimpleLambda(long loc, Variable parameter, Expression value) {
47 this.parameter = parameter;
51 public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
53 this.parameter = parameter;
59 public void collectVars(TObjectIntHashMap<Variable> allVars,
61 value.collectVars(allVars, vars);
64 public Expression decomposeMatching() {
65 value = value.decomposeMatching();
70 protected void updateType() throws MatchException {
71 setType(Types.functionE(Types.canonical(parameter.type),
72 effect, value.getType()));
76 public IVal toVal(CompilationContext context, CodeWriter w) {
77 return lambdaToVal(context, w);
81 public void collectFreeVariables(THashSet<Variable> vars) {
82 value.collectFreeVariables(vars);
83 vars.remove(parameter);
87 public Expression simplify(SimplificationContext context) {
88 value = value.simplify(context);
93 public Expression resolve(TranslationContext context) {
94 value = value.resolve(context);
99 public Expression replace(ReplaceContext context) {
100 Variable newParameter = parameter.copy();
101 context.varMap.put(parameter, new EVariable(newParameter));
102 ESimpleLambda result = new ESimpleLambda(getLocation(),
104 effect.replace(context.tvarMap),
105 value.replace(context));
106 // not absolutely needed, but maybe good for performance
107 context.varMap.remove(parameter);
111 public Type getLocalEffect() {
112 if(SCLCompilerConfiguration.DEBUG)
114 throw new InternalCompilerError();
118 public void setEffect(Type effect) {
120 throw new InternalCompilerError();
121 this.effect = effect;
125 public IExpression toIExpression(ExpressionInterpretationContext context) {
126 // Find parameters of the whole function definition
127 ArrayList<Variable> parameters = new ArrayList<Variable>(2);
128 parameters.add(parameter);
129 Expression cur = value;
131 if(cur instanceof ESimpleLambda) {
132 ESimpleLambda lambda = (ESimpleLambda)cur;
133 parameters.add(lambda.parameter);
136 else if(cur instanceof ELambdaType) {
137 cur = ((ELambdaType)cur).value;
145 ExpressionInterpretationContext innerContext = context.createNewContext();
146 THashSet<Variable> freeVariables = cur.getFreeVariables();
147 for(Variable parameter : parameters)
148 freeVariables.remove(parameter);
150 int[] inheritedVariableIds = new int[freeVariables.size()];
151 for(Variable var : freeVariables) {
152 innerContext.push(var);
153 inheritedVariableIds[i++] = context.getVariableId(var);
157 for(Variable parameter : parameters)
158 innerContext.push(parameter);
161 IExpression body = cur.toIExpression(innerContext);
162 return new ILambda(inheritedVariableIds,
164 innerContext.getMaxVariableId(),
168 public Expression checkBasicType(TypingContext context, Type requiredType) {
171 mfun = Types.unifyFunction(requiredType, 1);
172 } catch (UnificationException e) {
173 context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
174 setType(Types.metaVar(Kinds.STAR));
178 context.pushEffectUpperBound(location, mfun.effect);
179 parameter.setType(mfun.parameterTypes[0]);
180 value = value.checkType(context, mfun.returnType);
181 effect = context.popEffectUpperBound();
186 public Expression inferType(TypingContext context) {
187 effect = Types.metaVar(Kinds.EFFECT);
188 context.pushEffectUpperBound(location, effect);
189 if(parameter.type == null)
190 parameter.setType(Types.metaVar(Kinds.STAR));
191 value = value.checkType(context, Types.metaVar(Kinds.STAR));
192 context.popEffectUpperBound();
197 public boolean isEffectful() {
202 public void setLocationDeep(long loc) {
203 if(location == Locations.NO_LOCATION) {
205 value.setLocationDeep(loc);
210 public void accept(ExpressionVisitor visitor) {
214 public Expression getValue() {
218 public Variable getParameter() {
223 public Expression accept(ExpressionTransformer transformer) {
224 return transformer.transform(this);
228 public int getSyntacticFunctionArity() {
229 return 1 + value.getSyntacticFunctionArity();