1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import java.util.List;
\r
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
6 import org.simantics.scl.compiler.common.names.Name;
\r
7 import org.simantics.scl.compiler.constants.IntegerConstant;
\r
8 import org.simantics.scl.compiler.constants.JavaComparisonToZeroOperation;
\r
9 import org.simantics.scl.compiler.constants.JavaMathOperation;
\r
10 import org.simantics.scl.compiler.constants.NoRepConstant;
\r
11 import org.simantics.scl.compiler.constants.StringConstant;
\r
12 import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
\r
13 import org.simantics.scl.compiler.elaboration.java.Builtins;
\r
14 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
\r
15 import org.simantics.scl.compiler.elaboration.query.Query;
\r
16 import org.simantics.scl.compiler.errors.Locations;
\r
17 import org.simantics.scl.compiler.types.Type;
\r
18 import org.simantics.scl.compiler.types.Types;
\r
19 import org.simantics.scl.compiler.types.exceptions.MatchException;
\r
20 import org.simantics.scl.compiler.types.util.MultiFunction;
\r
22 public class Expressions {
\r
23 public static Expression apply(Expression function, Expression ... parameters) {
\r
24 if(parameters.length == 0)
\r
26 Type ftype = function.getType();
\r
28 MultiFunction mfun = Types.matchFunction(ftype, parameters.length);
\r
29 EApply apply = new EApply(Locations.NO_LOCATION, mfun.effect, function, parameters);
\r
30 apply.setType(mfun.returnType);
\r
32 } catch (MatchException e) {
\r
33 throw new InternalCompilerError("Type of the function " + ftype + " is not compatible with the number of parameters.");
\r
37 public static Expression apply(Type effect, Expression function, Expression ... parameters) {
\r
38 return new EApply(Locations.NO_LOCATION, effect, function, parameters);
\r
41 public static Expression apply(EnvironmentalContext context, Type effect, Name name, Expression ... parameters) {
\r
42 return apply(effect, constant(context, name), parameters);
\r
45 public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Expression ... parameters) {
\r
46 return apply(effect, constant(context, name, typeParameter1), parameters);
\r
49 public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Type typeParameter2, Expression ... parameters) {
\r
50 return apply(effect, constant(context, name, typeParameter1, typeParameter2), parameters);
\r
53 public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Type typeParameter2, Type typeParameter3, Expression ... parameters) {
\r
54 return apply(effect, constant(context, name, typeParameter1, typeParameter2, typeParameter3), parameters);
\r
57 public static Expression constant(SCLValue value) {
\r
58 return new EConstant(value);
\r
61 public static Expression constant(EnvironmentalContext context, Name name) {
\r
62 return new EConstant(context.getValue(name));
\r
65 public static Expression constant(EnvironmentalContext context, Name name, Type ... typeParameters) {
\r
66 return new EConstant(context.getValue(name), typeParameters);
\r
69 public static Expression if_(Expression condition, Expression then_, Expression else_) {
\r
70 return new EIf(condition, then_, else_);
\r
73 public static Expression var(Variable variable) {
\r
74 return new EVariable(variable);
\r
77 public static Variable newVar(String name, Type type) {
\r
78 return new Variable(name, type);
\r
81 public static Variable newBlankVar(Type type) {
\r
82 return new Variable("_", type);
\r
85 public static Expression computation(Type effect, Expression value) {
\r
86 return new ESimpleLambda(
\r
88 newBlankVar(Types.PUNIT),
\r
92 public static Expression blank(Type type) {
\r
93 return new EVariable(newBlankVar(type));
\r
95 public static Expression integer(int value) {
\r
96 return new ELiteral(new IntegerConstant(value));
\r
99 public static Expression string(String value) {
\r
100 return new ELiteral(new StringConstant(value));
\r
103 public static Expression tuple() {
\r
104 return new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]);
\r
107 public static Expression punit() {
\r
108 return new ELiteral(NoRepConstant.PUNIT);
\r
111 public static Expression tuple(Expression ... cs) {
\r
114 Type[] typeParameters = new Type[cs.length];
\r
115 for(int i=0;i<cs.length;++i)
\r
116 typeParameters[i] = cs[i].getType();
\r
117 EApply result = new EApply(
\r
118 new EConstant(Builtins.TUPLE_CONSTRUCTORS[cs.length], typeParameters),
\r
120 result.setType(Types.tuple(Types.getTypes(cs)));
\r
124 public static Expression[] vars(Variable ... variables) {
\r
125 Expression[] expressions = new Expression[variables.length];
\r
126 for(int i=0;i<variables.length;++i)
\r
127 expressions[i] = new EVariable(variables[i]);
\r
128 return expressions;
\r
131 public static Expression[] vars(List<Variable> variables) {
\r
132 Expression[] expressions = new Expression[variables.size()];
\r
133 for(int i=0;i<variables.size();++i)
\r
134 expressions[i] = new EVariable(variables.get(i));
\r
135 return expressions;
\r
138 public static Expression match(Expression scrutinee,
\r
139 Expression pattern1, Expression value1) {
\r
140 return new EMatch(scrutinee, new Case(pattern1, value1));
\r
143 public static Expression match(Expression scrutinee,
\r
144 Expression pattern1, Expression value1,
\r
145 Expression pattern2, Expression value2) {
\r
146 return new EMatch(scrutinee, new Case(pattern1, value1), new Case(pattern2, value2));
\r
149 public static Expression matchWithDefault(Expression scrutinee,
\r
150 Expression pattern1, Expression value1,
\r
151 Expression default_) {
\r
152 return new EMatch(scrutinee, new Case(pattern1, value1), new Case(blank(pattern1.getType()), default_));
\r
155 public static Expression let(Variable target, Expression value, Expression in) {
\r
156 return new ESimpleLet(target, value, in);
\r
159 public static Expression letRec(Variable target, Expression value, Expression in) {
\r
160 return new ELet(Locations.NO_LOCATION, new Assignment[] {new Assignment(var(target), value)}, in);
\r
163 public static Expression letRec(Variable[] targets, Expression[] values, Expression in) {
\r
164 if(targets.length != values.length)
\r
165 throw new InternalCompilerError();
\r
166 Assignment[] assignments = new Assignment[targets.length];
\r
167 for(int i=0;i<targets.length;++i)
\r
168 assignments[i] = new Assignment(var(targets[i]), values[i]);
\r
169 return new ELet(Locations.NO_LOCATION, assignments, in);
\r
172 public static Expression lambda(Type effect, Variable var, Expression value) {
\r
173 return new ESimpleLambda(effect, var, value);
\r
176 public static Expression lambda(Variable var, Expression value) {
\r
177 return new ESimpleLambda(value.getEffect(), var, value);
\r
180 public static Expression lambda(Type effect, Variable[] vars, Expression value) {
\r
181 for(int i=vars.length-1;i>=0;--i) {
\r
182 value = new ESimpleLambda(effect, vars[i], value);
\r
183 effect = Types.NO_EFFECTS;
\r
188 public static Expression lambda(Type effect, List<Variable> vars, Expression value) {
\r
189 for(int i=vars.size()-1;i>=0;--i) {
\r
190 value = new ESimpleLambda(effect, vars.get(i), value);
\r
191 effect = Types.NO_EFFECTS;
\r
196 public static Expression lambda(Variable[] vars, Expression value) {
\r
197 return lambda(value.getEffect(), vars, value);
\r
200 public static Expression lambda(List<Variable> vars, Expression value) {
\r
201 return lambda(value.getEffect(), vars, value);
\r
204 public static Expression Nothing(Type type) {
\r
205 return new EConstant(Builtins.Nothing, type);
\r
208 public static Expression Just(Expression expression) {
\r
209 return apply(Types.NO_EFFECTS, new EConstant(Builtins.Just, expression.getType()), expression);
\r
212 public static Expression seq(Expression first, Expression second) {
\r
213 return let(newBlankVar(first.getType()), first, second);
\r
216 public static Expression as(Variable var, Expression value) {
\r
217 return new EAsPattern(var, value);
\r
220 public static Expression loc(long location, Expression expression) {
\r
221 expression.setLocationDeep(location);
\r
225 public static Query loc(long location, Query query) {
\r
226 query.setLocationDeep(location);
\r
230 public static Expression applyTypes(Expression expression, Type[] types) {
\r
231 for(Type type : types)
\r
232 expression = new EApplyType(expression, type);
\r
236 public static Expression isZeroInteger(Expression value) {
\r
237 return apply(Types.NO_EFFECTS, new ELiteral(new JavaComparisonToZeroOperation("==")), value);
\r
240 public static Expression addInteger(Expression a, Expression b) {
\r
241 return apply(Types.NO_EFFECTS, new ELiteral(JavaMathOperation.IADD), a, b);
\r
244 public static Expression externalConstant(Object value, Type type) {
\r
245 return new EExternalConstant(value, type);
\r