1 | // -*- c-basic-offset: 2 -*- |
2 | /* |
3 | * This file is part of the KDE libraries |
4 | * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
5 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
6 | * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
7 | * Copyright (C) 2007, 2008 Maksim Orlovich (maksim@kde.org) |
8 | * |
9 | * This library is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU Library General Public |
11 | * License as published by the Free Software Foundation; either |
12 | * version 2 of the License, or (at your option) any later version. |
13 | * |
14 | * This library 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. See the GNU |
17 | * Library General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Library General Public License |
20 | * along with this library; see the file COPYING.LIB. If not, write to |
21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
22 | * Boston, MA 02110-1301, USA. |
23 | * |
24 | */ |
25 | |
26 | #ifndef NODES_H_ |
27 | #define NODES_H_ |
28 | |
29 | #include "Parser.h" |
30 | #include "internal.h" |
31 | #include "CompileState.h" |
32 | #include "operations.h" |
33 | #include "SymbolTable.h" |
34 | #include "opcodes.h" |
35 | #include "bytecode/opargs.h" |
36 | #include <wtf/ListRefPtr.h> |
37 | #include <wtf/Vector.h> |
38 | |
39 | |
40 | namespace KJS { |
41 | class ProgramNode; |
42 | class PropertyNameNode; |
43 | class PropertyListNode; |
44 | class RegExp; |
45 | class SourceElementsNode; |
46 | class SourceStream; |
47 | class PackageObject; |
48 | class FuncDeclNode; |
49 | class FunctionBodyNode; |
50 | class Node; |
51 | |
52 | class VarDeclVisitor; |
53 | class FuncDeclVisitor; |
54 | |
55 | class CompileState; |
56 | struct CompileReference; |
57 | |
58 | class NodeVisitor { |
59 | public: |
60 | virtual ~NodeVisitor() {} |
61 | /** |
62 | This method should be overridden by subclasses to process nodes, and |
63 | perhaps return pointers for replacement nodes. If the node should not be |
64 | changed, return 0. Otherwise, return the replacement node. |
65 | |
66 | The default implementation asks the node to visit its kids, and do |
67 | replacements on them if needed, but does not change anything for this node |
68 | */ |
69 | virtual Node* visit(Node* node); |
70 | }; |
71 | |
72 | class Node { |
73 | public: |
74 | enum NodeType { |
75 | UnknownNodeType, |
76 | NullNodeType, |
77 | BooleanNodeType, |
78 | NumberNodeType, |
79 | StringNodeType, |
80 | RegExpNodeType, |
81 | TryNodeType, |
82 | GroupNodeType, |
83 | LabelNodeType |
84 | }; |
85 | |
86 | Node(); |
87 | virtual ~Node(); |
88 | |
89 | virtual NodeType type() const { return UnknownNodeType; } |
90 | |
91 | UString toString() const; |
92 | |
93 | // This updates line numbers to the pretty-printed version, and |
94 | // returns it out. |
95 | UString reindent(int baseLine = 0) const; |
96 | |
97 | virtual void streamTo(SourceStream&) const = 0; |
98 | int lineNo() const { return m_line; } |
99 | |
100 | void ref(); |
101 | void deref(); |
102 | unsigned refcount(); |
103 | static void clearNewNodes(); |
104 | |
105 | virtual Node *nodeInsideAllParens(); |
106 | |
107 | virtual bool isLocation() const { return false; } |
108 | virtual bool isVarAccessNode() const { return false; } |
109 | bool isNumber() const { return type() == NumberNodeType; } |
110 | bool isString() const { return type() == StringNodeType; } |
111 | bool isGroupNode() const { return type() == GroupNodeType; } |
112 | bool isTryNode() const { return type() == TryNodeType; } |
113 | bool isLabelNode() const { return type() == LabelNodeType; } |
114 | virtual bool scanForDeclarations () const { return true; } |
115 | virtual bool isIterationStatement() const { return false; } |
116 | |
117 | virtual void breakCycle() { } |
118 | |
119 | // Processes all function and variable declarations below this node, |
120 | // adding them to symbol table or the current object depending on the |
121 | // execution context.. |
122 | void processDecls(ExecState*); |
123 | |
124 | /* |
125 | Implementations of this method should call visitor->visit on all the |
126 | children nodes, and if they return value is non-0, update the link to the child. |
127 | The recurseVisitLink helper takes care of this |
128 | */ |
129 | virtual void recurseVisit(NodeVisitor * /*visitor*/) {} |
130 | |
131 | template<typename T> |
132 | static void recurseVisitLink(NodeVisitor* visitor, RefPtr<T>& link) |
133 | { |
134 | if (!link) |
135 | return; |
136 | |
137 | T* newLink = static_cast<T*>(visitor->visit(link.get())); |
138 | if (newLink) |
139 | link = newLink; |
140 | } |
141 | |
142 | template<typename T> |
143 | static void recurseVisitLink(NodeVisitor* visitor, ListRefPtr<T>& link) |
144 | { |
145 | if (!link) |
146 | return; |
147 | |
148 | T* newLink = static_cast<T*>(visitor->visit(link.get())); |
149 | if (newLink) |
150 | link = newLink; |
151 | } |
152 | |
153 | |
154 | JSValue* throwError(ExecState*, ErrorType, const UString& msg); |
155 | JSValue* throwError(ExecState*, ErrorType, const UString& msg, const Identifier&); |
156 | JSValue* throwUndefinedVariableError(ExecState*, const Identifier&); |
157 | |
158 | virtual OpValue generateEvalCode(CompileState* comp); |
159 | protected: |
160 | mutable int m_line; |
161 | private: |
162 | virtual void processVarDecl (ExecState* state); |
163 | virtual void processFuncDecl(ExecState* state); |
164 | friend class VarDeclVisitor; |
165 | friend class FuncDeclVisitor; |
166 | |
167 | // disallow assignment |
168 | Node& operator=(const Node&); |
169 | Node(const Node &other); |
170 | }; |
171 | |
172 | class LocationNode : public Node { |
173 | public: |
174 | virtual bool isLocation() const { return true; } |
175 | |
176 | // For assignments, we need to conceptually evaluate the LHS to a reference before looking at the RHS |
177 | // generateRefBind corresponds to that action. It never issues an error. The returned |
178 | // reference should be passed to generateRefWrite when needed |
179 | virtual CompileReference* generateRefBind(CompileState*) = 0; |
180 | |
181 | // When we are doing a read-modify-write style op, or just plain read, we want to do a read |
182 | // right after the binding. This does that, and returns a reference for use of follow up |
183 | // writes. |
184 | virtual CompileReference* generateRefRead(CompileState*, OpValue* out) = 0; |
185 | |
186 | // Writes to a bound reference. |
187 | virtual void generateRefWrite (CompileState*, |
188 | CompileReference* ref, OpValue& valToStore) = 0; |
189 | |
190 | // The location nodes also handle deletes themselves. Note that this is called |
191 | // w/o generateRefBegin |
192 | virtual OpValue generateRefDelete(CompileState*) = 0; |
193 | |
194 | // For function calls, we also do a specialized lookup, getting both the valie and the |
195 | // scope/this, also making sure it's not an activation. |
196 | virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut) = 0; |
197 | }; |
198 | |
199 | class StatementNode : public Node { |
200 | public: |
201 | StatementNode(); |
202 | void setLoc(int line0, int line1) const; |
203 | int firstLine() const { return lineNo(); } |
204 | int lastLine() const { return m_lastLine; } |
205 | void hitStatement(ExecState*); |
206 | |
207 | void generateDebugInfoIfNeeded(CompileState* comp); |
208 | |
209 | virtual void generateExecCode(CompileState*); |
210 | private: |
211 | void generateDebugInfo(CompileState* comp); |
212 | mutable int m_lastLine; |
213 | }; |
214 | |
215 | inline void StatementNode::generateDebugInfoIfNeeded(CompileState* comp) |
216 | { |
217 | if (comp->compileType() == Debug) |
218 | generateDebugInfo(comp); |
219 | } |
220 | |
221 | class NullNode : public Node { |
222 | public: |
223 | NullNode() {} |
224 | virtual NodeType type() const { return NullNodeType; } |
225 | virtual OpValue generateEvalCode(CompileState* comp); |
226 | virtual void streamTo(SourceStream&) const; |
227 | }; |
228 | |
229 | class BooleanNode : public Node { |
230 | public: |
231 | BooleanNode(bool v) : val(v) {} |
232 | bool value() const { return val; } |
233 | |
234 | virtual NodeType type() const { return BooleanNodeType; } |
235 | virtual OpValue generateEvalCode(CompileState* comp); |
236 | virtual void streamTo(SourceStream&) const; |
237 | private: |
238 | bool val; |
239 | }; |
240 | |
241 | class NumberNode : public Node { |
242 | public: |
243 | NumberNode(double v) : val(v) {} |
244 | double value() const { return val; } |
245 | void setValue(double v) { val = v; } |
246 | |
247 | virtual NodeType type() const { return NumberNodeType; } |
248 | virtual OpValue generateEvalCode(CompileState* comp); |
249 | virtual void streamTo(SourceStream&) const; |
250 | private: |
251 | double val; |
252 | }; |
253 | |
254 | class StringNode : public Node { |
255 | public: |
256 | StringNode(const UString *v) : val(*v), interned(0) { } |
257 | ~StringNode(); // in nodes2bytecode.cpp |
258 | UString value() const { return val; } |
259 | void setValue(const UString& v) { val = v; } |
260 | |
261 | virtual NodeType type() const { return StringNodeType; } |
262 | virtual OpValue generateEvalCode(CompileState* comp); |
263 | virtual void streamTo(SourceStream&) const; |
264 | private: |
265 | UString val; |
266 | StringImp* interned; |
267 | }; |
268 | |
269 | class RegExpNode : public Node { |
270 | public: |
271 | RegExpNode(const UString &p, const UString &f) |
272 | : pattern(p), flags(f) { } |
273 | virtual NodeType type() const { return RegExpNodeType; } |
274 | virtual OpValue generateEvalCode(CompileState* comp); |
275 | virtual void streamTo(SourceStream&) const; |
276 | private: |
277 | UString pattern, flags; |
278 | }; |
279 | |
280 | class ThisNode : public Node { |
281 | public: |
282 | ThisNode() {} |
283 | virtual OpValue generateEvalCode(CompileState* comp); |
284 | virtual void streamTo(SourceStream&) const; |
285 | }; |
286 | |
287 | class VarAccessNode : public LocationNode { |
288 | public: |
289 | VarAccessNode(const Identifier& s) : ident(s) {} |
290 | |
291 | virtual bool isVarAccessNode() const { return true; } |
292 | virtual void streamTo(SourceStream&) const; |
293 | virtual OpValue generateEvalCode(CompileState* comp); |
294 | |
295 | virtual CompileReference* generateRefBind(CompileState*); |
296 | virtual CompileReference* generateRefRead(CompileState*, OpValue* out); |
297 | virtual void generateRefWrite (CompileState*, |
298 | CompileReference* ref, OpValue& valToStore); |
299 | virtual OpValue generateRefDelete(CompileState*); |
300 | virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); |
301 | |
302 | // This one never fails.. |
303 | OpValue valueForTypeOf(CompileState* comp); |
304 | |
305 | // Returns the ID this variable should be accessed as, or |
306 | // missingSymbolMarker(), along with the variable's classification |
307 | enum Classification { |
308 | Local, // local variable accessed by register # |
309 | NonLocal, // one scope above, unless local injected |
310 | Dynamic, // need to do a full lookup |
311 | Global // in the global object, if anywhere. |
312 | }; |
313 | |
314 | size_t classifyVariable(CompileState*, Classification& classify); |
315 | protected: |
316 | Identifier ident; |
317 | }; |
318 | |
319 | class GroupNode : public Node { |
320 | public: |
321 | GroupNode(Node *g) : group(g) { } |
322 | virtual NodeType type() const { return GroupNodeType; } |
323 | |
324 | virtual OpValue generateEvalCode(CompileState* comp); |
325 | virtual Node *nodeInsideAllParens(); |
326 | virtual void streamTo(SourceStream&) const; |
327 | virtual void recurseVisit(NodeVisitor *visitor); |
328 | private: |
329 | RefPtr<Node> group; |
330 | }; |
331 | |
332 | class ElementNode : public Node { |
333 | public: |
334 | // list pointer is tail of a circular list, cracked in the ArrayNode ctor |
335 | ElementNode(int e, Node *n) : next(this), elision(e), node(n) { Parser::noteNodeCycle(this); } |
336 | ElementNode(ElementNode *l, int e, Node *n) |
337 | : next(l->next), elision(e), node(n) { l->next = this; } |
338 | |
339 | virtual void streamTo(SourceStream&) const; |
340 | PassRefPtr<ElementNode> releaseNext() { return next.release(); } |
341 | virtual void breakCycle(); |
342 | virtual void recurseVisit(NodeVisitor *visitor); |
343 | private: |
344 | friend class ArrayNode; |
345 | ListRefPtr<ElementNode> next; |
346 | int elision; |
347 | RefPtr<Node> node; |
348 | }; |
349 | |
350 | class ArrayNode : public Node { |
351 | public: |
352 | ArrayNode(int e) : elision(e), opt(true) { } |
353 | ArrayNode(ElementNode *ele) |
354 | : element(ele->next.release()), elision(0), opt(false) { Parser::removeNodeCycle(element.get()); } |
355 | ArrayNode(int eli, ElementNode *ele) |
356 | : element(ele->next.release()), elision(eli), opt(true) { Parser::removeNodeCycle(element.get()); } |
357 | virtual OpValue generateEvalCode(CompileState* comp); |
358 | virtual void streamTo(SourceStream&) const; |
359 | virtual void recurseVisit(NodeVisitor *visitor); |
360 | virtual bool scanForDeclarations() const { return false; } |
361 | private: |
362 | RefPtr<ElementNode> element; |
363 | int elision; |
364 | bool opt; |
365 | }; |
366 | |
367 | class PropertyNameNode : public Node { |
368 | public: |
369 | PropertyNameNode(const Identifier &s) : str(s) { } |
370 | virtual void streamTo(SourceStream&) const; |
371 | private: |
372 | friend class ObjectLiteralNode; |
373 | Identifier str; |
374 | }; |
375 | |
376 | class PropertyNode : public Node { |
377 | public: |
378 | enum Type { Constant, Getter, Setter }; |
379 | PropertyNode(PropertyNameNode *n, Node *a, Type t) |
380 | : name(n), assign(a), type(t) { } |
381 | virtual void streamTo(SourceStream&) const; |
382 | friend class PropertyListNode; |
383 | virtual void recurseVisit(NodeVisitor *visitor); |
384 | private: |
385 | friend class ObjectLiteralNode; |
386 | RefPtr<PropertyNameNode> name; |
387 | RefPtr<Node> assign; |
388 | Type type; |
389 | }; |
390 | |
391 | class PropertyListNode : public Node { |
392 | public: |
393 | // list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor |
394 | PropertyListNode(PropertyNode *n) |
395 | : node(n), next(this) { Parser::noteNodeCycle(this); } |
396 | PropertyListNode(PropertyNode *n, PropertyListNode *l) |
397 | : node(n), next(l->next) { l->next = this; } |
398 | virtual void streamTo(SourceStream&) const; |
399 | PassRefPtr<PropertyListNode> releaseNext() { return next.release(); } |
400 | virtual void breakCycle(); |
401 | virtual void recurseVisit(NodeVisitor *visitor); |
402 | private: |
403 | friend class ObjectLiteralNode; |
404 | RefPtr<PropertyNode> node; |
405 | ListRefPtr<PropertyListNode> next; |
406 | }; |
407 | |
408 | class ObjectLiteralNode : public Node { |
409 | public: |
410 | ObjectLiteralNode() { } |
411 | ObjectLiteralNode(PropertyListNode *l) : list(l->next.release()) { Parser::removeNodeCycle(list.get()); } |
412 | virtual OpValue generateEvalCode(CompileState* comp); |
413 | virtual void streamTo(SourceStream&) const; |
414 | virtual void recurseVisit(NodeVisitor *visitor); |
415 | virtual bool scanForDeclarations() const { return false; } |
416 | private: |
417 | RefPtr<PropertyListNode> list; |
418 | }; |
419 | |
420 | class BracketAccessorNode : public LocationNode { |
421 | public: |
422 | BracketAccessorNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {} |
423 | virtual void streamTo(SourceStream&) const; |
424 | |
425 | virtual OpValue generateEvalCode(CompileState* comp); |
426 | |
427 | virtual CompileReference* generateRefBind(CompileState*); |
428 | virtual CompileReference* generateRefRead(CompileState*, OpValue* out); |
429 | virtual void generateRefWrite (CompileState*, |
430 | CompileReference* ref, OpValue& valToStore); |
431 | virtual OpValue generateRefDelete(CompileState*); |
432 | virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); |
433 | |
434 | Node *base() { return expr1.get(); } |
435 | Node *subscript() { return expr2.get(); } |
436 | |
437 | virtual void recurseVisit(NodeVisitor *visitor); |
438 | protected: |
439 | RefPtr<Node> expr1; |
440 | RefPtr<Node> expr2; |
441 | }; |
442 | |
443 | class DotAccessorNode : public LocationNode { |
444 | public: |
445 | DotAccessorNode(Node *e, const Identifier &s) : expr(e), ident(s) { } |
446 | virtual void streamTo(SourceStream&) const; |
447 | |
448 | virtual OpValue generateEvalCode(CompileState* comp); |
449 | |
450 | virtual CompileReference* generateRefBind(CompileState*); |
451 | virtual CompileReference* generateRefRead(CompileState*, OpValue* out); |
452 | virtual void generateRefWrite (CompileState*, |
453 | CompileReference* ref, OpValue& valToStore); |
454 | virtual OpValue generateRefDelete(CompileState*); |
455 | virtual void generateRefFunc(CompileState* comp, OpValue* funOut, OpValue* thisOut); |
456 | |
457 | Node *base() const { return expr.get(); } |
458 | const Identifier& identifier() const { return ident; } |
459 | |
460 | virtual void recurseVisit(NodeVisitor *visitor); |
461 | protected: |
462 | RefPtr<Node> expr; |
463 | Identifier ident; |
464 | }; |
465 | |
466 | class ArgumentListNode : public Node { |
467 | public: |
468 | // list pointer is tail of a circular list, cracked in the ArgumentsNode ctor |
469 | ArgumentListNode(Node *e) : next(this), expr(e) { Parser::noteNodeCycle(this); } |
470 | ArgumentListNode(ArgumentListNode *l, Node *e) |
471 | : next(l->next), expr(e) { l->next = this; } |
472 | |
473 | virtual void streamTo(SourceStream&) const; |
474 | PassRefPtr<ArgumentListNode> releaseNext() { return next.release(); } |
475 | virtual void breakCycle(); |
476 | |
477 | virtual void recurseVisit(NodeVisitor *visitor); |
478 | private: |
479 | friend class ArgumentsNode; |
480 | ListRefPtr<ArgumentListNode> next; |
481 | RefPtr<Node> expr; |
482 | }; |
483 | |
484 | class ArgumentsNode : public Node { |
485 | public: |
486 | ArgumentsNode() { } |
487 | ArgumentsNode(ArgumentListNode *l) |
488 | : list(l->next.release()) { Parser::removeNodeCycle(list.get()); } |
489 | |
490 | void generateEvalArguments(CompileState* comp); |
491 | virtual void streamTo(SourceStream&) const; |
492 | |
493 | virtual void recurseVisit(NodeVisitor *visitor); |
494 | private: |
495 | RefPtr<ArgumentListNode> list; |
496 | }; |
497 | |
498 | class NewExprNode : public Node { |
499 | public: |
500 | NewExprNode(Node *e) : expr(e) {} |
501 | NewExprNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} |
502 | |
503 | virtual OpValue generateEvalCode(CompileState* comp); |
504 | virtual void streamTo(SourceStream&) const; |
505 | virtual void recurseVisit(NodeVisitor *visitor); |
506 | private: |
507 | RefPtr<Node> expr; |
508 | RefPtr<ArgumentsNode> args; |
509 | }; |
510 | |
511 | class FunctionCallValueNode : public Node { |
512 | public: |
513 | FunctionCallValueNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} |
514 | |
515 | virtual OpValue generateEvalCode(CompileState* comp); |
516 | virtual void streamTo(SourceStream&) const; |
517 | virtual void recurseVisit(NodeVisitor *visitor); |
518 | private: |
519 | RefPtr<Node> expr; |
520 | RefPtr<ArgumentsNode> args; |
521 | }; |
522 | |
523 | class FunctionCallReferenceNode : public Node { |
524 | public: |
525 | FunctionCallReferenceNode(Node *e, ArgumentsNode *a) : expr(e), args(a) {} |
526 | |
527 | virtual OpValue generateEvalCode(CompileState* comp); |
528 | virtual void streamTo(SourceStream&) const; |
529 | virtual void recurseVisit(NodeVisitor *visitor); |
530 | private: |
531 | RefPtr<Node> expr; |
532 | RefPtr<ArgumentsNode> args; |
533 | }; |
534 | |
535 | class PostfixNode : public Node { |
536 | public: |
537 | PostfixNode(Node *l, Operator o) : m_loc(l), m_oper(o) {} |
538 | |
539 | void streamTo(SourceStream&) const; |
540 | void recurseVisit(NodeVisitor * visitor); |
541 | virtual OpValue generateEvalCode(CompileState* comp); |
542 | protected: |
543 | RefPtr<Node> m_loc; |
544 | Operator m_oper; |
545 | }; |
546 | |
547 | class DeleteReferenceNode : public Node { |
548 | public: |
549 | DeleteReferenceNode(LocationNode *l) : loc(l) {} |
550 | |
551 | void streamTo(SourceStream&) const; |
552 | void recurseVisit(NodeVisitor * visitor); |
553 | virtual OpValue generateEvalCode(CompileState* comp); |
554 | private: |
555 | RefPtr<LocationNode> loc; |
556 | }; |
557 | |
558 | class DeleteValueNode : public Node { |
559 | public: |
560 | DeleteValueNode(Node *e) : m_expr(e) {} |
561 | |
562 | virtual void streamTo(SourceStream&) const; |
563 | virtual void recurseVisit(NodeVisitor *visitor); |
564 | virtual OpValue generateEvalCode(CompileState* comp); |
565 | private: |
566 | RefPtr<Node> m_expr; |
567 | }; |
568 | |
569 | |
570 | class VoidNode : public Node { |
571 | public: |
572 | VoidNode(Node *e) : expr(e) {} |
573 | |
574 | virtual OpValue generateEvalCode(CompileState* comp); |
575 | virtual void streamTo(SourceStream&) const; |
576 | virtual void recurseVisit(NodeVisitor *visitor); |
577 | private: |
578 | RefPtr<Node> expr; |
579 | }; |
580 | |
581 | class TypeOfVarNode : public Node { |
582 | public: |
583 | TypeOfVarNode(VarAccessNode *l) : loc(l) {} |
584 | |
585 | virtual OpValue generateEvalCode(CompileState* comp); |
586 | void streamTo(SourceStream&) const; |
587 | void recurseVisit(NodeVisitor * visitor); |
588 | private: |
589 | RefPtr<VarAccessNode> loc; |
590 | }; |
591 | |
592 | class TypeOfValueNode : public Node { |
593 | public: |
594 | TypeOfValueNode(Node *e) : m_expr(e) {} |
595 | |
596 | virtual OpValue generateEvalCode(CompileState* comp); |
597 | virtual void streamTo(SourceStream&) const; |
598 | virtual void recurseVisit(NodeVisitor *visitor); |
599 | private: |
600 | RefPtr<Node> m_expr; |
601 | }; |
602 | |
603 | class PrefixNode : public Node { |
604 | public: |
605 | PrefixNode(Node *l, Operator o) : m_loc(l), m_oper(o) {} |
606 | |
607 | virtual OpValue generateEvalCode(CompileState* comp); |
608 | void streamTo(SourceStream&) const; |
609 | void recurseVisit(NodeVisitor * visitor); |
610 | protected: |
611 | RefPtr<Node> m_loc; |
612 | Operator m_oper; |
613 | }; |
614 | |
615 | class UnaryPlusNode : public Node { |
616 | public: |
617 | UnaryPlusNode(Node *e) : expr(e) {} |
618 | |
619 | virtual OpValue generateEvalCode(CompileState* comp); |
620 | virtual void streamTo(SourceStream&) const; |
621 | virtual void recurseVisit(NodeVisitor *visitor); |
622 | private: |
623 | RefPtr<Node> expr; |
624 | }; |
625 | |
626 | class NegateNode : public Node { |
627 | public: |
628 | NegateNode(Node *e) : expr(e) {} |
629 | |
630 | virtual OpValue generateEvalCode(CompileState* comp); |
631 | virtual void streamTo(SourceStream&) const; |
632 | virtual void recurseVisit(NodeVisitor *visitor); |
633 | private: |
634 | RefPtr<Node> expr; |
635 | }; |
636 | |
637 | class BitwiseNotNode : public Node { |
638 | public: |
639 | BitwiseNotNode(Node *e) : expr(e) {} |
640 | |
641 | virtual OpValue generateEvalCode(CompileState* comp); |
642 | virtual void streamTo(SourceStream&) const; |
643 | virtual void recurseVisit(NodeVisitor *visitor); |
644 | private: |
645 | RefPtr<Node> expr; |
646 | }; |
647 | |
648 | class LogicalNotNode : public Node { |
649 | public: |
650 | LogicalNotNode(Node *e) : expr(e) {} |
651 | |
652 | virtual OpValue generateEvalCode(CompileState* comp); |
653 | virtual void streamTo(SourceStream&) const; |
654 | virtual void recurseVisit(NodeVisitor *visitor); |
655 | private: |
656 | RefPtr<Node> expr; |
657 | }; |
658 | |
659 | class BinaryOperatorNode : public Node { |
660 | public: |
661 | BinaryOperatorNode(Node* e1, Node* e2, Operator op) |
662 | : expr1(e1), expr2(e2), oper(op) {} |
663 | |
664 | virtual OpValue generateEvalCode(CompileState* comp); |
665 | virtual void streamTo(SourceStream&) const; |
666 | virtual void recurseVisit(NodeVisitor* visitor); |
667 | private: |
668 | RefPtr<Node> expr1; |
669 | RefPtr<Node> expr2; |
670 | Operator oper; |
671 | }; |
672 | |
673 | /** |
674 | * expr1 && expr2, expr1 || expr2 |
675 | */ |
676 | class BinaryLogicalNode : public Node { |
677 | public: |
678 | BinaryLogicalNode(Node *e1, Operator o, Node *e2) : |
679 | expr1(e1), expr2(e2), oper(o) {} |
680 | |
681 | virtual OpValue generateEvalCode(CompileState* comp); |
682 | virtual void streamTo(SourceStream&) const; |
683 | virtual void recurseVisit(NodeVisitor *visitor); |
684 | private: |
685 | RefPtr<Node> expr1; |
686 | RefPtr<Node> expr2; |
687 | Operator oper; |
688 | }; |
689 | |
690 | /** |
691 | * The ternary operator, "logical ? expr1 : expr2" |
692 | */ |
693 | class ConditionalNode : public Node { |
694 | public: |
695 | ConditionalNode(Node *l, Node *e1, Node *e2) : |
696 | logical(l), expr1(e1), expr2(e2) {} |
697 | |
698 | virtual OpValue generateEvalCode(CompileState* comp); |
699 | virtual void streamTo(SourceStream&) const; |
700 | virtual void recurseVisit(NodeVisitor *visitor); |
701 | private: |
702 | RefPtr<Node> logical; |
703 | RefPtr<Node> expr1; |
704 | RefPtr<Node> expr2; |
705 | }; |
706 | |
707 | class AssignNode : public Node { |
708 | public: |
709 | AssignNode(Node* loc, Operator oper, Node *right) |
710 | : m_loc(loc), m_oper(oper), m_right(right) {} |
711 | |
712 | void streamTo(SourceStream&) const; |
713 | virtual OpValue generateEvalCode(CompileState* comp); |
714 | void recurseVisit(NodeVisitor * visitor); |
715 | protected: |
716 | RefPtr<Node> m_loc; |
717 | Operator m_oper; |
718 | RefPtr<Node> m_right; |
719 | }; |
720 | |
721 | class CommaNode : public Node { |
722 | public: |
723 | CommaNode(Node *e1, Node *e2) : expr1(e1), expr2(e2) {} |
724 | |
725 | virtual void streamTo(SourceStream&) const; |
726 | virtual void recurseVisit(NodeVisitor *visitor); |
727 | virtual OpValue generateEvalCode(CompileState* comp); |
728 | private: |
729 | RefPtr<Node> expr1; |
730 | RefPtr<Node> expr2; |
731 | }; |
732 | |
733 | class AssignExprNode : public Node { |
734 | public: |
735 | AssignExprNode(Node *e) : expr(e) {} |
736 | |
737 | virtual void streamTo(SourceStream&) const; |
738 | virtual void recurseVisit(NodeVisitor *visitor); |
739 | virtual OpValue generateEvalCode(CompileState* comp); |
740 | |
741 | Node* getExpr() { return expr.get(); } |
742 | private: |
743 | RefPtr<Node> expr; |
744 | }; |
745 | |
746 | class VarDeclNode : public Node { |
747 | public: |
748 | enum Type { Variable, Constant }; |
749 | VarDeclNode(const Identifier &id, AssignExprNode *in, Type t); |
750 | |
751 | void generateCode(CompileState* comp); |
752 | |
753 | virtual void streamTo(SourceStream&) const; |
754 | virtual void recurseVisit(NodeVisitor *visitor); |
755 | |
756 | virtual void processVarDecl(ExecState*); |
757 | private: |
758 | friend class VarStatementNode; |
759 | friend class VarDeclListNode; |
760 | Type varType; |
761 | Identifier ident; |
762 | RefPtr<AssignExprNode> init; |
763 | }; |
764 | |
765 | class VarDeclListNode : public Node { |
766 | public: |
767 | // list pointer is tail of a circular list, cracked in the ForNode/VarStatementNode ctor |
768 | VarDeclListNode(VarDeclNode *v) : next(this), var(v) { Parser::noteNodeCycle(this); } |
769 | VarDeclListNode(VarDeclListNode *l, VarDeclNode *v) |
770 | : next(l->next), var(v) { l->next = this; } |
771 | |
772 | virtual OpValue generateEvalCode(CompileState* comp); |
773 | virtual void streamTo(SourceStream&) const; |
774 | PassRefPtr<VarDeclListNode> releaseNext() { return next.release(); } |
775 | virtual void breakCycle(); |
776 | virtual void recurseVisit(NodeVisitor *visitor); |
777 | private: |
778 | friend class ForNode; |
779 | friend class VarStatementNode; |
780 | ListRefPtr<VarDeclListNode> next; |
781 | RefPtr<VarDeclNode> var; |
782 | }; |
783 | |
784 | class VarStatementNode : public StatementNode { |
785 | public: |
786 | VarStatementNode(VarDeclListNode *l) : next(l->next.release()) { Parser::removeNodeCycle(next.get()); } |
787 | |
788 | virtual void streamTo(SourceStream&) const; |
789 | virtual void recurseVisit(NodeVisitor *visitor); |
790 | virtual void generateExecCode(CompileState*); |
791 | private: |
792 | RefPtr<VarDeclListNode> next; |
793 | }; |
794 | |
795 | class BlockNode : public StatementNode { |
796 | public: |
797 | BlockNode(SourceElementsNode *s); |
798 | |
799 | virtual void streamTo(SourceStream&) const; |
800 | virtual void recurseVisit(NodeVisitor *visitor); |
801 | virtual void generateExecCode(CompileState*); |
802 | protected: |
803 | RefPtr<SourceElementsNode> source; |
804 | }; |
805 | |
806 | class EmptyStatementNode : public StatementNode { |
807 | public: |
808 | EmptyStatementNode() { } // debug |
809 | |
810 | virtual void streamTo(SourceStream&) const; |
811 | virtual void generateExecCode(CompileState*); |
812 | }; |
813 | |
814 | class ExprStatementNode : public StatementNode { |
815 | public: |
816 | ExprStatementNode(Node *e) : expr(e) { } |
817 | |
818 | virtual void streamTo(SourceStream&) const; |
819 | virtual void recurseVisit(NodeVisitor *visitor); |
820 | virtual void generateExecCode(CompileState*); |
821 | private: |
822 | RefPtr<Node> expr; |
823 | }; |
824 | |
825 | class IfNode : public StatementNode { |
826 | public: |
827 | IfNode(Node *e, StatementNode *s1, StatementNode *s2) |
828 | : expr(e), statement1(s1), statement2(s2) {} |
829 | |
830 | virtual void streamTo(SourceStream&) const; |
831 | virtual void recurseVisit(NodeVisitor *visitor); |
832 | virtual void generateExecCode(CompileState*); |
833 | private: |
834 | RefPtr<Node> expr; |
835 | RefPtr<StatementNode> statement1; |
836 | RefPtr<StatementNode> statement2; |
837 | }; |
838 | |
839 | class DoWhileNode : public StatementNode { |
840 | public: |
841 | DoWhileNode(StatementNode *s, Node *e) : statement(s), expr(e) {} |
842 | |
843 | virtual void streamTo(SourceStream&) const; |
844 | virtual void recurseVisit(NodeVisitor *visitor); |
845 | virtual void generateExecCode(CompileState*); |
846 | virtual bool isIterationStatement() const { return true; } |
847 | private: |
848 | RefPtr<StatementNode> statement; |
849 | RefPtr<Node> expr; |
850 | }; |
851 | |
852 | class WhileNode : public StatementNode { |
853 | public: |
854 | WhileNode(Node *e, StatementNode *s) : expr(e), statement(s) {} |
855 | |
856 | virtual void streamTo(SourceStream&) const; |
857 | virtual void recurseVisit(NodeVisitor *visitor); |
858 | virtual void generateExecCode(CompileState*); |
859 | virtual bool isIterationStatement() const { return true; } |
860 | private: |
861 | RefPtr<Node> expr; |
862 | RefPtr<StatementNode> statement; |
863 | }; |
864 | |
865 | class ForNode : public StatementNode { |
866 | public: |
867 | ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) : |
868 | expr1(e1), expr2(e2), expr3(e3), statement(s) {} |
869 | ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) : |
870 | expr1(e1->next.release()), expr2(e2), expr3(e3), statement(s) { Parser::removeNodeCycle(expr1.get()); } |
871 | |
872 | virtual void generateExecCode(CompileState*); |
873 | virtual void streamTo(SourceStream&) const; |
874 | virtual void recurseVisit(NodeVisitor *visitor); |
875 | virtual bool isIterationStatement() const { return true; } |
876 | private: |
877 | RefPtr<Node> expr1; |
878 | RefPtr<Node> expr2; |
879 | RefPtr<Node> expr3; |
880 | RefPtr<StatementNode> statement; |
881 | }; |
882 | |
883 | class ForInNode : public StatementNode { |
884 | public: |
885 | ForInNode(Node *l, Node *e, StatementNode *s); |
886 | ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s); |
887 | |
888 | virtual void generateExecCode(CompileState*); |
889 | virtual void streamTo(SourceStream&) const; |
890 | virtual void recurseVisit(NodeVisitor *visitor); |
891 | virtual bool isIterationStatement() const { return true; } |
892 | private: |
893 | Identifier ident; |
894 | RefPtr<AssignExprNode> init; |
895 | RefPtr<Node> lexpr; |
896 | RefPtr<Node> expr; |
897 | RefPtr<VarDeclNode> varDecl; |
898 | RefPtr<StatementNode> statement; |
899 | }; |
900 | |
901 | class ContinueNode : public StatementNode { |
902 | public: |
903 | ContinueNode() : target(0) { } |
904 | ContinueNode(const Identifier &i) : ident(i), target(0) { } |
905 | |
906 | virtual void generateExecCode(CompileState*); |
907 | virtual void streamTo(SourceStream&) const; |
908 | private: |
909 | Identifier ident; |
910 | const Node* target; |
911 | }; |
912 | |
913 | class BreakNode : public StatementNode { |
914 | public: |
915 | BreakNode() : target(0) { } |
916 | BreakNode(const Identifier &i) : ident(i), target(0) { } |
917 | |
918 | virtual void generateExecCode(CompileState*); |
919 | virtual void streamTo(SourceStream&) const; |
920 | private: |
921 | Identifier ident; |
922 | const Node* target; |
923 | }; |
924 | |
925 | class ReturnNode : public StatementNode { |
926 | public: |
927 | ReturnNode(Node *v) : value(v) {} |
928 | |
929 | virtual void generateExecCode(CompileState*); |
930 | virtual void streamTo(SourceStream&) const; |
931 | virtual void recurseVisit(NodeVisitor *visitor); |
932 | private: |
933 | RefPtr<Node> value; |
934 | }; |
935 | |
936 | class WithNode : public StatementNode { |
937 | public: |
938 | WithNode(Node *e, StatementNode *s) : expr(e), statement(s) {} |
939 | |
940 | virtual void generateExecCode(CompileState*); |
941 | virtual void streamTo(SourceStream&) const; |
942 | virtual void recurseVisit(NodeVisitor *visitor); |
943 | private: |
944 | RefPtr<Node> expr; |
945 | RefPtr<StatementNode> statement; |
946 | }; |
947 | |
948 | class LabelNode : public StatementNode { |
949 | public: |
950 | LabelNode(const Identifier &l, StatementNode *s) : label(l), statement(s) { } |
951 | |
952 | virtual void streamTo(SourceStream&) const; |
953 | virtual void recurseVisit(NodeVisitor *visitor); |
954 | virtual void generateExecCode(CompileState*); |
955 | virtual NodeType type() const { return LabelNodeType; } |
956 | private: |
957 | Identifier label; |
958 | RefPtr<StatementNode> statement; |
959 | }; |
960 | |
961 | class ThrowNode : public StatementNode { |
962 | public: |
963 | ThrowNode(Node *e) : expr(e) {} |
964 | |
965 | virtual void generateExecCode(CompileState*); |
966 | virtual void streamTo(SourceStream&) const; |
967 | virtual void recurseVisit(NodeVisitor *visitor); |
968 | private: |
969 | RefPtr<Node> expr; |
970 | }; |
971 | |
972 | class TryNode : public StatementNode { |
973 | public: |
974 | TryNode(StatementNode *b, const Identifier &e, StatementNode *c, StatementNode *f) |
975 | : tryBlock(b), exceptionIdent(e), catchBlock(c), finallyBlock(f) { } |
976 | virtual NodeType type() const { return TryNodeType; } |
977 | |
978 | virtual void generateExecCode(CompileState*); |
979 | virtual void streamTo(SourceStream&) const; |
980 | virtual void recurseVisit(NodeVisitor *visitor); |
981 | private: |
982 | RefPtr<StatementNode> tryBlock; |
983 | Identifier exceptionIdent; |
984 | RefPtr<StatementNode> catchBlock; |
985 | RefPtr<StatementNode> finallyBlock; |
986 | }; |
987 | |
988 | class ParameterNode : public Node { |
989 | public: |
990 | // list pointer is tail of a circular list, cracked in the FuncDeclNode/FuncExprNode ctor |
991 | ParameterNode(const Identifier &i) : id(i), next(this) { Parser::noteNodeCycle(this); } |
992 | ParameterNode(ParameterNode *next, const Identifier &i) |
993 | : id(i), next(next->next) { next->next = this; } |
994 | |
995 | const Identifier& ident() const { return id; } |
996 | ParameterNode *nextParam() const { return next.get(); } |
997 | virtual void streamTo(SourceStream&) const; |
998 | PassRefPtr<ParameterNode> releaseNext() { return next.release(); } |
999 | virtual void breakCycle(); |
1000 | |
1001 | virtual void recurseVisit(NodeVisitor *visitor); |
1002 | private: |
1003 | friend class FuncDeclNode; |
1004 | friend class FuncExprNode; |
1005 | Identifier id; |
1006 | ListRefPtr<ParameterNode> next; |
1007 | }; |
1008 | |
1009 | // Flags about function bodies we care about for codegen |
1010 | enum FunctionBodyFlags { |
1011 | // note: neither of the two below is set for things created via |
1012 | // top-level, eval, or function ctor |
1013 | FuncFl_Decl = 1, |
1014 | FuncFl_Expr = 2, |
1015 | FuncFl_HasEvalOp = 4 |
1016 | }; |
1017 | |
1018 | /** |
1019 | This AST node corresponds to the function body or top-level code in the AST, but is used to |
1020 | keep track of much of the information relevant to the whole function, |
1021 | such as parameter names and symbol tables. This is because there are both function |
1022 | declarations and expressions, so there is no natural single place to put this stuff |
1023 | above the body |
1024 | |
1025 | inherited by ProgramNode |
1026 | */ |
1027 | class FunctionBodyNode : public BlockNode { |
1028 | public: |
1029 | struct SymbolInfo { |
1030 | SymbolInfo(int _attr, FuncDeclNode* _funcDecl) : funcDecl(_funcDecl), attr(_attr) {} |
1031 | SymbolInfo() {} |
1032 | FuncDeclNode* funcDecl; |
1033 | int attr; |
1034 | }; |
1035 | FunctionBodyNode(SourceElementsNode *); |
1036 | int sourceId() { return m_sourceId; } |
1037 | const UString& sourceURL() { return m_sourceURL; } |
1038 | |
1039 | bool isCompiled() const { return m_compType != NotCompiled; } |
1040 | void compileIfNeeded(CodeType ctype, CompileType compType); |
1041 | void compile(CodeType ctype, CompileType compType); |
1042 | CompileType compileState() const { return m_compType; } |
1043 | |
1044 | virtual void generateExecCode(CompileState*); |
1045 | |
1046 | // Reserves a register for private use, making sure that id is in the right spot.. |
1047 | void reserveSlot(size_t id, bool shouldMark); |
1048 | |
1049 | // Symbol table functions |
1050 | SymbolTable& symbolTable() { return m_symbolTable; } |
1051 | size_t lookupSymbolID(const Identifier& id) const { return m_symbolTable.get(id.ustring().rep()); } |
1052 | |
1053 | int numLocalsAndRegisters() const { return m_symbolList.size(); } |
1054 | SymbolInfo* getLocalInfo() { return m_symbolList.data(); } |
1055 | |
1056 | size_t numFunctionLocals() const { return m_functionLocals.size(); } |
1057 | size_t* getFunctionLocalInfo() { return m_functionLocals.data(); } |
1058 | |
1059 | // Parameter stuff. We only collect the names during the parsing/ |
1060 | // while FunctionImp is responsible for managing the IDs. |
1061 | void addParam(const Identifier& ident); |
1062 | size_t numParams() const { return m_paramList.size(); } |
1063 | const Identifier& paramName(size_t pos) const { return m_paramList[pos]; } |
1064 | |
1065 | void addVarDecl(const Identifier& ident, int attr, ExecState* exec); |
1066 | void addFunDecl(const Identifier& ident, int attr, FuncDeclNode* funcDecl); |
1067 | |
1068 | // Adds a new symbol, killing any previous ID. |
1069 | void addSymbolOverwriteID(size_t id, const Identifier& ident, int attr); |
1070 | |
1071 | // Runs the code, compiling if needed. This should only be used for non-function ExecStates |
1072 | Completion execute(ExecState *exec); |
1073 | |
1074 | bool tearOffAtEnd() const { return m_tearOffAtEnd; } |
1075 | |
1076 | const CodeBlock& code() const { return m_compiledCode; } |
1077 | CodeBlock& code() { return m_compiledCode; } |
1078 | |
1079 | // Collection of FuncFl_* flags describing information collected about this function |
1080 | // during the parsing. |
1081 | unsigned flags() const { return m_flags; } |
1082 | |
1083 | private: |
1084 | size_t addSymbol(const Identifier& ident, int attr, FuncDeclNode* funcDecl = 0); |
1085 | UString m_sourceURL; |
1086 | int m_sourceId : 31; |
1087 | bool m_tearOffAtEnd : 1; |
1088 | CompileType m_compType; |
1089 | |
1090 | // Flags |
1091 | unsigned m_flags; |
1092 | |
1093 | // This maps id -> attributes and function decl info |
1094 | WTF::Vector<SymbolInfo> m_symbolList; |
1095 | |
1096 | // This contains the list of locals which contains function declarations |
1097 | WTF::Vector<size_t> m_functionLocals; |
1098 | |
1099 | // This maps name -> id |
1100 | SymbolTable m_symbolTable; |
1101 | |
1102 | // The list of parameter names |
1103 | WTF::Vector<Identifier> m_paramList; |
1104 | |
1105 | CodeBlock m_compiledCode; |
1106 | }; |
1107 | |
1108 | inline void FunctionBodyNode::compileIfNeeded(CodeType ctype, CompileType compType) { |
1109 | if (m_compType != compType) |
1110 | compile(ctype, compType); |
1111 | } |
1112 | |
1113 | class FuncExprNode : public Node { |
1114 | public: |
1115 | FuncExprNode(const Identifier &i, FunctionBodyNode *b, ParameterNode *p = 0) |
1116 | : ident(i), param(p ? p->next.release() : PassRefPtr<ParameterNode>(0)), body(b) { if (p) { Parser::removeNodeCycle(param.get()); } addParams(); } |
1117 | |
1118 | virtual OpValue generateEvalCode(CompileState* comp); |
1119 | virtual void streamTo(SourceStream&) const; |
1120 | virtual void recurseVisit(NodeVisitor *visitor); |
1121 | virtual bool scanForDeclarations() const { return false; } |
1122 | private: |
1123 | void addParams(); |
1124 | // Used for streamTo |
1125 | friend class PropertyNode; |
1126 | Identifier ident; |
1127 | RefPtr<ParameterNode> param; |
1128 | RefPtr<FunctionBodyNode> body; |
1129 | }; |
1130 | |
1131 | class FuncDeclNode : public StatementNode { |
1132 | public: |
1133 | FuncDeclNode(const Identifier &i, FunctionBodyNode *b) |
1134 | : ident(i), body(b) { addParams(); } |
1135 | FuncDeclNode(const Identifier &i, ParameterNode *p, FunctionBodyNode *b) |
1136 | : ident(i), param(p->next.release()), body(b) { Parser::removeNodeCycle(param.get()); addParams(); } |
1137 | |
1138 | virtual void generateExecCode(CompileState*); |
1139 | virtual void streamTo(SourceStream&) const; |
1140 | virtual void recurseVisit(NodeVisitor *visitor); |
1141 | virtual bool scanForDeclarations() const { return false; } |
1142 | |
1143 | virtual void processFuncDecl(ExecState*); |
1144 | FunctionImp* makeFunctionObject(ExecState*); |
1145 | private: |
1146 | void addParams(); |
1147 | Identifier ident; |
1148 | RefPtr<ParameterNode> param; |
1149 | RefPtr<FunctionBodyNode> body; |
1150 | }; |
1151 | |
1152 | // A linked list of source element nodes |
1153 | class SourceElementsNode : public StatementNode { |
1154 | public: |
1155 | // list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor |
1156 | SourceElementsNode(StatementNode*); |
1157 | SourceElementsNode(SourceElementsNode *s1, StatementNode *s2); |
1158 | |
1159 | virtual void generateExecCode(CompileState*); |
1160 | virtual void streamTo(SourceStream&) const; |
1161 | PassRefPtr<SourceElementsNode> releaseNext() { return next.release(); } |
1162 | virtual void breakCycle(); |
1163 | virtual void recurseVisit(NodeVisitor *visitor); |
1164 | private: |
1165 | friend class BlockNode; |
1166 | friend class CaseClauseNode; |
1167 | RefPtr<StatementNode> node; |
1168 | ListRefPtr<SourceElementsNode> next; |
1169 | }; |
1170 | |
1171 | class CaseClauseNode : public Node { |
1172 | public: |
1173 | CaseClauseNode(Node *e) : expr(e) { } |
1174 | CaseClauseNode(Node *e, SourceElementsNode *s) |
1175 | : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); } |
1176 | |
1177 | virtual void streamTo(SourceStream&) const; |
1178 | virtual void recurseVisit(NodeVisitor *visitor); |
1179 | private: |
1180 | friend class SwitchNode; |
1181 | RefPtr<Node> expr; |
1182 | RefPtr<SourceElementsNode> source; |
1183 | }; |
1184 | |
1185 | class ClauseListNode : public Node { |
1186 | public: |
1187 | // list pointer is tail of a circular list, cracked in the CaseBlockNode ctor |
1188 | ClauseListNode(CaseClauseNode *c) : clause(c), next(this) { Parser::noteNodeCycle(this); } |
1189 | ClauseListNode(ClauseListNode *n, CaseClauseNode *c) |
1190 | : clause(c), next(n->next) { n->next = this; } |
1191 | |
1192 | CaseClauseNode *getClause() const { return clause.get(); } |
1193 | ClauseListNode *getNext() const { return next.get(); } |
1194 | virtual void streamTo(SourceStream&) const; |
1195 | PassRefPtr<ClauseListNode> releaseNext() { return next.release(); } |
1196 | virtual void breakCycle(); |
1197 | virtual void recurseVisit(NodeVisitor *visitor); |
1198 | private: |
1199 | friend class SwitchNode; |
1200 | friend class CaseBlockNode; |
1201 | RefPtr<CaseClauseNode> clause; |
1202 | ListRefPtr<ClauseListNode> next; |
1203 | }; |
1204 | |
1205 | class CaseBlockNode : public Node { |
1206 | public: |
1207 | CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2); |
1208 | |
1209 | virtual void streamTo(SourceStream&) const; |
1210 | virtual void recurseVisit(NodeVisitor *visitor); |
1211 | private: |
1212 | friend class SwitchNode; |
1213 | RefPtr<ClauseListNode> list1; |
1214 | RefPtr<CaseClauseNode> def; |
1215 | RefPtr<ClauseListNode> list2; |
1216 | }; |
1217 | |
1218 | class SwitchNode : public StatementNode { |
1219 | public: |
1220 | SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { } |
1221 | |
1222 | virtual void streamTo(SourceStream&) const; |
1223 | virtual void recurseVisit(NodeVisitor *visitor); |
1224 | virtual void generateExecCode(CompileState* comp); |
1225 | private: |
1226 | RefPtr<Node> expr; |
1227 | RefPtr<CaseBlockNode> block; |
1228 | }; |
1229 | |
1230 | // important: these are also built when compiling things via the Function constructor |
1231 | // (see FunctionObjectImp::construct() and Parser::parseFunctionBody, so the existence |
1232 | // of this class rather than the bare FunctionBodyNode does not care much information. |
1233 | class ProgramNode : public FunctionBodyNode { |
1234 | public: |
1235 | ProgramNode(SourceElementsNode *s); |
1236 | virtual void streamTo(SourceStream&) const; |
1237 | }; |
1238 | |
1239 | class PackageNameNode : public Node { |
1240 | public: |
1241 | PackageNameNode(const Identifier &i) : names(0), id(i) { } |
1242 | PackageNameNode(PackageNameNode *n, |
1243 | const Identifier &i) : names(n), id(i) { } |
1244 | |
1245 | virtual void streamTo(SourceStream&) const; |
1246 | virtual void recurseVisit(NodeVisitor *visitor); |
1247 | |
1248 | Completion loadSymbol(ExecState* exec, bool wildcard); |
1249 | PackageObject* resolvePackage(ExecState* exec); |
1250 | |
1251 | private: |
1252 | PackageObject* resolvePackage(ExecState* exec, |
1253 | JSObject* baseObject, Package* basePackage); |
1254 | RefPtr<PackageNameNode> names; |
1255 | Identifier id; |
1256 | }; |
1257 | |
1258 | class ImportStatement : public StatementNode { |
1259 | public: |
1260 | ImportStatement(PackageNameNode *n) : name(n), wld(false) {} |
1261 | void enableWildcard() { wld = true; } |
1262 | void setAlias(const Identifier &a) { al = a; } |
1263 | |
1264 | virtual void generateExecCode(CompileState*); |
1265 | virtual void streamTo(SourceStream&) const; |
1266 | virtual void recurseVisit(NodeVisitor *visitor); |
1267 | private: |
1268 | virtual void processVarDecl (ExecState* state); |
1269 | RefPtr<PackageNameNode> name; |
1270 | Identifier al; |
1271 | bool wld; |
1272 | }; |
1273 | |
1274 | } // namespace |
1275 | |
1276 | #endif |
1277 | // kate: indent-width 2; replace-tabs on; tab-width 4; space-indent on; |
1278 | |