-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.precedence.Precedence;\r
-import org.simantics.scl.compiler.constants.NoRepConstant;\r
-import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;\r
-import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
-import org.simantics.scl.compiler.elaboration.query.QAtom;\r
-import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
-import org.simantics.scl.compiler.environment.Environment;\r
-import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
-import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
-import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.parsing.Symbol;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.TForAll;\r
-import org.simantics.scl.compiler.types.TFun;\r
-import org.simantics.scl.compiler.types.TPred;\r
-import org.simantics.scl.compiler.types.TVar;\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.kinds.Kinds;\r
-import org.simantics.scl.compiler.types.util.Typed;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public abstract class Expression extends Symbol implements Typed {\r
- public static final Expression[] EMPTY_ARRAY = new Expression[0];\r
- \r
- transient\r
- private Type type;\r
- \r
- public Expression() {\r
- }\r
- \r
- public Expression(long loc) {\r
- this.location = loc;\r
- }\r
- \r
- @Override\r
- public Type getType() {\r
- if(type == null) {\r
- try {\r
- updateType();\r
- } catch (MatchException e) {\r
- throw new InternalCompilerError(e);\r
- }\r
- if(type == null)\r
- throw new InternalCompilerError(getClass().getSimpleName() + \r
- ".updateType couldn't compute its type.");\r
- }\r
- return type;\r
- }\r
-\r
- public void setType(Type type) {\r
- if(type == null)\r
- throw new NullPointerException();\r
- this.type = type;\r
- }\r
- \r
- /**\r
- * Infers the type of the expression without any context. Adds type\r
- * applications and lambdas if needed. \r
- */\r
- public Expression inferType(TypingContext context) {\r
- return checkBasicType(context, Types.metaVar(Kinds.STAR));\r
- }\r
-\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- return context.subsume(inferType(context), requiredType);\r
- }\r
- \r
- protected Expression applyPUnit(EnvironmentalContext context) {\r
- Type type = Types.canonical(getType());\r
- if(type instanceof TFun) {\r
- TFun fun = (TFun)type;\r
- if(fun.getCanonicalDomain() == Types.PUNIT) {\r
- EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT));\r
- result.effect = fun.getCanonicalEffect();\r
- return result;\r
- }\r
- }\r
- return this;\r
- }\r
-\r
- public Expression checkIgnoredType(TypingContext context) {\r
- Expression expression = inferType(context);\r
- if(Types.canonical(expression.getType()) != Types.UNIT)\r
- expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT));\r
- return expression;\r
- }\r
- \r
- /**\r
- * Checks the type of the expression against the given type. Adds type\r
- * applications and lambdas if needed.\r
- */\r
- public final Expression checkType(TypingContext context, Type requiredType) {\r
- //System.out.println("checkType: " + this + " :: " + requiredType);\r
- if(!context.isInPattern()) {\r
- requiredType = Types.canonical(requiredType);\r
- if(requiredType instanceof TForAll) {\r
- TForAll forAll = (TForAll)requiredType;\r
- TVar var = forAll.var;\r
- TVar newVar = Types.var(var.getKind());\r
- requiredType = Types.canonical(forAll.type).replace(var, newVar);\r
- return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType));\r
- }\r
- while(requiredType instanceof TFun) {\r
- TFun fun = (TFun)requiredType;\r
- if(fun.domain instanceof TPred) { // No need to canonicalize\r
- ArrayList<Variable> constraints = new ArrayList<Variable>(2);\r
- while(true) {\r
- constraints.add(new Variable("constraint", fun.domain));\r
- requiredType = Types.canonical(fun.range);\r
- if(!(requiredType instanceof TFun))\r
- break;\r
- fun = (TFun)requiredType;\r
- if(!(fun.domain instanceof TPred))\r
- break;\r
- }\r
- context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()]));\r
- Expression expression = checkType(context, requiredType);\r
- context.popConstraintFrame();\r
- for(int i=constraints.size()-1;i>=0;--i)\r
- expression = new ESimpleLambda(constraints.get(i), expression);\r
- return expression;\r
- }\r
- else if(fun.domain == Types.PUNIT) {\r
- context.pushEffectUpperBound(location, fun.effect);\r
- Expression expr = checkType(context, fun.range);\r
- context.popEffectUpperBound(); \r
- \r
- // Wrap\r
- Variable var = new Variable("punit", Types.PUNIT);\r
- return new ESimpleLambda(location, var, fun.effect, expr);\r
- }\r
- else\r
- break;\r
- }\r
- }\r
- return checkBasicType(context, requiredType); \r
- }\r
-\r
- public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);\r
- public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);\r
- public abstract void forVariables(VariableProcedure procedure);\r
- \r
- public Expression decomposeMatching() {\r
- return this;\r
- }\r
-\r
- public String toString() {\r
- StringBuilder b = new StringBuilder();\r
- ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
- accept(visitor);\r
- return b.toString();\r
- }\r
-\r
- protected abstract void updateType() throws MatchException;\r
- \r
- public static class TypeValidationException extends Exception {\r
- private static final long serialVersionUID = 3181298127162041248L; \r
- \r
- long loc;\r
-\r
- public TypeValidationException(long loc) {\r
- this.loc = loc;\r
- }\r
- \r
- public long getLoc() {\r
- return loc;\r
- }\r
-\r
- public TypeValidationException(long loc, Throwable cause) {\r
- super(cause);\r
- this.loc = loc;\r
- }\r
- }\r
- \r
- public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException {\r
- if(!Types.equals(a, b))\r
- throw new TypeValidationException(loc);\r
- }\r
-\r
- public abstract IVal toVal(Environment env, CodeWriter w);\r
- \r
- public Expression closure(TVar ... vars) {\r
- if(vars.length == 0)\r
- return this;\r
- return new ELambdaType(vars, this);\r
- }\r
- \r
- public abstract void collectFreeVariables(THashSet<Variable> vars);\r
- \r
- public Expression simplify(SimplificationContext context) {\r
- throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");\r
- }\r
-\r
- public abstract Expression resolve(TranslationContext context);\r
- \r
- /**\r
- * Returns head of the pattern.\r
- */\r
- public EVar getPatternHead() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
- \r
- public LhsType getLhsType() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
-\r
- protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
-\r
- public void getParameters(TranslationContext translationContext,\r
- ArrayList<Expression> parameters) {\r
- throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters."); \r
- }\r
-\r
- public Expression resolveAsPattern(TranslationContext context) {\r
- context.getErrorLog().log(location, "Pattern was expected here.");\r
- return new EError();\r
- }\r
-\r
- public void removeFreeVariables(THashSet<Variable> vars) {\r
- throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern.");\r
- }\r
- \r
- public Expression checkTypeAsPattern(TypingContext context, Type requiredType) {\r
- if(context.isInPattern())\r
- throw new InternalCompilerError("Already in a pattern.");\r
- context.setInPattern(true);\r
- Expression expression = checkType(context, requiredType);\r
- context.setInPattern(false);\r
- return expression;\r
- }\r
-\r
- public THashSet<Variable> getFreeVariables() {\r
- THashSet<Variable> result = new THashSet<Variable>();\r
- collectFreeVariables(result);\r
- return result;\r
- } \r
-\r
- public static Expression[] concat(Expression[] a, Expression[] b) {\r
- if(a.length == 0)\r
- return b;\r
- if(b.length == 0)\r
- return a;\r
- Expression[] result = new Expression[a.length + b.length];\r
- for(int i=0;i<a.length;++i)\r
- result[i] = a[i];\r
- for(int i=0;i<b.length;++i)\r
- result[i+a.length] = b[i];\r
- return result;\r
- }\r
-\r
- public Expression replace(ReplaceContext context) {\r
- throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");\r
- }\r
- \r
- public static Expression[] replace(ReplaceContext context, Expression[] expressions) {\r
- Expression[] result = new Expression[expressions.length];\r
- for(int i=0;i<expressions.length;++i)\r
- result[i] = expressions[i].replace(context);\r
- return result;\r
- }\r
- \r
- public Expression copy() {\r
- return replace(new ReplaceContext(null));\r
- }\r
- \r
- public Expression copy(TypingContext typingContext) {\r
- return replace(new ReplaceContext(typingContext));\r
- }\r
-\r
- public abstract void setLocationDeep(long loc);\r
-\r
- public Expression replaceInPattern(ReplaceContext context) {\r
- context.inPattern = true;\r
- Expression result = replace(context);\r
- context.inPattern = false;\r
- return result;\r
- }\r
-\r
- public int getFunctionDefinitionArity() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
- \r
- public IVal lambdaToVal(Environment env, CodeWriter w) {\r
- DecomposedExpression decomposed = DecomposedExpression.decompose(this);\r
- CodeWriter newW = w.createFunction(decomposed.typeParameters, decomposed.effect, decomposed.returnType, decomposed.parameterTypes);\r
- IVal[] parameters = newW.getParameters();\r
- IVal functionVal = newW.getFunction().getTarget();\r
- for(int i=0;i<parameters.length;++i)\r
- decomposed.parameters[i].setVal(parameters[i]);\r
- newW.return_(decomposed.body.toVal(env, newW));\r
- return functionVal;\r
- }\r
- \r
- public IExpression toIExpression(ExpressionInterpretationContext context) {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- public static IExpression[] toIExpressions(ExpressionInterpretationContext target, Expression[] expressions) {\r
- IExpression[] result = new IExpression[expressions.length];\r
- for(int i=0;i<expressions.length;++i)\r
- result[i] = expressions[i].toIExpression(target);\r
- return result;\r
- }\r
- \r
- public Expression applyType(Type type) {\r
- return new EApplyType(location, this, type);\r
- }\r
- \r
- public abstract Expression decorate(ExpressionDecorator decorator);\r
-\r
- public boolean isEffectful() {\r
- return true;\r
- }\r
-\r
- public boolean isFunctionPattern() {\r
- return false;\r
- }\r
-\r
- public boolean isConstructorApplication() {\r
- return false;\r
- }\r
- \r
- public abstract void collectEffects(THashSet<Type> effects);\r
- \r
- public Type getEffect() {\r
- THashSet<Type> effects = new THashSet<Type>();\r
- collectEffects(effects);\r
- return Types.union(effects.toArray(new Type[effects.size()]));\r
- }\r
- \r
- public abstract void accept(ExpressionVisitor visitor);\r
- \r
- public void collectRelationRefs(\r
- final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {\r
- accept(new StandardExpressionVisitor() {\r
- @Override\r
- public void visit(QAtom query) {\r
- int id = allRefs.get(query.relation);\r
- if(id >= 0)\r
- refs.add(id);\r
- }\r
- });\r
- }\r
-\r
- public boolean isFunctionDefinitionLhs() {\r
- return false;\r
- }\r
-\r
- public Precedence getPrecedence() {\r
- return Precedence.DEFAULT;\r
- }\r
-\r
- public boolean isPattern(int arity) {\r
- return false;\r
- }\r
- \r
- public abstract Expression accept(ExpressionTransformer transformer);\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
+import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.query.QAtom;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.TForAll;
+import org.simantics.scl.compiler.types.TFun;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+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.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.Typed;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public abstract class Expression extends Symbol implements Typed {
+ public static final Expression[] EMPTY_ARRAY = new Expression[0];
+
+ transient
+ private Type type;
+
+ public Expression() {
+ }
+
+ public Expression(long loc) {
+ this.location = loc;
+ }
+
+ @Override
+ public Type getType() {
+ if(type == null) {
+ try {
+ updateType();
+ } catch (MatchException e) {
+ throw new InternalCompilerError(e);
+ }
+ if(type == null)
+ throw new InternalCompilerError(getClass().getSimpleName() +
+ ".updateType couldn't compute its type.");
+ }
+ return type;
+ }
+
+ public void setType(Type type) {
+ if(type == null)
+ throw new NullPointerException();
+ this.type = type;
+ }
+
+ /**
+ * Infers the type of the expression without any context. Adds type
+ * applications and lambdas if needed.
+ */
+ public Expression inferType(TypingContext context) {
+ return checkBasicType(context, Types.metaVar(Kinds.STAR));
+ }
+
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ return context.subsume(inferType(context), requiredType);
+ }
+
+ protected Expression applyPUnit(EnvironmentalContext context) {
+ Type type = Types.canonical(getType());
+ if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ if(fun.getCanonicalDomain() == Types.PUNIT) {
+ EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT));
+ result.effect = fun.getCanonicalEffect();
+ return result;
+ }
+ }
+ return this;
+ }
+
+ public Expression checkIgnoredType(TypingContext context) {
+ Expression expression = inferType(context);
+ if(Types.canonical(expression.getType()) != Types.UNIT)
+ expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT));
+ return expression;
+ }
+
+ /**
+ * Checks the type of the expression against the given type. Adds type
+ * applications and lambdas if needed.
+ */
+ public final Expression checkType(TypingContext context, Type requiredType) {
+ //System.out.println("checkType: " + this + " :: " + requiredType);
+ if(!context.isInPattern()) {
+ requiredType = Types.canonical(requiredType);
+ if(requiredType instanceof TForAll) {
+ TForAll forAll = (TForAll)requiredType;
+ TVar var = forAll.var;
+ TVar newVar = Types.var(var.getKind());
+ requiredType = Types.canonical(forAll.type).replace(var, newVar);
+ return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType));
+ }
+ while(requiredType instanceof TFun) {
+ TFun fun = (TFun)requiredType;
+ if(fun.domain instanceof TPred) { // No need to canonicalize
+ ArrayList<Variable> constraints = new ArrayList<Variable>(2);
+ while(true) {
+ constraints.add(new Variable("constraint", fun.domain));
+ requiredType = Types.canonical(fun.range);
+ if(!(requiredType instanceof TFun))
+ break;
+ fun = (TFun)requiredType;
+ if(!(fun.domain instanceof TPred))
+ break;
+ }
+ context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()]));
+ Expression expression = checkType(context, requiredType);
+ context.popConstraintFrame();
+ for(int i=constraints.size()-1;i>=0;--i)
+ expression = new ESimpleLambda(constraints.get(i), expression);
+ return expression;
+ }
+ else if(fun.domain == Types.PUNIT) {
+ context.pushEffectUpperBound(location, fun.effect);
+ Expression expr = checkType(context, fun.range);
+ context.popEffectUpperBound();
+
+ // Wrap
+ Variable var = new Variable("punit", Types.PUNIT);
+ return new ESimpleLambda(location, var, fun.effect, expr);
+ }
+ else
+ break;
+ }
+ }
+ return checkBasicType(context, requiredType);
+ }
+
+ public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);
+ public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);
+ public abstract void forVariables(VariableProcedure procedure);
+
+ public Expression decomposeMatching() {
+ return this;
+ }
+
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+ accept(visitor);
+ return b.toString();
+ }
+
+ protected abstract void updateType() throws MatchException;
+
+ public static class TypeValidationException extends Exception {
+ private static final long serialVersionUID = 3181298127162041248L;
+
+ long loc;
+
+ public TypeValidationException(long loc) {
+ this.loc = loc;
+ }
+
+ public long getLoc() {
+ return loc;
+ }
+
+ public TypeValidationException(long loc, Throwable cause) {
+ super(cause);
+ this.loc = loc;
+ }
+ }
+
+ public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException {
+ if(!Types.equals(a, b))
+ throw new TypeValidationException(loc);
+ }
+
+ public abstract IVal toVal(Environment env, CodeWriter w);
+
+ public Expression closure(TVar ... vars) {
+ if(vars.length == 0)
+ return this;
+ return new ELambdaType(vars, this);
+ }
+
+ public abstract void collectFreeVariables(THashSet<Variable> vars);
+
+ public Expression simplify(SimplificationContext context) {
+ System.out.println("#############################");
+ System.out.println(this);
+ throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");
+ }
+
+ public abstract Expression resolve(TranslationContext context);
+
+ /**
+ * Returns head of the pattern.
+ */
+ public EVar getPatternHead() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public LhsType getLhsType() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public void getParameters(TranslationContext translationContext,
+ ArrayList<Expression> parameters) {
+ throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters.");
+ }
+
+ public Expression resolveAsPattern(TranslationContext context) {
+ context.getErrorLog().log(location, "Pattern was expected here.");
+ return new EError();
+ }
+
+ public void removeFreeVariables(THashSet<Variable> vars) {
+ throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern.");
+ }
+
+ public Expression checkTypeAsPattern(TypingContext context, Type requiredType) {
+ if(context.isInPattern())
+ throw new InternalCompilerError("Already in a pattern.");
+ context.setInPattern(true);
+ Expression expression = checkType(context, requiredType);
+ context.setInPattern(false);
+ return expression;
+ }
+
+ public THashSet<Variable> getFreeVariables() {
+ THashSet<Variable> result = new THashSet<Variable>();
+ collectFreeVariables(result);
+ return result;
+ }
+
+ public static Expression[] concat(Expression[] a, Expression[] b) {
+ if(a.length == 0)
+ return b;
+ if(b.length == 0)
+ return a;
+ Expression[] result = new Expression[a.length + b.length];
+ for(int i=0;i<a.length;++i)
+ result[i] = a[i];
+ for(int i=0;i<b.length;++i)
+ result[i+a.length] = b[i];
+ return result;
+ }
+
+ public Expression replace(ReplaceContext context) {
+ throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");
+ }
+
+ public static Expression[] replace(ReplaceContext context, Expression[] expressions) {
+ Expression[] result = new Expression[expressions.length];
+ for(int i=0;i<expressions.length;++i)
+ result[i] = expressions[i].replace(context);
+ return result;
+ }
+
+ public Expression copy() {
+ return replace(new ReplaceContext(null));
+ }
+
+ public Expression copy(TypingContext typingContext) {
+ return replace(new ReplaceContext(typingContext));
+ }
+
+ public abstract void setLocationDeep(long loc);
+
+ public Expression replaceInPattern(ReplaceContext context) {
+ context.inPattern = true;
+ Expression result = replace(context);
+ context.inPattern = false;
+ return result;
+ }
+
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public IVal lambdaToVal(Environment env, CodeWriter w) {
+ DecomposedExpression decomposed = DecomposedExpression.decompose(this);
+ CodeWriter newW = w.createFunction(decomposed.typeParameters, decomposed.effect, decomposed.returnType, decomposed.parameterTypes);
+ IVal[] parameters = newW.getParameters();
+ IVal functionVal = newW.getFunction().getTarget();
+ for(int i=0;i<parameters.length;++i)
+ decomposed.parameters[i].setVal(parameters[i]);
+ newW.return_(decomposed.body.toVal(env, newW));
+ return functionVal;
+ }
+
+ public IExpression toIExpression(ExpressionInterpretationContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static IExpression[] toIExpressions(ExpressionInterpretationContext target, Expression[] expressions) {
+ IExpression[] result = new IExpression[expressions.length];
+ for(int i=0;i<expressions.length;++i)
+ result[i] = expressions[i].toIExpression(target);
+ return result;
+ }
+
+ public Expression applyType(Type type) {
+ return new EApplyType(location, this, type);
+ }
+
+ public abstract Expression decorate(ExpressionDecorator decorator);
+
+ public boolean isEffectful() {
+ return true;
+ }
+
+ public boolean isFunctionPattern() {
+ return false;
+ }
+
+ public boolean isConstructorApplication() {
+ return false;
+ }
+
+ public abstract void collectEffects(THashSet<Type> effects);
+
+ public Type getEffect() {
+ THashSet<Type> effects = new THashSet<Type>();
+ collectEffects(effects);
+ return Types.union(effects.toArray(new Type[effects.size()]));
+ }
+
+ public abstract void accept(ExpressionVisitor visitor);
+
+ public void collectRelationRefs(
+ final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {
+ accept(new StandardExpressionVisitor() {
+ @Override
+ public void visit(QAtom query) {
+ int id = allRefs.get(query.relation);
+ if(id >= 0)
+ refs.add(id);
+ }
+ });
+ }
+
+ public boolean isFunctionDefinitionLhs() {
+ return false;
+ }
+
+ public Precedence getPrecedence() {
+ return Precedence.DEFAULT;
+ }
+
+ public boolean isPattern(int arity) {
+ return false;
+ }
+
+ public abstract Expression accept(ExpressionTransformer transformer);
+
+ // TODO implement for all expressions
+ public boolean equalsExpression(Expression expression) {
+ return false;
+ }
+
+ /**
+ * This method returns a lower bound for the function arity of the value this expression defines.
+ * The lower bound is calculated purely looking the syntax of the expression, not the
+ * types of the constants and variables the expression refers to.
+ */
+ public int getSyntacticFunctionArity() {
+ return 0;
+ }
+}