1 package org.simantics.scl.compiler.elaboration.expressions;
3 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.errors.Locations;
8 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
9 import org.simantics.scl.compiler.types.Type;
10 import org.simantics.scl.compiler.types.Types;
11 import org.simantics.scl.compiler.types.exceptions.MatchException;
12 import org.simantics.scl.compiler.types.exceptions.UnificationException;
13 import org.simantics.scl.compiler.types.kinds.Kinds;
14 import org.simantics.scl.compiler.types.util.MultiFunction;
16 import gnu.trove.map.hash.TObjectIntHashMap;
17 import gnu.trove.set.hash.THashSet;
18 import gnu.trove.set.hash.TIntHashSet;
20 public class ELambda extends SimplifiableExpression {
22 Type effect = Types.NO_EFFECTS;
24 public ELambda(Case[] cases) {
28 public ELambda(Case case_) {
29 this(new Case[] {case_});
32 public ELambda(long loc, Case ... cases) {
37 public ELambda(long loc, Expression pat, Expression exp) {
38 this(loc, new Case(new Expression[] {pat}, exp));
41 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
42 for(Case case_ : cases)
43 case_.collectRefs(allRefs, refs);
47 public void collectVars(TObjectIntHashMap<Variable> allVars,
49 for(Case case_ : cases)
50 case_.collectVars(allVars, vars);
53 public Expression decomposeMatching() {
54 Expression[] patterns = cases[0].patterns;
55 int arity = patterns.length;
58 if(cases.length == 1 &&
59 !(cases[0].value instanceof GuardedExpressionGroup)) {
60 boolean noMatchingNeeded = true;
61 for(int i=0;i<arity;++i)
62 if(!(patterns[i] instanceof EVariable)) {
63 noMatchingNeeded = false;
66 if(noMatchingNeeded) {
67 Expression decomposed = cases[0].value.decomposeMatching();
68 Type effect = this.effect;
69 for(int i=arity-1;i>=0;--i) {
70 Variable var = ((EVariable)patterns[i]).getVariable();
71 decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
72 effect = Types.NO_EFFECTS;
79 Variable[] vars = new Variable[arity];
80 Expression[] scrutinee = new Expression[arity];
81 for(int i=0;i<arity;++i) {
82 vars[i] = new Variable("temp" + i);
83 Type type = patterns[i].getType();
84 vars[i].setType(type);
85 scrutinee[i] = new EVariable(getLocation(), vars[i]);
86 scrutinee[i].setType(type);
88 Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
89 Type curEffect = this.effect;
90 for(int i=arity-1;i>=0;--i) {
91 decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
92 curEffect = Types.NO_EFFECTS;
98 protected void updateType() throws MatchException {
99 setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
103 public Expression simplify(SimplificationContext context) {
104 return decomposeMatching().simplify(context);
108 public void collectFreeVariables(THashSet<Variable> vars) {
109 for(Case case_ : cases)
110 case_.collectFreeVariables(vars);
114 public Expression resolve(TranslationContext context) {
115 for(Case case_ : cases)
116 case_.resolve(context);
121 public void setLocationDeep(long loc) {
122 if(location == Locations.NO_LOCATION) {
124 for(Case case_ : cases)
125 case_.setLocationDeep(loc);
130 public Expression replace(ReplaceContext context) {
131 Case[] newCases = new Case[cases.length];
132 for(int i=0;i<cases.length;++i)
133 newCases[i] = cases[i].replace(context);
134 return new ELambda(newCases);
137 public Case[] getCases() {
141 public Expression checkBasicType(TypingContext context, Type requiredType) {
142 int arity = cases[0].patterns.length;
145 mfun = Types.unifyFunction(requiredType, arity);
146 } catch (UnificationException e) {
147 int requiredArity = Types.getArity(requiredType);
148 context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
149 + arity + " patterns have been given.");
150 setType(Types.metaVar(Kinds.STAR));
154 effect = mfun.effect;
155 context.pushEffectUpperBound(location, mfun.effect);
156 for(Case case_ : cases)
157 case_.checkType(context, mfun.parameterTypes, mfun.returnType);
158 context.popEffectUpperBound();
163 public Expression inferType(TypingContext context) {
164 int arity = cases[0].patterns.length;
165 effect = Types.metaVar(Kinds.EFFECT);
166 context.pushEffectUpperBound(location, effect);
167 Type[] parameterTypes = new Type[arity];
168 for(int i=0;i<parameterTypes.length;++i)
169 parameterTypes[i] = Types.metaVar(Kinds.STAR);
170 Type requiredType = Types.metaVar(Kinds.STAR);
171 for(Case case_ : cases)
172 case_.checkType(context, parameterTypes, requiredType);
173 context.popEffectUpperBound();
178 public Expression decorate(ExpressionDecorator decorator) {
179 if(decorator.decorateSubstructure(this))
180 for(Case case_ : cases)
181 case_.decorate(decorator);
182 return decorator.decorate(this);
186 public boolean isEffectful() {
191 public void collectEffects(THashSet<Type> effects) {
192 for(Case case_ : cases) {
193 for(Expression pattern : case_.patterns)
194 pattern.collectEffects(effects);
195 case_.value.collectEffects(effects);
200 public void accept(ExpressionVisitor visitor) {
205 public void forVariables(VariableProcedure procedure) {
206 for(Case case_ : cases)
207 case_.forVariables(procedure);
211 public Expression accept(ExpressionTransformer transformer) {
212 return transformer.transform(this);
216 public int getSyntacticFunctionArity() {
218 for(Case case_ : cases)
219 result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());