KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > js > rhino > IRFactory


1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * The contents of this file are subject to the Netscape Public
4  * License Version 1.1 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of
6  * the License at http://www.mozilla.org/NPL/
7  *
8  * Software distributed under the License is distributed on an "AS
9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10  * implied. See the License for the specific language governing
11  * rights and limitations under the License.
12  *
13  * The Original Code is Rhino code, released
14  * May 6, 1999.
15  *
16  * The Initial Developer of the Original Code is Netscape
17  * Communications Corporation. Portions created by Netscape are
18  * Copyright (C) 1997-1999 Netscape Communications Corporation. All
19  * Rights Reserved.
20  *
21  * Contributor(s):
22  * Norris Boyd
23  *
24  * Alternatively, the contents of this file may be used under the
25  * terms of the GNU Public License (the "GPL"), in which case the
26  * provisions of the GPL are applicable instead of those above.
27  * If you wish to allow use of your version of this file only
28  * under the terms of the GPL and not to allow others to use your
29  * version of this file under the NPL, indicate your decision by
30  * deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL. If you do not delete
32  * the provisions above, a recipient may use your version of this
33  * file under either the NPL or the GPL.
34  */

35
36 package com.google.gwt.dev.js.rhino;
37
38 /**
39  * This class allows the creation of nodes, and follows the Factory pattern.
40  *
41  * @see Node
42  * @author Mike McCabe
43  * @author Norris Boyd
44  */

45 public class IRFactory {
46
47     public IRFactory(TokenStream ts) {
48         this.ts = ts;
49     }
50
51     /**
52      * Script (for associating file/url names with toplevel scripts.)
53      */

54     public Object JavaDoc createScript(Object JavaDoc body, String JavaDoc sourceName,
55                                int baseLineno, int endLineno, Object JavaDoc source)
56     {
57         Node result = new Node(TokenStream.SCRIPT);
58         Node children = ((Node) body).getFirstChild();
59         if (children != null)
60             result.addChildrenToBack(children);
61         
62         result.putProp(Node.SOURCENAME_PROP, sourceName);
63         result.putIntProp(Node.BASE_LINENO_PROP, baseLineno);
64         result.putIntProp(Node.END_LINENO_PROP, endLineno);
65         if (source != null)
66             result.putProp(Node.SOURCE_PROP, source);
67         return result;
68     }
69
70     /**
71      * Leaf
72      */

73     public Object JavaDoc createLeaf(int nodeType) {
74             return new Node(nodeType);
75     }
76
77     public Object JavaDoc createLeaf(int nodeType, int nodeOp) {
78         return new Node(nodeType, nodeOp);
79     }
80
81     public int getLeafType(Object JavaDoc leaf) {
82         Node n = (Node) leaf;
83         return n.getType();
84     }
85
86     /**
87      * Statement leaf nodes.
88      */

89
90     public Object JavaDoc createSwitch(int lineno) {
91         return new Node(TokenStream.SWITCH, lineno);
92     }
93
94     public Object JavaDoc createVariables(int lineno) {
95         return new Node(TokenStream.VAR, lineno);
96     }
97
98     public Object JavaDoc createExprStatement(Object JavaDoc expr, int lineno) {
99         return new Node(TokenStream.EXPRSTMT, (Node) expr, lineno);
100     }
101
102     /**
103      * Name
104      */

105     public Object JavaDoc createName(String JavaDoc name) {
106         return Node.newString(TokenStream.NAME, name);
107     }
108
109     /**
110      * String (for literals)
111      */

112     public Object JavaDoc createString(String JavaDoc string) {
113         return Node.newString(string);
114     }
115
116     /**
117      * Number (for literals)
118      */

119     public Object JavaDoc createNumber(double number) {
120         return Node.newNumber(number);
121     }
122
123     /**
124      * Catch clause of try/catch/finally
125      * @param varName the name of the variable to bind to the exception
126      * @param catchCond the condition under which to catch the exception.
127      * May be null if no condition is given.
128      * @param stmts the statements in the catch clause
129      * @param lineno the starting line number of the catch clause
130      */

131     public Object JavaDoc createCatch(String JavaDoc varName, Object JavaDoc catchCond, Object JavaDoc stmts,
132                               int lineno)
133     {
134         if (catchCond == null) {
135             catchCond = new Node(TokenStream.PRIMARY, TokenStream.TRUE);
136         }
137         return new Node(TokenStream.CATCH, (Node)createName(varName),
138                                (Node)catchCond, (Node)stmts, lineno);
139     }
140
141     /**
142      * Throw
143      */

144     public Object JavaDoc createThrow(Object JavaDoc expr, int lineno) {
145         return new Node(TokenStream.THROW, (Node)expr, lineno);
146     }
147
148     /**
149      * Return
150      */

151     public Object JavaDoc createReturn(Object JavaDoc expr, int lineno) {
152         return expr == null
153             ? new Node(TokenStream.RETURN, lineno)
154             : new Node(TokenStream.RETURN, (Node)expr, lineno);
155     }
156
157     /**
158      * Label
159      */

160     public Object JavaDoc createLabel(String JavaDoc label, int lineno) {
161         Node result = new Node(TokenStream.LABEL, lineno);
162         Node name = Node.newString(TokenStream.NAME, label);
163         result.addChildToBack(name);
164         return result;
165     }
166
167     /**
168      * Break (possibly labeled)
169      */

170     public Object JavaDoc createBreak(String JavaDoc label, int lineno) {
171         Node result = new Node(TokenStream.BREAK, lineno);
172         if (label == null) {
173             return result;
174         } else {
175             Node name = Node.newString(TokenStream.NAME, label);
176             result.addChildToBack(name);
177             return result;
178         }
179     }
180
181     /**
182      * Continue (possibly labeled)
183      */

184     public Object JavaDoc createContinue(String JavaDoc label, int lineno) {
185         Node result = new Node(TokenStream.CONTINUE, lineno);
186         if (label == null) {
187             return result;
188         } else {
189             Node name = Node.newString(TokenStream.NAME, label);
190             result.addChildToBack(name);
191             return result;
192         }
193     }
194
195     /**
196      * debugger
197      */

198     public Object JavaDoc createDebugger(int lineno) {
199         Node result = new Node(TokenStream.DEBUGGER, lineno);
200         return result;
201     }
202
203     /**
204      * Statement block
205      * Creates the empty statement block
206      * Must make subsequent calls to add statements to the node
207      */

208     public Object JavaDoc createBlock(int lineno) {
209         return new Node(TokenStream.BLOCK, lineno);
210     }
211
212     public Object JavaDoc createFunction(String JavaDoc name, Object JavaDoc args, Object JavaDoc statements,
213                                  String JavaDoc sourceName, int baseLineno,
214                                  int endLineno, Object JavaDoc source,
215                                  boolean isExpr)
216     {
217         Node f = new Node(TokenStream.FUNCTION,
218                           Node.newString(TokenStream.NAME,
219                                          name == null ? "" : name),
220                           (Node)args, (Node)statements, baseLineno);
221
222         f.putProp(Node.SOURCENAME_PROP, sourceName);
223         f.putIntProp(Node.BASE_LINENO_PROP, baseLineno);
224         f.putIntProp(Node.END_LINENO_PROP, endLineno);
225         if (source != null)
226             f.putProp(Node.SOURCE_PROP, source);
227
228         return f;
229     }
230
231     /**
232      * Add a child to the back of the given node. This function
233      * breaks the Factory abstraction, but it removes a requirement
234      * from implementors of Node.
235      */

236     public void addChildToBack(Object JavaDoc parent, Object JavaDoc child) {
237         ((Node)parent).addChildToBack((Node)child);
238     }
239
240     /**
241      * While
242      */

243     public Object JavaDoc createWhile(Object JavaDoc cond, Object JavaDoc body, int lineno) {
244         return new Node(TokenStream.WHILE, (Node)cond, (Node)body, lineno);
245     }
246
247     /**
248      * DoWhile
249      */

250     public Object JavaDoc createDoWhile(Object JavaDoc body, Object JavaDoc cond, int lineno) {
251         return new Node(TokenStream.DO, (Node)body, (Node)cond, lineno);
252     }
253
254     /**
255      * For
256      */

257     public Object JavaDoc createFor(Object JavaDoc init, Object JavaDoc test, Object JavaDoc incr,
258                             Object JavaDoc body, int lineno)
259     {
260         return new Node(TokenStream.FOR, (Node)init, (Node)test, (Node)incr,
261                         (Node)body);
262     }
263
264     /**
265      * For .. In
266      *
267      */

268     public Object JavaDoc createForIn(Object JavaDoc lhs, Object JavaDoc obj, Object JavaDoc body, int lineno) {
269         return new Node(TokenStream.FOR, (Node)lhs, (Node)obj, (Node)body);
270     }
271
272     /**
273      * Try/Catch/Finally
274      */

275     public Object JavaDoc createTryCatchFinally(Object JavaDoc tryblock, Object JavaDoc catchblocks,
276                                         Object JavaDoc finallyblock, int lineno)
277     {
278         if (finallyblock == null) {
279             return new Node(TokenStream.TRY, (Node)tryblock, (Node)catchblocks);
280         }
281         return new Node(TokenStream.TRY, (Node)tryblock,
282                         (Node)catchblocks, (Node)finallyblock);
283     }
284
285     /**
286      * Throw, Return, Label, Break and Continue are defined in ASTFactory.
287      */

288
289     /**
290      * With
291      */

292     public Object JavaDoc createWith(Object JavaDoc obj, Object JavaDoc body, int lineno) {
293         return new Node(TokenStream.WITH, (Node)obj, (Node)body, lineno);
294     }
295
296     /**
297      * Array Literal
298      */

299     public Object JavaDoc createArrayLiteral(Object JavaDoc obj) {
300         return obj;
301     }
302
303     /**
304      * Object Literals
305      */

306     public Object JavaDoc createObjectLiteral(Object JavaDoc obj) {
307         return obj;
308     }
309
310     /**
311      * Regular expressions
312      */

313     public Object JavaDoc createRegExp(String JavaDoc string, String JavaDoc flags) {
314         return flags.length() == 0
315                ? new Node(TokenStream.REGEXP,
316                           Node.newString(string))
317                : new Node(TokenStream.REGEXP,
318                           Node.newString(string),
319                           Node.newString(flags));
320     }
321
322     /**
323      * If statement
324      */

325     public Object JavaDoc createIf(Object JavaDoc cond, Object JavaDoc ifTrue, Object JavaDoc ifFalse,
326                            int lineno)
327     {
328         if (ifFalse == null)
329             return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue);
330         return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, (Node)ifFalse);
331     }
332
333     public Object JavaDoc createTernary(Object JavaDoc cond, Object JavaDoc ifTrue, Object JavaDoc ifFalse) {
334         return new Node(TokenStream.HOOK,
335                         (Node)cond, (Node)ifTrue, (Node)ifFalse);
336     }
337
338     /**
339      * Unary
340      */

341     public Object JavaDoc createUnary(int nodeType, Object JavaDoc child) {
342         Node childNode = (Node) child;
343         return new Node(nodeType, childNode);
344     }
345
346     public Object JavaDoc createUnary(int nodeType, int nodeOp, Object JavaDoc child) {
347         return new Node(nodeType, (Node)child, nodeOp);
348     }
349
350     /**
351      * Binary
352      */

353     public Object JavaDoc createBinary(int nodeType, Object JavaDoc left, Object JavaDoc right) {
354         Node temp;
355         switch (nodeType) {
356
357           case TokenStream.DOT:
358             nodeType = TokenStream.GETPROP;
359             Node idNode = (Node) right;
360             idNode.setType(TokenStream.STRING);
361             String JavaDoc id = idNode.getString();
362             if (id.equals("__proto__") || id.equals("__parent__")) {
363                 Node result = new Node(nodeType, (Node) left);
364                 result.putProp(Node.SPECIAL_PROP_PROP, id);
365                 return result;
366             }
367             break;
368
369           case TokenStream.LB:
370             // OPT: could optimize to GETPROP iff string can't be a number
371
nodeType = TokenStream.GETELEM;
372             break;
373         }
374         return new Node(nodeType, (Node)left, (Node)right);
375     }
376
377     public Object JavaDoc createBinary(int nodeType, int nodeOp, Object JavaDoc left,
378                                Object JavaDoc right)
379     {
380         if (nodeType == TokenStream.ASSIGN) {
381             return createAssignment(nodeOp, (Node) left, (Node) right,
382                                     null, false);
383         }
384         return new Node(nodeType, (Node) left, (Node) right, nodeOp);
385     }
386
387     public Object JavaDoc createAssignment(int nodeOp, Node left, Node right,
388                                    Class JavaDoc convert, boolean postfix)
389     {
390         int nodeType = left.getType();
391         switch (nodeType) {
392             case TokenStream.NAME:
393             case TokenStream.GETPROP:
394             case TokenStream.GETELEM:
395                 break;
396             default:
397                 // TODO: This should be a ReferenceError--but that's a runtime
398
// exception. Should we compile an exception into the code?
399
reportError("msg.bad.lhs.assign");
400         }
401         
402         return new Node(TokenStream.ASSIGN, left, right, nodeOp);
403     }
404
405     private Node createConvert(Class JavaDoc toType, Node expr) {
406         if (toType == null)
407             return expr;
408         Node result = new Node(TokenStream.CONVERT, expr);
409         result.putProp(Node.TYPE_PROP, Number JavaDoc.class);
410         return result;
411     }
412
413     public static boolean hasSideEffects(Node exprTree) {
414         switch (exprTree.getType()) {
415             case TokenStream.INC:
416             case TokenStream.DEC:
417             case TokenStream.SETPROP:
418             case TokenStream.SETELEM:
419             case TokenStream.SETNAME:
420             case TokenStream.CALL:
421             case TokenStream.NEW:
422                 return true;
423             default:
424                 Node child = exprTree.getFirstChild();
425                 while (child != null) {
426                     if (hasSideEffects(child))
427                         return true;
428                     else
429                         child = child.getNext();
430                 }
431                 break;
432         }
433         return false;
434     }
435
436     private void reportError(String JavaDoc msgResource) {
437
438         String JavaDoc message = Context.getMessage0(msgResource);
439         Context.reportError(
440             message, ts.getSourceName(), ts.getLineno(),
441             ts.getLine(), ts.getOffset());
442     }
443
444     // Only needed to get file/line information. Could create an interface
445
// that TokenStream implements if we want to make the connection less
446
// direct.
447
private TokenStream ts;
448 }
449
Popular Tags