]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Improvements to SCL compiler error messages 28/228/3
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Wed, 28 Dec 2016 10:46:48 +0000 (12:46 +0200)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Wed, 28 Dec 2016 11:32:16 +0000 (13:32 +0200)
Better error message if type annotation has different number of
parameters than the function definition.

Refactored method names, we have now getSyntacticFunctionArity for
estimating function arity without type information and
getFunctionDefinitionPatternArity for arity calculations of patterns.

refs #6897

Change-Id: I032ee0e5da416f232517d1e03c7a7cb0208c4d45

21 files changed:
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeChecking.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Case.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/DecoratingExpression.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EApply.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambda.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELambdaType.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreRuleset.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLambda.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/errors/ErrorLog.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Arity1.scl

index d89c00c829773e1a7552c8644966ab070838752f..f5834aef1ac949b92a74a5c83c3cd2265a0f0fd5 100644 (file)
@@ -1198,7 +1198,7 @@ public class Elaboration {
         }
         else if(annotation.id.text.equals("@inline")) {
             try {
         }
         else if(annotation.id.text.equals("@inline")) {
             try {
-                int arity = defs.get(0).lhs.getFunctionDefinitionArity();
+                int arity = defs.get(0).lhs.getFunctionDefinitionPatternArity();
                 int phaseMask = 0xffffffff;
                 if(annotation.parameters.length > 0) {
                     phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
                 int phaseMask = 0xffffffff;
                 if(annotation.parameters.length > 0) {
                     phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
index 667c089c3e24fe58561a674622f053a0ed6d9662..3118142df09740dce51ead4cf262f058f0b11b0b 100644 (file)
@@ -204,6 +204,9 @@ public class TypeChecking {
 
                             Expression expression = value.getExpression();
 
 
                             Expression expression = value.getExpression();
 
+                            int errorCountBeforeTypeChecking = compilationContext.errorLog.getErrorCount();
+                            int functionArity = expression.getSyntacticFunctionArity();
+                            
                             try {
                                 ArrayList<TVar> vars = new ArrayList<TVar>();
                                 type = Types.removeForAll(type, vars);
                             try {
                                 ArrayList<TVar> vars = new ArrayList<TVar>();
                                 type = Types.removeForAll(type, vars);
@@ -218,6 +221,13 @@ public class TypeChecking {
                                     overloaded.assertResolved(compilationContext.errorLog);
                                 expression.getType().addPolarity(Polarity.POSITIVE);
                                 context.solveSubsumptions(expression.getLocation());
                                     overloaded.assertResolved(compilationContext.errorLog);
                                 expression.getType().addPolarity(Polarity.POSITIVE);
                                 context.solveSubsumptions(expression.getLocation());
+                                
+                                if(compilationContext.errorLog.getErrorCount() != errorCountBeforeTypeChecking) {
+                                    int typeArity = Types.getArity(type); 
+                                    if(typeArity != functionArity)
+                                        compilationContext.errorLog.log(value.definitionLocation, "Possible problem: type declaration has " + typeArity + " parameter types, but function definition has " + functionArity + " parameters.");
+                                }
+                                
                                 ArrayList<EVariable> demands = context.getConstraintDemand();
                                 if(!demands.isEmpty() || !givenConstraints.isEmpty()) {
                                     ReducedConstraints red = 
                                 ArrayList<EVariable> demands = context.getConstraintDemand();
                                 if(!demands.isEmpty() || !givenConstraints.isEmpty()) {
                                     ReducedConstraints red = 
index 50eda1c130d6840475875276a71f011760ce53ce..4a34cebcf4b283dbc146b111f6c7e9d5474e097a 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.parsing.Symbol;\r
-import org.simantics.scl.compiler.types.Type;\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 class Case extends Symbol {\r
-    public Expression[] patterns;\r
-    public Expression value;\r
-    \r
-    long lhs;\r
-    \r
-    public Case(Expression[] patterns, Expression value) {\r
-        this.patterns = patterns;\r
-        this.value = value;\r
-    }\r
-    \r
-    public Case(Expression pattern, Expression value) {\r
-        this(new Expression[] {pattern}, value);\r
-    }\r
-\r
-    public void setLhs(long lhs) {\r
-        this.lhs = lhs;\r
-    }\r
-    \r
-    public long getLhs() {\r
-        return lhs;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        value.collectRefs(allRefs, refs);\r
-    }\r
-\r
-    public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-            TIntHashSet vars) {\r
-        value.collectVars(allVars, vars);\r
-    }\r
-\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        value.collectFreeVariables(vars);\r
-        for(int i=patterns.length-1;i>=0;--i)\r
-            patterns[i].removeFreeVariables(vars);\r
-    }\r
-\r
-    public void resolve(TranslationContext context) {\r
-        context.pushFrame();\r
-        for(int i=0;i<patterns.length;++i)\r
-            patterns[i] = patterns[i].resolveAsPattern(context);\r
-        value = value.resolve(context);\r
-        context.popFrame();\r
-    }\r
-\r
-    public void simplify(SimplificationContext context) {\r
-        for(int i=0;i<patterns.length;++i)\r
-            patterns[i] = patterns[i].simplify(context);\r
-        value = value.simplify(context);\r
-    }\r
-\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(Expression pattern : patterns)\r
-                pattern.setLocationDeep(loc);\r
-            value.setLocationDeep(loc);\r
-        }\r
-    }\r
-\r
-    public Case replace(ReplaceContext context) {\r
-        Expression[] newPatterns = new Expression[patterns.length];        \r
-        for(int i=0;i<patterns.length;++i)\r
-            newPatterns[i] = patterns[i].replaceInPattern(context);\r
-        Expression newValue = value.replace(context);\r
-        Case result = new Case(newPatterns, newValue);\r
-        result.setLhs(lhs);\r
-        return result;\r
-    }\r
-\r
-    public Expression[] getPatterns() {\r
-        return patterns;\r
-    }\r
-\r
-    public void checkType(TypingContext context, Type[] parameterTypes,\r
-            Type requiredType) {\r
-        if(patterns.length != parameterTypes.length) {\r
-            context.getErrorLog().log(location, "This case has different arity ("+patterns.length+\r
-                    ") than than the first case (+"+parameterTypes.length+"+).");\r
-            return;\r
-        }\r
-        for(int i=0;i<patterns.length;++i)\r
-            patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
-        value = value.checkType(context, requiredType);\r
-    }\r
-    \r
-    public void checkIgnoredType(TypingContext context, Type[] parameterTypes) {\r
-        if(patterns.length != parameterTypes.length) {\r
-            context.getErrorLog().log(location, "This case has different arity ("+patterns.length+\r
-                    ") than than the first case (+"+parameterTypes.length+"+).");\r
-            return;\r
-        }\r
-        for(int i=0;i<patterns.length;++i)\r
-            patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
-        value = value.checkIgnoredType(context);\r
-    }\r
-        \r
-    public void decorate(ExpressionDecorator decorator) {\r
-        for(int i=0;i<patterns.length;++i)\r
-            patterns[i] = patterns[i].decorate(decorator);\r
-        value = value.decorate(decorator);\r
-    }\r
-\r
-    public void forVariables(VariableProcedure procedure) {\r
-        value.forVariables(procedure);\r
-    }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.errors.Locations;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class Case extends Symbol {
+    public Expression[] patterns;
+    public Expression value;
+    
+    long lhs;
+    
+    public Case(Expression[] patterns, Expression value) {
+        this.patterns = patterns;
+        this.value = value;
+    }
+    
+    public Case(Expression pattern, Expression value) {
+        this(new Expression[] {pattern}, value);
+    }
+
+    public void setLhs(long lhs) {
+        this.lhs = lhs;
+    }
+    
+    public long getLhs() {
+        return lhs;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        value.collectRefs(allRefs, refs);
+    }
+
+    public void collectVars(TObjectIntHashMap<Variable> allVars,
+            TIntHashSet vars) {
+        value.collectVars(allVars, vars);
+    }
+
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        value.collectFreeVariables(vars);
+        for(int i=patterns.length-1;i>=0;--i)
+            patterns[i].removeFreeVariables(vars);
+    }
+
+    public void resolve(TranslationContext context) {
+        context.pushFrame();
+        for(int i=0;i<patterns.length;++i)
+            patterns[i] = patterns[i].resolveAsPattern(context);
+        value = value.resolve(context);
+        context.popFrame();
+    }
+
+    public void simplify(SimplificationContext context) {
+        for(int i=0;i<patterns.length;++i)
+            patterns[i] = patterns[i].simplify(context);
+        value = value.simplify(context);
+    }
+
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(Expression pattern : patterns)
+                pattern.setLocationDeep(loc);
+            value.setLocationDeep(loc);
+        }
+    }
+
+    public Case replace(ReplaceContext context) {
+        Expression[] newPatterns = new Expression[patterns.length];        
+        for(int i=0;i<patterns.length;++i)
+            newPatterns[i] = patterns[i].replaceInPattern(context);
+        Expression newValue = value.replace(context);
+        Case result = new Case(newPatterns, newValue);
+        result.setLhs(lhs);
+        return result;
+    }
+
+    public Expression[] getPatterns() {
+        return patterns;
+    }
+
+    public void checkType(TypingContext context, Type[] parameterTypes,
+            Type requiredType) {
+        if(patterns.length != parameterTypes.length) {
+            context.getErrorLog().log(location, "This case has different arity ("+patterns.length+
+                    ") than than the first case (+"+parameterTypes.length+"+).");
+            return;
+        }
+        for(int i=0;i<patterns.length;++i)
+            patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);
+        value = value.checkType(context, requiredType);
+    }
+    
+    public void checkIgnoredType(TypingContext context, Type[] parameterTypes) {
+        if(patterns.length != parameterTypes.length) {
+            context.getErrorLog().log(location, "This case has different arity ("+patterns.length+
+                    ") than than the first case (+"+parameterTypes.length+"+).");
+            return;
+        }
+        for(int i=0;i<patterns.length;++i)
+            patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);
+        value = value.checkIgnoredType(context);
+    }
+        
+    public void decorate(ExpressionDecorator decorator) {
+        for(int i=0;i<patterns.length;++i)
+            patterns[i] = patterns[i].decorate(decorator);
+        value = value.decorate(decorator);
+    }
+
+    public void forVariables(VariableProcedure procedure) {
+        value.forVariables(procedure);
+    }
+}
index 95b18efd62abd266e90af0b7a6237172899302d2..398d86762d3e8f102075d7051057e1fe878139e5 100644 (file)
@@ -84,8 +84,8 @@ public abstract class DecoratingExpression extends SimplifiableExpression {
     }
 
     @Override
     }
 
     @Override
-    public int getFunctionDefinitionArity() throws NotPatternException {
-        return expression.getFunctionDefinitionArity();
+    public int getFunctionDefinitionPatternArity() throws NotPatternException {
+        return expression.getFunctionDefinitionPatternArity();
     }
 
     @Override
     }
 
     @Override
@@ -134,4 +134,9 @@ public abstract class DecoratingExpression extends SimplifiableExpression {
         expression = expression.checkIgnoredType(context);
         return this;
     }
         expression = expression.checkIgnoredType(context);
         return this;
     }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return expression.getSyntacticFunctionArity();
+    }
 }
 }
index 1de0944ebd3d0dc80d9f66d285b4a4c02949f2bc..fd5822743432a533e3ec9d5e482adfb2582733b1 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.names.Name;\r
-import org.simantics.scl.compiler.constants.NoRepConstant;\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.Skeletons;\r
-import org.simantics.scl.compiler.types.TFun;\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
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class EApply extends Expression {\r
-    public Expression function;\r
-    public 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
-    private void inferType(TypingContext context, boolean ignoreResult) {\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;\r
-        }\r
-        if((ignoreResult && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun &&\r
-                Types.canonical(mfun.effect) == Types.NO_EFFECTS) ||\r
-                (context.isInPattern() && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun)) {\r
-            context.getErrorLog().log(location, "The function is applied with too few parameters.");\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
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        inferType(context, false);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkIgnoredType(TypingContext context) {\r
-        inferType(context, true);\r
-        if(Types.canonical(getType()) != Types.UNIT)\r
-            return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));\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
-    @Override\r
-    public boolean equalsExpression(Expression expression) {\r
-        if(expression.getClass() != getClass())\r
-            return false;\r
-        EApply other = (EApply)expression;\r
-        if(parameters.length != other.parameters.length)\r
-            return false;\r
-        if(!function.equalsExpression(other.function))\r
-            return false;\r
-        for(int i=0;i<parameters.length;++i)\r
-            if(!parameters[i].equalsExpression(other.parameters[i]))\r
-                return false;\r
-        return true;\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.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.environment.Environment;
+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(Environment env, CodeWriter w) {
+        IVal functionVal = function.toVal(env, w);
+        IVal[] parameterVals = new IVal[parameters.length];
+        for(int i=0;i<parameters.length;++i)
+            parameterVals[i] = parameters[i].toVal(env, 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) {
+        inferType(context, false);
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext 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;
+    }
+}
index 58274a7a0269553521a840af33b5362faf6d8a70..274624aee0e08e97c22ad7c2f7c1ac1183c5d049 100755 (executable)
-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.names.Names;\r
-import org.simantics.scl.compiler.common.precedence.Associativity;\r
-import org.simantics.scl.compiler.common.precedence.Precedence;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-\r
-\r
-public class EBinary extends ASTExpression {\r
-    public static final int NEGATION_LEVEL = 6;\r
-    \r
-    public Expression left;\r
-    public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();\r
-    public EVar negation;\r
-\r
-    public EBinary(Expression left, EVar negation) {\r
-        this.left = left;\r
-        this.negation = negation;\r
-    }\r
-\r
-    private EBinary(Expression left, EVar operator, Expression right) {\r
-        this.left = left;\r
-        rights.add(new EBinaryRightSide(operator, right));\r
-    }\r
-\r
-    public static EBinary create(Expression left, EVar operator, Expression right) {\r
-        if(left instanceof EBinary) {\r
-            EBinary left_ = (EBinary)left;\r
-            left_.rights.add(new EBinaryRightSide(operator, right));\r
-            return left_;\r
-        }\r
-        else\r
-            return new EBinary(left, operator, right);\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        return parseOperators(context).resolve(context);\r
-    }\r
-    \r
-    public Expression parseOperators(TranslationContext context) {\r
-        ArrayList<Expression> output = new ArrayList<Expression>();\r
-        ArrayList<Expression> ops = new ArrayList<Expression>();\r
-        ArrayList<EVar> opAsts = new ArrayList<EVar>();\r
-        \r
-        EVar negation = this.negation;\r
-        \r
-        output.add(left);\r
-        for(EBinaryRightSide right : rights) {\r
-            // Read op\r
-            Expression op = context.resolveExpression(right.operator.location, right.operator.name);\r
-            if(op == null)\r
-                return new EError(location);\r
-            Precedence opPrec = op.getPrecedence();\r
-            while(!ops.isEmpty()) {\r
-                Expression oldOp = ops.get(ops.size()-1);\r
-                Precedence oldOpPrecedence = oldOp.getPrecedence();\r
-                \r
-                if(oldOpPrecedence.level < opPrec.level)\r
-                    break;\r
-                if(oldOpPrecedence.level == opPrec.level) {\r
-                    if(opPrec.associativity == Associativity.RIGHT)\r
-                        break;\r
-                    if(opPrec.associativity == Associativity.NONASSOC) {\r
-                        context.getErrorLog().log(right.operator.location, \r
-                                "Operator " + right.operator.name + " is not associative.");\r
-                        return new EError(location);    \r
-                    }\r
-                }\r
-                \r
-                // Pop op                \r
-                ops.remove(ops.size()-1);\r
-                Expression r = output.remove(output.size()-1);\r
-                Expression l = output.remove(output.size()-1);\r
-                output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));\r
-            }\r
-            if(negation != null && ops.isEmpty()) {\r
-                if(opPrec.level <= NEGATION_LEVEL) {      \r
-                    SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
-                    if(neg == null) {\r
-                        context.getErrorLog().log(location, \r
-                                "Couldn't resolve variable neg.");\r
-                        return new EError(location);\r
-                    }\r
-                    output.set(0, unary(neg, negation, output.get(0)));\r
-                    negation = null;\r
-                }\r
-            }\r
-            ops.add(op);\r
-            opAsts.add(right.operator);\r
-            \r
-            // Read value\r
-            output.add(right.right);\r
-        }\r
-        \r
-        // Pop rest\r
-        while(!ops.isEmpty()) {            \r
-            Expression oldOp = ops.remove(ops.size()-1);\r
-            Expression r = output.remove(output.size()-1);\r
-            Expression l = output.remove(output.size()-1);\r
-            output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));\r
-        }\r
-        if(negation != null) {\r
-            SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
-            if(neg == null) {\r
-                context.getErrorLog().log(location, \r
-                        "Couldn't resolve variable neg.");\r
-                return new EError(location);\r
-            }\r
-            output.set(0, unary(neg, negation, output.get(0)));\r
-        }\r
-        \r
-        return output.get(0);\r
-        \r
-        //System.out.println("parseOperators: " + this);\r
-        //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));\r
-    }\r
-\r
-    /*\r
-    private Expression parse(TranslationContext context,\r
-            Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {\r
-        while(it.hasNext()) {\r
-            EBinaryRightSide right = it.next();\r
-            SCLValue op = context.resolveValue(right.operator.name);\r
-            if(op == null) {\r
-                context.getErrorLog().log(right.operator, \r
-                        "Couldn't resolve variable " + right.operator.name + ".");\r
-                return lhs;\r
-            }\r
-            Precedence opPrec = op.getPrecedence();\r
-            if(minPrec.level > opPrec.level)\r
-                break;\r
-            Expression rhs = right.right;\r
-            while(it.hasNext()) {\r
-                EVar var = it.next().operator;\r
-                SCLValue nextOp = context.resolveValue(var.name);\r
-                if(nextOp == null) {\r
-                    context.getErrorLog().log(var, \r
-                            "Couldn't resolve variable " + var.name + ".");\r
-                    return lhs;\r
-                }\r
-                it.previous();\r
-                Precedence nextPrec = nextOp.getPrecedence();\r
-                int precDiff = opPrec.level - nextPrec.level;\r
-                if(precDiff == 0) {\r
-                    if(opPrec.associativity == Associativity.LEFT)\r
-                        break;\r
-                    else if(opPrec.associativity == Associativity.NONASSOC) {\r
-                        context.getErrorLog().log(it.next().operator, "Nonassociative operator.");\r
-                        return lhs;\r
-                    }\r
-                }\r
-                else if(precDiff > 0)\r
-                    break;\r
-                rhs = parse(context, rhs, it, nextPrec);\r
-            }\r
-            lhs = binary(lhs, op, right.operator, rhs);\r
-        }   \r
-        return lhs;\r
-    }\r
-    */\r
-    private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {\r
-        return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs);        \r
-    }\r
-    \r
-    private Expression unary(SCLValue operator, EVar opAst, Expression expression) {\r
-        EConstant op = new EConstant(opAst.location, operator);\r
-        return new EApply(expression.location /*wrong*/, op, expression);\r
-    }\r
-    \r
-    @Override\r
-    public EVar getPatternHead() throws NotPatternException {\r
-        if(rights.size() == 1)\r
-            return rights.get(0).operator;\r
-        else\r
-            throw new NotPatternException(this);\r
-    }\r
-    \r
-    @Override\r
-    public LhsType getLhsType() throws NotPatternException {\r
-        if(rights.size() == 1)\r
-            return new FunctionDefinitionLhs(rights.get(0).operator.name);\r
-        else\r
-            throw new InternalCompilerError();\r
-    }\r
-        \r
-    @Override\r
-    public void getParameters(TranslationContext context,\r
-            ArrayList<Expression> parameters) {\r
-        parseOperators(context).getParameters(context, parameters);\r
-    }\r
-\r
-    public static Expression negate(EVar op, Expression expression) {\r
-        if(expression instanceof EBinary) {\r
-            ((EBinary)expression).negation = op;\r
-            return expression;\r
-        }\r
-        /*else if(expression instanceof EIntegerLiteral) {\r
-            EIntegerLiteral literal = (EIntegerLiteral)expression;\r
-            literal.value = -literal.value;\r
-            return expression;\r
-        }*/\r
-        else\r
-            return new EBinary(expression, op);\r
-    }\r
-    \r
-    @Override\r
-    public int getFunctionDefinitionArity() throws NotPatternException {\r
-        return 2;\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            left.setLocationDeep(loc);\r
-            if(negation != null)\r
-                negation.setLocationDeep(loc);\r
-            for(EBinaryRightSide right : rights)\r
-                right.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\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.names.Names;
+import org.simantics.scl.compiler.common.precedence.Associativity;
+import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.errors.Locations;
+
+
+
+public class EBinary extends ASTExpression {
+    public static final int NEGATION_LEVEL = 6;
+    
+    public Expression left;
+    public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();
+    public EVar negation;
+
+    public EBinary(Expression left, EVar negation) {
+        this.left = left;
+        this.negation = negation;
+    }
+
+    private EBinary(Expression left, EVar operator, Expression right) {
+        this.left = left;
+        rights.add(new EBinaryRightSide(operator, right));
+    }
+
+    public static EBinary create(Expression left, EVar operator, Expression right) {
+        if(left instanceof EBinary) {
+            EBinary left_ = (EBinary)left;
+            left_.rights.add(new EBinaryRightSide(operator, right));
+            return left_;
+        }
+        else
+            return new EBinary(left, operator, right);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        return parseOperators(context).resolve(context);
+    }
+    
+    public Expression parseOperators(TranslationContext context) {
+        ArrayList<Expression> output = new ArrayList<Expression>();
+        ArrayList<Expression> ops = new ArrayList<Expression>();
+        ArrayList<EVar> opAsts = new ArrayList<EVar>();
+        
+        EVar negation = this.negation;
+        
+        output.add(left);
+        for(EBinaryRightSide right : rights) {
+            // Read op
+            Expression op = context.resolveExpression(right.operator.location, right.operator.name);
+            if(op == null)
+                return new EError(location);
+            Precedence opPrec = op.getPrecedence();
+            while(!ops.isEmpty()) {
+                Expression oldOp = ops.get(ops.size()-1);
+                Precedence oldOpPrecedence = oldOp.getPrecedence();
+                
+                if(oldOpPrecedence.level < opPrec.level)
+                    break;
+                if(oldOpPrecedence.level == opPrec.level) {
+                    if(opPrec.associativity == Associativity.RIGHT)
+                        break;
+                    if(opPrec.associativity == Associativity.NONASSOC) {
+                        context.getErrorLog().log(right.operator.location, 
+                                "Operator " + right.operator.name + " is not associative.");
+                        return new EError(location);    
+                    }
+                }
+                
+                // Pop op                
+                ops.remove(ops.size()-1);
+                Expression r = output.remove(output.size()-1);
+                Expression l = output.remove(output.size()-1);
+                output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
+            }
+            if(negation != null && ops.isEmpty()) {
+                if(opPrec.level <= NEGATION_LEVEL) {      
+                    SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
+                    if(neg == null) {
+                        context.getErrorLog().log(location, 
+                                "Couldn't resolve variable neg.");
+                        return new EError(location);
+                    }
+                    output.set(0, unary(neg, negation, output.get(0)));
+                    negation = null;
+                }
+            }
+            ops.add(op);
+            opAsts.add(right.operator);
+            
+            // Read value
+            output.add(right.right);
+        }
+        
+        // Pop rest
+        while(!ops.isEmpty()) {            
+            Expression oldOp = ops.remove(ops.size()-1);
+            Expression r = output.remove(output.size()-1);
+            Expression l = output.remove(output.size()-1);
+            output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
+        }
+        if(negation != null) {
+            SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
+            if(neg == null) {
+                context.getErrorLog().log(location, 
+                        "Couldn't resolve variable neg.");
+                return new EError(location);
+            }
+            output.set(0, unary(neg, negation, output.get(0)));
+        }
+        
+        return output.get(0);
+        
+        //System.out.println("parseOperators: " + this);
+        //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));
+    }
+
+    /*
+    private Expression parse(TranslationContext context,
+            Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {
+        while(it.hasNext()) {
+            EBinaryRightSide right = it.next();
+            SCLValue op = context.resolveValue(right.operator.name);
+            if(op == null) {
+                context.getErrorLog().log(right.operator, 
+                        "Couldn't resolve variable " + right.operator.name + ".");
+                return lhs;
+            }
+            Precedence opPrec = op.getPrecedence();
+            if(minPrec.level > opPrec.level)
+                break;
+            Expression rhs = right.right;
+            while(it.hasNext()) {
+                EVar var = it.next().operator;
+                SCLValue nextOp = context.resolveValue(var.name);
+                if(nextOp == null) {
+                    context.getErrorLog().log(var, 
+                            "Couldn't resolve variable " + var.name + ".");
+                    return lhs;
+                }
+                it.previous();
+                Precedence nextPrec = nextOp.getPrecedence();
+                int precDiff = opPrec.level - nextPrec.level;
+                if(precDiff == 0) {
+                    if(opPrec.associativity == Associativity.LEFT)
+                        break;
+                    else if(opPrec.associativity == Associativity.NONASSOC) {
+                        context.getErrorLog().log(it.next().operator, "Nonassociative operator.");
+                        return lhs;
+                    }
+                }
+                else if(precDiff > 0)
+                    break;
+                rhs = parse(context, rhs, it, nextPrec);
+            }
+            lhs = binary(lhs, op, right.operator, rhs);
+        }   
+        return lhs;
+    }
+    */
+    private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {
+        return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs);        
+    }
+    
+    private Expression unary(SCLValue operator, EVar opAst, Expression expression) {
+        EConstant op = new EConstant(opAst.location, operator);
+        return new EApply(expression.location /*wrong*/, op, expression);
+    }
+    
+    @Override
+    public EVar getPatternHead() throws NotPatternException {
+        if(rights.size() == 1)
+            return rights.get(0).operator;
+        else
+            throw new NotPatternException(this);
+    }
+    
+    @Override
+    public LhsType getLhsType() throws NotPatternException {
+        if(rights.size() == 1)
+            return new FunctionDefinitionLhs(rights.get(0).operator.name);
+        else
+            throw new InternalCompilerError();
+    }
+        
+    @Override
+    public void getParameters(TranslationContext context,
+            ArrayList<Expression> parameters) {
+        parseOperators(context).getParameters(context, parameters);
+    }
+
+    public static Expression negate(EVar op, Expression expression) {
+        if(expression instanceof EBinary) {
+            ((EBinary)expression).negation = op;
+            return expression;
+        }
+        /*else if(expression instanceof EIntegerLiteral) {
+            EIntegerLiteral literal = (EIntegerLiteral)expression;
+            literal.value = -literal.value;
+            return expression;
+        }*/
+        else
+            return new EBinary(expression, op);
+    }
+    
+    @Override
+    public int getFunctionDefinitionPatternArity() throws NotPatternException {
+        return 2;
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            left.setLocationDeep(loc);
+            if(negation != null)
+                negation.setLocationDeep(loc);
+            for(EBinaryRightSide right : rights)
+                right.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+}
index fb5c2bdfaf1ca6ce0777d5f5aeeea2c066fe82ae..ebe88b499aab482e79bef9baac25a544898abaa1 100755 (executable)
@@ -119,4 +119,13 @@ public class EBlock extends ASTExpression {
         return transformer.transform(this);
     }
 
         return transformer.transform(this);
     }
 
+    @Override
+    public int getSyntacticFunctionArity() {
+        if(monadic)
+            return 0;
+        Statement lastStatement = statements.getLast();
+        if(!(lastStatement instanceof GuardStatement))
+            return 0;
+        return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
+    }
 }
 }
index b714d7678aa7e4c88461b5c3ac529a0fc75414bb..e3bb2fe0a313d86e24c3b82d1a32d04eb0e47a65 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.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.IConstant;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.IIf;\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.runtime.tuple.Tuple0;\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 class EIf extends Expression {\r
-    public Expression condition;\r
-    public Expression then_;\r
-    public Expression else_; // may be null\r
-    \r
-    public EIf(Expression condition, Expression then_, Expression else_) {\r
-        this.condition = condition;\r
-        this.then_ = then_;\r
-        this.else_ = else_;\r
-    }\r
-\r
-    public EIf(long loc, Expression condition, Expression then_, Expression else_) {\r
-        super(loc);\r
-        this.condition = condition;\r
-        this.then_ = then_;\r
-        this.else_ = else_;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        condition.collectRefs(allRefs, refs);\r
-        then_.collectRefs(allRefs, refs);\r
-        if(else_ != null)\r
-            else_.collectRefs(allRefs, refs);\r
-    }\r
-\r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           condition.collectVars(allVars, vars);\r
-        then_.collectVars(allVars, vars);\r
-        if(else_ != null)\r
-            else_.collectVars(allVars, vars);\r
-       }\r
-\r
-       @Override\r
-       protected void updateType() throws MatchException {\r
-           setType(then_.getType());\r
-       }\r
-       \r
-       @Override\r
-       public IVal toVal(Environment env, CodeWriter w) {\r
-        IVal conditionVal = condition.toVal(env, w); \r
-        CodeWriter joinPoint = w.createBlock(getType());\r
-        CodeWriter thenBlock = w.createBlock();\r
-        if(else_ != null) {\r
-            CodeWriter elseBlock = w.createBlock();        \r
-            w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());\r
-                \r
-            IVal elseVal = else_.toVal(env, elseBlock);\r
-            elseBlock.jump(joinPoint.getContinuation(), elseVal);\r
-        }\r
-        else {\r
-            w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());\r
-        }\r
-        IVal thenVal = then_.toVal(env, thenBlock);\r
-        thenBlock.jump(joinPoint.getContinuation(), thenVal);\r
-        w.continueAs(joinPoint);\r
-        \r
-        return w.getParameters()[0];\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        condition.collectFreeVariables(vars);\r
-        then_.collectFreeVariables(vars);\r
-        if(else_ != null)\r
-            else_.collectFreeVariables(vars);\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        condition = condition.simplify(context);\r
-        then_ = then_.simplify(context);\r
-        if(else_ != null)\r
-            else_ = else_.simplify(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        condition = condition.resolve(context);\r
-        then_ = then_.resolve(context);\r
-        if(else_ != null)\r
-            else_ = else_.resolve(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        return new EIf(condition.replace(context), \r
-                then_.replace(context), \r
-                else_ == null ? null : else_.replace(context));\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        condition = condition.checkType(context, Types.BOOLEAN);\r
-        then_ = then_.checkType(context, requiredType);\r
-        if(else_ != null)\r
-            else_ = else_.checkType(context, requiredType);\r
-        else\r
-            context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkIgnoredType(TypingContext context) {\r
-        condition = condition.checkType(context, Types.BOOLEAN);\r
-        then_ = then_.checkIgnoredType(context);\r
-        if(else_ != null)\r
-            else_ = else_.checkIgnoredType(context);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        condition = condition.decorate(decorator);\r
-        then_ = then_.decorate(decorator);\r
-        if(else_ != null)\r
-            else_ = else_.decorate(decorator);        \r
-        return decorator.decorate(this);\r
-    }\r
-    \r
-    @Override\r
-    public boolean isEffectful() {\r
-       return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        condition.collectEffects(effects);\r
-        then_.collectEffects(effects);\r
-        if(else_ != null)\r
-            else_.collectEffects(effects);\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            condition.setLocationDeep(loc);\r
-            then_.setLocationDeep(loc);\r
-            if(else_ != null)\r
-                else_.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-    \r
-    @Override\r
-    public IExpression toIExpression(ExpressionInterpretationContext target) {\r
-        return new IIf(condition.toIExpression(target), then_.toIExpression(target), \r
-                else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        condition.forVariables(procedure);\r
-        then_.forVariables(procedure);\r
-        if(else_ != null)\r
-            else_.forVariables(procedure);\r
-    }\r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.environment.Environment;
+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.IConstant;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.IIf;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+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.runtime.tuple.Tuple0;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EIf extends Expression {
+    public Expression condition;
+    public Expression then_;
+    public Expression else_; // may be null
+    
+    public EIf(Expression condition, Expression then_, Expression else_) {
+        this.condition = condition;
+        this.then_ = then_;
+        this.else_ = else_;
+    }
+
+    public EIf(long loc, Expression condition, Expression then_, Expression else_) {
+        super(loc);
+        this.condition = condition;
+        this.then_ = then_;
+        this.else_ = else_;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        condition.collectRefs(allRefs, refs);
+        then_.collectRefs(allRefs, refs);
+        if(else_ != null)
+            else_.collectRefs(allRefs, refs);
+    }
+
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           condition.collectVars(allVars, vars);
+        then_.collectVars(allVars, vars);
+        if(else_ != null)
+            else_.collectVars(allVars, vars);
+       }
+
+       @Override
+       protected void updateType() throws MatchException {
+           setType(then_.getType());
+       }
+       
+       @Override
+       public IVal toVal(Environment env, CodeWriter w) {
+        IVal conditionVal = condition.toVal(env, w); 
+        CodeWriter joinPoint = w.createBlock(getType());
+        CodeWriter thenBlock = w.createBlock();
+        if(else_ != null) {
+            CodeWriter elseBlock = w.createBlock();        
+            w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
+                
+            IVal elseVal = else_.toVal(env, elseBlock);
+            elseBlock.jump(joinPoint.getContinuation(), elseVal);
+        }
+        else {
+            w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
+        }
+        IVal thenVal = then_.toVal(env, thenBlock);
+        thenBlock.jump(joinPoint.getContinuation(), thenVal);
+        w.continueAs(joinPoint);
+        
+        return w.getParameters()[0];
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        condition.collectFreeVariables(vars);
+        then_.collectFreeVariables(vars);
+        if(else_ != null)
+            else_.collectFreeVariables(vars);
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        condition = condition.simplify(context);
+        then_ = then_.simplify(context);
+        if(else_ != null)
+            else_ = else_.simplify(context);
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        condition = condition.resolve(context);
+        then_ = then_.resolve(context);
+        if(else_ != null)
+            else_ = else_.resolve(context);
+        return this;
+    }
+
+    @Override
+    public Expression replace(ReplaceContext context) {
+        return new EIf(condition.replace(context), 
+                then_.replace(context), 
+                else_ == null ? null : else_.replace(context));
+    }
+    
+    @Override
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        condition = condition.checkType(context, Types.BOOLEAN);
+        then_ = then_.checkType(context, requiredType);
+        if(else_ != null)
+            else_ = else_.checkType(context, requiredType);
+        else
+            context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext context) {
+        condition = condition.checkType(context, Types.BOOLEAN);
+        then_ = then_.checkIgnoredType(context);
+        if(else_ != null)
+            else_ = else_.checkIgnoredType(context);
+        return this;
+    }
+    
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        condition = condition.decorate(decorator);
+        then_ = then_.decorate(decorator);
+        if(else_ != null)
+            else_ = else_.decorate(decorator);        
+        return decorator.decorate(this);
+    }
+    
+    @Override
+    public boolean isEffectful() {
+       return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        condition.collectEffects(effects);
+        then_.collectEffects(effects);
+        if(else_ != null)
+            else_.collectEffects(effects);
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            condition.setLocationDeep(loc);
+            then_.setLocationDeep(loc);
+            if(else_ != null)
+                else_.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext target) {
+        return new IIf(condition.toIExpression(target), then_.toIExpression(target), 
+                else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        condition.forVariables(procedure);
+        then_.forVariables(procedure);
+        if(else_ != null)
+            else_.forVariables(procedure);
+    }
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+    @Override
+    public int getSyntacticFunctionArity() {
+        return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());
+    }
+}
index abf4c89da4f282a79425f3a08eba5d03357e9d21..67a7e147653ef9ce916858e60ab8554a27b57767 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\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
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class ELambda extends SimplifiableExpression {\r
-    public Case[] cases;\r
-    Type effect = Types.NO_EFFECTS;\r
-    \r
-    public ELambda(Case[] cases) {\r
-        this.cases = cases;\r
-    }\r
-    \r
-    public ELambda(Case case_) {\r
-        this(new Case[] {case_});\r
-    }\r
-\r
-    public ELambda(long loc, Case ... cases) {\r
-        super(loc);\r
-        this.cases = cases;\r
-    }\r
-    \r
-    public ELambda(long loc, Expression pat, Expression exp) {\r
-        this(loc, new Case(new Expression[] {pat}, exp));\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        for(Case case_ : cases)\r
-            case_.collectRefs(allRefs, refs);\r
-    }\r
-       \r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           for(Case case_ : cases)\r
-            case_.collectVars(allVars, vars);\r
-       }\r
-\r
-       public Expression decomposeMatching() {\r
-           Expression[] patterns = cases[0].patterns;\r
-        int arity = patterns.length;\r
-        \r
-        // Simple cases\r
-        if(cases.length == 1 && \r
-                !(cases[0].value instanceof GuardedExpressionGroup)) {\r
-            boolean noMatchingNeeded = true;\r
-            for(int i=0;i<arity;++i)\r
-                if(!(patterns[i] instanceof EVariable)) {\r
-                    noMatchingNeeded = false;\r
-                    break;\r
-                }\r
-            if(noMatchingNeeded) {\r
-                Expression decomposed = cases[0].value.decomposeMatching();\r
-                Type effect = this.effect;\r
-                for(int i=arity-1;i>=0;--i) {\r
-                    Variable var = ((EVariable)patterns[i]).getVariable(); \r
-                    decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);\r
-                    effect = Types.NO_EFFECTS;\r
-                }\r
-                return decomposed;\r
-            }\r
-        }\r
-        \r
-        // Complex case\r
-        Variable[] vars = new Variable[arity];\r
-        Expression[] scrutinee = new Expression[arity];\r
-        for(int i=0;i<arity;++i) {\r
-            vars[i] = new Variable("temp" + i);\r
-            Type type = patterns[i].getType();\r
-            vars[i].setType(type);\r
-            scrutinee[i] = new EVariable(getLocation(), vars[i]);\r
-            scrutinee[i].setType(type);\r
-        }\r
-        Expression decomposed = new EMatch(getLocation(), scrutinee, cases);\r
-        Type curEffect = this.effect;\r
-        for(int i=arity-1;i>=0;--i) {            \r
-            decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);            \r
-            curEffect = Types.NO_EFFECTS;                 \r
-        }\r
-        return decomposed;\r
-    }\r
-       \r
-       @Override\r
-       protected void updateType() throws MatchException {\r
-           setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));\r
-       }\r
-       \r
-       @Override\r
-       public Expression simplify(SimplificationContext context) {\r
-           return decomposeMatching().simplify(context);\r
-       }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        for(Case case_ : cases)\r
-            case_.collectFreeVariables(vars);\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        for(Case case_ : cases)\r
-            case_.resolve(context);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(Case case_ : cases)\r
-                case_.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        Case[] newCases = new Case[cases.length];\r
-        for(int i=0;i<cases.length;++i)\r
-            newCases[i] = cases[i].replace(context);\r
-        return new ELambda(newCases);\r
-    }\r
-\r
-    public Case[] getCases() {\r
-        return cases;\r
-    }\r
-    \r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        int arity = cases[0].patterns.length;\r
-        MultiFunction mfun;\r
-        try {\r
-            mfun = Types.unifyFunction(requiredType, arity);\r
-        } catch (UnificationException e) {\r
-            int requiredArity = Types.getArity(requiredType);\r
-            context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "\r
-                    + arity + " patterns have been given.");\r
-            setType(Types.metaVar(Kinds.STAR));\r
-            return this;\r
-        }\r
-        \r
-        effect = mfun.effect;\r
-        context.pushEffectUpperBound(location, mfun.effect);\r
-        for(Case case_ : cases)\r
-            case_.checkType(context, mfun.parameterTypes,  mfun.returnType);\r
-        context.popEffectUpperBound();\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        int arity = cases[0].patterns.length;\r
-        effect = Types.metaVar(Kinds.EFFECT);\r
-        context.pushEffectUpperBound(location, effect);\r
-        Type[] parameterTypes = new Type[arity];        \r
-        for(int i=0;i<parameterTypes.length;++i)\r
-            parameterTypes[i] = Types.metaVar(Kinds.STAR);\r
-        Type requiredType = Types.metaVar(Kinds.STAR);\r
-        for(Case case_ : cases)\r
-            case_.checkType(context, parameterTypes, requiredType);\r
-        context.popEffectUpperBound();\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        if(decorator.decorateSubstructure(this))\r
-            for(Case case_ : cases)\r
-                case_.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-    \r
-    @Override\r
-    public boolean isEffectful() {\r
-       return false;\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        for(Case case_ : cases) {\r
-            for(Expression pattern : case_.patterns)\r
-                pattern.collectEffects(effects);\r
-            case_.value.collectEffects(effects);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        for(Case case_ : cases)\r
-            case_.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.errors.Locations;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+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 ELambda extends SimplifiableExpression {
+    public Case[] cases;
+    Type effect = Types.NO_EFFECTS;
+    
+    public ELambda(Case[] cases) {
+        this.cases = cases;
+    }
+    
+    public ELambda(Case case_) {
+        this(new Case[] {case_});
+    }
+
+    public ELambda(long loc, Case ... cases) {
+        super(loc);
+        this.cases = cases;
+    }
+    
+    public ELambda(long loc, Expression pat, Expression exp) {
+        this(loc, new Case(new Expression[] {pat}, exp));
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        for(Case case_ : cases)
+            case_.collectRefs(allRefs, refs);
+    }
+       
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           for(Case case_ : cases)
+            case_.collectVars(allVars, vars);
+       }
+
+       public Expression decomposeMatching() {
+           Expression[] patterns = cases[0].patterns;
+        int arity = patterns.length;
+        
+        // Simple cases
+        if(cases.length == 1 && 
+                !(cases[0].value instanceof GuardedExpressionGroup)) {
+            boolean noMatchingNeeded = true;
+            for(int i=0;i<arity;++i)
+                if(!(patterns[i] instanceof EVariable)) {
+                    noMatchingNeeded = false;
+                    break;
+                }
+            if(noMatchingNeeded) {
+                Expression decomposed = cases[0].value.decomposeMatching();
+                Type effect = this.effect;
+                for(int i=arity-1;i>=0;--i) {
+                    Variable var = ((EVariable)patterns[i]).getVariable(); 
+                    decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
+                    effect = Types.NO_EFFECTS;
+                }
+                return decomposed;
+            }
+        }
+        
+        // Complex case
+        Variable[] vars = new Variable[arity];
+        Expression[] scrutinee = new Expression[arity];
+        for(int i=0;i<arity;++i) {
+            vars[i] = new Variable("temp" + i);
+            Type type = patterns[i].getType();
+            vars[i].setType(type);
+            scrutinee[i] = new EVariable(getLocation(), vars[i]);
+            scrutinee[i].setType(type);
+        }
+        Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
+        Type curEffect = this.effect;
+        for(int i=arity-1;i>=0;--i) {            
+            decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);            
+            curEffect = Types.NO_EFFECTS;                 
+        }
+        return decomposed;
+    }
+       
+       @Override
+       protected void updateType() throws MatchException {
+           setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
+       }
+       
+       @Override
+       public Expression simplify(SimplificationContext context) {
+           return decomposeMatching().simplify(context);
+       }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        for(Case case_ : cases)
+            case_.collectFreeVariables(vars);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        for(Case case_ : cases)
+            case_.resolve(context);
+        return this;
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(Case case_ : cases)
+                case_.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression replace(ReplaceContext context) {
+        Case[] newCases = new Case[cases.length];
+        for(int i=0;i<cases.length;++i)
+            newCases[i] = cases[i].replace(context);
+        return new ELambda(newCases);
+    }
+
+    public Case[] getCases() {
+        return cases;
+    }
+    
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        int arity = cases[0].patterns.length;
+        MultiFunction mfun;
+        try {
+            mfun = Types.unifyFunction(requiredType, arity);
+        } catch (UnificationException e) {
+            int requiredArity = Types.getArity(requiredType);
+            context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
+                    + arity + " patterns have been given.");
+            setType(Types.metaVar(Kinds.STAR));
+            return this;
+        }
+        
+        effect = mfun.effect;
+        context.pushEffectUpperBound(location, mfun.effect);
+        for(Case case_ : cases)
+            case_.checkType(context, mfun.parameterTypes,  mfun.returnType);
+        context.popEffectUpperBound();
+        return this;
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        int arity = cases[0].patterns.length;
+        effect = Types.metaVar(Kinds.EFFECT);
+        context.pushEffectUpperBound(location, effect);
+        Type[] parameterTypes = new Type[arity];        
+        for(int i=0;i<parameterTypes.length;++i)
+            parameterTypes[i] = Types.metaVar(Kinds.STAR);
+        Type requiredType = Types.metaVar(Kinds.STAR);
+        for(Case case_ : cases)
+            case_.checkType(context, parameterTypes, requiredType);
+        context.popEffectUpperBound();
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        if(decorator.decorateSubstructure(this))
+            for(Case case_ : cases)
+                case_.decorate(decorator);
+        return decorator.decorate(this);
+    }
+    
+    @Override
+    public boolean isEffectful() {
+       return false;
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        for(Case case_ : cases) {
+            for(Expression pattern : case_.patterns)
+                pattern.collectEffects(effects);
+            case_.value.collectEffects(effects);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        for(Case case_ : cases)
+            case_.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        int result = 0;
+        for(Case case_ : cases)
+            result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());
+        return result;
+    }
+
+}
index 8e9a74cd5146ea0fbb1212b660726a8fa1353366..08e47bf95f78d3fd0b75299e897f69ee42608832 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\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.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.IExpression;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\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
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class ELambdaType extends Expression {\r
-    public TVar[] parameters;\r
-    public Expression value;\r
-    \r
-    public ELambdaType(TVar[] parameters, Expression value) {\r
-        super(value.getLocation());\r
-        this.parameters = parameters;\r
-        this.value = value;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        value.collectRefs(allRefs, refs);\r
-    }\r
-       \r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           value.collectVars(allVars, vars);\r
-       }\r
-       \r
-       @Override\r
-       protected void updateType() throws MatchException {\r
-           setType(Types.forAll(parameters, value.getType()));\r
-       }\r
-\r
-       @Override\r
-    public IVal toVal(Environment env, CodeWriter w) {\r
-        return lambdaToVal(env, w);\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        value.collectFreeVariables(vars);\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        value = value.simplify(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        value = value.resolve(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        TVar[] newParameters = new TVar[parameters.length];\r
-        for(int i=0;i<parameters.length;++i) {\r
-            TVar var = Types.var(parameters[i].getKind());\r
-            newParameters[i] = var;\r
-            context.tvarMap.put(parameters[i], var);\r
-        }\r
-            \r
-        ELambdaType result = new ELambdaType(newParameters, value.replace(context));\r
-        for(int i=0;i<parameters.length;++i)\r
-            context.tvarMap.remove(parameters[i]);\r
-        return result;\r
-    }\r
-    \r
-    @Override\r
-    public IExpression toIExpression(ExpressionInterpretationContext target) {\r
-        return value.toIExpression(target);\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        throw new InternalCompilerError("Should not type check " + getClass().getSimpleName() + ".");\r
-    }\r
-    \r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        value = value.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            value.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        value.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+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.environment.Environment;
+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.IExpression;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+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 gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ELambdaType extends Expression {
+    public TVar[] parameters;
+    public Expression value;
+    
+    public ELambdaType(TVar[] parameters, Expression value) {
+        super(value.getLocation());
+        this.parameters = parameters;
+        this.value = value;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        value.collectRefs(allRefs, refs);
+    }
+       
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           value.collectVars(allVars, vars);
+       }
+       
+       @Override
+       protected void updateType() throws MatchException {
+           setType(Types.forAll(parameters, value.getType()));
+       }
+
+       @Override
+    public IVal toVal(Environment env, CodeWriter w) {
+        return lambdaToVal(env, w);
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        value.collectFreeVariables(vars);
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        value = value.simplify(context);
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        value = value.resolve(context);
+        return this;
+    }
+
+    @Override
+    public Expression replace(ReplaceContext context) {
+        TVar[] newParameters = new TVar[parameters.length];
+        for(int i=0;i<parameters.length;++i) {
+            TVar var = Types.var(parameters[i].getKind());
+            newParameters[i] = var;
+            context.tvarMap.put(parameters[i], var);
+        }
+            
+        ELambdaType result = new ELambdaType(newParameters, value.replace(context));
+        for(int i=0;i<parameters.length;++i)
+            context.tvarMap.remove(parameters[i]);
+        return result;
+    }
+    
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext target) {
+        return value.toIExpression(target);
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        throw new InternalCompilerError("Should not type check " + getClass().getSimpleName() + ".");
+    }
+    
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        value = value.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            value.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        value.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return value.getSyntacticFunctionArity();
+    }
+
+}
index bbbc25c4de4ed7e7841172fb44f96834c5a15b85..d10066f90047a303bb2462089ae2a5d987c217f6 100755 (executable)
-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.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.environment.Environment;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\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.codegen.writer.RecursiveDefinitionWriter;\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.elaboration.utils.StronglyConnectedComponents;\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
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class ELet extends Expression {\r
-    public Assignment[] assignments;\r
-    public Expression in;\r
-    \r
-    public ELet(long loc, Assignment[] assignments, Expression in) {\r
-        super(loc);\r
-        this.assignments = assignments;\r
-        this.in = in;\r
-    }\r
-\r
-    @Override\r
-    public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {\r
-        for(Assignment assign : assignments)\r
-            assign.value.collectRefs(allRefs, refs);\r
-        in.collectRefs(allRefs, refs);\r
-    }\r
-    \r
-    @Override\r
-    public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-            TIntHashSet vars) {\r
-        for(Assignment assign : assignments)\r
-            assign.value.collectVars(allVars, vars);\r
-        in.collectVars(allVars, vars);\r
-    }\r
-    \r
-    @Override\r
-    protected void updateType() throws MatchException {\r
-        setType(in.getType());\r
-    }\r
-   \r
-    /**\r
-     * Splits let \r
-     */\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        \r
-        // Simplify assignments\r
-        for(Assignment assignment : assignments) {\r
-            assignment.value = assignment.value.simplify(context);\r
-        }\r
-        \r
-        // Find strongly connected components\r
-        final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(\r
-                2*assignments.length, 0.5f, -1);\r
-\r
-        for(int i=0;i<assignments.length;++i)\r
-            for(Variable var : assignments[i].pattern.getFreeVariables())\r
-                allVars.put(var, i);\r
-        final boolean isRecursive[] = new boolean[assignments.length];\r
-        final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length)); \r
-        new StronglyConnectedComponents(assignments.length) {\r
-            @Override\r
-            protected int[] findDependencies(int u) {\r
-                TIntHashSet vars = new TIntHashSet();\r
-                assignments[u].value.collectVars(allVars, vars);\r
-                if(vars.contains(u))\r
-                    isRecursive[u] = true;\r
-                return vars.toArray();\r
-            }\r
-\r
-            @Override\r
-            protected void reportComponent(int[] component) {\r
-                components.add(component);\r
-            }\r
-\r
-        }.findComponents();\r
-\r
-        // Simplify in\r
-        Expression result = in.simplify(context);\r
-        \r
-        // Handle each component\r
-        for(int j=components.size()-1;j>=0;--j) {\r
-            int[] component = components.get(j);\r
-            boolean recursive = component.length > 1 || isRecursive[component[0]];\r
-            if(recursive) {\r
-                Assignment[] cAssignments = new Assignment[component.length];\r
-                for(int i=0;i<component.length;++i)\r
-                    cAssignments[i] = assignments[component[i]];\r
-                result = new ELet(location, cAssignments, result);\r
-            }\r
-            else {\r
-                Assignment assignment = assignments[component[0]];\r
-                Expression pattern = assignment.pattern;\r
-                \r
-                if(pattern instanceof EVariable) {\r
-                    EVariable pvar = (EVariable)pattern;\r
-                    result = new ESimpleLet(location, pvar.variable, assignment.value, result);\r
-                }\r
-                else {\r
-                    result = new EMatch(location, new Expression[] {assignment.value},\r
-                                    new Case(new Expression[] {pattern}, result));\r
-                }\r
-            }\r
-        }\r
-        \r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        in.collectFreeVariables(vars);\r
-        for(Assignment assign : assignments)\r
-            assign.value.collectFreeVariables(vars);\r
-        for(Assignment assign : assignments) \r
-            assign.pattern.removeFreeVariables(vars);\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        throw new InternalCompilerError("ELet should be already resolved.");\r
-    }\r
-    \r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        Assignment[] newAssignments = new Assignment[assignments.length];\r
-        for(int i=0;i<assignments.length;++i)\r
-            newAssignments[i] = assignments[i].replace(context);            \r
-        Expression newIn = in.replace(context);\r
-        return new ELet(getLocation(), newAssignments, newIn);\r
-    }\r
-    \r
-    @Override\r
-    public IVal toVal(Environment env, CodeWriter w) {\r
-        // Create bound variables\r
-        BoundVar[] vars = new BoundVar[assignments.length];\r
-        for(int i=0;i<assignments.length;++i) {\r
-            Expression pattern = assignments[i].pattern;\r
-            if(!(pattern instanceof EVariable))\r
-                throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");\r
-            vars[i] = new BoundVar(pattern.getType());\r
-            ((EVariable)pattern).getVariable().setVal(vars[i]);\r
-        }\r
-        \r
-        // Create values\r
-        RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();\r
-        long range = Locations.NO_LOCATION;\r
-        for(Assignment assign2 : assignments) {\r
-            range = Locations.combine(range, assign2.pattern.location);\r
-            range = Locations.combine(range, assign2.value.location);\r
-        }\r
-        rdw.setLocation(range);\r
-        for(int i=0;i<assignments.length;++i) {\r
-            DecomposedExpression decomposed = \r
-                    DecomposedExpression.decompose(assignments[i].value);\r
-            CodeWriter newW = rdw.createFunction(vars[i], \r
-                    decomposed.typeParameters,\r
-                    decomposed.effect,\r
-                    decomposed.returnType, \r
-                    decomposed.parameterTypes);\r
-            IVal[] parameters = newW.getParameters();\r
-            for(int j=0;j<parameters.length;++j)\r
-                decomposed.parameters[j].setVal(parameters[j]);\r
-            newW.return_(decomposed.body.toVal(env, newW));\r
-        }\r
-        return in.toVal(env, w);\r
-    }\r
-        \r
-    private void checkAssignments(TypingContext context) {\r
-        for(Assignment assign : assignments)\r
-            assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));\r
-        for(Assignment assign : assignments)\r
-            assign.value = assign.value.checkType(context, assign.pattern.getType());\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        checkAssignments(context);\r
-        in = in.inferType(context);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        checkAssignments(context);\r
-        in = in.checkType(context, requiredType);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkIgnoredType(TypingContext context) {\r
-        checkAssignments(context);\r
-        in = in.checkIgnoredType(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        in = in.decorate(decorator);\r
-        for(Assignment assignment : assignments)\r
-            assignment.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        for(Assignment assignment : assignments) {\r
-            assignment.pattern.collectEffects(effects);\r
-            assignment.value.collectEffects(effects);\r
-        }\r
-        in.collectEffects(effects);\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(Assignment assignment : assignments)\r
-                assignment.setLocationDeep(loc);\r
-            in.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        for(Assignment assignment : assignments)\r
-            assignment.forVariables(procedure);\r
-        in.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\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.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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter;
+import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
+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 gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ELet extends Expression {
+    public Assignment[] assignments;
+    public Expression in;
+    
+    public ELet(long loc, Assignment[] assignments, Expression in) {
+        super(loc);
+        this.assignments = assignments;
+        this.in = in;
+    }
+
+    @Override
+    public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {
+        for(Assignment assign : assignments)
+            assign.value.collectRefs(allRefs, refs);
+        in.collectRefs(allRefs, refs);
+    }
+    
+    @Override
+    public void collectVars(TObjectIntHashMap<Variable> allVars,
+            TIntHashSet vars) {
+        for(Assignment assign : assignments)
+            assign.value.collectVars(allVars, vars);
+        in.collectVars(allVars, vars);
+    }
+    
+    @Override
+    protected void updateType() throws MatchException {
+        setType(in.getType());
+    }
+   
+    /**
+     * Splits let 
+     */
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        
+        // Simplify assignments
+        for(Assignment assignment : assignments) {
+            assignment.value = assignment.value.simplify(context);
+        }
+        
+        // Find strongly connected components
+        final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
+                2*assignments.length, 0.5f, -1);
+
+        for(int i=0;i<assignments.length;++i)
+            for(Variable var : assignments[i].pattern.getFreeVariables())
+                allVars.put(var, i);
+        final boolean isRecursive[] = new boolean[assignments.length];
+        final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length)); 
+        new StronglyConnectedComponents(assignments.length) {
+            @Override
+            protected int[] findDependencies(int u) {
+                TIntHashSet vars = new TIntHashSet();
+                assignments[u].value.collectVars(allVars, vars);
+                if(vars.contains(u))
+                    isRecursive[u] = true;
+                return vars.toArray();
+            }
+
+            @Override
+            protected void reportComponent(int[] component) {
+                components.add(component);
+            }
+
+        }.findComponents();
+
+        // Simplify in
+        Expression result = in.simplify(context);
+        
+        // Handle each component
+        for(int j=components.size()-1;j>=0;--j) {
+            int[] component = components.get(j);
+            boolean recursive = component.length > 1 || isRecursive[component[0]];
+            if(recursive) {
+                Assignment[] cAssignments = new Assignment[component.length];
+                for(int i=0;i<component.length;++i)
+                    cAssignments[i] = assignments[component[i]];
+                result = new ELet(location, cAssignments, result);
+            }
+            else {
+                Assignment assignment = assignments[component[0]];
+                Expression pattern = assignment.pattern;
+                
+                if(pattern instanceof EVariable) {
+                    EVariable pvar = (EVariable)pattern;
+                    result = new ESimpleLet(location, pvar.variable, assignment.value, result);
+                }
+                else {
+                    result = new EMatch(location, new Expression[] {assignment.value},
+                                    new Case(new Expression[] {pattern}, result));
+                }
+            }
+        }
+        
+        return result;
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        in.collectFreeVariables(vars);
+        for(Assignment assign : assignments)
+            assign.value.collectFreeVariables(vars);
+        for(Assignment assign : assignments) 
+            assign.pattern.removeFreeVariables(vars);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        throw new InternalCompilerError("ELet should be already resolved.");
+    }
+    
+    @Override
+    public Expression replace(ReplaceContext context) {
+        Assignment[] newAssignments = new Assignment[assignments.length];
+        for(int i=0;i<assignments.length;++i)
+            newAssignments[i] = assignments[i].replace(context);            
+        Expression newIn = in.replace(context);
+        return new ELet(getLocation(), newAssignments, newIn);
+    }
+    
+    @Override
+    public IVal toVal(Environment env, CodeWriter w) {
+        // Create bound variables
+        BoundVar[] vars = new BoundVar[assignments.length];
+        for(int i=0;i<assignments.length;++i) {
+            Expression pattern = assignments[i].pattern;
+            if(!(pattern instanceof EVariable))
+                throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");
+            vars[i] = new BoundVar(pattern.getType());
+            ((EVariable)pattern).getVariable().setVal(vars[i]);
+        }
+        
+        // Create values
+        RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();
+        long range = Locations.NO_LOCATION;
+        for(Assignment assign2 : assignments) {
+            range = Locations.combine(range, assign2.pattern.location);
+            range = Locations.combine(range, assign2.value.location);
+        }
+        rdw.setLocation(range);
+        for(int i=0;i<assignments.length;++i) {
+            DecomposedExpression decomposed = 
+                    DecomposedExpression.decompose(assignments[i].value);
+            CodeWriter newW = rdw.createFunction(vars[i], 
+                    decomposed.typeParameters,
+                    decomposed.effect,
+                    decomposed.returnType, 
+                    decomposed.parameterTypes);
+            IVal[] parameters = newW.getParameters();
+            for(int j=0;j<parameters.length;++j)
+                decomposed.parameters[j].setVal(parameters[j]);
+            newW.return_(decomposed.body.toVal(env, newW));
+        }
+        return in.toVal(env, w);
+    }
+        
+    private void checkAssignments(TypingContext context) {
+        for(Assignment assign : assignments)
+            assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
+        for(Assignment assign : assignments)
+            assign.value = assign.value.checkType(context, assign.pattern.getType());
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        checkAssignments(context);
+        in = in.inferType(context);
+        return this;
+    }
+    
+    @Override
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        checkAssignments(context);
+        in = in.checkType(context, requiredType);
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext context) {
+        checkAssignments(context);
+        in = in.checkIgnoredType(context);
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        in = in.decorate(decorator);
+        for(Assignment assignment : assignments)
+            assignment.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        for(Assignment assignment : assignments) {
+            assignment.pattern.collectEffects(effects);
+            assignment.value.collectEffects(effects);
+        }
+        in.collectEffects(effects);
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(Assignment assignment : assignments)
+                assignment.setLocationDeep(loc);
+            in.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        for(Assignment assignment : assignments)
+            assignment.forVariables(procedure);
+        in.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return in.getSyntacticFunctionArity();
+    }
+
+}
index 11877a60e086e9d0e6ba16f7eac4aaaccedd8cac..d1a96d04a36696f214a16b626e8ba83f788ad41f 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\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.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.ssa.exits.Throw;\r
-import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
-import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;\r
-import org.simantics.scl.compiler.internal.elaboration.matching.Row;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\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 class EMatch extends Expression {\r
-\r
-    public Expression[] scrutinee;\r
-    public Case[] cases;\r
-    \r
-    public EMatch(Expression[] scrutinee, Case ... cases) {\r
-        this.scrutinee = scrutinee;\r
-        this.cases = cases;\r
-    }\r
-    \r
-    public EMatch(Expression scrutinee, Case ... cases) {\r
-        this(new Expression[] {scrutinee}, cases);\r
-    }\r
-\r
-    public EMatch(long loc, Expression[] scrutinee, Case ... cases) {\r
-        super(loc);\r
-        this.scrutinee = scrutinee;\r
-        this.cases = cases;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        for(Expression s : scrutinee)\r
-            s.collectRefs(allRefs, refs);\r
-        for(Case case_ : cases)\r
-            case_.collectRefs(allRefs, refs);\r
-    }\r
-       \r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           for(Expression s : scrutinee)\r
-            s.collectVars(allVars, vars);\r
-           for(Case case_ : cases)\r
-            case_.collectVars(allVars, vars);\r
-       }\r
-       \r
-       @Override\r
-       protected void updateType() {\r
-           setType(cases[0].value.getType());\r
-       }\r
-\r
-       @Override\r
-       public IVal toVal(Environment env, CodeWriter w) {\r
-           ArrayList<Row> rows = new ArrayList<Row>(cases.length);\r
-           for(Case case_ : cases)\r
-               rows.add(new Row(case_.patterns, case_.value));\r
-           \r
-           IVal[] scrutineeVals = new IVal[scrutinee.length];\r
-           for(int i=0;i<scrutinee.length;++i)\r
-               scrutineeVals[i] = scrutinee[i].toVal(env, w);\r
-           \r
-           CodeWriter joinPoint = w.createBlock(getType());\r
-           CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function\r
-           PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);\r
-           failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
-           w.continueAs(joinPoint);\r
-           return w.getParameters()[0];\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        for(Expression s : scrutinee)\r
-            s.collectFreeVariables(vars);\r
-        for(Case case_ : cases)\r
-            case_.collectFreeVariables(vars);\r
-    }\r
-    \r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        for(int i=0;i<scrutinee.length;++i)\r
-            scrutinee[i] = scrutinee[i].simplify(context);\r
-        for(Case case_ : cases)\r
-            case_.simplify(context);                    \r
-        if(cases.length == 1 && scrutinee.length == 1) {\r
-            Case case_ = cases[0];\r
-            Expression pattern = case_.patterns[0];\r
-            if(case_.patterns[0] instanceof EVariable\r
-                    && !(case_.value instanceof GuardedExpressionGroup)) {\r
-                Variable var = ((EVariable)pattern).variable;\r
-                return new ESimpleLet(var, scrutinee[0], case_.value);\r
-            }\r
-        }\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        for(int i=0;i<scrutinee.length;++i)\r
-            scrutinee[i] = scrutinee[i].resolve(context);\r
-        for(Case case_ : cases)\r
-            case_.resolve(context);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(Case case_ : cases)\r
-                case_.setLocationDeep(loc);\r
-            for(Expression e : scrutinee)\r
-                e.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        Expression[] newScrutinee = new Expression[scrutinee.length];\r
-        for(int i=0;i<scrutinee.length;++i)\r
-            newScrutinee[i] = scrutinee[i].replace(context);\r
-        Case[] newCases = new Case[cases.length];\r
-        for(int i=0;i<cases.length;++i)\r
-            newCases[i] = cases[i].replace(context);\r
-        return new EMatch(getLocation(), newScrutinee, newCases);\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        Type[] scrutineeTypes = new Type[scrutinee.length];\r
-        for(int i=0;i<scrutinee.length;++i) {\r
-            scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
-            scrutineeTypes[i] = scrutinee[i].getType();\r
-        }\r
-        for(Case case_ : cases)\r
-            case_.checkType(context, scrutineeTypes, requiredType);\r
-        setType(requiredType);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkIgnoredType(TypingContext context) {\r
-        Type[] scrutineeTypes = new Type[scrutinee.length];\r
-        for(int i=0;i<scrutinee.length;++i) {\r
-            scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
-            scrutineeTypes[i] = scrutinee[i].getType();\r
-        }\r
-        for(Case case_ : cases)\r
-            case_.checkIgnoredType(context, scrutineeTypes);\r
-        setType(Types.UNIT);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        for(int i=0;i<scrutinee.length;++i)\r
-            scrutinee[i] = scrutinee[i].decorate(decorator);\r
-        for(Case case_ : cases)\r
-            case_.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        for(Expression s : scrutinee)\r
-            s.collectEffects(effects);\r
-        for(Case case_ : cases) {\r
-            for(Expression pattern : case_.patterns)\r
-                pattern.collectEffects(effects);\r
-            case_.value.collectEffects(effects);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-    \r
-    public Expression[] getScrutinee() {\r
-        return scrutinee;\r
-    }\r
-    \r
-    public Case[] getCases() {\r
-        return cases;\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        for(Expression s : scrutinee)\r
-            s.forVariables(procedure);\r
-        for(Case case_ : cases)\r
-            case_.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;
+import org.simantics.scl.compiler.internal.elaboration.matching.Row;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EMatch extends Expression {
+
+    public Expression[] scrutinee;
+    public Case[] cases;
+    
+    public EMatch(Expression[] scrutinee, Case ... cases) {
+        this.scrutinee = scrutinee;
+        this.cases = cases;
+    }
+    
+    public EMatch(Expression scrutinee, Case ... cases) {
+        this(new Expression[] {scrutinee}, cases);
+    }
+
+    public EMatch(long loc, Expression[] scrutinee, Case ... cases) {
+        super(loc);
+        this.scrutinee = scrutinee;
+        this.cases = cases;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        for(Expression s : scrutinee)
+            s.collectRefs(allRefs, refs);
+        for(Case case_ : cases)
+            case_.collectRefs(allRefs, refs);
+    }
+       
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           for(Expression s : scrutinee)
+            s.collectVars(allVars, vars);
+           for(Case case_ : cases)
+            case_.collectVars(allVars, vars);
+       }
+       
+       @Override
+       protected void updateType() {
+           setType(cases[0].value.getType());
+       }
+
+       @Override
+       public IVal toVal(Environment env, CodeWriter w) {
+           ArrayList<Row> rows = new ArrayList<Row>(cases.length);
+           for(Case case_ : cases)
+               rows.add(new Row(case_.patterns, case_.value));
+           
+           IVal[] scrutineeVals = new IVal[scrutinee.length];
+           for(int i=0;i<scrutinee.length;++i)
+               scrutineeVals[i] = scrutinee[i].toVal(env, w);
+           
+           CodeWriter joinPoint = w.createBlock(getType());
+           CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function
+           PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);
+           failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
+           w.continueAs(joinPoint);
+           return w.getParameters()[0];
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        for(Expression s : scrutinee)
+            s.collectFreeVariables(vars);
+        for(Case case_ : cases)
+            case_.collectFreeVariables(vars);
+    }
+    
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        for(int i=0;i<scrutinee.length;++i)
+            scrutinee[i] = scrutinee[i].simplify(context);
+        for(Case case_ : cases)
+            case_.simplify(context);                    
+        if(cases.length == 1 && scrutinee.length == 1) {
+            Case case_ = cases[0];
+            Expression pattern = case_.patterns[0];
+            if(case_.patterns[0] instanceof EVariable
+                    && !(case_.value instanceof GuardedExpressionGroup)) {
+                Variable var = ((EVariable)pattern).variable;
+                return new ESimpleLet(var, scrutinee[0], case_.value);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        for(int i=0;i<scrutinee.length;++i)
+            scrutinee[i] = scrutinee[i].resolve(context);
+        for(Case case_ : cases)
+            case_.resolve(context);
+        return this;
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(Case case_ : cases)
+                case_.setLocationDeep(loc);
+            for(Expression e : scrutinee)
+                e.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression replace(ReplaceContext context) {
+        Expression[] newScrutinee = new Expression[scrutinee.length];
+        for(int i=0;i<scrutinee.length;++i)
+            newScrutinee[i] = scrutinee[i].replace(context);
+        Case[] newCases = new Case[cases.length];
+        for(int i=0;i<cases.length;++i)
+            newCases[i] = cases[i].replace(context);
+        return new EMatch(getLocation(), newScrutinee, newCases);
+    }
+    
+    @Override
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        Type[] scrutineeTypes = new Type[scrutinee.length];
+        for(int i=0;i<scrutinee.length;++i) {
+            scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
+            scrutineeTypes[i] = scrutinee[i].getType();
+        }
+        for(Case case_ : cases)
+            case_.checkType(context, scrutineeTypes, requiredType);
+        setType(requiredType);
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext context) {
+        Type[] scrutineeTypes = new Type[scrutinee.length];
+        for(int i=0;i<scrutinee.length;++i) {
+            scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
+            scrutineeTypes[i] = scrutinee[i].getType();
+        }
+        for(Case case_ : cases)
+            case_.checkIgnoredType(context, scrutineeTypes);
+        setType(Types.UNIT);
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        for(int i=0;i<scrutinee.length;++i)
+            scrutinee[i] = scrutinee[i].decorate(decorator);
+        for(Case case_ : cases)
+            case_.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        for(Expression s : scrutinee)
+            s.collectEffects(effects);
+        for(Case case_ : cases) {
+            for(Expression pattern : case_.patterns)
+                pattern.collectEffects(effects);
+            case_.value.collectEffects(effects);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    public Expression[] getScrutinee() {
+        return scrutinee;
+    }
+    
+    public Case[] getCases() {
+        return cases;
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        for(Expression s : scrutinee)
+            s.forVariables(procedure);
+        for(Case case_ : cases)
+            case_.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+    @Override
+    public int getSyntacticFunctionArity() {
+        int result = 0;
+        for(Case case_ : cases)
+            result = Math.max(result, case_.value.getSyntacticFunctionArity());
+        return result;
+    }
+}
index 8d8883eae66f5e0fe2f20832f922aa7ca37ffe7e..c78b9f4572bda462183776f8e7cc140694eaa2ec 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-\r
-public class EPreLet extends ASTExpression {\r
-\r
-    List<LetStatement> assignments;\r
-    Expression in;\r
-    \r
-    public EPreLet(List<LetStatement> assignments, Expression in) {\r
-        this.assignments = assignments;\r
-        this.in = in;\r
-    }\r
-    \r
-    @Override\r
-    public Expression resolve(final TranslationContext context) {\r
-        context.pushFrame();\r
-        THashMap<String, ArrayList<LetStatement>> functionDefinitions =\r
-                new THashMap<String, ArrayList<LetStatement>>();\r
-        ArrayList<LetStatement> otherDefinitions = new ArrayList<LetStatement>();\r
-        final THashMap<String, Variable> localVars = new THashMap<String, Variable>();\r
-        try {\r
-            for(LetStatement assign : assignments) {\r
-                LhsType lhsType = assign.pattern.getLhsType();\r
-                if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) {\r
-                    String name = ((FunctionDefinitionLhs)lhsType).functionName;\r
-                    ArrayList<LetStatement> group = functionDefinitions.get(name);\r
-                    if(group == null) {\r
-                        group = new ArrayList<LetStatement>(2);\r
-                        functionDefinitions.put(name, group);\r
-                    }\r
-                    group.add(assign);\r
-                    localVars.put(name, context.newVariable(name));\r
-                }\r
-                else {\r
-                    otherDefinitions.add(assign);\r
-                    assign.pattern = assign.pattern.resolveAsPattern(context);\r
-                }\r
-            }\r
-        } catch (NotPatternException e) {\r
-            context.getErrorLog().log(e.getExpression().location, "Not a pattern.");\r
-            return new EError();\r
-        }\r
-        \r
-        final ArrayList<Assignment> as = new ArrayList<Assignment>(functionDefinitions.size() + otherDefinitions.size());\r
-        functionDefinitions.forEachEntry(new TObjectObjectProcedure<String, ArrayList<LetStatement>>() {\r
-            @Override\r
-            public boolean execute(String name, ArrayList<LetStatement> cases) {\r
-                as.add(new Assignment(\r
-                        new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), \r
-                        context.translateCases(cases)));\r
-                return true;\r
-            }\r
-        });\r
-        for(LetStatement stat : otherDefinitions)\r
-            as.add(new Assignment(\r
-                    stat.pattern /* already resolved above */, \r
-                    stat.value.resolve(context)));\r
-        Expression inExpr = in.resolve(context);\r
-        context.popFrame();\r
-        \r
-        ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr);\r
-        /*System.out.println("-----------------------------------------");\r
-        System.out.println(this);\r
-        System.out.println("-----------------------------------------");\r
-        System.out.println(result);\r
-        System.out.println("-----------------------------------------");*/\r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(LetStatement assignment : assignments)\r
-                assignment.setLocationDeep(loc);\r
-            in.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.errors.Locations;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+
+public class EPreLet extends ASTExpression {
+
+    List<LetStatement> assignments;
+    Expression in;
+    
+    public EPreLet(List<LetStatement> assignments, Expression in) {
+        this.assignments = assignments;
+        this.in = in;
+    }
+    
+    @Override
+    public Expression resolve(final TranslationContext context) {
+        context.pushFrame();
+        THashMap<String, ArrayList<LetStatement>> functionDefinitions =
+                new THashMap<String, ArrayList<LetStatement>>();
+        ArrayList<LetStatement> otherDefinitions = new ArrayList<LetStatement>();
+        final THashMap<String, Variable> localVars = new THashMap<String, Variable>();
+        try {
+            for(LetStatement assign : assignments) {
+                LhsType lhsType = assign.pattern.getLhsType();
+                if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) {
+                    String name = ((FunctionDefinitionLhs)lhsType).functionName;
+                    ArrayList<LetStatement> group = functionDefinitions.get(name);
+                    if(group == null) {
+                        group = new ArrayList<LetStatement>(2);
+                        functionDefinitions.put(name, group);
+                    }
+                    group.add(assign);
+                    localVars.put(name, context.newVariable(name));
+                }
+                else {
+                    otherDefinitions.add(assign);
+                    assign.pattern = assign.pattern.resolveAsPattern(context);
+                }
+            }
+        } catch (NotPatternException e) {
+            context.getErrorLog().log(e.getExpression().location, "Not a pattern.");
+            return new EError();
+        }
+        
+        final ArrayList<Assignment> as = new ArrayList<Assignment>(functionDefinitions.size() + otherDefinitions.size());
+        functionDefinitions.forEachEntry(new TObjectObjectProcedure<String, ArrayList<LetStatement>>() {
+            @Override
+            public boolean execute(String name, ArrayList<LetStatement> cases) {
+                as.add(new Assignment(
+                        new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), 
+                        context.translateCases(cases)));
+                return true;
+            }
+        });
+        for(LetStatement stat : otherDefinitions)
+            as.add(new Assignment(
+                    stat.pattern /* already resolved above */, 
+                    stat.value.resolve(context)));
+        Expression inExpr = in.resolve(context);
+        context.popFrame();
+        
+        ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr);
+        /*System.out.println("-----------------------------------------");
+        System.out.println(this);
+        System.out.println("-----------------------------------------");
+        System.out.println(result);
+        System.out.println("-----------------------------------------");*/
+        return result;
+    }
+
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(LetStatement assignment : assignments)
+                assignment.setLocationDeep(loc);
+            in.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return in.getSyntacticFunctionArity();
+    }
+
+}
index 74f24ebb82496048e0d1c5c599c20350c642f646..41880a0224bd2fb960f9acd7cc3f05bf03c0c093 100644 (file)
@@ -1,83 +1,88 @@
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;\r
-import org.simantics.scl.compiler.elaboration.relations.LocalRelation;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-public class EPreRuleset extends ASTExpression {\r
-\r
-    RuleStatement[] statements;\r
-    Expression in;\r
-    \r
-    public EPreRuleset(RuleStatement[] statements, Expression in) {\r
-        this.statements = statements;\r
-        this.in = in;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        THashMap<String, LocalRelation> relations = new THashMap<String, LocalRelation>(); \r
-        DatalogRule[] rules = new DatalogRule[statements.length];\r
-        context.pushRelationFrame();\r
-        try {\r
-            for(int i=0;i<statements.length;++i) {\r
-                RuleStatement statement = statements[i];\r
-                Expression head = statement.head;\r
-                if(!(head instanceof EApply)) {\r
-                    context.getErrorLog().log(head.location, "Invalid rule head.");\r
-                    return new EError();\r
-                }\r
-                EApply apply = (EApply)head;\r
-                if(!(apply.function instanceof EVar)) {\r
-                    context.getErrorLog().log(head.location, "Invalid relation in rule head.");\r
-                    return new EError();\r
-                }\r
-                String relationName = ((EVar)apply.function).name;\r
-                LocalRelation relation = relations.get(relationName);\r
-                if(relation == null) {\r
-                    relation = new LocalRelation(relationName, apply.parameters.length);\r
-                    relations.put(relationName, relation);\r
-                    context.newRelation(relationName, relation);\r
-                }\r
-                else if(apply.parameters.length != relation.getArity()) {\r
-                    context.getErrorLog().log(apply.location, "Different rules have different relation arity.");\r
-                    return new EError();\r
-                }\r
-                rules[i] = new DatalogRule(relation, apply.parameters, statement.body);\r
-            }\r
-            for(DatalogRule rule : rules) {\r
-                context.pushExistentialFrame();\r
-                for(int i=0;i<rule.headParameters.length;++i)\r
-                    rule.headParameters[i] = rule.headParameters[i].resolve(context);\r
-                rule.body = rule.body.resolve(context);\r
-                rule.variables = context.popExistentialFrame();\r
-            }\r
-            return new ERuleset(\r
-                    relations.values().toArray(new LocalRelation[relations.size()]),\r
-                    rules,\r
-                    in.resolve(context));\r
-        } finally {\r
-            context.popRelationFrame();\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(RuleStatement statement : statements)\r
-                statement.setLocationDeep(loc);\r
-            in.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;
+import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
+import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
+import org.simantics.scl.compiler.errors.Locations;
+
+import gnu.trove.map.hash.THashMap;
+
+public class EPreRuleset extends ASTExpression {
+
+    RuleStatement[] statements;
+    Expression in;
+    
+    public EPreRuleset(RuleStatement[] statements, Expression in) {
+        this.statements = statements;
+        this.in = in;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        THashMap<String, LocalRelation> relations = new THashMap<String, LocalRelation>(); 
+        DatalogRule[] rules = new DatalogRule[statements.length];
+        context.pushRelationFrame();
+        try {
+            for(int i=0;i<statements.length;++i) {
+                RuleStatement statement = statements[i];
+                Expression head = statement.head;
+                if(!(head instanceof EApply)) {
+                    context.getErrorLog().log(head.location, "Invalid rule head.");
+                    return new EError();
+                }
+                EApply apply = (EApply)head;
+                if(!(apply.function instanceof EVar)) {
+                    context.getErrorLog().log(head.location, "Invalid relation in rule head.");
+                    return new EError();
+                }
+                String relationName = ((EVar)apply.function).name;
+                LocalRelation relation = relations.get(relationName);
+                if(relation == null) {
+                    relation = new LocalRelation(relationName, apply.parameters.length);
+                    relations.put(relationName, relation);
+                    context.newRelation(relationName, relation);
+                }
+                else if(apply.parameters.length != relation.getArity()) {
+                    context.getErrorLog().log(apply.location, "Different rules have different relation arity.");
+                    return new EError();
+                }
+                rules[i] = new DatalogRule(relation, apply.parameters, statement.body);
+            }
+            for(DatalogRule rule : rules) {
+                context.pushExistentialFrame();
+                for(int i=0;i<rule.headParameters.length;++i)
+                    rule.headParameters[i] = rule.headParameters[i].resolve(context);
+                rule.body = rule.body.resolve(context);
+                rule.variables = context.popExistentialFrame();
+            }
+            return new ERuleset(
+                    relations.values().toArray(new LocalRelation[relations.size()]),
+                    rules,
+                    in.resolve(context));
+        } finally {
+            context.popRelationFrame();
+        }
+    }
+
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(RuleStatement statement : statements)
+                statement.setLocationDeep(loc);
+            in.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return in.getSyntacticFunctionArity();
+    }
+
+}
index e1efb30457b25973dd60ee3110930dede5b6bc38..29eff29103dc6a8e2c257c7857b3125c2ccd2982 100755 (executable)
-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.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.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.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.ILambda;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\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
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class ESimpleLambda extends Expression {\r
-    public Variable parameter;\r
-    public Expression value;\r
-    public Type effect = Types.NO_EFFECTS;\r
-    \r
-    public ESimpleLambda(Variable parameter, Expression value) {\r
-        this.parameter = parameter;\r
-        this.value = value;\r
-    }\r
-    \r
-    public ESimpleLambda(Type effect, Variable parameter, Expression value) {\r
-        this.parameter = parameter;\r
-        this.value = value;\r
-        this.effect = effect;\r
-    }\r
-\r
-    public ESimpleLambda(long loc, Variable parameter, Expression value) {\r
-        super(loc);\r
-        this.parameter = parameter;\r
-        this.value = value;\r
-    }\r
-    \r
-    public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {\r
-        super(loc);\r
-        this.parameter = parameter;\r
-        this.value = value;\r
-        this.effect = effect;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        value.collectRefs(allRefs, refs);\r
-    }\r
-       \r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           value.collectVars(allVars, vars);\r
-       }\r
-\r
-       public Expression decomposeMatching() {\r
-        value = value.decomposeMatching();\r
-        return this;\r
-    }\r
-\r
-       @Override\r
-       protected void updateType() throws MatchException {\r
-           setType(Types.functionE(Types.canonical(parameter.type),\r
-                   effect, value.getType()));\r
-       }\r
-       \r
-       @Override\r
-       public IVal toVal(Environment env, CodeWriter w) {\r
-           return lambdaToVal(env, w);\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        value.collectFreeVariables(vars);\r
-        vars.remove(parameter);\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        value = value.simplify(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        value = value.resolve(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        Variable newParameter = parameter.copy();\r
-        context.varMap.put(parameter, new EVariable(newParameter));\r
-        ESimpleLambda result = new ESimpleLambda(getLocation(),\r
-                newParameter, \r
-                effect.replace(context.tvarMap),\r
-                value.replace(context));\r
-        // not absolutely needed, but maybe good for performance\r
-        context.varMap.remove(parameter); \r
-        return result;\r
-    }\r
-        \r
-    public Type getLocalEffect() {\r
-        if(SCLCompilerConfiguration.DEBUG)\r
-            if(effect == null)\r
-                throw new InternalCompilerError();\r
-        return effect;\r
-    }\r
-    \r
-    public void setEffect(Type effect) {\r
-        if(effect == null)\r
-            throw new InternalCompilerError();\r
-        this.effect = effect;\r
-    }\r
-    \r
-    @Override\r
-    public IExpression toIExpression(ExpressionInterpretationContext context) {\r
-        // Find parameters of the whole function definition\r
-        ArrayList<Variable> parameters = new ArrayList<Variable>(2);\r
-        parameters.add(parameter);\r
-        Expression cur = value;\r
-        while(true) {\r
-            if(cur instanceof ESimpleLambda) {\r
-                ESimpleLambda lambda = (ESimpleLambda)cur;\r
-                parameters.add(lambda.parameter);\r
-                cur = lambda.value;\r
-            }\r
-            else if(cur instanceof ELambdaType) {\r
-                cur = ((ELambdaType)cur).value;\r
-            }\r
-            else\r
-                break;\r
-            \r
-        }\r
-        \r
-        // Free variables;\r
-        ExpressionInterpretationContext innerContext =  context.createNewContext();\r
-        THashSet<Variable> freeVariables = cur.getFreeVariables();\r
-        for(Variable parameter : parameters)\r
-            freeVariables.remove(parameter);\r
-        int i=0;\r
-        int[] inheritedVariableIds = new int[freeVariables.size()];\r
-        for(Variable var : freeVariables) {\r
-            innerContext.push(var);\r
-            inheritedVariableIds[i++] = context.getVariableId(var);\r
-        }\r
-        \r
-        // Parameters\r
-        for(Variable parameter : parameters)\r
-            innerContext.push(parameter);\r
-        \r
-        // Construct lambda\r
-        IExpression body = cur.toIExpression(innerContext); \r
-        return new ILambda(inheritedVariableIds,\r
-                parameters.size(),\r
-                innerContext.getMaxVariableId(),\r
-                body);\r
-    }\r
-    \r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        MultiFunction mfun;\r
-        try {\r
-            mfun = Types.unifyFunction(requiredType, 1);\r
-        } catch (UnificationException e) {\r
-            context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");\r
-            setType(Types.metaVar(Kinds.STAR));\r
-            return this;\r
-        }\r
-        \r
-        effect = mfun.effect;\r
-        context.pushEffectUpperBound(location, mfun.effect);\r
-        parameter.setType(mfun.parameterTypes[0]);\r
-        value = value.checkType(context, mfun.returnType);\r
-        context.popEffectUpperBound();\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        effect = Types.metaVar(Kinds.EFFECT);\r
-        context.pushEffectUpperBound(location, effect);\r
-        if(parameter.type == null)\r
-            parameter.setType(Types.metaVar(Kinds.STAR));\r
-        value = value.checkType(context, Types.metaVar(Kinds.STAR));\r
-        context.popEffectUpperBound();\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        if(decorator.decorateSubstructure(this))\r
-            value = value.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public boolean isEffectful() {\r
-       return false;\r
-    }\r
-    \r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            value.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-    \r
-    public Expression getValue() {\r
-        return value;\r
-    }\r
-    \r
-    public Variable getParameter() {\r
-        return parameter;\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        value.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\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.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.environment.Environment;
+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.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.ILambda;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
+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 ESimpleLambda extends Expression {
+    public Variable parameter;
+    public Expression value;
+    public Type effect = Types.NO_EFFECTS;
+    
+    public ESimpleLambda(Variable parameter, Expression value) {
+        this.parameter = parameter;
+        this.value = value;
+    }
+    
+    public ESimpleLambda(Type effect, Variable parameter, Expression value) {
+        this.parameter = parameter;
+        this.value = value;
+        this.effect = effect;
+    }
+
+    public ESimpleLambda(long loc, Variable parameter, Expression value) {
+        super(loc);
+        this.parameter = parameter;
+        this.value = value;
+    }
+    
+    public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
+        super(loc);
+        this.parameter = parameter;
+        this.value = value;
+        this.effect = effect;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        value.collectRefs(allRefs, refs);
+    }
+       
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           value.collectVars(allVars, vars);
+       }
+
+       public Expression decomposeMatching() {
+        value = value.decomposeMatching();
+        return this;
+    }
+
+       @Override
+       protected void updateType() throws MatchException {
+           setType(Types.functionE(Types.canonical(parameter.type),
+                   effect, value.getType()));
+       }
+       
+       @Override
+       public IVal toVal(Environment env, CodeWriter w) {
+           return lambdaToVal(env, w);
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        value.collectFreeVariables(vars);
+        vars.remove(parameter);
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        value = value.simplify(context);
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        value = value.resolve(context);
+        return this;
+    }
+
+    @Override
+    public Expression replace(ReplaceContext context) {
+        Variable newParameter = parameter.copy();
+        context.varMap.put(parameter, new EVariable(newParameter));
+        ESimpleLambda result = new ESimpleLambda(getLocation(),
+                newParameter, 
+                effect.replace(context.tvarMap),
+                value.replace(context));
+        // not absolutely needed, but maybe good for performance
+        context.varMap.remove(parameter); 
+        return result;
+    }
+        
+    public Type getLocalEffect() {
+        if(SCLCompilerConfiguration.DEBUG)
+            if(effect == null)
+                throw new InternalCompilerError();
+        return effect;
+    }
+    
+    public void setEffect(Type effect) {
+        if(effect == null)
+            throw new InternalCompilerError();
+        this.effect = effect;
+    }
+    
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext context) {
+        // Find parameters of the whole function definition
+        ArrayList<Variable> parameters = new ArrayList<Variable>(2);
+        parameters.add(parameter);
+        Expression cur = value;
+        while(true) {
+            if(cur instanceof ESimpleLambda) {
+                ESimpleLambda lambda = (ESimpleLambda)cur;
+                parameters.add(lambda.parameter);
+                cur = lambda.value;
+            }
+            else if(cur instanceof ELambdaType) {
+                cur = ((ELambdaType)cur).value;
+            }
+            else
+                break;
+            
+        }
+        
+        // Free variables;
+        ExpressionInterpretationContext innerContext =  context.createNewContext();
+        THashSet<Variable> freeVariables = cur.getFreeVariables();
+        for(Variable parameter : parameters)
+            freeVariables.remove(parameter);
+        int i=0;
+        int[] inheritedVariableIds = new int[freeVariables.size()];
+        for(Variable var : freeVariables) {
+            innerContext.push(var);
+            inheritedVariableIds[i++] = context.getVariableId(var);
+        }
+        
+        // Parameters
+        for(Variable parameter : parameters)
+            innerContext.push(parameter);
+        
+        // Construct lambda
+        IExpression body = cur.toIExpression(innerContext); 
+        return new ILambda(inheritedVariableIds,
+                parameters.size(),
+                innerContext.getMaxVariableId(),
+                body);
+    }
+    
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        MultiFunction mfun;
+        try {
+            mfun = Types.unifyFunction(requiredType, 1);
+        } catch (UnificationException e) {
+            context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
+            setType(Types.metaVar(Kinds.STAR));
+            return this;
+        }
+        
+        effect = mfun.effect;
+        context.pushEffectUpperBound(location, mfun.effect);
+        parameter.setType(mfun.parameterTypes[0]);
+        value = value.checkType(context, mfun.returnType);
+        context.popEffectUpperBound();
+        return this;
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        effect = Types.metaVar(Kinds.EFFECT);
+        context.pushEffectUpperBound(location, effect);
+        if(parameter.type == null)
+            parameter.setType(Types.metaVar(Kinds.STAR));
+        value = value.checkType(context, Types.metaVar(Kinds.STAR));
+        context.popEffectUpperBound();
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        if(decorator.decorateSubstructure(this))
+            value = value.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public boolean isEffectful() {
+       return false;
+    }
+    
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            value.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    public Expression getValue() {
+        return value;
+    }
+    
+    public Variable getParameter() {
+        return parameter;
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        value.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return 1 + value.getSyntacticFunctionArity();
+    }
+
+}
index 8e73b2392fd3add380c8e656df2eae19777c2211..047d77a47cc4b76bccb7288128b88e01a5722ff6 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.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.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.ILet;\r
-import org.simantics.scl.compiler.internal.interpreted.ISeq;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\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 class ESimpleLet extends Expression {\r
-    Variable variable; // may be null\r
-    Expression value;\r
-    Expression in;\r
-    \r
-    public ESimpleLet(Variable variable, Expression value, Expression in) {\r
-        if(value == null)\r
-            throw new NullPointerException();\r
-        if(in == null)\r
-            throw new NullPointerException();\r
-        this.variable = variable;\r
-        this.value = value;\r
-        this.in = in;\r
-    }\r
-\r
-    public ESimpleLet(long loc, Variable variable, Expression value, Expression in) {\r
-        super(loc);\r
-        if(value == null)\r
-            throw new NullPointerException();\r
-        if(in == null)\r
-            throw new NullPointerException();\r
-        this.variable = variable;\r
-        this.value = value;\r
-        this.in = in;\r
-    }\r
-\r
-       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
-        value.collectRefs(allRefs, refs);\r
-        in.collectRefs(allRefs, refs);\r
-    }\r
-       \r
-       @Override\r
-       public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-               TIntHashSet vars) {\r
-           value.collectVars(allVars, vars);\r
-           in.collectVars(allVars, vars);\r
-       }\r
-\r
-    @Override\r
-    protected void updateType() throws MatchException {\r
-        setType(in.getType());\r
-    }\r
-    \r
-       @Override\r
-       public IVal toVal(Environment env, CodeWriter w) {\r
-           IVal valueVal = value.toVal(env, w);\r
-           if(variable != null)\r
-               variable.setVal(valueVal);\r
-        return in.toVal(env, w);\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        value.collectFreeVariables(vars);\r
-        in.collectFreeVariables(vars);\r
-        vars.remove(variable);\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        value = value.simplify(context);\r
-        if(value instanceof EConstant || value instanceof ELiteral) {\r
-            context.addInlinedVariable(variable, value);\r
-            return in.simplify(context);\r
-        }\r
-        in = in.simplify(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        value = value.resolve(context);\r
-        in = in.resolve(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        if(variable == null)\r
-            return new ESimpleLet(location,\r
-                    null, \r
-                    value.replace(context), \r
-                    in.replace(context));\r
-        else {\r
-            Variable newVariable = variable.copy();\r
-            context.varMap.put(variable, new EVariable(newVariable));\r
-            ESimpleLet result = new ESimpleLet(location, newVariable, \r
-                    value.replace(context), \r
-                    in.replace(context));\r
-            context.varMap.remove(variable);\r
-            return result;\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            value.setLocationDeep(loc);\r
-            in.setLocationDeep(loc);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public IExpression toIExpression(ExpressionInterpretationContext context) {\r
-        if(variable == null) {\r
-            IExpression valueI = value.toIExpression(context);\r
-            IExpression inI = in.toIExpression(context);\r
-            return new ISeq(valueI, inI);\r
-        }\r
-        else {\r
-            IExpression valueI = value.toIExpression(context);\r
-            int variableId = context.push(variable);\r
-            IExpression inI = in.toIExpression(context);\r
-            context.pop(variable);\r
-            return new ILet(variableId, valueI, inI);\r
-        }\r
-    }\r
-\r
-    private void checkBinding(TypingContext context) {\r
-        if(variable == null)\r
-            value = value.checkIgnoredType(context);\r
-        else if(variable.getType() == null) {\r
-            value = value.inferType(context);\r
-            variable.setType(value.getType());\r
-        }\r
-        else\r
-            value = value.checkType(context, variable.type);\r
-        /*else {\r
-            if(variable.getType() == null)\r
-                variable.setType(Types.metaVar(Kinds.STAR));\r
-            value = value.checkType(context, variable.type);\r
-        }*/\r
-    }\r
-    \r
-    @Override\r
-    public Expression inferType(TypingContext context) {\r
-        checkBinding(context);\r
-        in = in.inferType(context);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        checkBinding(context);\r
-        in = in.checkType(context, requiredType);\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkIgnoredType(TypingContext context) {\r
-        checkBinding(context);\r
-        in = in.checkIgnoredType(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        value = value.decorate(decorator);\r
-        in = in.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        value.collectEffects(effects);\r
-        in.collectEffects(effects);\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-    \r
-    public Expression getValue() {\r
-        return value;\r
-    }\r
-    \r
-    public Variable getVariable() {\r
-        return variable;\r
-    }\r
-    \r
-    public Expression getIn() {\r
-        return in;\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        value.forVariables(procedure);\r
-        in.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.environment.Environment;
+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.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.ILet;
+import org.simantics.scl.compiler.internal.interpreted.ISeq;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ESimpleLet extends Expression {
+    Variable variable; // may be null
+    Expression value;
+    Expression in;
+    
+    public ESimpleLet(Variable variable, Expression value, Expression in) {
+        if(value == null)
+            throw new NullPointerException();
+        if(in == null)
+            throw new NullPointerException();
+        this.variable = variable;
+        this.value = value;
+        this.in = in;
+    }
+
+    public ESimpleLet(long loc, Variable variable, Expression value, Expression in) {
+        super(loc);
+        if(value == null)
+            throw new NullPointerException();
+        if(in == null)
+            throw new NullPointerException();
+        this.variable = variable;
+        this.value = value;
+        this.in = in;
+    }
+
+       public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        value.collectRefs(allRefs, refs);
+        in.collectRefs(allRefs, refs);
+    }
+       
+       @Override
+       public void collectVars(TObjectIntHashMap<Variable> allVars,
+               TIntHashSet vars) {
+           value.collectVars(allVars, vars);
+           in.collectVars(allVars, vars);
+       }
+
+    @Override
+    protected void updateType() throws MatchException {
+        setType(in.getType());
+    }
+    
+       @Override
+       public IVal toVal(Environment env, CodeWriter w) {
+           IVal valueVal = value.toVal(env, w);
+           if(variable != null)
+               variable.setVal(valueVal);
+        return in.toVal(env, w);
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        value.collectFreeVariables(vars);
+        in.collectFreeVariables(vars);
+        vars.remove(variable);
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        value = value.simplify(context);
+        if(value instanceof EConstant || value instanceof ELiteral) {
+            context.addInlinedVariable(variable, value);
+            return in.simplify(context);
+        }
+        in = in.simplify(context);
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        value = value.resolve(context);
+        in = in.resolve(context);
+        return this;
+    }
+
+    @Override
+    public Expression replace(ReplaceContext context) {
+        if(variable == null)
+            return new ESimpleLet(location,
+                    null, 
+                    value.replace(context), 
+                    in.replace(context));
+        else {
+            Variable newVariable = variable.copy();
+            context.varMap.put(variable, new EVariable(newVariable));
+            ESimpleLet result = new ESimpleLet(location, newVariable, 
+                    value.replace(context), 
+                    in.replace(context));
+            context.varMap.remove(variable);
+            return result;
+        }
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            value.setLocationDeep(loc);
+            in.setLocationDeep(loc);
+        }
+    }
+
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext context) {
+        if(variable == null) {
+            IExpression valueI = value.toIExpression(context);
+            IExpression inI = in.toIExpression(context);
+            return new ISeq(valueI, inI);
+        }
+        else {
+            IExpression valueI = value.toIExpression(context);
+            int variableId = context.push(variable);
+            IExpression inI = in.toIExpression(context);
+            context.pop(variable);
+            return new ILet(variableId, valueI, inI);
+        }
+    }
+
+    private void checkBinding(TypingContext context) {
+        if(variable == null)
+            value = value.checkIgnoredType(context);
+        else if(variable.getType() == null) {
+            value = value.inferType(context);
+            variable.setType(value.getType());
+        }
+        else
+            value = value.checkType(context, variable.type);
+        /*else {
+            if(variable.getType() == null)
+                variable.setType(Types.metaVar(Kinds.STAR));
+            value = value.checkType(context, variable.type);
+        }*/
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        checkBinding(context);
+        in = in.inferType(context);
+        return this;
+    }
+    
+    @Override
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        checkBinding(context);
+        in = in.checkType(context, requiredType);
+        return this;
+    }
+    
+    @Override
+    public Expression checkIgnoredType(TypingContext context) {
+        checkBinding(context);
+        in = in.checkIgnoredType(context);
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        value = value.decorate(decorator);
+        in = in.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        value.collectEffects(effects);
+        in.collectEffects(effects);
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    public Expression getValue() {
+        return value;
+    }
+    
+    public Variable getVariable() {
+        return variable;
+    }
+    
+    public Expression getIn() {
+        return in;
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        value.forVariables(procedure);
+        in.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+    @Override
+    public int getSyntacticFunctionArity() {
+        return in.getSyntacticFunctionArity();
+    }
+}
index 5ad1e31266bc33a1613a6eb251d9c6bd9dc06c85..f1c3e31e0a3c0678abe2bb60a778b852c1150ac2 100755 (executable)
@@ -1,82 +1,82 @@
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\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.errors.Locations;\r
-\r
-public class EVar extends ASTExpression {\r
-    public final String name;\r
-\r
-    public EVar(long location, String name) {\r
-        this.location = location;\r
-        this.name = name;\r
-    }\r
-    \r
-    public EVar(String name) {\r
-        this(Locations.NO_LOCATION, name);\r
-    }\r
-   \r
-    @Override\r
-    public EVar getPatternHead() {\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public LhsType getLhsType() throws NotPatternException {\r
-        if(TranslationContext.isConstructorName(name))\r
-            return new PatternMatchingLhs();\r
-        else\r
-            return new FunctionDefinitionLhs(name);\r
-    }\r
-    \r
-    @Override\r
-    protected void collectVariableNames(PatternMatchingLhs lhsType)\r
-            throws NotPatternException {\r
-        if(!TranslationContext.isConstructorName(name))\r
-            lhsType.variableNames.add(name);\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        return context.resolveExpression(location, name);\r
-    }\r
-    \r
-    @Override\r
-    public void getParameters(TranslationContext translationContext,\r
-            ArrayList<Expression> parameters) {\r
-    }\r
-    \r
-    @Override\r
-    public Expression resolveAsPattern(TranslationContext context) {\r
-        return context.resolvePattern(this);\r
-    }\r
-    \r
-    @Override\r
-    public int getFunctionDefinitionArity() throws NotPatternException {\r
-        if(TranslationContext.isConstructorName(name))\r
-            throw new NotPatternException(this);\r
-        else\r
-            return 0;\r
-    }\r
-    \r
-    @Override\r
-    public boolean isConstructorApplication() {\r
-        return TranslationContext.isConstructorName(name);\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION)\r
-            location = loc;\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.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
+import org.simantics.scl.compiler.errors.Locations;
+
+public class EVar extends ASTExpression {
+    public final String name;
+
+    public EVar(long location, String name) {
+        this.location = location;
+        this.name = name;
+    }
+    
+    public EVar(String name) {
+        this(Locations.NO_LOCATION, name);
+    }
+   
+    @Override
+    public EVar getPatternHead() {
+        return this;
+    }
+    
+    @Override
+    public LhsType getLhsType() throws NotPatternException {
+        if(TranslationContext.isConstructorName(name))
+            return new PatternMatchingLhs();
+        else
+            return new FunctionDefinitionLhs(name);
+    }
+    
+    @Override
+    protected void collectVariableNames(PatternMatchingLhs lhsType)
+            throws NotPatternException {
+        if(!TranslationContext.isConstructorName(name))
+            lhsType.variableNames.add(name);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        return context.resolveExpression(location, name);
+    }
+    
+    @Override
+    public void getParameters(TranslationContext translationContext,
+            ArrayList<Expression> parameters) {
+    }
+    
+    @Override
+    public Expression resolveAsPattern(TranslationContext context) {
+        return context.resolvePattern(this);
+    }
+    
+    @Override
+    public int getFunctionDefinitionPatternArity() throws NotPatternException {
+        if(TranslationContext.isConstructorName(name))
+            throw new NotPatternException(this);
+        else
+            return 0;
+    }
+    
+    @Override
+    public boolean isConstructorApplication() {
+        return TranslationContext.isConstructorName(name);
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION)
+            location = loc;
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+}
index 9a5fefb9f95cc64f55f2ec36eb7aa8e54ad89313..8adf33936524d266115b25a0b706052b30e6ea9c 100755 (executable)
-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
-        System.out.println("#############################");\r
-        System.out.println(this);\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
-    // TODO implement for all expressions\r
-    public boolean equalsExpression(Expression expression) {\r
-        return false;\r
-    }\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;
+    }
+}
index 48f72eeac0b1a3f743fb0a042eb5c78b32e54619..890d11f8c7a2dc084611786332159f4a3ec48dd5 100755 (executable)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.environment.Environment;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
-import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;\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.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\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 class GuardedExpressionGroup extends Expression {\r
-    public GuardedExpression[] expressions;\r
-\r
-    public GuardedExpressionGroup(GuardedExpression[] expressions) {\r
-        this.expressions = expressions;\r
-    }\r
-\r
-    @Override\r
-    public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
-            TIntHashSet refs) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(Expression guard : expression.guards)\r
-                guard.collectRefs(allRefs, refs);\r
-            expression.value.collectRefs(allRefs, refs);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-            TIntHashSet vars) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(Expression guard : expression.guards)\r
-                guard.collectVars(allVars, vars);\r
-            expression.value.collectVars(allVars, vars);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    protected void updateType() throws MatchException {\r
-        setType(expressions[0].value.getType());\r
-    }\r
-\r
-    @Override\r
-    public IVal toVal(Environment env, CodeWriter w) {\r
-        CodeWriter success = w.createBlock(getType());\r
-        IVal result = success.getParameters()[0];\r
-        CodeWriter failure = w.createBlock();\r
-        compile(env, w, success.getContinuation(), failure.getContinuation());\r
-        w.continueAs(success);\r
-        failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
-        return result;\r
-        //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(Expression guard : expression.guards)\r
-                guard.collectFreeVariables(vars);\r
-            expression.value.collectFreeVariables(vars);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(int i=0;i<expression.guards.length;++i)\r
-                expression.guards[i] = expression.guards[i].simplify(context);\r
-            expression.value = expression.value.simplify(context);\r
-        }\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(int i=0;i<expression.guards.length;++i)\r
-                expression.guards[i] = expression.guards[i].resolve(context);\r
-            expression.value = expression.value.resolve(context);\r
-        }\r
-        return this;\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        for(GuardedExpression expression : expressions) {\r
-            for(int i=0;i<expression.guards.length;++i)\r
-                expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);\r
-            expression.value = expression.value.checkType(context, requiredType);\r
-        }\r
-        return this;\r
-    }\r
-    \r
-    public void compile(Environment env, CodeWriter firstWriter, ICont success,\r
-            ICont lastFailure) {\r
-        // Create all code blocks\r
-        CodeWriter[] writers = new CodeWriter[expressions.length];                \r
-        ICont[] failures = new ICont[expressions.length];\r
-        writers[0] = firstWriter;\r
-        failures[expressions.length-1] = lastFailure;\r
-        for(int i=1;i<expressions.length;++i) {\r
-            CodeWriter writer = firstWriter.createBlock();\r
-            writers[i] = writer;\r
-            failures[i-1] = writer.getContinuation();\r
-        }\r
-        \r
-        // Compile\r
-        for(int i=0;i<expressions.length;++i) {\r
-            CodeWriter w = writers[i];\r
-            ICont failure = failures[i];\r
-            \r
-            for(Expression guard : expressions[i].guards) {\r
-                CodeWriter nextW = w.createBlock();\r
-                w.if_(guard.toVal(env, w), nextW.getContinuation(), failure);\r
-                w = nextW;\r
-            }\r
-            \r
-            w.jump(success, expressions[i].value.toVal(env, w));\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression replace(ReplaceContext context) {\r
-        GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];\r
-        for(int i=0;i<expressions.length;++i)\r
-            newExpressions[i] = expressions[i].replace(context);\r
-        return new GuardedExpressionGroup(newExpressions);            \r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        for(GuardedExpression expression : expressions)\r
-            expression.decorate(decorator);\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        for(GuardedExpression ge : expressions) {\r
-            for(Expression guard : ge.guards)\r
-                guard.collectEffects(effects);\r
-            ge.value.collectEffects(effects);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(GuardedExpression expression : expressions)\r
-                expression.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        for(GuardedExpression expression : expressions)\r
-            expression.forVariables(procedure);\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 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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class GuardedExpressionGroup extends Expression {
+    public GuardedExpression[] expressions;
+
+    public GuardedExpressionGroup(GuardedExpression[] expressions) {
+        this.expressions = expressions;
+    }
+
+    @Override
+    public void collectRefs(TObjectIntHashMap<Object> allRefs,
+            TIntHashSet refs) {
+        for(GuardedExpression expression : expressions) {
+            for(Expression guard : expression.guards)
+                guard.collectRefs(allRefs, refs);
+            expression.value.collectRefs(allRefs, refs);
+        }
+    }
+
+    @Override
+    public void collectVars(TObjectIntHashMap<Variable> allVars,
+            TIntHashSet vars) {
+        for(GuardedExpression expression : expressions) {
+            for(Expression guard : expression.guards)
+                guard.collectVars(allVars, vars);
+            expression.value.collectVars(allVars, vars);
+        }
+    }
+
+    @Override
+    protected void updateType() throws MatchException {
+        setType(expressions[0].value.getType());
+    }
+
+    @Override
+    public IVal toVal(Environment env, CodeWriter w) {
+        CodeWriter success = w.createBlock(getType());
+        IVal result = success.getParameters()[0];
+        CodeWriter failure = w.createBlock();
+        compile(env, w, success.getContinuation(), failure.getContinuation());
+        w.continueAs(success);
+        failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
+        return result;
+        //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        for(GuardedExpression expression : expressions) {
+            for(Expression guard : expression.guards)
+                guard.collectFreeVariables(vars);
+            expression.value.collectFreeVariables(vars);
+        }
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        for(GuardedExpression expression : expressions) {
+            for(int i=0;i<expression.guards.length;++i)
+                expression.guards[i] = expression.guards[i].simplify(context);
+            expression.value = expression.value.simplify(context);
+        }
+        return this;
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        for(GuardedExpression expression : expressions) {
+            for(int i=0;i<expression.guards.length;++i)
+                expression.guards[i] = expression.guards[i].resolve(context);
+            expression.value = expression.value.resolve(context);
+        }
+        return this;
+    }
+    
+    @Override
+    public Expression checkBasicType(TypingContext context, Type requiredType) {
+        for(GuardedExpression expression : expressions) {
+            for(int i=0;i<expression.guards.length;++i)
+                expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);
+            expression.value = expression.value.checkType(context, requiredType);
+        }
+        return this;
+    }
+    
+    public void compile(Environment env, CodeWriter firstWriter, ICont success,
+            ICont lastFailure) {
+        // Create all code blocks
+        CodeWriter[] writers = new CodeWriter[expressions.length];                
+        ICont[] failures = new ICont[expressions.length];
+        writers[0] = firstWriter;
+        failures[expressions.length-1] = lastFailure;
+        for(int i=1;i<expressions.length;++i) {
+            CodeWriter writer = firstWriter.createBlock();
+            writers[i] = writer;
+            failures[i-1] = writer.getContinuation();
+        }
+        
+        // Compile
+        for(int i=0;i<expressions.length;++i) {
+            CodeWriter w = writers[i];
+            ICont failure = failures[i];
+            
+            for(Expression guard : expressions[i].guards) {
+                CodeWriter nextW = w.createBlock();
+                w.if_(guard.toVal(env, w), nextW.getContinuation(), failure);
+                w = nextW;
+            }
+            
+            w.jump(success, expressions[i].value.toVal(env, w));
+        }
+    }
+    
+    @Override
+    public Expression replace(ReplaceContext context) {
+        GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];
+        for(int i=0;i<expressions.length;++i)
+            newExpressions[i] = expressions[i].replace(context);
+        return new GuardedExpressionGroup(newExpressions);            
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        for(GuardedExpression expression : expressions)
+            expression.decorate(decorator);
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        for(GuardedExpression ge : expressions) {
+            for(Expression guard : ge.guards)
+                guard.collectEffects(effects);
+            ge.value.collectEffects(effects);
+        }
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(GuardedExpression expression : expressions)
+                expression.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        for(GuardedExpression expression : expressions)
+            expression.forVariables(procedure);
+    }
+
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public int getSyntacticFunctionArity() {
+        return expressions[0].value.getSyntacticFunctionArity();
+    }
+}
index 13e80fc6d62755e6d162d14536b74cff6e32e160..2287f919bbea59a99d55f123e46d107bff31e076 100644 (file)
@@ -61,4 +61,8 @@ public class ErrorLog {
     public String toString() {
         return getErrorsAsString();
     }
     public String toString() {
         return getErrorsAsString();
     }
+
+    public int getErrorCount() {
+        return errors.size();
+    }
 }
 }
index fa48e47c17efdce12aa2b8270c9fe9083ab96a23..fc21692fc583a83216bc23e3bee15fc9af2dcbe9 100644 (file)
@@ -1,9 +1,22 @@
-\r
-data Foo a = Foo a\r
-\r
-f :: Foo a -> a\r
-f = \Foo a -> a \r
-\r
-main = "Not to be executed"\r
---\r
-5:6-5:11: Arity is 1 but 2 patterns have been given.
\ No newline at end of file
+data Foo a = Foo a
+
+f :: Foo a -> a
+f = \Foo a -> a 
+
+main = "Not to be executed"
+--
+3:1-3:2: Possible problem: type declaration has 1 parameter types, but function definition has 2 parameters.
+4:6-4:11: Arity is 1 but 2 patterns have been given.
+--
+import "Prelude"
+
+f :: Integer -> Integer -> <Proc> Integer
+f x = do
+    print x
+    x
+
+main = "Not to be executed"
+--
+3:1-3:2: Possible problem: type declaration has 2 parameter types, but function definition has 1 parameters.
+5:5-5:12: No side-effects allowed here.
+6:5-6:6: Expected <Integer -> <Proc> Integer> got <Integer>.
\ No newline at end of file