KickJava   Java API By Example, From Geeks To Geeks.

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


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.ESException;
33 import com.caucho.es.ESId;
34 import com.caucho.util.CharBuffer;
35
36 import java.util.ArrayList JavaDoc;
37 import java.util.HashMap JavaDoc;
38
39 /**
40  * Block is an intermediate form representing an expression.
41  */

42 class Block {
43   private static HashMap JavaDoc specialNames;
44
45   Function function;
46   private Block parent;
47   private Expr lastExpr;
48   boolean isDead;
49   private boolean hasStatementValue;
50   private Parser parser;
51   private boolean isLoop;
52   private boolean canExit;
53   private boolean hasDefault;
54   private int withDepth;
55   private ESId id;
56   private Expr mark;
57   
58   private Object JavaDoc switchTop;
59   private Object JavaDoc top;
60   private int topMark;
61
62   
63   private Block()
64   {
65   }
66
67   Block create()
68     throws ESException
69   {
70     evalExpr();
71     
72     Block block = new Block();
73     
74     block.function = function;
75     block.parent = this;
76     block.lastExpr = null;
77     block.isDead = false;
78     block.hasStatementValue = hasStatementValue;
79     block.parser = parser;
80     block.isLoop = false;
81     block.canExit = false;
82     block.withDepth = withDepth;
83     block.id = null;
84     block.mark = null;
85     block.switchTop = null;
86     block.top = null;
87
88     block.setTop();
89
90     return block;
91   }
92
93   static Block create(Parser parser, Function function)
94   {
95     Block block = new Block();
96
97     block.function = function;
98     block.parent = null;
99     block.lastExpr = null;
100     block.isDead = false;
101     block.hasStatementValue = function.needsStatementResults();
102     block.parser = parser;
103     block.isLoop = false;
104     block.canExit = false;
105     block.withDepth = 0;
106     block.id = null;
107
108     block.top = null;
109     block.topMark = 0;
110
111     function.setVars();
112
113     return block;
114   }
115
116   ClassLoader JavaDoc getClassLoader()
117   {
118     return parser.getClassLoader();
119   }
120
121   void setTop()
122   {
123     top = function.getTop();
124     if (top instanceof CharBuffer) {
125       CharBuffer cb = (CharBuffer) top;
126       topMark = cb.length();
127     }
128     else
129       topMark = 0;
130   }
131
132   Block pop()
133   {
134     Block parent = this.parent;
135     function.setVars();
136     free();
137
138     return parent;
139   }
140
141   boolean isGlobal()
142   {
143     return function.isGlobal();
144   }
145
146   int getDepth()
147   {
148     return withDepth;
149   }
150
151   boolean allowSpecial()
152   {
153     return parent == null;
154   }
155
156   String JavaDoc getFilename()
157   {
158     String JavaDoc filename = parser.lexer.getLastFilename();
159     int p = filename.lastIndexOf('/');
160     if (p > 0)
161       filename = filename.substring(p + 1);
162     p = filename.lastIndexOf('\\');
163     if (p > 0)
164       filename = filename.substring(p + 1);
165     
166     return filename;
167   }
168
169   int getLine()
170   {
171     int line = parser.lexer.getLastLine();
172     
173     return line;
174   }
175
176   void setLine(int line)
177   {
178   }
179
180   /**
181    * Returns true if the variable is already declared.
182    */

183   boolean hasVar(ESId name)
184   {
185     return function.hasVar(name) || specialNames.get(name) != null;
186   }
187
188   /**
189    * Returns an expression for a new variable
190    */

191   IdExpr newVar(ESId name)
192   {
193     return newVar(name, null);
194   }
195
196   IdExpr newVar(ESId name, Expr type)
197   {
198     if (withDepth > 0)
199       return new IdExpr(this, new Variable(this, name, type, false));
200     
201     IdExpr expr = function.newVar(this, name, type);
202
203     // Kill variables inside an if
204
if (parent != null)
205       expr.getType();
206
207     return expr;
208   }
209
210   /**
211    * Define a new variable.
212    */

213   void defVar(ESId name)
214   {
215     function.addVariable(this, name, null);
216   }
217
218   /**
219    * Define a new variable with the given type.
220    */

221   void defVar(ESId name, Expr type)
222   {
223     function.addVariable(this, name, type);
224   }
225
226   Expr newLiteral(ESBase value)
227   {
228     return new LiteralExpr(this, value);
229   }
230
231   Expr newRegexp(ESBase value, String JavaDoc flags)
232     throws ESException
233   {
234     return new RegexpExpr(this, value, flags);
235   }
236
237   Expr newThis()
238   {
239     return new SpecialExpr(this, SpecialExpr.THIS);
240   }
241
242   Expr newArray(Expr expr)
243   {
244     return new SpecialExpr(this, SpecialExpr.ARRAY, expr);
245   }
246   
247   Expr hasNext(String JavaDoc iter)
248   {
249     return new SpecialExpr(this, SpecialExpr.HAS_NEXT, iter);
250   }
251
252   Expr newType(ESId name)
253   {
254     return TypeExpr.create(this, name);
255   }
256   
257   void addExpr(Expr expr)
258     throws ESException
259   {
260     if (isDead)
261       throw error("Statement is unreachable.");
262     if (lastExpr != null)
263       lastExpr.exprStatement(function);
264     
265     if (hasStatementValue && ! void.class.equals(expr.getJavaClass()))
266       lastExpr = expr;
267     else {
268       lastExpr = null;
269       expr.exprStatement(function);
270     }
271   }
272   
273   Block startBlock()
274     throws ESException
275   {
276     evalExpr();
277     function.println("{");
278     return create();
279   }
280   
281   Block startBlock(ESId id)
282     throws ESException
283   {
284     if (findBlock(id) != null)
285       throw error("duplicate label `" + id + "'");
286     
287     evalExpr();
288     Block block = create();
289     block.id = id;
290     function.println(id + ": {");
291     block.setTop();
292     return block;
293   }
294
295   Block finishBlock()
296     throws ESException
297   {
298     evalExpr();
299     function.println("}");
300     this.id = null;
301     Block old = pop();
302     if (isDead && ! canExit)
303       old.isDead = true;
304
305     return old;
306   }
307
308   void endBlock()
309     throws ESException
310   {
311     evalExpr();
312     function.println("}");
313     this.id = null;
314   }
315   
316   void startIf(Expr expr, boolean isElse)
317     throws ESException
318   {
319     evalExpr();
320     if (isElse)
321       function.print(" else ");
322     function.print("if (");
323     function.addBoolean(expr);
324     function.println(") {");
325     setTop();
326   }
327   
328   void startElse()
329     throws ESException
330   {
331     evalExpr();
332     function.println(" else {");
333     setTop();
334   }
335   
336   Block startWhile(ESId id, Expr expr)
337     throws ESException
338   {
339     evalExpr();
340     if (id != null)
341       function.println(id + ":");
342     function.print("while (");
343     function.addBoolean(expr);
344     function.println(") {");
345
346     Block block = create();
347     startLoop(id);
348
349     if (! (expr instanceof LiteralExpr) ||
350         ! ((LiteralExpr) expr).getLiteral().toBoolean())
351       canExit = true;
352         
353     return block;
354   }
355   
356   Block startFor(ESId id, Expr test, Expr incr)
357     throws ESException
358   {
359     evalExpr();
360     if (id != null)
361       function.println(id + ":");
362     function.print("for (;");
363     if (test != null)
364       function.addBoolean(test);
365     function.print(";");
366     if (incr != null)
367       function.addExpr(incr);
368     function.println(") {");
369     function.cl.pushDepth();
370
371     Block block = create();
372     startLoop(id);
373
374     if (test == null)
375       canExit = false;
376     else if (! (test instanceof LiteralExpr) ||
377              ! ((LiteralExpr) test).getLiteral().toBoolean())
378       canExit = true;
379         
380     return block;
381   }
382   
383   Block startDo(ESId id)
384     throws ESException
385   {
386     evalExpr();
387     if (id != null)
388       function.println(id + ":");
389     function.print("do {");
390     
391     Block block = create();
392     startLoop(id);
393     return block;
394   }
395   
396   Block endDo(Expr expr)
397     throws ESException
398   {
399     evalExpr();
400     
401     Block old = endLoop();
402     
403     if (! (expr instanceof LiteralExpr) ||
404         ! ((LiteralExpr) expr).getLiteral().toBoolean())
405       old.canExit = true;
406
407     if (old.canExit)
408       old.isDead = false;
409     
410     function.print("while (");
411     function.addBoolean(expr);
412     function.println(");");
413
414     return old;
415   }
416
417   void startLoop(ESId id)
418   {
419     String JavaDoc oldVar = function.getStatementVar();
420     function.pushStatementLoop();
421     String JavaDoc newVar = function.getStatementVar();
422     if (oldVar != null)
423       function.println(newVar + " = " + oldVar + ";");
424     this.id = id;
425     isLoop = true;
426     canExit = false;
427   }
428
429   Block endLoop()
430     throws ESException
431   {
432     evalExpr();
433     String JavaDoc newVar = function.getStatementVar();
434     function.popStatementLoop();
435     String JavaDoc oldVar = function.getStatementVar();
436     if (oldVar != null && ! isDead)
437       function.println(oldVar + " = " + newVar + ";");
438     function.cl.popDepth();
439     function.println("}");
440
441     Block old = pop();
442     if (! old.canExit)
443       old.isDead = true;
444
445     return old;
446   }
447
448   Block startSwitch(Expr test)
449     throws ESException
450   {
451     ESId id = ESId.intern("_switchtemp");
452     
453     function.print("_switchtemp = ");
454     function.addExpr(test);
455     function.println(";");
456     
457     Block block = create();
458     block.switchTop = function.getSwitch();
459     block.isLoop = true;
460     block.hasDefault = false;
461     
462     function.println("switch (_switchcode) {");
463     return block;
464   }
465
466   void doCase(int i)
467     throws ESException
468   {
469     isDead = false;
470     evalExpr();
471     function.println("case " + i + ":");
472   }
473
474   void doDefault()
475     throws ESException
476   {
477     isDead = false;
478     hasDefault = true;
479     evalExpr();
480     function.println("default:");
481   }
482
483   Block fillSwitch(ArrayList JavaDoc exprs)
484     throws ESException
485   {
486     evalExpr();
487     if (! hasDefault && ! isDead) {
488       function.println("default:");
489       function.println(" break;");
490     }
491     else if (! isDead)
492       function.println("break;");
493     function.println("}");
494
495     int mark = function.mark();
496     
497     for (int i = 0; i < exprs.size(); i++) {
498       if (i != 0)
499         function.print("else ");
500
501       Expr test = (Expr) exprs.get(i);
502
503       function.print("if (_switchtemp.equals(");
504       function.addExpr(test);
505       function.println(")) _switchcode = " + i + ";");
506     }
507     if (exprs.size() > 0)
508       function.print("else ");
509     function.println("_switchcode = -1;");
510
511     function.moveChunk(switchTop, mark);
512
513     Block old = pop();
514     if (isDead && ! canExit && hasDefault)
515       old.isDead = true;
516
517     return old;
518   }
519   
520   void doBreak(ESId id)
521     throws ESException
522   {
523     Block block = this;
524     for (; block != null; block = block.parent) {
525       if (block.id == id) {
526         block.canExit = true;
527         break;
528       }
529     }
530     
531     if (block == null)
532       throw error("break needs enclosing loop");
533     
534     function.setVars();
535     evalExpr();
536     function.println("break " + id + ";");
537     isDead = true;
538   }
539   
540   void doBreak()
541     throws ESException
542   {
543     Block block = this;
544     for (; block != null; block = block.parent) {
545       if (block.isLoop) {
546         block.canExit = true;
547         break;
548       }
549     }
550     
551     if (block == null)
552       throw error("break needs enclosing loop");
553     
554     function.setVars();
555     evalExpr();
556     function.println("break;");
557     isDead = true;
558   }
559   
560   void doContinue(ESId id)
561     throws ESException
562   {
563     Block block = this;
564     for (; block != null; block = block.parent) {
565       if (block.id == id && block.isLoop)
566         break;
567       /*
568       else
569         block.canExit = true;
570       */

571     }
572     if (block == null)
573       throw error("continue needs enclosing loop");
574     
575     function.setVars();
576     evalExpr();
577     function.println("continue " + id + ";");
578     isDead = true;
579   }
580   
581   void doContinue()
582     throws ESException
583   {
584     if (findBlock(null) == null)
585       throw error("continue needs enclosing loop");
586     
587     function.setVars();
588     evalExpr();
589     function.println("continue;");
590     isDead = true;
591   }
592
593   private Block findBlock(ESId id)
594   {
595     for (Block block = this; block != null; block = block.parent) {
596       if (id != null && block.id == id)
597         return block;
598       else if (id == null && block.isLoop)
599         return block;
600     }
601     
602     return null;
603   }
604   
605   Block startWith(Expr expr)
606     throws ESException
607   {
608     function.setArguments();
609     function.setUseAllVariables();
610     evalExpr();
611     withDepth++;
612     function.println("try {");
613     function.print("_env.pushScope(");
614     function.addExpr(expr);
615     function.println(");");
616     setTop();
617     
618     return this;
619   }
620   
621   Block endWith()
622     throws ESException
623   {
624     evalExpr();
625     withDepth--;
626     function.println("} finally {");
627     function.println("_env.popScope();");
628     function.println("}");
629     
630     return this;
631   }
632
633   int getWithDepth()
634   {
635     return withDepth;
636   }
637   
638   Block startTry()
639     throws ESException
640   {
641     function.setVars();
642     evalExpr();
643     function.println("try {");
644     return this;
645   }
646   
647   Block endTry()
648     throws ESException
649   {
650     function.setVars();
651     evalExpr();
652     function.println("}");
653     
654     return this;
655   }
656   
657   void doTry()
658     throws ESException
659   {
660     evalExpr();
661
662     int i = 0;
663     for (; i < function.data.size(); i++) {
664       Object JavaDoc o = function.data.get(i);
665       if (o != top) {
666       }
667       else if (o instanceof CharBuffer) {
668         CharBuffer cb = (CharBuffer) o;
669         cb.insert(topMark, " try {\n");
670         break;
671       }
672       else {
673         function.data.add(i + 1, new CharBuffer(" try {\n"));
674         break;
675       }
676     }
677     if (i < function.data.size()) {
678     }
679     else if (function.tail != null && top == function.tail)
680       function.tail.insert(topMark, " try {\n");
681     else
682       function.data.add(0, new CharBuffer(" try {\n"));
683
684     function.println("}");
685   }
686   
687   Block startCatch(String JavaDoc exn, Expr var)
688     throws ESException
689   {
690     evalExpr();
691     String JavaDoc temp = "_e" + function.getTemp();
692     function.println("catch (" + exn + " " + temp + ") {");
693     if (var != null) {
694       Expr expr = new SpecialExpr(this, SpecialExpr.EXCEPTION, temp);
695       var.assign(expr).exprStatement(function);
696     }
697       
698     isDead = false;
699     setTop();
700     
701     return this;
702   }
703   
704   Block endCatch()
705     throws ESException
706   {
707     evalExpr();
708     function.println("}");
709     return this;
710   }
711   
712   Block startFinally()
713     throws ESException
714   {
715     evalExpr();
716     Block block = create();
717     function.println("finally {");
718     function.pushStatementLoop();
719     block.setTop();
720
721     return block;
722   }
723   
724   Block endFinally()
725     throws ESException
726   {
727     evalExpr();
728     function.println("}");
729     function.popStatementLoop();
730     return pop();
731   }
732   
733   Block startSynchronized(Expr expr)
734     throws ESException
735   {
736     evalExpr();
737     function.print("synchronized (");
738     function.addExpr(expr);
739     function.println(".toJavaObject()) {");
740
741     return create();
742   }
743   
744   Block endSynchronized()
745     throws ESException
746   {
747     evalExpr();
748
749     function.println("}");
750     
751     Block old = pop();
752     old.isDead = isDead;
753     
754     return old;
755   }
756   
757   void doThrow(Expr expr)
758     throws ESException
759   {
760     function.print("throw (Exception)");
761     function.addExpr(expr);
762     function.println(".toJavaObject();");
763     isDead = true;
764   }
765   
766   void doReturn(Expr value)
767     throws ESException
768   {
769     evalExpr();
770     function.print("return ");
771
772     value.setUsed();
773     if (function.getReturnType() != null)
774       function.addExpr(new TopExpr(this, value,
775                                    function.getReturnType()));
776     else
777       function.addExpr(value);
778     
779     function.println(";");
780     isDead = true;
781     /* can't break
782     for (Block block = this; block != null; block = block.parent)
783       block.canExit = true;
784     */

785   }
786   
787   void doReturn()
788     throws ESException
789   {
790     evalExpr();
791     
792     if (function.getReturnType() != null)
793       function.print("return 0;");
794     else
795       function.print("return ESBase.esUndefined;");
796     isDead = true;
797     /*
798     for (Block block = this; block != null; block = block.parent)
799       block.canExit = true;
800     */

801   }
802
803   void finish()
804     throws ESException
805   {
806     if (isDead)
807       return;
808
809     if (lastExpr != null) {
810       function.print("return ");
811       function.addExpr(lastExpr);
812       function.println(";");
813       lastExpr = null;
814     }
815     else if (hasStatementValue)
816       function.println("return _val0;");
817     else
818       function.println("return ESBase.esUndefined;");
819   }
820
821   String JavaDoc newIterator(ESId id, Expr expr)
822     throws ESException
823   {
824     evalExpr();
825     
826     String JavaDoc iter = "iter" + function.getIter();
827     function.print(iter + " = ");
828     function.addExpr(expr);
829     function.println(".keys();");
830     
831     return iter;
832   }
833
834   void evalExpr() throws ESException
835   {
836     if (lastExpr == null)
837       return;
838
839     function.print(function.getStatementVar() + " = ");
840     function.addExpr(lastExpr);
841     function.println(";");
842     
843     lastExpr = null;
844   }
845
846   private static Block allocate()
847   {
848     Block block = new Block();
849
850     return block;
851   }
852
853   ESException error(String JavaDoc message)
854   {
855     return parser.lexer.error(message);
856   }
857   
858   void free()
859   {
860   }
861
862   static {
863     specialNames = new HashMap JavaDoc();
864     specialNames.put(ESId.intern("Object"), "Object");
865     specialNames.put(ESId.intern("Date"), "Date");
866     specialNames.put(ESId.intern("String"), "String");
867     specialNames.put(ESId.intern("Number"), "Number");
868     specialNames.put(ESId.intern("Array"), "Array");
869     specialNames.put(ESId.intern("Boolean"), "Boolean");
870     specialNames.put(ESId.intern("Math"), "Math");
871   };
872 }
873
Popular Tags