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