]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java
(refs #7278, refs #7279) Small fixes to InternalCompilerExceptions
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EApply.java
old mode 100755 (executable)
new mode 100644 (file)
index fb27b91..c7bce46
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.names.Name;\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.java.ListConstructor;\r
-import org.simantics.scl.compiler.elaboration.macros.MacroRule;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.environment.Environment;\r
-import org.simantics.scl.compiler.errors.Locations;\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.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.interpreted.IApply;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.IListLiteral;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\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.exceptions.UnificationException;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-import org.simantics.scl.compiler.types.util.MultiFunction;\r
-\r
-public class EApply extends Expression {\r
-    Expression function;\r
-    Expression[] parameters;\r
-    Type effect = Types.NO_EFFECTS;\r
-    \r
-    public EApply(Expression function, Expression ... parameters) {\r
-        this.function = function;\r
-        this.parameters = parameters;\r
-    }\r
-    \r
-    public EApply(Expression function, Expression parameter) {\r
-        this(function, new Expression[] {parameter});\r
-    }\r
-\r
-    public EApply(long loc, Expression function, Expression ... parameters) {\r
-        super(loc);\r
-        this.function = function;\r
-        this.parameters = parameters;\r
-    }\r
-    \r
-    public EApply(long loc, Type effect, Expression function, Expression ... parameters) {\r
-        super(loc);\r
-        this.effect = effect;\r
-        this.function = function;\r
-        this.parameters = parameters;\r
-    }\r
-    \r
-    public void set(Expression function, Expression[] parameters) {\r
-        this.function = function;\r
-        this.parameters = parameters;\r
-    }\r
-\r
-    public Expression getFunction() {\r
-        return function;\r
-    }\r
-    \r
-    public Expression[] getParameters() {\r
-        return parameters;\r
-    }\r
-    \r
-\r
-    public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        function.collectRefs(allRefs, refs);\r
-        for(Expression parameter : parameters)\r
-            parameter.collectRefs(allRefs, refs);\r
-    }\r
-    \r
-    public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
-        function.collectVars(allVars, vars);\r
-        for(Expression parameter : parameters)\r
-            parameter.collectVars(allVars, vars);\r
-    }\r
-       \r
-       @Override\r
-       protected void updateType() throws MatchException {\r
-        MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
-        /*for(int i=0;i<parameters.length;++i)\r
-            if(!Types.equals(parameters[i].getType(), mfun.parameterTypes[i]))\r
-                throw new MatchException();*/\r
-        effect = mfun.effect;\r
-        setType(mfun.returnType);\r
-       }\r
-\r
-       @Override\r
-       public IVal toVal(Environment env, CodeWriter w) {\r
-        IVal functionVal = function.toVal(env, w);\r
-        IVal[] parameterVals = new IVal[parameters.length];\r
-        for(int i=0;i<parameters.length;++i)\r
-            parameterVals[i] = parameters[i].toVal(env, w);\r
-        Type type = getType();\r
-        effect = Types.simplifyFinalEffect(effect);\r
-        return w.applyWithEffect(location, effect, type, functionVal, parameterVals);\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        function.collectFreeVariables(vars);\r
-        for(Expression parameter : parameters)\r
-            parameter.collectFreeVariables(vars);\r
-    }\r
-    \r
-    private void combineApplications() {\r
-        if(function instanceof EApply) {\r
-            EApply apply = (EApply)function;\r
-            if(Types.canonical(apply.effect) == Types.NO_EFFECTS) {\r
-                function = apply.function;\r
-                parameters = Expression.concat(apply.parameters, parameters); \r
-            } \r
-        }\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        function = function.simplify(context);\r
-        for(int i=0;i<parameters.length;++i)\r
-            parameters[i] = parameters[i].simplify(context);\r
-        combineApplications();\r
-        \r
-        // Try to apply macro rule\r
-        if(function instanceof EConstant) {\r
-            EConstant constant = (EConstant)function;\r
-            MacroRule rule = constant.value.getMacroRule();\r
-            if(rule != null) {\r
-                Expression simplified = rule.apply(context, constant.typeParameters, this);\r
-                if(simplified != null)\r
-                    // There may be more to simplify after macro application\r
-                    // However this may cause performance problems (O(n^2) algorithm in pathologic cases)\r
-                    return simplified.simplify(context);\r
-            }\r
-        }\r
-        \r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public EVar getPatternHead() throws NotPatternException {\r
-        return function.getPatternHead();\r
-    }\r
-\r
-    @Override\r
-    public LhsType getLhsType() throws NotPatternException {\r
-        LhsType lhsType = function.getLhsType();\r
-        if(lhsType instanceof PatternMatchingLhs)\r
-            for(Expression parameter : parameters)\r
-                parameter.collectVariableNames((PatternMatchingLhs)lhsType);\r
-        return lhsType;\r
-    }\r
-    \r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        function = function.resolve(context);\r
-        for(int i=0;i<parameters.length;++i)\r
-            parameters[i] = parameters[i].resolve(context);\r
-        //combineApplications();\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression resolveAsPattern(TranslationContext context) {\r
-        function = function.resolveAsPattern(context);\r
-        for(int i=0;i<parameters.length;++i)\r
-            parameters[i] = parameters[i].resolveAsPattern(context);\r
-        combineApplications();\r
-        if(!(function instanceof EConstant || function instanceof EError)) {\r
-            context.getErrorLog().log(location, "Only constants can be applied in patterns.");\r
-            return new EError();\r
-        }\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public void getParameters(TranslationContext context,\r
-            ArrayList<Expression> parameters) {\r
-        function.getParameters(context, parameters);\r
-        for(Expression parameter : this.parameters)\r
-            parameters.add(parameter);\r
-    }\r
-    \r
-    @Override\r
-    public void removeFreeVariables(THashSet<Variable> vars) {\r
-        function.removeFreeVariables(vars);\r
-        for(Expression parameter : parameters)\r
-            parameter.removeFreeVariables(vars);\r
-    }\r
-\r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        return new EApply(\r
-                getLocation(),                \r
-                effect.replace(context.tvarMap),\r
-                function.replace(context),\r
-                replace(context, parameters));\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            function.setLocationDeep(loc);\r
-            for(Expression parameter : parameters)\r
-                parameter.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public int getFunctionDefinitionArity() throws NotPatternException {\r
-        return function.getFunctionDefinitionArity() + parameters.length;\r
-    }\r
-    \r
-    @Override\r
-    public IExpression toIExpression(ExpressionInterpretationContext target) {\r
-        IExpression[] parametersI = toIExpressions(target, parameters);\r
-        \r
-        Expression function = this.function;\r
-        while(function instanceof EApplyType)\r
-            function = ((EApplyType)function).expression;\r
-        \r
-        // Special cases\r
-        if(function instanceof EConstant) {\r
-            SCLValue functionValue = ((EConstant)function).value;\r
-            Name name = functionValue.getName();\r
-            if(name.module.equals("Builtin")) {\r
-                IVal val = functionValue.getValue();\r
-                if(val instanceof ListConstructor) {\r
-                    if(((ListConstructor)val).arity == parametersI.length)\r
-                        return new IListLiteral(parametersI);\r
-                }\r
-            }\r
-        }\r
-        //System.out.println("--> " + function + " " + function.getClass().getSimpleName());\r
-        \r
-        // The basic case\r
-        return new IApply(function.toIExpression(target), parametersI);\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        function = function.inferType(context);\r
-        function = context.instantiate(function);\r
-        MultiFunction mfun;\r
-        try {\r
-            mfun = Types.unifyFunction(function.getType(), parameters.length);\r
-        } catch (UnificationException e) {\r
-            int arity = Types.getArity(function.getType());\r
-            if(arity == 0)\r
-                context.getErrorLog().log(location, "Application of non-function.");\r
-            else\r
-                context.getErrorLog().log(location, "Function of arity " + arity + \r
-                        " is applied with " + parameters.length + " parameters.");\r
-            setType(Types.metaVar(Kinds.STAR));\r
-            for(int i=0;i<parameters.length;++i)\r
-                parameters[i] = parameters[i].inferType(context);\r
-            return this;\r
-        }\r
-        \r
-        // Check parameter types\r
-        for(int i=0;i<parameters.length;++i)\r
-            parameters[i] = parameters[i].checkType(context, mfun.parameterTypes[i]);\r
-\r
-        effect = mfun.effect;\r
-        \r
-        context.declareEffect(location, mfun.effect);\r
-        setType(mfun.returnType);\r
-\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        if(decorator.decorateSubstructure(this)) {\r
-            function = function.decorate(decorator);\r
-            for(int i=0;i<parameters.length;++i)\r
-                parameters[i] = parameters[i].decorate(decorator);\r
-        }\r
-        return decorator.decorate(this);\r
-    }\r
-    \r
-    public Type getLocalEffect() {\r
-        return effect;\r
-    }\r
-    \r
-    public Expression toANormalForm(Expression root) {\r
-       Expression expression = root;\r
-       for(int i=parameters.length-1;i>=0;--i) {\r
-               Expression parameter = parameters[i];\r
-               if(parameter.isEffectful()) {\r
-                       Variable var = new Variable("aNormalTemp" + i, parameter.getType());\r
-                       expression = new ESimpleLet(var, parameter, expression);\r
-                       parameters[i] = new EVariable(var);\r
-               }\r
-       }\r
-       if(function.isEffectful()) {\r
-               Variable var = new Variable("aNormalTempF", function.getType());\r
-               expression = new ESimpleLet(var, function, expression);\r
-               function = new EVariable(var);\r
-       }\r
-       return expression;\r
-    }\r
-    \r
-    @Override\r
-    public boolean isEffectful() {\r
-       if(effect != Types.NO_EFFECTS)\r
-               return true;            \r
-       for(Expression parameter : parameters)\r
-               if(parameter.isEffectful())\r
-                       return true;\r
-       if(function.isEffectful())\r
-               return true;\r
-       return false;\r
-    }\r
-    \r
-    @Override\r
-    public boolean isFunctionPattern() {\r
-        return !isConstructorApplication();\r
-    }\r
-    \r
-    @Override\r
-    public boolean isConstructorApplication() {\r
-        return function.isConstructorApplication();\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        effects.add(effect);\r
-        function.collectEffects(effects);\r
-        for(Expression parameter : parameters)\r
-            parameter.collectEffects(effects);\r
-    }\r
-\r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-    \r
-    @Override\r
-    public boolean isFunctionDefinitionLhs() {\r
-        try {\r
-            EVar patternHead = function.getPatternHead();\r
-            return !Character.isUpperCase(patternHead.name.charAt(0));\r
-        } catch(NotPatternException e) {\r
-            return false;\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        function.forVariables(procedure);\r
-        for(Expression parameter : parameters)\r
-            parameter.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public boolean isPattern(int arity) {\r
-        if(!function.isPattern(arity+parameters.length))\r
-            return false;\r
-        for(Expression parameter : parameters)\r
-            if(!parameter.isPattern(0))\r
-                return false;\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+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.java.ListConstructor;
+import org.simantics.scl.compiler.elaboration.macros.MacroRule;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.errors.Locations;
+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.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IApply;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.IListLiteral;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.Skeletons;
+import org.simantics.scl.compiler.types.TFun;
+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.exceptions.UnificationException;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.MultiFunction;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EApply extends Expression {
+    public Expression function;
+    public Expression[] parameters;
+    Type effect = Types.NO_EFFECTS;
+    
+    public EApply(Expression function, Expression ... parameters) {
+        this.function = function;
+        this.parameters = parameters;
+    }
+    
+    public EApply(Expression function, Expression parameter) {
+        this(function, new Expression[] {parameter});
+    }
+
+    public EApply(long loc, Expression function, Expression ... parameters) {
+        super(loc);
+        this.function = function;
+        this.parameters = parameters;
+    }
+    
+    public EApply(long loc, Type effect, Expression function, Expression ... parameters) {
+        super(loc);
+        this.effect = effect;
+        this.function = function;
+        this.parameters = parameters;
+    }
+    
+    public void set(Expression function, Expression[] parameters) {
+        this.function = function;
+        this.parameters = parameters;
+    }
+
+    public Expression getFunction() {
+        return function;
+    }
+    
+    public Expression[] getParameters() {
+        return parameters;
+    }
+    
+
+    public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        function.collectRefs(allRefs, refs);
+        for(Expression parameter : parameters)
+            parameter.collectRefs(allRefs, refs);
+    }
+    
+    public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+        function.collectVars(allVars, vars);
+        for(Expression parameter : parameters)
+            parameter.collectVars(allVars, vars);
+    }
+       
+       @Override
+       protected void updateType() throws MatchException {
+        MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
+        /*for(int i=0;i<parameters.length;++i)
+            if(!Types.equals(parameters[i].getType(), mfun.parameterTypes[i]))
+                throw new MatchException();*/
+        effect = mfun.effect;
+        setType(mfun.returnType);
+       }
+
+       @Override
+       public IVal toVal(CompilationContext context, CodeWriter w) {
+        IVal functionVal = function.toVal(context, w);
+        IVal[] parameterVals = new IVal[parameters.length];
+        for(int i=0;i<parameters.length;++i)
+            parameterVals[i] = parameters[i].toVal(context, w);
+        Type type = getType();
+        effect = Types.simplifyFinalEffect(effect);
+        return w.applyWithEffect(location, effect, type, functionVal, parameterVals);
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        function.collectFreeVariables(vars);
+        for(Expression parameter : parameters)
+            parameter.collectFreeVariables(vars);
+    }
+    
+    private void combineApplications() {
+        if(function instanceof EApply) {
+            EApply apply = (EApply)function;
+            if(Types.canonical(apply.effect) == Types.NO_EFFECTS) {
+                function = apply.function;
+                parameters = Expression.concat(apply.parameters, parameters); 
+            } 
+        }
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        function = function.simplify(context);
+        for(int i=0;i<parameters.length;++i)
+            parameters[i] = parameters[i].simplify(context);
+        combineApplications();
+        
+        // Try to apply macro rule
+        if(function instanceof EConstant) {
+            EConstant constant = (EConstant)function;
+            MacroRule rule = constant.value.getMacroRule();
+            if(rule != null) {
+                Expression simplified = rule.apply(context, constant.typeParameters, this);
+                if(simplified != null)
+                    // There may be more to simplify after macro application
+                    // However this may cause performance problems (O(n^2) algorithm in pathologic cases)
+                    return simplified.simplify(context);
+            }
+        }
+        
+        return this;
+    }
+    
+    @Override
+    public EVar getPatternHead() throws NotPatternException {
+        return function.getPatternHead();
+    }
+
+    @Override
+    public LhsType getLhsType() throws NotPatternException {
+        LhsType lhsType = function.getLhsType();
+        if(lhsType instanceof PatternMatchingLhs)
+            for(Expression parameter : parameters)
+                parameter.collectVariableNames((PatternMatchingLhs)lhsType);
+        return lhsType;
+    }
+    
+    @Override
+    public Expression resolve(TranslationContext context) {
+        function = function.resolve(context);
+        for(int i=0;i<parameters.length;++i)
+            parameters[i] = parameters[i].resolve(context);
+        //combineApplications();
+        return this;
+    }
+    
+    @Override
+    public Expression resolveAsPattern(TranslationContext context) {
+        function = function.resolveAsPattern(context);
+        for(int i=0;i<parameters.length;++i)
+            parameters[i] = parameters[i].resolveAsPattern(context);
+        combineApplications();
+        if(!(function instanceof EConstant || function instanceof EError)) {
+            context.getErrorLog().log(location, "Only constants can be applied in patterns.");
+            return new EError();
+        }
+        return this;
+    }
+    
+    @Override
+    public void getParameters(TranslationContext context,
+            ArrayList<Expression> parameters) {
+        function.getParameters(context, parameters);
+        for(Expression parameter : this.parameters)
+            parameters.add(parameter);
+    }
+    
+    @Override
+    public void removeFreeVariables(THashSet<Variable> vars) {
+        function.removeFreeVariables(vars);
+        for(Expression parameter : parameters)
+            parameter.removeFreeVariables(vars);
+    }
+
+    @Override
+    public Expression replace(ReplaceContext context) {
+        return new EApply(
+                getLocation(),                
+                effect.replace(context.tvarMap),
+                function.replace(context),
+                replace(context, parameters));
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            function.setLocationDeep(loc);
+            for(Expression parameter : parameters)
+                parameter.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public int getFunctionDefinitionPatternArity() throws NotPatternException {
+        return function.getFunctionDefinitionPatternArity() + parameters.length;
+    }
+    
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext target) {
+        IExpression[] parametersI = toIExpressions(target, parameters);
+        
+        Expression function = this.function;
+        while(function instanceof EApplyType)
+            function = ((EApplyType)function).expression;
+        
+        // Special cases
+        if(function instanceof EConstant) {
+            SCLValue functionValue = ((EConstant)function).value;
+            Name name = functionValue.getName();
+            if(name.module.equals("Builtin")) {
+                IVal val = functionValue.getValue();
+                if(val instanceof ListConstructor) {
+                    if(((ListConstructor)val).arity == parametersI.length)
+                        return new IListLiteral(parametersI);
+                }
+            }
+        }
+        //System.out.println("--> " + function + " " + function.getClass().getSimpleName());
+        
+        // The basic case
+        return new IApply(function.toIExpression(target), parametersI);
+    }
+    
+    private void inferType(TypingContext context, boolean ignoreResult) {
+        function = function.inferType(context);
+        function = context.instantiate(function);
+        MultiFunction mfun;
+        try {
+            mfun = Types.unifyFunction(function.getType(), parameters.length);
+        } catch (UnificationException e) {
+            int arity = Types.getArity(function.getType());
+            if(arity == 0)
+                context.getErrorLog().log(location, "Application of non-function.");
+            else
+                context.getErrorLog().log(location, "Function of arity " + arity + 
+                        " is applied with " + parameters.length + " parameters.");
+            setType(Types.metaVar(Kinds.STAR));
+            for(int i=0;i<parameters.length;++i)
+                parameters[i] = parameters[i].inferType(context);
+            return;
+        }
+        if((ignoreResult && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun &&
+                Types.canonical(mfun.effect) == Types.NO_EFFECTS) ||
+                (context.isInPattern() && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun)) {
+            context.getErrorLog().log(location, "The function is applied with too few parameters.");
+        }
+        
+        // Check parameter types
+        for(int i=0;i<parameters.length;++i)
+            parameters[i] = parameters[i].checkType(context, mfun.parameterTypes[i]);
+
+        effect = mfun.effect;
+        
+        context.declareEffect(location, mfun.effect);
+        setType(mfun.returnType);
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        if(parameters.length == 2 && function instanceof EConstant && ((EConstant)function).value.getName() == Names.Prelude_dollar)
+            return new EApply(location, parameters[0], parameters[1]).inferType(context);
+        inferType(context, false);
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext context) {
+        if(parameters.length == 2 && function instanceof EConstant && ((EConstant)function).value.getName() == Names.Prelude_dollar)
+            return new EApply(location, parameters[0], parameters[1]).inferType(context);
+        inferType(context, true);
+        if(Types.canonical(getType()) != Types.UNIT)
+            return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        if(decorator.decorateSubstructure(this)) {
+            function = function.decorate(decorator);
+            for(int i=0;i<parameters.length;++i)
+                parameters[i] = parameters[i].decorate(decorator);
+        }
+        return decorator.decorate(this);
+    }
+    
+    public Type getLocalEffect() {
+        return effect;
+    }
+    
+    public Expression toANormalForm(Expression root) {
+       Expression expression = root;
+       for(int i=parameters.length-1;i>=0;--i) {
+               Expression parameter = parameters[i];
+               if(parameter.isEffectful()) {
+                       Variable var = new Variable("aNormalTemp" + i, parameter.getType());
+                       expression = new ESimpleLet(var, parameter, expression);
+                       parameters[i] = new EVariable(var);
+               }
+       }
+       if(function.isEffectful()) {
+               Variable var = new Variable("aNormalTempF", function.getType());
+               expression = new ESimpleLet(var, function, expression);
+               function = new EVariable(var);
+       }
+       return expression;
+    }
+    
+    @Override
+    public boolean isEffectful() {
+       if(effect != Types.NO_EFFECTS)
+               return true;            
+       for(Expression parameter : parameters)
+               if(parameter.isEffectful())
+                       return true;
+       if(function.isEffectful())
+               return true;
+       return false;
+    }
+    
+    @Override
+    public boolean isFunctionPattern() {
+        return !isConstructorApplication();
+    }
+    
+    @Override
+    public boolean isConstructorApplication() {
+        return function.isConstructorApplication();
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        effects.add(effect);
+        function.collectEffects(effects);
+        for(Expression parameter : parameters)
+            parameter.collectEffects(effects);
+    }
+
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    @Override
+    public boolean isFunctionDefinitionLhs() {
+        try {
+            EVar patternHead = function.getPatternHead();
+            return !Character.isUpperCase(patternHead.name.charAt(0));
+        } catch(NotPatternException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        function.forVariables(procedure);
+        for(Expression parameter : parameters)
+            parameter.forVariables(procedure);
+    }
+    
+    @Override
+    public boolean isPattern(int arity) {
+        if(!function.isPattern(arity+parameters.length))
+            return false;
+        for(Expression parameter : parameters)
+            if(!parameter.isPattern(0))
+                return false;
+        return true;
+    }
+
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public boolean equalsExpression(Expression expression) {
+        if(expression.getClass() != getClass())
+            return false;
+        EApply other = (EApply)expression;
+        if(parameters.length != other.parameters.length)
+            return false;
+        if(!function.equalsExpression(other.function))
+            return false;
+        for(int i=0;i<parameters.length;++i)
+            if(!parameters[i].equalsExpression(other.parameters[i]))
+                return false;
+        return true;
+    }
+}