KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > es > parser > Expr


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.es.parser;
30
31 import com.caucho.es.ESBase;
32 import com.caucho.es.ESBoolean;
33 import com.caucho.es.ESException;
34 import com.caucho.es.ESId;
35 import com.caucho.es.ESNumber;
36
37 import java.io.IOException JavaDoc;
38
39 /**
40  * Expr is an intermediate form representing an expression.
41  */

42 class Expr {
43   protected final static int TYPE_UNKNOWN = 0;
44   protected final static int TYPE_ES = TYPE_UNKNOWN + 1;
45   protected final static int TYPE_STRING = TYPE_ES + 1;
46   protected final static int TYPE_NUMBER = TYPE_STRING + 1;
47   protected final static int TYPE_LONG = TYPE_NUMBER;
48   protected final static int TYPE_INTEGER = TYPE_LONG + 1;
49   protected final static int TYPE_BOOLEAN = TYPE_INTEGER + 1;
50   
51   protected final static int TYPE_JAVA = TYPE_BOOLEAN + 1;
52   protected final static int TYPE_VOID = TYPE_JAVA + 1;
53
54   protected ParseClass cl;
55   protected Block block;
56   protected Function function;
57   protected int type;
58   protected Class JavaDoc javaType;
59   protected boolean isTop;
60   protected boolean noValue;
61   
62   private String JavaDoc filename;
63   private int line;
64   protected int withDepth;
65
66   Expr(Block block)
67   {
68     this.block = block;
69     this.withDepth = block.getWithDepth();
70     this.function = block.function;
71     this.cl = function.cl;
72     this.filename = block.getFilename();
73     this.line = block.getLine();
74
75     type = TYPE_UNKNOWN;
76   }
77
78   String JavaDoc getFilename()
79   {
80     return filename;
81   }
82
83   int getLine()
84   {
85     return line;
86   }
87
88   void killValue()
89   {
90     noValue = true;
91   }
92
93   void setUsed()
94   {
95     getType();
96   }
97
98   void setTop()
99   {
100     noValue = true;
101     isTop = true;
102   }
103
104   /**
105    * Returns the javascript type of the expression.
106    */

107   int getType()
108   {
109     return type;
110   }
111
112   Expr getTypeExpr()
113   {
114     return null;
115   }
116
117   /**
118    * Returns the Java class representing this type.
119    */

120   Class JavaDoc getJavaClass()
121   {
122     if (javaType != null)
123       return javaType;
124     
125     Expr type = getTypeExpr();
126
127     if (! (type instanceof TypeExpr)) {
128       switch (getType()) {
129       case TYPE_STRING:
130         return String JavaDoc.class;
131
132       case TYPE_INTEGER:
133         return int.class;
134
135       case TYPE_NUMBER:
136         return double.class;
137
138       case TYPE_BOOLEAN:
139         return boolean.class;
140
141       default:
142         return ESBase.class;
143       }
144     }
145
146     TypeExpr javaType = (TypeExpr) type;
147
148     return javaType.getJavaClass();
149   }
150
151   boolean isSimple()
152   {
153     return false;
154   }
155
156   /**
157    * True if the type of this expression is easily converted to a number.
158    */

159   boolean isNumeric()
160   {
161     int type = getType();
162     
163     return type >= TYPE_NUMBER && type <= TYPE_BOOLEAN;
164   }
165
166   boolean isNum()
167   {
168     int type = getType();
169     
170     return type == TYPE_NUMBER || type == TYPE_INTEGER;
171   }
172
173   /**
174    * This expression will be used in a boolean context.
175    */

176   Expr setBoolean()
177   {
178     return new BooleanExpr(block, this);
179   }
180   
181   Expr next(String JavaDoc iter, Expr lhs) throws ESException
182   {
183     return lhs.assign(new SpecialExpr(block, SpecialExpr.NEXT, iter));
184   }
185
186   /**
187    * Gets the field of the current expr
188    */

189   Expr fieldReference(Expr expr)
190   {
191     return new FieldExpr(block, this, expr);
192   }
193
194   /**
195    * Gets the field of the current expr
196    */

197   Expr fieldReference(ESId id)
198     throws ESException
199   {
200     return new FieldExpr(block, this, new LiteralExpr(block, id));
201   }
202   
203   /**
204    * A unary op
205    */

206   Expr unaryOp(int op)
207   {
208     return new UnaryExpr(block, this, op);
209   }
210   
211   /**
212    * A unary op
213    */

214   Expr doVoid()
215   {
216     return new UnaryExpr(block, this, 'v');
217   }
218   
219   /**
220    * The typeof operator
221    */

222   Expr typeof()
223   {
224     return new UnaryExpr(block, this, 't');
225   }
226   
227   /**
228    * The delete operator
229    */

230   Expr delete()
231     throws ESException
232   {
233     return BinaryExpr.create(block, this,
234                              new LiteralExpr(block, ESBoolean.TRUE),
235                              ',');
236   }
237
238   /**
239    * The assignment operator
240    */

241   Expr assign(Expr value)
242     throws ESException
243   {
244     throw error("illegal left-hand-side of assignment");
245   }
246
247   CallExpr startCall()
248     throws ESException
249   {
250     return new CallExpr(block, this, null, false);
251   }
252
253   CallExpr startNew()
254     throws ESException
255   {
256     return new CallExpr(block, this, null, true);
257   }
258   
259   /**
260    * Handle autoincrement
261    */

262   Expr prefix(int op)
263     throws ESException
264   {
265     return unaryOp('+').binaryOp(op, op,
266                                  new LiteralExpr(block, ESNumber.create(1.0)));
267   }
268   
269   /**
270    * Handle autoincrement
271    */

272   Expr postfix(int op)
273   {
274     return unaryOp('+');
275   }
276   
277   /**
278    * A binary op
279    */

280   Expr binaryOp(int lex, int op, Expr rexpr)
281     throws ESException
282   {
283     setUsed();
284     rexpr.setUsed();
285     
286     if (lex != '=') {
287       switch (op) {
288       case '<':
289       case '>':
290       case Lexer.LEQ:
291       case Lexer.GEQ:
292       case Lexer.EQ:
293       case Lexer.NEQ:
294       case Lexer.STRICT_EQ:
295       case Lexer.STRICT_NEQ:
296         return BooleanBinaryExpr.create(block, this, rexpr, op);
297         
298       case '+':
299         return PlusExpr.create(block, this, rexpr);
300         
301       default:
302         return BinaryExpr.create(block, this, rexpr, op);
303       }
304     }
305     else if (op == '=')
306       return assign(rexpr);
307
308     else
309       return assign(binaryOp(op, op, rexpr));
310   }
311
312   Expr cast(Expr castType)
313     throws ESException
314   {
315     return CastExpr.create(block, this, (TypeExpr) castType);
316   }
317         
318   /**
319    * The conditional ? : operation
320    */

321   Expr conditional(Expr mexpr, Expr rexpr)
322   {
323     return new ConditionalExpr(block, this, mexpr, rexpr);
324   }
325
326   void printExpr() throws IOException JavaDoc
327   {
328     print();
329   }
330
331   void print() throws IOException JavaDoc
332   {
333     if (ESBase.class.isAssignableFrom(getJavaClass()) ||
334         this instanceof LiteralExpr) {
335       printImpl();
336
337       if (isTop)
338         cl.println(";");
339       return;
340     }
341     
342     switch (getType()) {
343     case TYPE_NUMBER:
344       if (! noValue)
345         cl.print("ESNumber.create(");
346       printNumImpl();
347       if (! noValue)
348         cl.print(")");
349       break;
350       
351     case TYPE_INTEGER:
352       if (! noValue)
353         cl.print("ESNumber.create(");
354       printInt32Impl();
355       if (! noValue)
356         cl.print(")");
357       break;
358       
359     case TYPE_BOOLEAN:
360       if (! noValue)
361         cl.print("(");
362       printBooleanImpl();
363       if (! noValue)
364         cl.print("?ESBoolean.TRUE:ESBoolean.FALSE)");
365       break;
366
367     case TYPE_STRING:
368       if (ESBase.class.isAssignableFrom(getJavaClass()))
369         printImpl();
370       else {
371         if (! noValue)
372           cl.print("ESString.create(");
373         printStringImpl();
374         if (! noValue)
375           cl.print(")");
376       }
377       break;
378
379     case TYPE_JAVA:
380       if (! noValue)
381         cl.print("_env.wrap(");
382       printJavaImpl();
383       if (! noValue)
384         cl.print(")");
385       break;
386
387     case TYPE_VOID:
388       if (! noValue)
389         cl.print("_env.wrap(");
390       printJavaImpl();
391       if (! noValue)
392         cl.print(")");
393       break;
394
395     default:
396       printImpl();
397     }
398
399     if (isTop)
400       cl.println(";");
401   }
402
403   void printBoolean() throws IOException JavaDoc
404   {
405     switch (getType()) {
406     case TYPE_NUMBER:
407       cl.print("(");
408       printNumImpl();
409       cl.print("!=0.0)");
410       break;
411       
412     case TYPE_INTEGER:
413       cl.print("(");
414       printInt32Impl();
415       cl.print("!=0)");
416       break;
417       
418     case TYPE_BOOLEAN:
419       printBooleanImpl();
420       break;
421
422     case TYPE_JAVA:
423       cl.print("(");
424       printJava();
425       cl.print("!=null)");
426       break;
427       
428     default:
429       print();
430       cl.print(".toBoolean()");
431     }
432     
433     if (isTop)
434       cl.println(";");
435   }
436
437   void printInt32() throws IOException JavaDoc
438   {
439     switch (getType()) {
440     case TYPE_INTEGER:
441       printInt32Impl();
442       break;
443       
444     case TYPE_NUMBER:
445       cl.print("((int)");
446       printNumImpl();
447       cl.print(")");
448       break;
449       
450     case TYPE_BOOLEAN:
451       cl.print("(");
452       printBooleanImpl();
453       cl.print("?1:0)");
454       break;
455       
456     default:
457       printImpl();
458       cl.print(".toInt32()");
459     }
460   }
461   
462   void printInt64() throws IOException JavaDoc
463   {
464     printInt32();
465   }
466
467   void printNum() throws IOException JavaDoc
468   {
469     switch (getType()) {
470     case TYPE_NUMBER:
471       printNumImpl();
472       break;
473       
474     case TYPE_INTEGER:
475       cl.print("((double)");
476       printInt32Impl();
477       cl.print(")");
478       break;
479       
480     case TYPE_BOOLEAN:
481       cl.print("(");
482       printBooleanImpl();
483       cl.print("?1.0:0.0)");
484       break;
485       
486     default:
487       printImpl();
488       cl.print(".toNum()");
489     }
490   }
491
492   /**
493    * Prints the expression as a java object.
494    */

495   void printJava() throws IOException JavaDoc
496   {
497     switch (getType()) {
498     case TYPE_INTEGER:
499       printInt32Impl();
500       break;
501
502     case TYPE_BOOLEAN:
503       printBooleanImpl();
504       break;
505
506     case TYPE_STRING:
507       printStringImpl();
508       break;
509
510     case TYPE_NUMBER:
511       printNumImpl();
512       break;
513
514     case TYPE_JAVA:
515       printJavaImpl();
516       break;
517       
518     default:
519       print();
520       cl.print(".toJavaObject()");
521       break;
522     }
523   }
524
525   /**
526    * Prints a string value
527    */

528   void printStr() throws IOException JavaDoc
529   {
530     print();
531     cl.print(".toStr()");
532   }
533
534   void printJavaString() throws IOException JavaDoc
535   {
536     switch (getType()) {
537     case TYPE_STRING:
538       if (this instanceof LiteralExpr) {
539         printStringImpl();
540       }
541       else {
542         cl.print("String.valueOf(");
543         printStringImpl();
544         cl.print(")");
545       }
546       break;
547
548     case TYPE_JAVA:
549       if (getJavaClass().equals(String JavaDoc.class))
550         printJavaImpl();
551       else {
552         cl.print("String.valueOf(");
553         printJavaImpl();
554         cl.print(")");
555       }
556       break;
557
558       // JavaScript's double printing differs from Java's, so
559
// we need to convert to the JavaScript object.
560
default:
561       print();
562       cl.print(".toStr().toString()");
563       break;
564     }
565   }
566
567   void printJavaClass(Class JavaDoc type)
568     throws IOException JavaDoc
569   {
570     if (type.isArray()) {
571       printJavaClass(type.getComponentType());
572       cl.print("[]");
573     }
574     else
575       cl.print(type.getName());
576   }
577
578   /**
579    * Print where the result is a string.
580    */

581   void printString() throws IOException JavaDoc
582   {
583     switch (getType()) {
584     case TYPE_INTEGER:
585       printInt32Impl();
586       break;
587
588     case TYPE_BOOLEAN:
589       printBooleanImpl();
590       break;
591
592     case TYPE_STRING:
593       printStringImpl();
594       break;
595
596     case TYPE_JAVA:
597       printJavaImpl();
598       break;
599
600       // JavaScript's double printing differs from Java's, so
601
// we need to convert to the JavaScript object.
602
case TYPE_NUMBER:
603     default:
604       print();
605       cl.print(".valueOf()");
606       break;
607     }
608   }
609
610   void printImpl() throws IOException JavaDoc
611   {
612     throw new RuntimeException JavaDoc("" + this);
613   }
614
615   void printBooleanImpl() throws IOException JavaDoc
616   {
617     throw new RuntimeException JavaDoc("" + this);
618   }
619
620   void printNumImpl() throws IOException JavaDoc
621   {
622     throw new RuntimeException JavaDoc("" + this);
623   }
624
625   void printInt32Impl() throws IOException JavaDoc
626   {
627     throw new RuntimeException JavaDoc("" + this);
628   }
629
630   void printInt64Impl() throws IOException JavaDoc
631   {
632     throw new RuntimeException JavaDoc("" + this);
633   }
634
635   void printStringImpl() throws IOException JavaDoc
636   {
637     throw new RuntimeException JavaDoc("no string impl for " + getClass());
638   }
639
640   void printJavaImpl() throws IOException JavaDoc
641   {
642     throw new RuntimeException JavaDoc("" + this);
643   }
644
645   void printLiteral(ESBase literal) throws IOException JavaDoc
646   {
647     cl.printLiteral(literal);
648   }
649
650   void exprStatement(Function fun) throws ESException
651   {
652   }
653
654   private ESException error(String JavaDoc msg)
655   {
656     return block.error(msg);
657   }
658 }
659
Popular Tags