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 import gnu.trove.map.hash.TObjectIntHashMap;
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 Expression simplify(SimplificationContext context) {
82 value = value.simplify(context);
87 public Expression resolve(TranslationContext context) {
88 value = value.resolve(context);
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(),
98 effect.replace(context.tvarMap),
99 value.replace(context));
100 // not absolutely needed, but maybe good for performance
101 context.varMap.remove(parameter);
105 public Type getLocalEffect() {
106 if(SCLCompilerConfiguration.DEBUG)
108 throw new InternalCompilerError();
112 public void setEffect(Type effect) {
114 throw new InternalCompilerError();
115 this.effect = effect;
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;
125 if(cur instanceof ESimpleLambda) {
126 ESimpleLambda lambda = (ESimpleLambda)cur;
127 parameters.add(lambda.parameter);
130 else if(cur instanceof ELambdaType) {
131 cur = ((ELambdaType)cur).value;
139 ExpressionInterpretationContext innerContext = context.createNewContext();
140 Set<Variable> freeVariables = cur.getFreeVariables();
141 for(Variable parameter : parameters)
142 freeVariables.remove(parameter);
144 int[] inheritedVariableIds = new int[freeVariables.size()];
145 for(Variable var : freeVariables) {
146 innerContext.push(var);
147 inheritedVariableIds[i++] = context.getVariableId(var);
151 for(Variable parameter : parameters)
152 innerContext.push(parameter);
155 IExpression body = cur.toIExpression(innerContext);
156 return new ILambda(inheritedVariableIds,
158 innerContext.getMaxVariableId(),
162 public Expression checkBasicType(TypingContext context, Type requiredType) {
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));
172 context.pushEffectUpperBound(location, mfun.effect);
173 parameter.setType(mfun.parameterTypes[0]);
174 value = value.checkType(context, mfun.returnType);
175 effect = context.popEffectUpperBound();
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();
191 public boolean isEffectful() {
196 public void setLocationDeep(long loc) {
197 if(location == Locations.NO_LOCATION) {
199 value.setLocationDeep(loc);
204 public void accept(ExpressionVisitor visitor) {
208 public Expression getValue() {
212 public Variable getParameter() {
217 public Expression accept(ExpressionTransformer transformer) {
218 return transformer.transform(this);
222 public int getSyntacticFunctionArity() {
223 return 1 + value.getSyntacticFunctionArity();