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.types.Type;
9 import org.simantics.scl.compiler.types.Types;
10 import org.simantics.scl.compiler.types.exceptions.MatchException;
11 import org.simantics.scl.compiler.types.exceptions.UnificationException;
12 import org.simantics.scl.compiler.types.kinds.Kinds;
13 import org.simantics.scl.compiler.types.util.MultiFunction;
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.set.hash.THashSet;
17 import gnu.trove.set.hash.TIntHashSet;
19 public class ELambda extends SimplifiableExpression {
21 Type effect = Types.NO_EFFECTS;
23 public ELambda(Case[] cases) {
27 public ELambda(Case case_) {
28 this(new Case[] {case_});
31 public ELambda(long loc, Case ... cases) {
36 public ELambda(long loc, Expression pat, Expression exp) {
37 this(loc, new Case(new Expression[] {pat}, exp));
40 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
41 for(Case case_ : cases)
42 case_.collectRefs(allRefs, refs);
46 public void collectVars(TObjectIntHashMap<Variable> allVars,
48 for(Case case_ : cases)
49 case_.collectVars(allVars, vars);
52 public Expression decomposeMatching() {
53 Expression[] patterns = cases[0].patterns;
54 int arity = patterns.length;
57 if(cases.length == 1 &&
58 !(cases[0].value instanceof GuardedExpressionGroup)) {
59 boolean noMatchingNeeded = true;
60 for(int i=0;i<arity;++i)
61 if(!(patterns[i] instanceof EVariable)) {
62 noMatchingNeeded = false;
65 if(noMatchingNeeded) {
66 Expression decomposed = cases[0].value.decomposeMatching();
67 Type effect = this.effect;
68 for(int i=arity-1;i>=0;--i) {
69 Variable var = ((EVariable)patterns[i]).getVariable();
70 decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
71 effect = Types.NO_EFFECTS;
78 Variable[] vars = new Variable[arity];
79 Expression[] scrutinee = new Expression[arity];
80 for(int i=0;i<arity;++i) {
81 vars[i] = new Variable("temp" + i);
82 Type type = patterns[i].getType();
83 vars[i].setType(type);
84 scrutinee[i] = new EVariable(getLocation(), vars[i]);
85 scrutinee[i].setType(type);
87 Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
88 Type curEffect = this.effect;
89 for(int i=arity-1;i>=0;--i) {
90 decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
91 curEffect = Types.NO_EFFECTS;
97 protected void updateType() throws MatchException {
98 setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
102 public Expression simplify(SimplificationContext context) {
103 return decomposeMatching().simplify(context);
107 public void collectFreeVariables(THashSet<Variable> vars) {
108 for(Case case_ : cases)
109 case_.collectFreeVariables(vars);
113 public Expression resolve(TranslationContext context) {
114 for(Case case_ : cases)
115 case_.resolve(context);
120 public void setLocationDeep(long loc) {
121 if(location == Locations.NO_LOCATION) {
123 for(Case case_ : cases)
124 case_.setLocationDeep(loc);
129 public Expression replace(ReplaceContext context) {
130 Case[] newCases = new Case[cases.length];
131 for(int i=0;i<cases.length;++i)
132 newCases[i] = cases[i].replace(context);
133 return new ELambda(newCases);
136 public Case[] getCases() {
140 public Expression checkBasicType(TypingContext context, Type requiredType) {
141 int arity = cases[0].patterns.length;
144 mfun = Types.unifyFunction(requiredType, arity);
145 } catch (UnificationException e) {
146 int requiredArity = Types.getArity(requiredType);
147 context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
148 + arity + " patterns have been given.");
149 setType(Types.metaVar(Kinds.STAR));
153 effect = mfun.effect;
154 context.pushEffectUpperBound(location, mfun.effect);
155 for(Case case_ : cases)
156 case_.checkType(context, mfun.parameterTypes, mfun.returnType);
157 context.popEffectUpperBound();
162 public Expression inferType(TypingContext context) {
163 int arity = cases[0].patterns.length;
164 effect = Types.metaVar(Kinds.EFFECT);
165 context.pushEffectUpperBound(location, effect);
166 Type[] parameterTypes = new Type[arity];
167 for(int i=0;i<parameterTypes.length;++i)
168 parameterTypes[i] = Types.metaVar(Kinds.STAR);
169 Type requiredType = Types.metaVar(Kinds.STAR);
170 for(Case case_ : cases)
171 case_.checkType(context, parameterTypes, requiredType);
172 context.popEffectUpperBound();
177 public boolean isEffectful() {
182 public void collectEffects(THashSet<Type> effects) {
183 for(Case case_ : cases) {
184 for(Expression pattern : case_.patterns)
185 pattern.collectEffects(effects);
186 case_.value.collectEffects(effects);
191 public void accept(ExpressionVisitor visitor) {
196 public Expression accept(ExpressionTransformer transformer) {
197 return transformer.transform(this);
201 public int getSyntacticFunctionArity() {
203 for(Case case_ : cases)
204 result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());