]> git.saurik.com Git - apple/javascriptcore.git/blob - kjs/nodes2string.cpp
JavaScriptCore-466.1.6.tar.gz
[apple/javascriptcore.git] / kjs / nodes2string.cpp
1 /*
2 * Copyright (C) 2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "config.h"
24 #include "nodes.h"
25
26 #include <wtf/MathExtras.h>
27 #include <wtf/StringExtras.h>
28 #include <wtf/unicode/Unicode.h>
29
30 using namespace WTF;
31 using namespace Unicode;
32
33 namespace KJS {
34
35 // A simple text streaming class that helps with code indentation.
36
37 enum EndlType { Endl };
38 enum IndentType { Indent };
39 enum UnindentType { Unindent };
40 enum DotExprType { DotExpr };
41
42 class SourceStream {
43 public:
44 SourceStream()
45 : m_numberNeedsParens(false)
46 , m_atStartOfStatement(true)
47 , m_precedence(PrecExpression)
48 {
49 }
50
51 UString toString() const { return m_string; }
52
53 SourceStream& operator<<(const Identifier&);
54 SourceStream& operator<<(const UString&);
55 SourceStream& operator<<(const char*);
56 SourceStream& operator<<(double);
57 SourceStream& operator<<(char);
58 SourceStream& operator<<(EndlType);
59 SourceStream& operator<<(IndentType);
60 SourceStream& operator<<(UnindentType);
61 SourceStream& operator<<(DotExprType);
62 SourceStream& operator<<(Precedence);
63 SourceStream& operator<<(Node*);
64 template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); }
65
66 private:
67 UString m_string;
68 UString m_spacesForIndentation;
69 bool m_numberNeedsParens;
70 bool m_atStartOfStatement;
71 Precedence m_precedence;
72 };
73
74 // --------
75
76 static UString escapeStringForPrettyPrinting(const UString& s)
77 {
78 UString escapedString;
79
80 for (int i = 0; i < s.size(); i++) {
81 unsigned short c = s.data()[i].unicode();
82 switch (c) {
83 case '\"':
84 escapedString += "\\\"";
85 break;
86 case '\n':
87 escapedString += "\\n";
88 break;
89 case '\r':
90 escapedString += "\\r";
91 break;
92 case '\t':
93 escapedString += "\\t";
94 break;
95 case '\\':
96 escapedString += "\\\\";
97 break;
98 default:
99 if (c < 128 && isPrintableChar(c))
100 escapedString.append(c);
101 else {
102 char hexValue[7];
103 snprintf(hexValue, 7, "\\u%04x", c);
104 escapedString += hexValue;
105 }
106 }
107 }
108
109 return escapedString;
110 }
111
112 static const char* operatorString(Operator oper)
113 {
114 switch (oper) {
115 case OpEqual:
116 return "=";
117 case OpMultEq:
118 return "*=";
119 case OpDivEq:
120 return "/=";
121 case OpPlusEq:
122 return "+=";
123 case OpMinusEq:
124 return "-=";
125 case OpLShift:
126 return "<<=";
127 case OpRShift:
128 return ">>=";
129 case OpURShift:
130 return ">>>=";
131 case OpAndEq:
132 return "&=";
133 case OpXOrEq:
134 return "^=";
135 case OpOrEq:
136 return "|=";
137 case OpModEq:
138 return "%=";
139 case OpPlusPlus:
140 return "++";
141 case OpMinusMinus:
142 return "--";
143 }
144 ASSERT_NOT_REACHED();
145 return "???";
146 }
147
148 static bool isParserRoundTripNumber(const UString& string)
149 {
150 double number = string.toDouble(false, false);
151 if (isnan(number) || isinf(number))
152 return false;
153 return string == UString::from(number);
154 }
155
156 // --------
157
158 SourceStream& SourceStream::operator<<(char c)
159 {
160 m_numberNeedsParens = false;
161 m_atStartOfStatement = false;
162 UChar ch(c);
163 m_string.append(ch);
164 return *this;
165 }
166
167 SourceStream& SourceStream::operator<<(const char* s)
168 {
169 m_numberNeedsParens = false;
170 m_atStartOfStatement = false;
171 m_string += s;
172 return *this;
173 }
174
175 SourceStream& SourceStream::operator<<(double value)
176 {
177 bool needParens = m_numberNeedsParens;
178 m_numberNeedsParens = false;
179 m_atStartOfStatement = false;
180
181 if (needParens)
182 m_string.append('(');
183 m_string += UString::from(value);
184 if (needParens)
185 m_string.append(')');
186
187 return *this;
188 }
189
190 SourceStream& SourceStream::operator<<(const UString& s)
191 {
192 m_numberNeedsParens = false;
193 m_atStartOfStatement = false;
194 m_string += s;
195 return *this;
196 }
197
198 SourceStream& SourceStream::operator<<(const Identifier& s)
199 {
200 m_numberNeedsParens = false;
201 m_atStartOfStatement = false;
202 m_string += s.ustring();
203 return *this;
204 }
205
206 SourceStream& SourceStream::operator<<(Node* n)
207 {
208 bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost());
209 m_precedence = PrecExpression;
210 if (!n)
211 return *this;
212 if (needParens) {
213 m_numberNeedsParens = false;
214 m_string.append('(');
215 }
216 n->streamTo(*this);
217 if (needParens)
218 m_string.append(')');
219 return *this;
220 }
221
222 SourceStream& SourceStream::operator<<(EndlType)
223 {
224 m_numberNeedsParens = false;
225 m_atStartOfStatement = true;
226 m_string.append('\n');
227 m_string.append(m_spacesForIndentation);
228 return *this;
229 }
230
231 SourceStream& SourceStream::operator<<(IndentType)
232 {
233 m_numberNeedsParens = false;
234 m_atStartOfStatement = false;
235 m_spacesForIndentation += " ";
236 return *this;
237 }
238
239 SourceStream& SourceStream::operator<<(UnindentType)
240 {
241 m_numberNeedsParens = false;
242 m_atStartOfStatement = false;
243 m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
244 return *this;
245 }
246
247 inline SourceStream& SourceStream::operator<<(DotExprType)
248 {
249 m_numberNeedsParens = true;
250 return *this;
251 }
252
253 inline SourceStream& SourceStream::operator<<(Precedence precedence)
254 {
255 m_precedence = precedence;
256 return *this;
257 }
258
259 static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
260 const char* operatorString, Node* left, Node* right)
261 {
262 s << precedence << left
263 << ' ' << operatorString << ' '
264 << static_cast<Precedence>(precedence - 1) << right;
265 }
266
267 template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
268 Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
269 {
270 streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
271 }
272
273 static inline void bracketNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const RefPtr<ExpressionNode>& subscript)
274 {
275 s << PrecCall << base.get() << "[" << subscript.get() << "]";
276 }
277
278 static inline void dotNodeStreamTo(SourceStream& s, const RefPtr<ExpressionNode>& base, const Identifier& ident)
279 {
280 s << DotExpr << PrecCall << base.get() << "." << ident;
281 }
282
283 // --------
284
285 UString Node::toString()
286 {
287 SourceStream stream;
288 streamTo(stream);
289 return stream.toString();
290 }
291
292 // --------
293
294 void NullNode::streamTo(SourceStream& s)
295 {
296 s << "null";
297 }
298
299 void FalseNode::streamTo(SourceStream& s)
300 {
301 s << "false";
302 }
303
304 void TrueNode::streamTo(SourceStream& s)
305 {
306 s << "true";
307 }
308
309 void PlaceholderTrueNode::streamTo(SourceStream&)
310 {
311 }
312
313 void NumberNode::streamTo(SourceStream& s)
314 {
315 s << value();
316 }
317
318 void StringNode::streamTo(SourceStream& s)
319 {
320 s << '"' << escapeStringForPrettyPrinting(m_value) << '"';
321 }
322
323 void RegExpNode::streamTo(SourceStream& s)
324 {
325 s << '/' << m_regExp->pattern() << '/' << m_regExp->flags();
326 }
327
328 void ThisNode::streamTo(SourceStream& s)
329 {
330 s << "this";
331 }
332
333 void ResolveNode::streamTo(SourceStream& s)
334 {
335 s << m_ident;
336 }
337
338 void ElementNode::streamTo(SourceStream& s)
339 {
340 for (const ElementNode* n = this; n; n = n->m_next.get()) {
341 for (int i = 0; i < n->m_elision; i++)
342 s << ',';
343 s << PrecAssignment << n->m_node;
344 if (n->m_next)
345 s << ',';
346 }
347 }
348
349 void ArrayNode::streamTo(SourceStream& s)
350 {
351 s << '[' << m_element;
352 for (int i = 0; i < m_elision; i++)
353 s << ',';
354 // Parser consumes one elision comma if there's array elements
355 // present in the expression.
356 if (m_optional && m_element)
357 s << ',';
358 s << ']';
359 }
360
361 void ObjectLiteralNode::streamTo(SourceStream& s)
362 {
363 if (m_list)
364 s << "{ " << m_list << " }";
365 else
366 s << "{ }";
367 }
368
369 void PropertyListNode::streamTo(SourceStream& s)
370 {
371 s << m_node;
372 for (const PropertyListNode* n = m_next.get(); n; n = n->m_next.get())
373 s << ", " << n->m_node;
374 }
375
376 void PropertyNode::streamTo(SourceStream& s)
377 {
378 switch (m_type) {
379 case Constant: {
380 UString propertyName = name().ustring();
381 if (isParserRoundTripNumber(propertyName))
382 s << propertyName;
383 else
384 s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
385 s << ": " << PrecAssignment << m_assign;
386 break;
387 }
388 case Getter:
389 case Setter: {
390 const FuncExprNode* func = static_cast<const FuncExprNode*>(m_assign.get());
391 if (m_type == Getter)
392 s << "get ";
393 else
394 s << "set ";
395 s << escapeStringForPrettyPrinting(name().ustring())
396 << "(" << func->m_parameter << ')' << func->m_body;
397 break;
398 }
399 }
400 }
401
402 void BracketAccessorNode::streamTo(SourceStream& s)
403 {
404 bracketNodeStreamTo(s, m_base, m_subscript);
405 }
406
407 void DotAccessorNode::streamTo(SourceStream& s)
408 {
409 dotNodeStreamTo(s, m_base, m_ident);
410 }
411
412 void ArgumentListNode::streamTo(SourceStream& s)
413 {
414 s << PrecAssignment << m_expr;
415 for (ArgumentListNode* n = m_next.get(); n; n = n->m_next.get())
416 s << ", " << PrecAssignment << n->m_expr;
417 }
418
419 void ArgumentsNode::streamTo(SourceStream& s)
420 {
421 s << '(' << m_listNode << ')';
422 }
423
424 void NewExprNode::streamTo(SourceStream& s)
425 {
426 s << "new " << PrecMember << m_expr << m_args;
427 }
428
429 void FunctionCallValueNode::streamTo(SourceStream& s)
430 {
431 s << PrecCall << m_expr << m_args;
432 }
433
434 void FunctionCallResolveNode::streamTo(SourceStream& s)
435 {
436 s << m_ident << m_args;
437 }
438
439 void FunctionCallBracketNode::streamTo(SourceStream& s)
440 {
441 bracketNodeStreamTo(s, m_base, m_subscript);
442 s << m_args;
443 }
444
445 void FunctionCallDotNode::streamTo(SourceStream& s)
446 {
447 dotNodeStreamTo(s, m_base, m_ident);
448 s << m_args;
449 }
450
451 void PostIncResolveNode::streamTo(SourceStream& s)
452 {
453 s << m_ident << "++";
454 }
455
456 void PostDecResolveNode::streamTo(SourceStream& s)
457 {
458 s << m_ident << "--";
459 }
460
461 void PostIncBracketNode::streamTo(SourceStream& s)
462 {
463 bracketNodeStreamTo(s, m_base, m_subscript);
464 s << "++";
465 }
466
467 void PostDecBracketNode::streamTo(SourceStream& s)
468 {
469 bracketNodeStreamTo(s, m_base, m_subscript);
470 s << "--";
471 }
472
473 void PostIncDotNode::streamTo(SourceStream& s)
474 {
475 dotNodeStreamTo(s, m_base, m_ident);
476 s << "++";
477 }
478
479 void PostDecDotNode::streamTo(SourceStream& s)
480 {
481 dotNodeStreamTo(s, m_base, m_ident);
482 s << "--";
483 }
484
485 void PostfixErrorNode::streamTo(SourceStream& s)
486 {
487 s << PrecLeftHandSide << m_expr;
488 if (m_operator == OpPlusPlus)
489 s << "++";
490 else
491 s << "--";
492 }
493
494 void DeleteResolveNode::streamTo(SourceStream& s)
495 {
496 s << "delete " << m_ident;
497 }
498
499 void DeleteBracketNode::streamTo(SourceStream& s)
500 {
501 s << "delete ";
502 bracketNodeStreamTo(s, m_base, m_subscript);
503 }
504
505 void DeleteDotNode::streamTo(SourceStream& s)
506 {
507 s << "delete ";
508 dotNodeStreamTo(s, m_base, m_ident);
509 }
510
511 void DeleteValueNode::streamTo(SourceStream& s)
512 {
513 s << "delete " << PrecUnary << m_expr;
514 }
515
516 void VoidNode::streamTo(SourceStream& s)
517 {
518 s << "void " << PrecUnary << m_expr;
519 }
520
521 void TypeOfValueNode::streamTo(SourceStream& s)
522 {
523 s << "typeof " << PrecUnary << m_expr;
524 }
525
526 void TypeOfResolveNode::streamTo(SourceStream& s)
527 {
528 s << "typeof " << m_ident;
529 }
530
531 void PreIncResolveNode::streamTo(SourceStream& s)
532 {
533 s << "++" << m_ident;
534 }
535
536 void PreDecResolveNode::streamTo(SourceStream& s)
537 {
538 s << "--" << m_ident;
539 }
540
541 void PreIncBracketNode::streamTo(SourceStream& s)
542 {
543 s << "++";
544 bracketNodeStreamTo(s, m_base, m_subscript);
545 }
546
547 void PreDecBracketNode::streamTo(SourceStream& s)
548 {
549 s << "--";
550 bracketNodeStreamTo(s, m_base, m_subscript);
551 }
552
553 void PreIncDotNode::streamTo(SourceStream& s)
554 {
555 s << "++";
556 dotNodeStreamTo(s, m_base, m_ident);
557 }
558
559 void PreDecDotNode::streamTo(SourceStream& s)
560 {
561 s << "--";
562 dotNodeStreamTo(s, m_base, m_ident);
563 }
564
565 void PrefixErrorNode::streamTo(SourceStream& s)
566 {
567 if (m_operator == OpPlusPlus)
568 s << "++" << PrecUnary << m_expr;
569 else
570 s << "--" << PrecUnary << m_expr;
571 }
572
573 void UnaryPlusNode::streamTo(SourceStream& s)
574 {
575 s << "+ " << PrecUnary << m_expr;
576 }
577
578 void NegateNode::streamTo(SourceStream& s)
579 {
580 s << "- " << PrecUnary << m_expr;
581 }
582
583 void BitwiseNotNode::streamTo(SourceStream& s)
584 {
585 s << "~" << PrecUnary << m_expr;
586 }
587
588 void LogicalNotNode::streamTo(SourceStream& s)
589 {
590 s << "!" << PrecUnary << m_expr;
591 }
592
593 void MultNode::streamTo(SourceStream& s)
594 {
595 streamLeftAssociativeBinaryOperator(s, precedence(), "*", m_term1, m_term2);
596 }
597
598 void DivNode::streamTo(SourceStream& s)
599 {
600 streamLeftAssociativeBinaryOperator(s, precedence(), "/", m_term1, m_term2);
601 }
602
603 void ModNode::streamTo(SourceStream& s)
604 {
605 streamLeftAssociativeBinaryOperator(s, precedence(), "%", m_term1, m_term2);
606 }
607
608 void AddNode::streamTo(SourceStream& s)
609 {
610 streamLeftAssociativeBinaryOperator(s, precedence(), "+", m_term1, m_term2);
611 }
612
613 void SubNode::streamTo(SourceStream& s)
614 {
615 streamLeftAssociativeBinaryOperator(s, precedence(), "-", m_term1, m_term2);
616 }
617
618 void LeftShiftNode::streamTo(SourceStream& s)
619 {
620 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", m_term1, m_term2);
621 }
622
623 void RightShiftNode::streamTo(SourceStream& s)
624 {
625 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", m_term1, m_term2);
626 }
627
628 void UnsignedRightShiftNode::streamTo(SourceStream& s)
629 {
630 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", m_term1, m_term2);
631 }
632
633 void LessNode::streamTo(SourceStream& s)
634 {
635 streamLeftAssociativeBinaryOperator(s, precedence(), "<", m_expr1, m_expr2);
636 }
637
638 void GreaterNode::streamTo(SourceStream& s)
639 {
640 streamLeftAssociativeBinaryOperator(s, precedence(), ">", m_expr1, m_expr2);
641 }
642
643 void LessEqNode::streamTo(SourceStream& s)
644 {
645 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", m_expr1, m_expr2);
646 }
647
648 void GreaterEqNode::streamTo(SourceStream& s)
649 {
650 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", m_expr1, m_expr2);
651 }
652
653 void InstanceOfNode::streamTo(SourceStream& s)
654 {
655 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", m_expr1, m_expr2);
656 }
657
658 void InNode::streamTo(SourceStream& s)
659 {
660 streamLeftAssociativeBinaryOperator(s, precedence(), "in", m_expr1, m_expr2);
661 }
662
663 void EqualNode::streamTo(SourceStream& s)
664 {
665 streamLeftAssociativeBinaryOperator(s, precedence(), "==", m_expr1, m_expr2);
666 }
667
668 void NotEqualNode::streamTo(SourceStream& s)
669 {
670 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", m_expr1, m_expr2);
671 }
672
673 void StrictEqualNode::streamTo(SourceStream& s)
674 {
675 streamLeftAssociativeBinaryOperator(s, precedence(), "===", m_expr1, m_expr2);
676 }
677
678 void NotStrictEqualNode::streamTo(SourceStream& s)
679 {
680 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", m_expr1, m_expr2);
681 }
682
683 void BitAndNode::streamTo(SourceStream& s)
684 {
685 streamLeftAssociativeBinaryOperator(s, precedence(), "&", m_expr1, m_expr2);
686 }
687
688 void BitXOrNode::streamTo(SourceStream& s)
689 {
690 streamLeftAssociativeBinaryOperator(s, precedence(), "^", m_expr1, m_expr2);
691 }
692
693 void BitOrNode::streamTo(SourceStream& s)
694 {
695 streamLeftAssociativeBinaryOperator(s, precedence(), "|", m_expr1, m_expr2);
696 }
697
698 void LogicalAndNode::streamTo(SourceStream& s)
699 {
700 streamLeftAssociativeBinaryOperator(s, precedence(), "&&", m_expr1, m_expr2);
701 }
702
703 void LogicalOrNode::streamTo(SourceStream& s)
704 {
705 streamLeftAssociativeBinaryOperator(s, precedence(), "||", m_expr1, m_expr2);
706 }
707
708 void ConditionalNode::streamTo(SourceStream& s)
709 {
710 s << PrecLogicalOr << m_logical
711 << " ? " << PrecAssignment << m_expr1
712 << " : " << PrecAssignment << m_expr2;
713 }
714
715 void ReadModifyResolveNode::streamTo(SourceStream& s)
716 {
717 s << m_ident << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
718 }
719
720 void AssignResolveNode::streamTo(SourceStream& s)
721 {
722 s << m_ident << " = " << PrecAssignment << m_right;
723 }
724
725 void ReadModifyBracketNode::streamTo(SourceStream& s)
726 {
727 bracketNodeStreamTo(s, m_base, m_subscript);
728 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
729 }
730
731 void AssignBracketNode::streamTo(SourceStream& s)
732 {
733 bracketNodeStreamTo(s, m_base, m_subscript);
734 s << " = " << PrecAssignment << m_right;
735 }
736
737 void ReadModifyDotNode::streamTo(SourceStream& s)
738 {
739 dotNodeStreamTo(s, m_base, m_ident);
740 s << ' ' << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
741 }
742
743 void AssignDotNode::streamTo(SourceStream& s)
744 {
745 dotNodeStreamTo(s, m_base, m_ident);
746 s << " = " << PrecAssignment << m_right;
747 }
748
749 void AssignErrorNode::streamTo(SourceStream& s)
750 {
751 s << PrecLeftHandSide << m_left << ' '
752 << operatorString(m_operator) << ' ' << PrecAssignment << m_right;
753 }
754
755 void CommaNode::streamTo(SourceStream& s)
756 {
757 s << PrecAssignment << m_expr1 << ", " << PrecAssignment << m_expr2;
758 }
759
760 void ConstDeclNode::streamTo(SourceStream& s)
761 {
762 s << m_ident;
763 if (m_init)
764 s << " = " << m_init;
765 for (ConstDeclNode* n = m_next.get(); n; n = n->m_next.get()) {
766 s << ", " << m_ident;
767 if (m_init)
768 s << " = " << m_init;
769 }
770 }
771
772 void ConstStatementNode::streamTo(SourceStream& s)
773 {
774 s << Endl << "const " << m_next << ';';
775 }
776
777 static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
778 {
779 for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
780 s << *ptr;
781 }
782
783 void BlockNode::streamTo(SourceStream& s)
784 {
785 s << Endl << "{" << Indent;
786 statementListStreamTo(m_children, s);
787 s << Unindent << Endl << "}";
788 }
789
790 void ScopeNode::streamTo(SourceStream& s)
791 {
792 s << Endl << "{" << Indent;
793
794 bool printedVar = false;
795 for (size_t i = 0; i < m_varStack.size(); ++i) {
796 if (m_varStack[i].second == 0) {
797 if (!printedVar) {
798 s << Endl << "var ";
799 printedVar = true;
800 } else
801 s << ", ";
802 s << m_varStack[i].first;
803 }
804 }
805 if (printedVar)
806 s << ';';
807
808 statementListStreamTo(m_children, s);
809 s << Unindent << Endl << "}";
810 }
811
812 void FunctionBodyNode::streamTo(SourceStream& s)
813 {
814 if (m_children.isEmpty())
815 parser().reparse(this);
816 ScopeNode::streamTo(s);
817 }
818
819 void EmptyStatementNode::streamTo(SourceStream& s)
820 {
821 s << Endl << ';';
822 }
823
824 void ExprStatementNode::streamTo(SourceStream& s)
825 {
826 s << Endl << m_expr << ';';
827 }
828
829 void VarStatementNode::streamTo(SourceStream& s)
830 {
831 s << Endl << "var " << m_expr << ';';
832 }
833
834 void IfNode::streamTo(SourceStream& s)
835 {
836 s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
837 }
838
839 void IfElseNode::streamTo(SourceStream& s)
840 {
841 IfNode::streamTo(s);
842 s << Endl << "else" << Indent << m_elseBlock << Unindent;
843 }
844
845 void DoWhileNode::streamTo(SourceStream& s)
846 {
847 s << Endl << "do " << Indent << m_statement << Unindent << Endl
848 << "while (" << m_expr << ");";
849 }
850
851 void WhileNode::streamTo(SourceStream& s)
852 {
853 s << Endl << "while (" << m_expr << ')' << Indent << m_statement << Unindent;
854 }
855
856 void ForNode::streamTo(SourceStream& s)
857 {
858 s << Endl << "for ("
859 << (m_expr1WasVarDecl ? "var " : "")
860 << m_expr1
861 << "; " << m_expr2
862 << "; " << m_expr3
863 << ')' << Indent << m_statement << Unindent;
864 }
865
866 void ForInNode::streamTo(SourceStream& s)
867 {
868 s << Endl << "for (";
869 if (m_identIsVarDecl) {
870 s << "var ";
871 if (m_init)
872 s << m_init;
873 else
874 s << PrecLeftHandSide << m_lexpr;
875 } else
876 s << PrecLeftHandSide << m_lexpr;
877
878 s << " in " << m_expr << ')' << Indent << m_statement << Unindent;
879 }
880
881 void ContinueNode::streamTo(SourceStream& s)
882 {
883 s << Endl << "continue";
884 if (!m_ident.isNull())
885 s << ' ' << m_ident;
886 s << ';';
887 }
888
889 void BreakNode::streamTo(SourceStream& s)
890 {
891 s << Endl << "break";
892 if (!m_ident.isNull())
893 s << ' ' << m_ident;
894 s << ';';
895 }
896
897 void ReturnNode::streamTo(SourceStream& s)
898 {
899 s << Endl << "return";
900 if (m_value)
901 s << ' ' << m_value;
902 s << ';';
903 }
904
905 void WithNode::streamTo(SourceStream& s)
906 {
907 s << Endl << "with (" << m_expr << ") " << m_statement;
908 }
909
910 void CaseClauseNode::streamTo(SourceStream& s)
911 {
912 s << Endl;
913 if (m_expr)
914 s << "case " << m_expr;
915 else
916 s << "default";
917 s << ":" << Indent;
918 statementListStreamTo(m_children, s);
919 s << Unindent;
920 }
921
922 void ClauseListNode::streamTo(SourceStream& s)
923 {
924 for (const ClauseListNode* n = this; n; n = n->getNext())
925 s << n->getClause();
926 }
927
928 void CaseBlockNode::streamTo(SourceStream& s)
929 {
930 for (const ClauseListNode* n = m_list1.get(); n; n = n->getNext())
931 s << n->getClause();
932 s << m_defaultClause;
933 for (const ClauseListNode* n = m_list2.get(); n; n = n->getNext())
934 s << n->getClause();
935 }
936
937 void SwitchNode::streamTo(SourceStream& s)
938 {
939 s << Endl << "switch (" << m_expr << ") {"
940 << Indent << m_block << Unindent
941 << Endl << "}";
942 }
943
944 void LabelNode::streamTo(SourceStream& s)
945 {
946 s << Endl << m_label << ":" << Indent << m_statement << Unindent;
947 }
948
949 void ThrowNode::streamTo(SourceStream& s)
950 {
951 s << Endl << "throw " << m_expr << ';';
952 }
953
954 void TryNode::streamTo(SourceStream& s)
955 {
956 s << Endl << "try " << m_tryBlock;
957 if (m_catchBlock)
958 s << Endl << "catch (" << m_exceptionIdent << ')' << m_catchBlock;
959 if (m_finallyBlock)
960 s << Endl << "finally " << m_finallyBlock;
961 }
962
963 void ParameterNode::streamTo(SourceStream& s)
964 {
965 s << m_ident;
966 for (ParameterNode* n = m_next.get(); n; n = n->m_next.get())
967 s << ", " << n->m_ident;
968 }
969
970 void FuncDeclNode::streamTo(SourceStream& s)
971 {
972 s << Endl << "function " << m_ident << '(' << m_parameter << ')' << m_body;
973 }
974
975 void FuncExprNode::streamTo(SourceStream& s)
976 {
977 s << "function " << m_ident << '(' << m_parameter << ')' << m_body;
978 }
979
980 } // namespace KJS