001: /*
002: * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.es.parser;
030:
031: import com.caucho.es.ESBase;
032: import com.caucho.es.ESException;
033: import com.caucho.es.ESNumber;
034: import com.caucho.es.ESWrapperException;
035:
036: import java.io.IOException;
037:
038: /**
039: * Expr is an intermediate form representing an expression.
040: */
041: class BinaryExpr extends Expr {
042: Expr left;
043: Expr right;
044: int op;
045: String temp;
046: boolean isSimple;
047:
048: protected BinaryExpr(Block block, Expr left, Expr right, int op) {
049: super (block);
050:
051: this .left = left;
052: this .right = right;
053: this .op = op;
054: isSimple = left.isSimple();
055: if ((op == Lexer.AND || op == Lexer.OR) && !isSimple)
056: temp = block.function.getTemp();
057: }
058:
059: static Expr create(Block block, Expr left, Expr right, int op)
060: throws ESException {
061: if (left != null)
062: left.setUsed();
063: if (right != null)
064: right.setUsed();
065:
066: if (!(left instanceof LiteralExpr)
067: || !(right instanceof LiteralExpr))
068: return new BinaryExpr(block, left, right, op);
069:
070: ESBase lvalue = ((LiteralExpr) left).getLiteral();
071: ESBase rvalue = ((LiteralExpr) right).getLiteral();
072: ESBase value;
073:
074: try {
075: switch (op) {
076: case '*':
077: value = ESNumber
078: .create(lvalue.toNum() * rvalue.toNum());
079: break;
080:
081: case '/':
082: value = ESNumber
083: .create(lvalue.toNum() / rvalue.toNum());
084: break;
085:
086: case '-':
087: value = ESNumber
088: .create(lvalue.toNum() - rvalue.toNum());
089: break;
090:
091: case '%':
092: value = ESNumber
093: .create(lvalue.toNum() % rvalue.toNum());
094: break;
095:
096: case Lexer.LSHIFT:
097: value = ESNumber.create(lvalue.toInt32() << rvalue
098: .toInt32());
099: break;
100:
101: case Lexer.RSHIFT:
102: value = ESNumber.create(lvalue.toInt32() >> rvalue
103: .toInt32());
104: break;
105:
106: case Lexer.URSHIFT:
107: value = ESNumber.create(lvalue.toInt32() >>> rvalue
108: .toInt32());
109: break;
110:
111: case '&':
112: value = ESNumber.create(lvalue.toInt32()
113: & rvalue.toInt32());
114: break;
115:
116: case '|':
117: value = ESNumber.create(lvalue.toInt32()
118: | rvalue.toInt32());
119: break;
120:
121: case '^':
122: value = ESNumber.create(lvalue.toInt32()
123: ^ rvalue.toInt32());
124: break;
125:
126: case Lexer.AND:
127: value = lvalue.toBoolean() ? rvalue : lvalue;
128: break;
129:
130: case Lexer.OR:
131: value = lvalue.toBoolean() ? lvalue : rvalue;
132: break;
133:
134: case ',':
135: value = rvalue;
136: break;
137:
138: default:
139: throw new RuntimeException("" + (char) op);
140: }
141: } catch (Throwable e) {
142: throw new ESWrapperException(e);
143: }
144:
145: return new LiteralExpr(block, value);
146: }
147:
148: int getType() {
149:
150: switch (op) {
151: case '*':
152: case '/':
153: case '%':
154: return TYPE_NUMBER;
155:
156: case '-':
157: if (left.getType() == TYPE_INTEGER
158: && right.getType() == TYPE_INTEGER)
159: return TYPE_INTEGER;
160: else
161: return TYPE_NUMBER;
162:
163: case Lexer.LSHIFT:
164: case Lexer.RSHIFT:
165: case Lexer.URSHIFT:
166: case '&':
167: case '|':
168: case '^':
169: return TYPE_INTEGER;
170:
171: case Lexer.AND:
172: case Lexer.OR:
173: if (left.getType() == right.getType())
174: return left.getType();
175: else if (left.isNum() && right.isNum())
176: return TYPE_NUMBER;
177: else
178: return TYPE_ES;
179:
180: case ',':
181: return TYPE_ES;
182:
183: default:
184: throw new RuntimeException("" + (char) op + " " + op);
185: }
186: }
187:
188: void exprStatement(Function fun) throws ESException {
189: switch (op) {
190: default:
191: left.exprStatement(fun);
192: right.exprStatement(fun);
193: break;
194: }
195: }
196:
197: void printNumImpl() throws IOException {
198: cl.print("(");
199:
200: switch (op) {
201: case '*':
202: case '/':
203: case '-':
204: case '%':
205: left.printNum();
206: cl.print(" " + (char) op + " ");
207: right.printNum();
208: break;
209:
210: case Lexer.AND:
211: if (isSimple) {
212: left.printBoolean();
213: cl.print(" ? ");
214: right.printNum();
215: cl.print(":");
216: left.printNum();
217: } else {
218: cl.print("(" + temp + " = ");
219: left.print();
220: cl.print(").toBoolean() ? ");
221: right.printNum();
222: cl.print(":" + temp + ".toNum()");
223: }
224: break;
225:
226: case Lexer.OR:
227: if (isSimple) {
228: left.printBoolean();
229: cl.print(" ? ");
230: left.printNum();
231: cl.print(":");
232: right.printNum();
233: } else {
234: cl.print("(" + temp + " = ");
235: left.print();
236: cl.print(").toBoolean() ? " + temp + ".toNum() : ");
237: right.printNum();
238: }
239: break;
240:
241: default:
242: throw new IOException("foo");
243: }
244:
245: cl.print(")");
246: }
247:
248: void printInt32Impl() throws IOException {
249: cl.print("(");
250:
251: switch (op) {
252: case '-':
253: left.printInt32();
254: cl.print(" " + (char) op + " ");
255: right.printInt32();
256: break;
257:
258: case Lexer.LSHIFT:
259: left.printInt32();
260: cl.print(" << ");
261: right.printInt32();
262: break;
263:
264: case Lexer.RSHIFT:
265: left.printInt32();
266: cl.print(" >> ");
267: right.printInt32();
268: break;
269:
270: case Lexer.URSHIFT:
271: left.printInt32();
272: cl.print(" >>> ");
273: right.printInt32();
274: break;
275:
276: case '&':
277: case '|':
278: case '^':
279: left.printInt32();
280: cl.print(" " + (char) op + " ");
281: right.printInt32();
282: break;
283:
284: case Lexer.AND:
285: if (isSimple) {
286: left.printBoolean();
287: cl.print(" ? ");
288: right.printInt32();
289: cl.print(":");
290: left.printInt32();
291: } else {
292: cl.print("(" + temp + " = ");
293: left.print();
294: cl.print(").toBoolean() ? ");
295: right.printInt32();
296: cl.print(":" + temp + ".toInt32()");
297: }
298: break;
299:
300: case Lexer.OR:
301: if (isSimple) {
302: left.printBoolean();
303: cl.print(" ? ");
304: left.printInt32();
305: cl.print(":");
306: right.printInt32();
307: } else {
308: cl.print("(" + temp + " = ");
309: left.print();
310: cl.print(").toBoolean() ? " + temp + ".toInt32() : ");
311: right.printInt32();
312: }
313: break;
314:
315: default:
316: throw new IOException("foo");
317: }
318:
319: cl.print(")");
320: }
321:
322: void printBoolean() throws IOException {
323: switch (op) {
324: case Lexer.AND:
325: cl.print("(");
326: left.printBoolean();
327: cl.print(" && ");
328: right.printBoolean();
329: cl.print(")");
330: break;
331:
332: case Lexer.OR:
333: cl.print("(");
334: left.printBoolean();
335: cl.print(" || ");
336: right.printBoolean();
337: cl.print(")");
338: break;
339:
340: default:
341: super .printBoolean();
342: }
343: }
344:
345: void printBooleanImpl() throws IOException {
346: cl.print("(");
347:
348: switch (op) {
349: case Lexer.AND:
350: left.printBoolean();
351: cl.print(" && ");
352: right.printBoolean();
353: break;
354:
355: case Lexer.OR:
356: left.printBoolean();
357: cl.print(" || ");
358: right.printBoolean();
359: break;
360:
361: default:
362: throw new IOException("foo");
363: }
364:
365: cl.print(")");
366: }
367:
368: void printImpl() throws IOException {
369: switch (op) {
370: case Lexer.AND:
371: if (isSimple) {
372: left.printBoolean();
373: cl.print(" ? ");
374: right.print();
375: cl.print(":");
376: left.print();
377: } else {
378: cl.print("((" + temp + " = ");
379: left.print();
380: cl.print(").toBoolean() ? ");
381: right.print();
382: cl.print(":" + temp + ")");
383: }
384: break;
385:
386: case Lexer.OR:
387: if (isSimple) {
388: left.printBoolean();
389: cl.print(" ? ");
390: left.print();
391: cl.print(":");
392: right.print();
393: } else {
394: cl.print("((" + temp + " = ");
395: left.print();
396: cl.print(").toBoolean() ? " + temp + " : ");
397: right.print();
398: cl.print(")");
399: }
400: break;
401:
402: case ',':
403: cl.print("_env.comma(");
404: left.print();
405: cl.print(", ");
406: right.print();
407: cl.print(")");
408: break;
409:
410: default:
411: throw new IOException("foo");
412: }
413: }
414: }
|