1 package org.simantics.scl.compiler.elaboration.expressions;
3 import java.util.ArrayList;
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;
26 public class ESimpleLambda extends Expression {
27 public Variable parameter;
28 public Expression value;
29 public Type effect = Types.NO_EFFECTS;
31 public ESimpleLambda(Variable parameter, Expression value) {
32 this.parameter = parameter;
36 public ESimpleLambda(Type effect, Variable parameter, Expression value) {
37 this.parameter = parameter;
42 public ESimpleLambda(long loc, Variable parameter, Expression value) {
44 this.parameter = parameter;
48 public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
50 this.parameter = parameter;
55 public Expression decomposeMatching() {
56 value = value.decomposeMatching();
61 protected void updateType() throws MatchException {
62 setType(Types.functionE(Types.canonical(parameter.type),
63 effect, value.getType()));
67 public IVal toVal(CompilationContext context, CodeWriter w) {
68 return lambdaToVal(context, w);
72 public Expression simplify(SimplificationContext context) {
73 value = value.simplify(context);
78 public Expression resolve(TranslationContext context) {
79 value = value.resolve(context);
84 public Expression replace(ReplaceContext context) {
85 Variable newParameter = parameter.copy();
86 context.varMap.put(parameter, new EVariable(newParameter));
87 ESimpleLambda result = new ESimpleLambda(getLocation(),
89 effect.replace(context.tvarMap),
90 value.replace(context));
91 // not absolutely needed, but maybe good for performance
92 context.varMap.remove(parameter);
96 public Type getLocalEffect() {
97 if(SCLCompilerConfiguration.DEBUG)
99 throw new InternalCompilerError();
103 public void setEffect(Type effect) {
105 throw new InternalCompilerError();
106 this.effect = effect;
110 public IExpression toIExpression(ExpressionInterpretationContext context) {
111 // Find parameters of the whole function definition
112 ArrayList<Variable> parameters = new ArrayList<Variable>(2);
113 parameters.add(parameter);
114 Expression cur = value;
116 if(cur instanceof ESimpleLambda) {
117 ESimpleLambda lambda = (ESimpleLambda)cur;
118 parameters.add(lambda.parameter);
121 else if(cur instanceof ELambdaType) {
122 cur = ((ELambdaType)cur).value;
130 ExpressionInterpretationContext innerContext = context.createNewContext();
131 Set<Variable> freeVariables = cur.getFreeVariables();
132 for(Variable parameter : parameters)
133 freeVariables.remove(parameter);
135 int[] inheritedVariableIds = new int[freeVariables.size()];
136 for(Variable var : freeVariables) {
137 innerContext.push(var);
138 inheritedVariableIds[i++] = context.getVariableId(var);
142 for(Variable parameter : parameters)
143 innerContext.push(parameter);
146 IExpression body = cur.toIExpression(innerContext);
147 return new ILambda(inheritedVariableIds,
149 innerContext.getMaxVariableId(),
153 public Expression checkBasicType(TypingContext context, Type requiredType) {
156 mfun = Types.unifyFunction(requiredType, 1);
157 } catch (UnificationException e) {
158 context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
159 setType(Types.metaVar(Kinds.STAR));
163 context.pushEffectUpperBound(location, mfun.effect);
164 parameter.setType(mfun.parameterTypes[0]);
165 value = value.checkType(context, mfun.returnType);
166 effect = context.popEffectUpperBound();
171 public Expression inferType(TypingContext context) {
172 effect = Types.metaVar(Kinds.EFFECT);
173 context.pushEffectUpperBound(location, effect);
174 if(parameter.type == null)
175 parameter.setType(Types.metaVar(Kinds.STAR));
176 value = value.checkType(context, Types.metaVar(Kinds.STAR));
177 context.popEffectUpperBound();
182 public boolean isEffectful() {
187 public void setLocationDeep(long loc) {
188 if(location == Locations.NO_LOCATION) {
190 value.setLocationDeep(loc);
195 public void accept(ExpressionVisitor visitor) {
199 public Expression getValue() {
203 public Variable getParameter() {
208 public Expression accept(ExpressionTransformer transformer) {
209 return transformer.transform(this);
213 public int getSyntacticFunctionArity() {
214 return 1 + value.getSyntacticFunctionArity();