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;
58 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
59 value.collectRefs(allRefs, refs);
63 public void collectVars(TObjectIntHashMap<Variable> allVars,
65 value.collectVars(allVars, vars);
68 public Expression decomposeMatching() {
69 value = value.decomposeMatching();
74 protected void updateType() throws MatchException {
75 setType(Types.functionE(Types.canonical(parameter.type),
76 effect, value.getType()));
80 public IVal toVal(CompilationContext context, CodeWriter w) {
81 return lambdaToVal(context, w);
85 public void collectFreeVariables(THashSet<Variable> vars) {
86 value.collectFreeVariables(vars);
87 vars.remove(parameter);
91 public Expression simplify(SimplificationContext context) {
92 value = value.simplify(context);
97 public Expression resolve(TranslationContext context) {
98 value = value.resolve(context);
103 public Expression replace(ReplaceContext context) {
104 Variable newParameter = parameter.copy();
105 context.varMap.put(parameter, new EVariable(newParameter));
106 ESimpleLambda result = new ESimpleLambda(getLocation(),
108 effect.replace(context.tvarMap),
109 value.replace(context));
110 // not absolutely needed, but maybe good for performance
111 context.varMap.remove(parameter);
115 public Type getLocalEffect() {
116 if(SCLCompilerConfiguration.DEBUG)
118 throw new InternalCompilerError();
122 public void setEffect(Type effect) {
124 throw new InternalCompilerError();
125 this.effect = effect;
129 public IExpression toIExpression(ExpressionInterpretationContext context) {
130 // Find parameters of the whole function definition
131 ArrayList<Variable> parameters = new ArrayList<Variable>(2);
132 parameters.add(parameter);
133 Expression cur = value;
135 if(cur instanceof ESimpleLambda) {
136 ESimpleLambda lambda = (ESimpleLambda)cur;
137 parameters.add(lambda.parameter);
140 else if(cur instanceof ELambdaType) {
141 cur = ((ELambdaType)cur).value;
149 ExpressionInterpretationContext innerContext = context.createNewContext();
150 THashSet<Variable> freeVariables = cur.getFreeVariables();
151 for(Variable parameter : parameters)
152 freeVariables.remove(parameter);
154 int[] inheritedVariableIds = new int[freeVariables.size()];
155 for(Variable var : freeVariables) {
156 innerContext.push(var);
157 inheritedVariableIds[i++] = context.getVariableId(var);
161 for(Variable parameter : parameters)
162 innerContext.push(parameter);
165 IExpression body = cur.toIExpression(innerContext);
166 return new ILambda(inheritedVariableIds,
168 innerContext.getMaxVariableId(),
172 public Expression checkBasicType(TypingContext context, Type requiredType) {
175 mfun = Types.unifyFunction(requiredType, 1);
176 } catch (UnificationException e) {
177 context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
178 setType(Types.metaVar(Kinds.STAR));
182 context.pushEffectUpperBound(location, mfun.effect);
183 parameter.setType(mfun.parameterTypes[0]);
184 value = value.checkType(context, mfun.returnType);
185 effect = context.popEffectUpperBound();
190 public Expression inferType(TypingContext context) {
191 effect = Types.metaVar(Kinds.EFFECT);
192 context.pushEffectUpperBound(location, effect);
193 if(parameter.type == null)
194 parameter.setType(Types.metaVar(Kinds.STAR));
195 value = value.checkType(context, Types.metaVar(Kinds.STAR));
196 context.popEffectUpperBound();
201 public boolean isEffectful() {
206 public void collectEffects(THashSet<Type> effects) {
210 public void setLocationDeep(long loc) {
211 if(location == Locations.NO_LOCATION) {
213 value.setLocationDeep(loc);
218 public void accept(ExpressionVisitor visitor) {
222 public Expression getValue() {
226 public Variable getParameter() {
231 public void forVariables(VariableProcedure procedure) {
232 value.forVariables(procedure);
236 public Expression accept(ExpressionTransformer transformer) {
237 return transformer.transform(this);
241 public int getSyntacticFunctionArity() {
242 return 1 + value.getSyntacticFunctionArity();