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.TIntHashSet;
18 public class ELambda extends SimplifiableExpression {
20 Type effect = Types.NO_EFFECTS;
22 public ELambda(Case[] cases) {
26 public ELambda(Case case_) {
27 this(new Case[] {case_});
30 public ELambda(long loc, Case ... cases) {
35 public ELambda(long loc, Expression pat, Expression exp) {
36 this(loc, new Case(new Expression[] {pat}, exp));
40 public void collectVars(TObjectIntHashMap<Variable> allVars,
42 for(Case case_ : cases)
43 case_.collectVars(allVars, vars);
46 public Expression decomposeMatching() {
47 Expression[] patterns = cases[0].patterns;
48 int arity = patterns.length;
51 if(cases.length == 1 &&
52 !(cases[0].value instanceof GuardedExpressionGroup)) {
53 boolean noMatchingNeeded = true;
54 for(int i=0;i<arity;++i)
55 if(!(patterns[i] instanceof EVariable)) {
56 noMatchingNeeded = false;
59 if(noMatchingNeeded) {
60 Expression decomposed = cases[0].value.decomposeMatching();
61 Type effect = this.effect;
62 for(int i=arity-1;i>=0;--i) {
63 Variable var = ((EVariable)patterns[i]).getVariable();
64 decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
65 effect = Types.NO_EFFECTS;
72 Variable[] vars = new Variable[arity];
73 Expression[] scrutinee = new Expression[arity];
74 for(int i=0;i<arity;++i) {
75 vars[i] = new Variable("temp" + i);
76 Type type = patterns[i].getType();
77 vars[i].setType(type);
78 scrutinee[i] = new EVariable(getLocation(), vars[i]);
79 scrutinee[i].setType(type);
81 Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
82 Type curEffect = this.effect;
83 for(int i=arity-1;i>=0;--i) {
84 decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
85 curEffect = Types.NO_EFFECTS;
91 protected void updateType() throws MatchException {
92 setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
96 public Expression simplify(SimplificationContext context) {
97 return decomposeMatching().simplify(context);
101 public Expression resolve(TranslationContext context) {
102 for(Case case_ : cases)
103 case_.resolve(context);
108 public void setLocationDeep(long loc) {
109 if(location == Locations.NO_LOCATION) {
111 for(Case case_ : cases)
112 case_.setLocationDeep(loc);
117 public Expression replace(ReplaceContext context) {
118 Case[] newCases = new Case[cases.length];
119 for(int i=0;i<cases.length;++i)
120 newCases[i] = cases[i].replace(context);
121 return new ELambda(newCases);
124 public Case[] getCases() {
128 public Expression checkBasicType(TypingContext context, Type requiredType) {
129 int arity = cases[0].patterns.length;
132 mfun = Types.unifyFunction(requiredType, arity);
133 } catch (UnificationException e) {
134 int requiredArity = Types.getArity(requiredType);
135 context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
136 + arity + " patterns have been given.");
137 setType(Types.metaVar(Kinds.STAR));
141 effect = mfun.effect;
142 context.pushEffectUpperBound(location, mfun.effect);
143 for(Case case_ : cases)
144 case_.checkType(context, mfun.parameterTypes, mfun.returnType);
145 context.popEffectUpperBound();
150 public Expression inferType(TypingContext context) {
151 int arity = cases[0].patterns.length;
152 effect = Types.metaVar(Kinds.EFFECT);
153 context.pushEffectUpperBound(location, effect);
154 Type[] parameterTypes = new Type[arity];
155 for(int i=0;i<parameterTypes.length;++i)
156 parameterTypes[i] = Types.metaVar(Kinds.STAR);
157 Type requiredType = Types.metaVar(Kinds.STAR);
158 for(Case case_ : cases)
159 case_.checkType(context, parameterTypes, requiredType);
160 context.popEffectUpperBound();
165 public boolean isEffectful() {
170 public void accept(ExpressionVisitor visitor) {
175 public Expression accept(ExpressionTransformer transformer) {
176 return transformer.transform(this);
180 public int getSyntacticFunctionArity() {
182 for(Case case_ : cases)
183 result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());