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