--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.constants.IntegerConstant;\r
+import org.simantics.scl.compiler.constants.JavaComparisonToZeroOperation;\r
+import org.simantics.scl.compiler.constants.JavaMathOperation;\r
+import org.simantics.scl.compiler.constants.NoRepConstant;\r
+import org.simantics.scl.compiler.constants.StringConstant;\r
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
+import org.simantics.scl.compiler.elaboration.java.Builtins;\r
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
+import org.simantics.scl.compiler.elaboration.query.Query;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+import org.simantics.scl.compiler.types.util.MultiFunction;\r
+\r
+public class Expressions {\r
+ public static Expression apply(Expression function, Expression ... parameters) {\r
+ if(parameters.length == 0)\r
+ return function;\r
+ Type ftype = function.getType();\r
+ try {\r
+ MultiFunction mfun = Types.matchFunction(ftype, parameters.length);\r
+ EApply apply = new EApply(Locations.NO_LOCATION, mfun.effect, function, parameters);\r
+ apply.setType(mfun.returnType);\r
+ return apply;\r
+ } catch (MatchException e) {\r
+ throw new InternalCompilerError("Type of the function " + ftype + " is not compatible with the number of parameters.");\r
+ }\r
+ }\r
+ \r
+ public static Expression apply(Type effect, Expression function, Expression ... parameters) {\r
+ return new EApply(Locations.NO_LOCATION, effect, function, parameters);\r
+ }\r
+ \r
+ public static Expression apply(EnvironmentalContext context, Type effect, Name name, Expression ... parameters) {\r
+ return apply(effect, constant(context, name), parameters);\r
+ }\r
+ \r
+ public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Expression ... parameters) {\r
+ return apply(effect, constant(context, name, typeParameter1), parameters);\r
+ }\r
+ \r
+ public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Type typeParameter2, Expression ... parameters) {\r
+ return apply(effect, constant(context, name, typeParameter1, typeParameter2), parameters);\r
+ }\r
+\r
+ public static Expression apply(EnvironmentalContext context, Type effect, Name name, Type typeParameter1, Type typeParameter2, Type typeParameter3, Expression ... parameters) {\r
+ return apply(effect, constant(context, name, typeParameter1, typeParameter2, typeParameter3), parameters);\r
+ }\r
+\r
+ public static Expression constant(SCLValue value) {\r
+ return new EConstant(value);\r
+ }\r
+ \r
+ public static Expression constant(EnvironmentalContext context, Name name) {\r
+ return new EConstant(context.getValue(name));\r
+ }\r
+ \r
+ public static Expression constant(EnvironmentalContext context, Name name, Type ... typeParameters) {\r
+ return new EConstant(context.getValue(name), typeParameters);\r
+ }\r
+\r
+ public static Expression if_(Expression condition, Expression then_, Expression else_) {\r
+ return new EIf(condition, then_, else_);\r
+ }\r
+ \r
+ public static Expression var(Variable variable) {\r
+ return new EVariable(variable);\r
+ }\r
+ \r
+ public static Variable newVar(String name, Type type) {\r
+ return new Variable(name, type);\r
+ }\r
+ \r
+ public static Variable newBlankVar(Type type) {\r
+ return new Variable("_", type);\r
+ }\r
+ \r
+ public static Expression computation(Type effect, Expression value) {\r
+ return new ESimpleLambda(\r
+ effect,\r
+ newBlankVar(Types.PUNIT),\r
+ value);\r
+ }\r
+ \r
+ public static Expression blank(Type type) {\r
+ return new EVariable(newBlankVar(type));\r
+ }\r
+ public static Expression integer(int value) {\r
+ return new ELiteral(new IntegerConstant(value));\r
+ }\r
+\r
+ public static Expression string(String value) {\r
+ return new ELiteral(new StringConstant(value));\r
+ }\r
+\r
+ public static Expression tuple() {\r
+ return new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]);\r
+ }\r
+ \r
+ public static Expression punit() {\r
+ return new ELiteral(NoRepConstant.PUNIT);\r
+ }\r
+ \r
+ public static Expression tuple(Expression ... cs) {\r
+ if(cs.length == 1)\r
+ return cs[0];\r
+ Type[] typeParameters = new Type[cs.length];\r
+ for(int i=0;i<cs.length;++i)\r
+ typeParameters[i] = cs[i].getType();\r
+ EApply result = new EApply(\r
+ new EConstant(Builtins.TUPLE_CONSTRUCTORS[cs.length], typeParameters),\r
+ cs);\r
+ result.setType(Types.tuple(Types.getTypes(cs)));\r
+ return result;\r
+ }\r
+ \r
+ public static Expression[] vars(Variable ... variables) {\r
+ Expression[] expressions = new Expression[variables.length];\r
+ for(int i=0;i<variables.length;++i)\r
+ expressions[i] = new EVariable(variables[i]);\r
+ return expressions;\r
+ }\r
+ \r
+ public static Expression[] vars(List<Variable> variables) {\r
+ Expression[] expressions = new Expression[variables.size()];\r
+ for(int i=0;i<variables.size();++i)\r
+ expressions[i] = new EVariable(variables.get(i));\r
+ return expressions;\r
+ }\r
+ \r
+ public static Expression match(Expression scrutinee,\r
+ Expression pattern1, Expression value1) {\r
+ return new EMatch(scrutinee, new Case(pattern1, value1));\r
+ }\r
+ \r
+ public static Expression match(Expression scrutinee,\r
+ Expression pattern1, Expression value1,\r
+ Expression pattern2, Expression value2) {\r
+ return new EMatch(scrutinee, new Case(pattern1, value1), new Case(pattern2, value2));\r
+ }\r
+ \r
+ public static Expression matchWithDefault(Expression scrutinee,\r
+ Expression pattern1, Expression value1,\r
+ Expression default_) {\r
+ return new EMatch(scrutinee, new Case(pattern1, value1), new Case(blank(pattern1.getType()), default_));\r
+ }\r
+ \r
+ public static Expression let(Variable target, Expression value, Expression in) {\r
+ return new ESimpleLet(target, value, in);\r
+ }\r
+ \r
+ public static Expression letRec(Variable target, Expression value, Expression in) {\r
+ return new ELet(Locations.NO_LOCATION, new Assignment[] {new Assignment(var(target), value)}, in);\r
+ }\r
+ \r
+ public static Expression letRec(Variable[] targets, Expression[] values, Expression in) {\r
+ if(targets.length != values.length)\r
+ throw new InternalCompilerError();\r
+ Assignment[] assignments = new Assignment[targets.length];\r
+ for(int i=0;i<targets.length;++i)\r
+ assignments[i] = new Assignment(var(targets[i]), values[i]);\r
+ return new ELet(Locations.NO_LOCATION, assignments, in);\r
+ }\r
+ \r
+ public static Expression lambda(Type effect, Variable var, Expression value) {\r
+ return new ESimpleLambda(effect, var, value);\r
+ }\r
+ \r
+ public static Expression lambda(Variable var, Expression value) {\r
+ return new ESimpleLambda(value.getEffect(), var, value);\r
+ }\r
+ \r
+ public static Expression lambda(Type effect, Variable[] vars, Expression value) {\r
+ for(int i=vars.length-1;i>=0;--i) {\r
+ value = new ESimpleLambda(effect, vars[i], value);\r
+ effect = Types.NO_EFFECTS;\r
+ }\r
+ return value;\r
+ }\r
+ \r
+ public static Expression lambda(Type effect, List<Variable> vars, Expression value) {\r
+ for(int i=vars.size()-1;i>=0;--i) {\r
+ value = new ESimpleLambda(effect, vars.get(i), value);\r
+ effect = Types.NO_EFFECTS;\r
+ }\r
+ return value;\r
+ }\r
+ \r
+ public static Expression lambda(Variable[] vars, Expression value) {\r
+ return lambda(value.getEffect(), vars, value);\r
+ }\r
+ \r
+ public static Expression lambda(List<Variable> vars, Expression value) {\r
+ return lambda(value.getEffect(), vars, value);\r
+ }\r
+ \r
+ public static Expression Nothing(Type type) {\r
+ return new EConstant(Builtins.Nothing, type);\r
+ }\r
+ \r
+ public static Expression Just(Expression expression) {\r
+ return apply(Types.NO_EFFECTS, new EConstant(Builtins.Just, expression.getType()), expression);\r
+ }\r
+ \r
+ public static Expression seq(Expression first, Expression second) {\r
+ return let(newBlankVar(first.getType()), first, second);\r
+ }\r
+ \r
+ public static Expression as(Variable var, Expression value) {\r
+ return new EAsPattern(var, value);\r
+ }\r
+ \r
+ public static Expression loc(long location, Expression expression) {\r
+ expression.setLocationDeep(location);\r
+ return expression;\r
+ }\r
+ \r
+ public static Query loc(long location, Query query) {\r
+ query.setLocationDeep(location);\r
+ return query;\r
+ }\r
+\r
+ public static Expression applyTypes(Expression expression, Type[] types) {\r
+ for(Type type : types)\r
+ expression = new EApplyType(expression, type);\r
+ return expression;\r
+ }\r
+ \r
+ public static Expression isZeroInteger(Expression value) {\r
+ return apply(Types.NO_EFFECTS, new ELiteral(new JavaComparisonToZeroOperation("==")), value);\r
+ }\r
+ \r
+ public static Expression addInteger(Expression a, Expression b) {\r
+ return apply(Types.NO_EFFECTS, new ELiteral(JavaMathOperation.IADD), a, b);\r
+ }\r
+\r
+ public static Expression externalConstant(Object value, Type type) {\r
+ return new EExternalConstant(value, type);\r
+ }\r
+}\r