]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java
(refs #7375) Replaced collectVars method by a visitor
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / Expression.java
old mode 100755 (executable)
new mode 100644 (file)
index e01098c..427acbd
-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 java.util.Set;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+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.expressions.visitors.CollectEffectsVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectFreeVariablesVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectRefsVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectVarsVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.ForVariablesUsesVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.StandardExpressionVisitor;
+import org.simantics.scl.compiler.elaboration.query.QAtom;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+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.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.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(TypingContext 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();
+                context.declareEffect(this.location, result.effect);
+                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 final void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        accept(new CollectRefsVisitor(allRefs, refs));
+    }
+
+    public final void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+        accept(new CollectVarsVisitor(allVars, vars));
+    }
+
+    public final void forVariableUses(VariableProcedure procedure) {
+        accept(new ForVariablesUsesVisitor(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(CompilationContext context, CodeWriter w);
+               
+       public Expression closure(TVar ... vars) {
+           if(vars.length == 0)
+            return this;
+        return new ELambdaType(vars, this);
+       }
+    
+    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 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;
+    }
+
+    /**
+     * Used during simplification and in toIExpression
+     */
+    public Set<Variable> getFreeVariables() {
+        CollectFreeVariablesVisitor visitor = new CollectFreeVariablesVisitor(); 
+        accept(visitor);
+        return visitor.getFreeVariables();
+    }
+
+    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(CompilationContext context, CodeWriter w) {
+        DecomposedExpression decomposed = DecomposedExpression.decompose(context.errorLog, 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(context, 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 boolean isEffectful() {
+               return true;
+       }
+
+    public boolean isFunctionPattern() {
+        return false;
+    }
+
+    public boolean isConstructorApplication() {
+        return false;
+    }
+    
+    public Type getEffect() {
+        CollectEffectsVisitor visitor = new CollectEffectsVisitor();
+        accept(visitor);
+        return visitor.getCombinedEffect();
+    }
+    
+    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;
+    }
+}