X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fexpressions%2FEBinary.java;h=274624aee0e08e97c22ad7c2f7c1ac1183c5d049;hb=e73c1660b2f4d2a03784451e9e6afe1552b00877;hp=58274a7a0269553521a840af33b5362faf6d8a70;hpb=4bf8562ab7cbb3747f9c5844a07469291d43e905;p=simantics%2Fplatform.git 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 index 58274a7a0..274624aee 100755 --- 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 @@ -1,238 +1,238 @@ -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 rights = new ArrayList(); - 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 output = new ArrayList(); - ArrayList ops = new ArrayList(); - ArrayList opAsts = new ArrayList(); - - 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 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 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 getFunctionDefinitionArity() 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); - } - -} +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 rights = new ArrayList(); + 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 output = new ArrayList(); + ArrayList ops = new ArrayList(); + ArrayList opAsts = new ArrayList(); + + 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 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 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); + } + +}