]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
Added info on backup location to documentation backup.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EBinary.java
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import java.util.ArrayList;\r
4 \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
15 \r
16 \r
17 \r
18 public class EBinary extends ASTExpression {\r
19     public static final int NEGATION_LEVEL = 6;\r
20     \r
21     public Expression left;\r
22     public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();\r
23     public EVar negation;\r
24 \r
25     public EBinary(Expression left, EVar negation) {\r
26         this.left = left;\r
27         this.negation = negation;\r
28     }\r
29 \r
30     private EBinary(Expression left, EVar operator, Expression right) {\r
31         this.left = left;\r
32         rights.add(new EBinaryRightSide(operator, right));\r
33     }\r
34 \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
39             return left_;\r
40         }\r
41         else\r
42             return new EBinary(left, operator, right);\r
43     }\r
44 \r
45     @Override\r
46     public Expression resolve(TranslationContext context) {\r
47         return parseOperators(context).resolve(context);\r
48     }\r
49 \r
50     private static final Name NEG = Name.create("Prelude", "neg");\r
51     \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
56         \r
57         EVar negation = this.negation;\r
58         \r
59         output.add(left);\r
60         for(EBinaryRightSide right : rights) {\r
61             // Read op\r
62             Expression op = context.resolveExpression(right.operator.location, right.operator.name);\r
63             if(op == null)\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
69                 \r
70                 if(oldOpPrecedence.level < opPrec.level)\r
71                     break;\r
72                 if(oldOpPrecedence.level == opPrec.level) {\r
73                     if(opPrec.associativity == Associativity.RIGHT)\r
74                         break;\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
79                     }\r
80                 }\r
81                 \r
82                 // Pop op                \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
87             }\r
88             if(negation != null && ops.isEmpty()) {\r
89                 if(opPrec.level <= NEGATION_LEVEL) {      \r
90                     SCLValue neg = context.getEnvironment().getValue(NEG);\r
91                     if(neg == null) {\r
92                         context.getErrorLog().log(location, \r
93                                 "Couldn't resolve variable neg.");\r
94                         return new EError(location);\r
95                     }\r
96                     output.set(0, unary(neg, negation, output.get(0)));\r
97                     negation = null;\r
98                 }\r
99             }\r
100             ops.add(op);\r
101             opAsts.add(right.operator);\r
102             \r
103             // Read value\r
104             output.add(right.right);\r
105         }\r
106         \r
107         // Pop rest\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
113         }\r
114         if(negation != null) {\r
115             SCLValue neg = context.getEnvironment().getValue(NEG);\r
116             if(neg == null) {\r
117                 context.getErrorLog().log(location, \r
118                         "Couldn't resolve variable neg.");\r
119                 return new EError(location);\r
120             }\r
121             output.set(0, unary(neg, negation, output.get(0)));\r
122         }\r
123         \r
124         return output.get(0);\r
125         \r
126         //System.out.println("parseOperators: " + this);\r
127         //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));\r
128     }\r
129 \r
130     /*\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
136             if(op == null) {\r
137                 context.getErrorLog().log(right.operator, \r
138                         "Couldn't resolve variable " + right.operator.name + ".");\r
139                 return lhs;\r
140             }\r
141             Precedence opPrec = op.getPrecedence();\r
142             if(minPrec.level > opPrec.level)\r
143                 break;\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
151                     return lhs;\r
152                 }\r
153                 it.previous();\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
158                         break;\r
159                     else if(opPrec.associativity == Associativity.NONASSOC) {\r
160                         context.getErrorLog().log(it.next().operator, "Nonassociative operator.");\r
161                         return lhs;\r
162                     }\r
163                 }\r
164                 else if(precDiff > 0)\r
165                     break;\r
166                 rhs = parse(context, rhs, it, nextPrec);\r
167             }\r
168             lhs = binary(lhs, op, right.operator, rhs);\r
169         }   \r
170         return lhs;\r
171     }\r
172     */\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
175     }\r
176     \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
180     }\r
181     \r
182     @Override\r
183     public EVar getPatternHead() throws NotPatternException {\r
184         if(rights.size() == 1)\r
185             return rights.get(0).operator;\r
186         else\r
187             throw new NotPatternException(this);\r
188     }\r
189     \r
190     @Override\r
191     public LhsType getLhsType() throws NotPatternException {\r
192         if(rights.size() == 1)\r
193             return new FunctionDefinitionLhs(rights.get(0).operator.name);\r
194         else\r
195             throw new InternalCompilerError();\r
196     }\r
197         \r
198     @Override\r
199     public void getParameters(TranslationContext context,\r
200             ArrayList<Expression> parameters) {\r
201         parseOperators(context).getParameters(context, parameters);\r
202     }\r
203 \r
204     public static Expression negate(EVar op, Expression expression) {\r
205         if(expression instanceof EBinary) {\r
206             ((EBinary)expression).negation = op;\r
207             return expression;\r
208         }\r
209         /*else if(expression instanceof EIntegerLiteral) {\r
210             EIntegerLiteral literal = (EIntegerLiteral)expression;\r
211             literal.value = -literal.value;\r
212             return expression;\r
213         }*/\r
214         else\r
215             return new EBinary(expression, op);\r
216     }\r
217     \r
218     @Override\r
219     public int getFunctionDefinitionArity() throws NotPatternException {\r
220         return 2;\r
221     }\r
222     \r
223     @Override\r
224     public void setLocationDeep(long loc) {\r
225         if(location == Locations.NO_LOCATION) {\r
226             location = loc;\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
232         }\r
233     }\r
234     \r
235     @Override\r
236     public Expression accept(ExpressionTransformer transformer) {\r
237         return transformer.transform(this);\r
238     }\r
239 \r
240 }\r