1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import java.util.ArrayList;
\r
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
6 import org.simantics.scl.compiler.common.names.Names;
\r
7 import org.simantics.scl.compiler.common.precedence.Associativity;
\r
8 import org.simantics.scl.compiler.common.precedence.Precedence;
\r
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
10 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
\r
11 import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
\r
12 import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
\r
13 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
\r
14 import org.simantics.scl.compiler.errors.Locations;
\r
18 public class EBinary extends ASTExpression {
\r
19 public static final int NEGATION_LEVEL = 6;
\r
21 public Expression left;
\r
22 public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();
\r
23 public EVar negation;
\r
25 public EBinary(Expression left, EVar negation) {
\r
27 this.negation = negation;
\r
30 private EBinary(Expression left, EVar operator, Expression right) {
\r
32 rights.add(new EBinaryRightSide(operator, right));
\r
35 public static EBinary create(Expression left, EVar operator, Expression right) {
\r
36 if(left instanceof EBinary) {
\r
37 EBinary left_ = (EBinary)left;
\r
38 left_.rights.add(new EBinaryRightSide(operator, right));
\r
42 return new EBinary(left, operator, right);
\r
46 public Expression resolve(TranslationContext context) {
\r
47 return parseOperators(context).resolve(context);
\r
50 public Expression parseOperators(TranslationContext context) {
\r
51 ArrayList<Expression> output = new ArrayList<Expression>();
\r
52 ArrayList<Expression> ops = new ArrayList<Expression>();
\r
53 ArrayList<EVar> opAsts = new ArrayList<EVar>();
\r
55 EVar negation = this.negation;
\r
58 for(EBinaryRightSide right : rights) {
\r
60 Expression op = context.resolveExpression(right.operator.location, right.operator.name);
\r
62 return new EError(location);
\r
63 Precedence opPrec = op.getPrecedence();
\r
64 while(!ops.isEmpty()) {
\r
65 Expression oldOp = ops.get(ops.size()-1);
\r
66 Precedence oldOpPrecedence = oldOp.getPrecedence();
\r
68 if(oldOpPrecedence.level < opPrec.level)
\r
70 if(oldOpPrecedence.level == opPrec.level) {
\r
71 if(opPrec.associativity == Associativity.RIGHT)
\r
73 if(opPrec.associativity == Associativity.NONASSOC) {
\r
74 context.getErrorLog().log(right.operator.location,
\r
75 "Operator " + right.operator.name + " is not associative.");
\r
76 return new EError(location);
\r
81 ops.remove(ops.size()-1);
\r
82 Expression r = output.remove(output.size()-1);
\r
83 Expression l = output.remove(output.size()-1);
\r
84 output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
\r
86 if(negation != null && ops.isEmpty()) {
\r
87 if(opPrec.level <= NEGATION_LEVEL) {
\r
88 SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
\r
90 context.getErrorLog().log(location,
\r
91 "Couldn't resolve variable neg.");
\r
92 return new EError(location);
\r
94 output.set(0, unary(neg, negation, output.get(0)));
\r
99 opAsts.add(right.operator);
\r
102 output.add(right.right);
\r
106 while(!ops.isEmpty()) {
\r
107 Expression oldOp = ops.remove(ops.size()-1);
\r
108 Expression r = output.remove(output.size()-1);
\r
109 Expression l = output.remove(output.size()-1);
\r
110 output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
\r
112 if(negation != null) {
\r
113 SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
\r
115 context.getErrorLog().log(location,
\r
116 "Couldn't resolve variable neg.");
\r
117 return new EError(location);
\r
119 output.set(0, unary(neg, negation, output.get(0)));
\r
122 return output.get(0);
\r
124 //System.out.println("parseOperators: " + this);
\r
125 //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));
\r
129 private Expression parse(TranslationContext context,
\r
130 Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {
\r
131 while(it.hasNext()) {
\r
132 EBinaryRightSide right = it.next();
\r
133 SCLValue op = context.resolveValue(right.operator.name);
\r
135 context.getErrorLog().log(right.operator,
\r
136 "Couldn't resolve variable " + right.operator.name + ".");
\r
139 Precedence opPrec = op.getPrecedence();
\r
140 if(minPrec.level > opPrec.level)
\r
142 Expression rhs = right.right;
\r
143 while(it.hasNext()) {
\r
144 EVar var = it.next().operator;
\r
145 SCLValue nextOp = context.resolveValue(var.name);
\r
146 if(nextOp == null) {
\r
147 context.getErrorLog().log(var,
\r
148 "Couldn't resolve variable " + var.name + ".");
\r
152 Precedence nextPrec = nextOp.getPrecedence();
\r
153 int precDiff = opPrec.level - nextPrec.level;
\r
154 if(precDiff == 0) {
\r
155 if(opPrec.associativity == Associativity.LEFT)
\r
157 else if(opPrec.associativity == Associativity.NONASSOC) {
\r
158 context.getErrorLog().log(it.next().operator, "Nonassociative operator.");
\r
162 else if(precDiff > 0)
\r
164 rhs = parse(context, rhs, it, nextPrec);
\r
166 lhs = binary(lhs, op, right.operator, rhs);
\r
171 private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {
\r
172 return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs);
\r
175 private Expression unary(SCLValue operator, EVar opAst, Expression expression) {
\r
176 EConstant op = new EConstant(opAst.location, operator);
\r
177 return new EApply(expression.location /*wrong*/, op, expression);
\r
181 public EVar getPatternHead() throws NotPatternException {
\r
182 if(rights.size() == 1)
\r
183 return rights.get(0).operator;
\r
185 throw new NotPatternException(this);
\r
189 public LhsType getLhsType() throws NotPatternException {
\r
190 if(rights.size() == 1)
\r
191 return new FunctionDefinitionLhs(rights.get(0).operator.name);
\r
193 throw new InternalCompilerError();
\r
197 public void getParameters(TranslationContext context,
\r
198 ArrayList<Expression> parameters) {
\r
199 parseOperators(context).getParameters(context, parameters);
\r
202 public static Expression negate(EVar op, Expression expression) {
\r
203 if(expression instanceof EBinary) {
\r
204 ((EBinary)expression).negation = op;
\r
207 /*else if(expression instanceof EIntegerLiteral) {
\r
208 EIntegerLiteral literal = (EIntegerLiteral)expression;
\r
209 literal.value = -literal.value;
\r
213 return new EBinary(expression, op);
\r
217 public int getFunctionDefinitionArity() throws NotPatternException {
\r
222 public void setLocationDeep(long loc) {
\r
223 if(location == Locations.NO_LOCATION) {
\r
225 left.setLocationDeep(loc);
\r
226 if(negation != null)
\r
227 negation.setLocationDeep(loc);
\r
228 for(EBinaryRightSide right : rights)
\r
229 right.setLocationDeep(loc);
\r
234 public Expression accept(ExpressionTransformer transformer) {
\r
235 return transformer.transform(this);
\r