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.Name;
\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 private static final Name NEG = Name.create("Prelude", "neg");
\r
52 public Expression parseOperators(TranslationContext context) {
\r
53 ArrayList<Expression> output = new ArrayList<Expression>();
\r
54 ArrayList<Expression> ops = new ArrayList<Expression>();
\r
55 ArrayList<EVar> opAsts = new ArrayList<EVar>();
\r
57 EVar negation = this.negation;
\r
60 for(EBinaryRightSide right : rights) {
\r
62 Expression op = context.resolveExpression(right.operator.location, right.operator.name);
\r
64 return new EError(location);
\r
65 Precedence opPrec = op.getPrecedence();
\r
66 while(!ops.isEmpty()) {
\r
67 Expression oldOp = ops.get(ops.size()-1);
\r
68 Precedence oldOpPrecedence = oldOp.getPrecedence();
\r
70 if(oldOpPrecedence.level < opPrec.level)
\r
72 if(oldOpPrecedence.level == opPrec.level) {
\r
73 if(opPrec.associativity == Associativity.RIGHT)
\r
75 if(opPrec.associativity == Associativity.NONASSOC) {
\r
76 context.getErrorLog().log(right.operator.location,
\r
77 "Operator " + right.operator.name + " is not associative.");
\r
78 return new EError(location);
\r
83 ops.remove(ops.size()-1);
\r
84 Expression r = output.remove(output.size()-1);
\r
85 Expression l = output.remove(output.size()-1);
\r
86 output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
\r
88 if(negation != null && ops.isEmpty()) {
\r
89 if(opPrec.level <= NEGATION_LEVEL) {
\r
90 SCLValue neg = context.getEnvironment().getValue(NEG);
\r
92 context.getErrorLog().log(location,
\r
93 "Couldn't resolve variable neg.");
\r
94 return new EError(location);
\r
96 output.set(0, unary(neg, negation, output.get(0)));
\r
101 opAsts.add(right.operator);
\r
104 output.add(right.right);
\r
108 while(!ops.isEmpty()) {
\r
109 Expression oldOp = ops.remove(ops.size()-1);
\r
110 Expression r = output.remove(output.size()-1);
\r
111 Expression l = output.remove(output.size()-1);
\r
112 output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
\r
114 if(negation != null) {
\r
115 SCLValue neg = context.getEnvironment().getValue(NEG);
\r
117 context.getErrorLog().log(location,
\r
118 "Couldn't resolve variable neg.");
\r
119 return new EError(location);
\r
121 output.set(0, unary(neg, negation, output.get(0)));
\r
124 return output.get(0);
\r
126 //System.out.println("parseOperators: " + this);
\r
127 //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));
\r
131 private Expression parse(TranslationContext context,
\r
132 Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {
\r
133 while(it.hasNext()) {
\r
134 EBinaryRightSide right = it.next();
\r
135 SCLValue op = context.resolveValue(right.operator.name);
\r
137 context.getErrorLog().log(right.operator,
\r
138 "Couldn't resolve variable " + right.operator.name + ".");
\r
141 Precedence opPrec = op.getPrecedence();
\r
142 if(minPrec.level > opPrec.level)
\r
144 Expression rhs = right.right;
\r
145 while(it.hasNext()) {
\r
146 EVar var = it.next().operator;
\r
147 SCLValue nextOp = context.resolveValue(var.name);
\r
148 if(nextOp == null) {
\r
149 context.getErrorLog().log(var,
\r
150 "Couldn't resolve variable " + var.name + ".");
\r
154 Precedence nextPrec = nextOp.getPrecedence();
\r
155 int precDiff = opPrec.level - nextPrec.level;
\r
156 if(precDiff == 0) {
\r
157 if(opPrec.associativity == Associativity.LEFT)
\r
159 else if(opPrec.associativity == Associativity.NONASSOC) {
\r
160 context.getErrorLog().log(it.next().operator, "Nonassociative operator.");
\r
164 else if(precDiff > 0)
\r
166 rhs = parse(context, rhs, it, nextPrec);
\r
168 lhs = binary(lhs, op, right.operator, rhs);
\r
173 private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {
\r
174 return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs);
\r
177 private Expression unary(SCLValue operator, EVar opAst, Expression expression) {
\r
178 EConstant op = new EConstant(opAst.location, operator);
\r
179 return new EApply(expression.location /*wrong*/, op, expression);
\r
183 public EVar getPatternHead() throws NotPatternException {
\r
184 if(rights.size() == 1)
\r
185 return rights.get(0).operator;
\r
187 throw new NotPatternException(this);
\r
191 public LhsType getLhsType() throws NotPatternException {
\r
192 if(rights.size() == 1)
\r
193 return new FunctionDefinitionLhs(rights.get(0).operator.name);
\r
195 throw new InternalCompilerError();
\r
199 public void getParameters(TranslationContext context,
\r
200 ArrayList<Expression> parameters) {
\r
201 parseOperators(context).getParameters(context, parameters);
\r
204 public static Expression negate(EVar op, Expression expression) {
\r
205 if(expression instanceof EBinary) {
\r
206 ((EBinary)expression).negation = op;
\r
209 /*else if(expression instanceof EIntegerLiteral) {
\r
210 EIntegerLiteral literal = (EIntegerLiteral)expression;
\r
211 literal.value = -literal.value;
\r
215 return new EBinary(expression, op);
\r
219 public int getFunctionDefinitionArity() throws NotPatternException {
\r
224 public void setLocationDeep(long loc) {
\r
225 if(location == Locations.NO_LOCATION) {
\r
227 left.setLocationDeep(loc);
\r
228 if(negation != null)
\r
229 negation.setLocationDeep(loc);
\r
230 for(EBinaryRightSide right : rights)
\r
231 right.setLocationDeep(loc);
\r
236 public Expression accept(ExpressionTransformer transformer) {
\r
237 return transformer.transform(this);
\r