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