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, Expression pat, Expression exp) {
33 this(loc, new Case(new Expression[] {pat}, exp));
36 public Expression decomposeMatching() {
37 Expression[] patterns = cases[0].patterns;
38 int arity = patterns.length;
41 if(cases.length == 1 &&
42 !(cases[0].value instanceof GuardedExpressionGroup)) {
43 boolean noMatchingNeeded = true;
44 for(int i=0;i<arity;++i)
45 if(!(patterns[i] instanceof EVariable)) {
46 noMatchingNeeded = false;
49 if(noMatchingNeeded) {
50 Expression decomposed = cases[0].value.decomposeMatching();
51 Type effect = this.effect;
52 for(int i=arity-1;i>=0;--i) {
53 Variable var = ((EVariable)patterns[i]).getVariable();
54 decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
55 effect = Types.NO_EFFECTS;
62 Variable[] vars = new Variable[arity];
63 Expression[] scrutinee = new Expression[arity];
64 for(int i=0;i<arity;++i) {
65 vars[i] = new Variable("temp" + i);
66 Type type = patterns[i].getType();
67 vars[i].setType(type);
68 scrutinee[i] = new EVariable(getLocation(), vars[i]);
69 scrutinee[i].setType(type);
71 Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
72 Type curEffect = this.effect;
73 for(int i=arity-1;i>=0;--i) {
74 decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
75 curEffect = Types.NO_EFFECTS;
81 protected void updateType() throws MatchException {
82 setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
86 public Expression simplify(SimplificationContext context) {
87 return decomposeMatching().simplify(context);
91 public Expression resolve(TranslationContext context) {
92 for(Case case_ : cases)
93 case_.resolve(context);
98 public void setLocationDeep(long loc) {
99 if(location == Locations.NO_LOCATION) {
101 for(Case case_ : cases)
102 case_.setLocationDeep(loc);
107 public Expression replace(ReplaceContext context) {
108 Case[] newCases = new Case[cases.length];
109 for(int i=0;i<cases.length;++i)
110 newCases[i] = cases[i].replace(context);
111 return new ELambda(newCases);
114 public Case[] getCases() {
118 public Expression checkBasicType(TypingContext context, Type requiredType) {
119 int arity = cases[0].patterns.length;
122 mfun = Types.unifyFunction(requiredType, arity);
123 } catch (UnificationException e) {
124 int requiredArity = Types.getArity(requiredType);
125 context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
126 + arity + " patterns have been given.");
127 setType(Types.metaVar(Kinds.STAR));
131 effect = mfun.effect;
132 context.pushEffectUpperBound(location, mfun.effect);
133 for(Case case_ : cases)
134 case_.checkType(context, mfun.parameterTypes, mfun.returnType);
135 context.popEffectUpperBound();
140 public Expression inferType(TypingContext context) {
141 int arity = cases[0].patterns.length;
142 effect = Types.metaVar(Kinds.EFFECT);
143 context.pushEffectUpperBound(location, effect);
144 Type[] parameterTypes = new Type[arity];
145 for(int i=0;i<parameterTypes.length;++i)
146 parameterTypes[i] = Types.metaVar(Kinds.STAR);
147 Type requiredType = Types.metaVar(Kinds.STAR);
148 for(Case case_ : cases)
149 case_.checkType(context, parameterTypes, requiredType);
150 context.popEffectUpperBound();
155 public boolean isEffectful() {
160 public void accept(ExpressionVisitor visitor) {
165 public Expression accept(ExpressionTransformer transformer) {
166 return transformer.transform(this);
170 public int getSyntacticFunctionArity() {
172 for(Case case_ : cases)
173 result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());