]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
Merged changes from feature/scl to master.
[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.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
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     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
54         \r
55         EVar negation = this.negation;\r
56         \r
57         output.add(left);\r
58         for(EBinaryRightSide right : rights) {\r
59             // Read op\r
60             Expression op = context.resolveExpression(right.operator.location, right.operator.name);\r
61             if(op == null)\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
67                 \r
68                 if(oldOpPrecedence.level < opPrec.level)\r
69                     break;\r
70                 if(oldOpPrecedence.level == opPrec.level) {\r
71                     if(opPrec.associativity == Associativity.RIGHT)\r
72                         break;\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
77                     }\r
78                 }\r
79                 \r
80                 // Pop op                \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
85             }\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
89                     if(neg == null) {\r
90                         context.getErrorLog().log(location, \r
91                                 "Couldn't resolve variable neg.");\r
92                         return new EError(location);\r
93                     }\r
94                     output.set(0, unary(neg, negation, output.get(0)));\r
95                     negation = null;\r
96                 }\r
97             }\r
98             ops.add(op);\r
99             opAsts.add(right.operator);\r
100             \r
101             // Read value\r
102             output.add(right.right);\r
103         }\r
104         \r
105         // Pop rest\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
111         }\r
112         if(negation != null) {\r
113             SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
114             if(neg == null) {\r
115                 context.getErrorLog().log(location, \r
116                         "Couldn't resolve variable neg.");\r
117                 return new EError(location);\r
118             }\r
119             output.set(0, unary(neg, negation, output.get(0)));\r
120         }\r
121         \r
122         return output.get(0);\r
123         \r
124         //System.out.println("parseOperators: " + this);\r
125         //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));\r
126     }\r
127 \r
128     /*\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
134             if(op == null) {\r
135                 context.getErrorLog().log(right.operator, \r
136                         "Couldn't resolve variable " + right.operator.name + ".");\r
137                 return lhs;\r
138             }\r
139             Precedence opPrec = op.getPrecedence();\r
140             if(minPrec.level > opPrec.level)\r
141                 break;\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
149                     return lhs;\r
150                 }\r
151                 it.previous();\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
156                         break;\r
157                     else if(opPrec.associativity == Associativity.NONASSOC) {\r
158                         context.getErrorLog().log(it.next().operator, "Nonassociative operator.");\r
159                         return lhs;\r
160                     }\r
161                 }\r
162                 else if(precDiff > 0)\r
163                     break;\r
164                 rhs = parse(context, rhs, it, nextPrec);\r
165             }\r
166             lhs = binary(lhs, op, right.operator, rhs);\r
167         }   \r
168         return lhs;\r
169     }\r
170     */\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
173     }\r
174     \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
178     }\r
179     \r
180     @Override\r
181     public EVar getPatternHead() throws NotPatternException {\r
182         if(rights.size() == 1)\r
183             return rights.get(0).operator;\r
184         else\r
185             throw new NotPatternException(this);\r
186     }\r
187     \r
188     @Override\r
189     public LhsType getLhsType() throws NotPatternException {\r
190         if(rights.size() == 1)\r
191             return new FunctionDefinitionLhs(rights.get(0).operator.name);\r
192         else\r
193             throw new InternalCompilerError();\r
194     }\r
195         \r
196     @Override\r
197     public void getParameters(TranslationContext context,\r
198             ArrayList<Expression> parameters) {\r
199         parseOperators(context).getParameters(context, parameters);\r
200     }\r
201 \r
202     public static Expression negate(EVar op, Expression expression) {\r
203         if(expression instanceof EBinary) {\r
204             ((EBinary)expression).negation = op;\r
205             return expression;\r
206         }\r
207         /*else if(expression instanceof EIntegerLiteral) {\r
208             EIntegerLiteral literal = (EIntegerLiteral)expression;\r
209             literal.value = -literal.value;\r
210             return expression;\r
211         }*/\r
212         else\r
213             return new EBinary(expression, op);\r
214     }\r
215     \r
216     @Override\r
217     public int getFunctionDefinitionArity() throws NotPatternException {\r
218         return 2;\r
219     }\r
220     \r
221     @Override\r
222     public void setLocationDeep(long loc) {\r
223         if(location == Locations.NO_LOCATION) {\r
224             location = loc;\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
230         }\r
231     }\r
232     \r
233     @Override\r
234     public Expression accept(ExpressionTransformer transformer) {\r
235         return transformer.transform(this);\r
236     }\r
237 \r
238 }\r