]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EBinary.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
new file mode 100755 (executable)
index 0000000..e74dde7
--- /dev/null
@@ -0,0 +1,240 @@
+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.Name;\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
+    private static final Name NEG = Name.create("Prelude", "neg");\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(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(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