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 public class ELambda extends SimplifiableExpression {
17 Type effect = Types.NO_EFFECTS;
19 public ELambda(Case[] cases) {
23 public ELambda(Case case_) {
24 this(new Case[] {case_});
27 public ELambda(long loc, Case ... cases) {
32 public ELambda(long loc, Type effect, Case ... cases) {
38 public ELambda(long loc, Expression pat, Expression exp) {
39 this(loc, new Case(new Expression[] {pat}, exp));
42 public Expression decomposeMatching() {
43 Expression[] patterns = cases[0].patterns;
44 int arity = patterns.length;
47 if(cases.length == 1 &&
48 !(cases[0].value instanceof GuardedExpressionGroup)) {
49 boolean noMatchingNeeded = true;
50 for(int i=0;i<arity;++i)
51 if(!(patterns[i] instanceof EVariable)) {
52 noMatchingNeeded = false;
55 if(noMatchingNeeded) {
56 Expression decomposed = cases[0].value.decomposeMatching();
57 Type effect = this.effect;
58 for(int i=arity-1;i>=0;--i) {
59 Variable var = ((EVariable)patterns[i]).getVariable();
60 decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
61 effect = Types.NO_EFFECTS;
68 Variable[] vars = new Variable[arity];
69 Expression[] scrutinee = new Expression[arity];
70 for(int i=0;i<arity;++i) {
71 vars[i] = new Variable("temp" + i);
72 Type type = patterns[i].getType();
73 vars[i].setType(type);
74 scrutinee[i] = new EVariable(getLocation(), vars[i]);
75 scrutinee[i].setType(type);
77 Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
78 Type curEffect = this.effect;
79 for(int i=arity-1;i>=0;--i) {
80 decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
81 curEffect = Types.NO_EFFECTS;
87 protected void updateType() throws MatchException {
88 setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
92 public Expression simplify(SimplificationContext context) {
93 return decomposeMatching().simplify(context);
97 public Expression resolve(TranslationContext context) {
98 for(Case case_ : cases)
99 case_.resolve(context);
104 public void setLocationDeep(long loc) {
105 if(location == Locations.NO_LOCATION) {
107 for(Case case_ : cases)
108 case_.setLocationDeep(loc);
113 public Expression replace(ReplaceContext context) {
114 Case[] newCases = new Case[cases.length];
115 for(int i=0;i<cases.length;++i)
116 newCases[i] = cases[i].replace(context);
117 return new ELambda(newCases);
120 public Case[] getCases() {
124 public Expression checkBasicType(TypingContext context, Type requiredType) {
125 int arity = cases[0].patterns.length;
128 mfun = Types.unifyFunction(requiredType, arity);
129 } catch (UnificationException e) {
130 int requiredArity = Types.getArity(requiredType);
131 context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
132 + arity + " patterns have been given.");
133 setType(Types.metaVar(Kinds.STAR));
137 effect = mfun.effect;
138 context.pushEffectUpperBound(location, mfun.effect);
139 for(Case case_ : cases)
140 case_.checkType(context, mfun.parameterTypes, mfun.returnType);
141 context.popEffectUpperBound();
146 public Expression inferType(TypingContext context) {
147 int arity = cases[0].patterns.length;
148 effect = Types.metaVar(Kinds.EFFECT);
149 context.pushEffectUpperBound(location, effect);
150 Type[] parameterTypes = new Type[arity];
151 for(int i=0;i<parameterTypes.length;++i)
152 parameterTypes[i] = Types.metaVar(Kinds.STAR);
153 Type requiredType = Types.metaVar(Kinds.STAR);
154 for(Case case_ : cases)
155 case_.checkType(context, parameterTypes, requiredType);
156 context.popEffectUpperBound();
161 public boolean isEffectful() {
166 public void accept(ExpressionVisitor visitor) {
171 public Expression accept(ExpressionTransformer transformer) {
172 return transformer.transform(this);
176 public int getSyntacticFunctionArity() {
178 for(Case case_ : cases)
179 result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());