source: webkit/trunk/JavaScriptCore/kjs/nodes2string.cpp@ 29815

Last change on this file since 29815 was 29815, checked in by Darin Adler, 17 years ago

JavaScriptCore:

Reviewed by Oliver.

Test: fast/js/function-toString-parentheses.html

The problem here was that a NumberNode with a negative number in it had the wrong
precedence. It's not a primary expression, it's a unary operator with a primary
expression after it.

Once the precedence of NumberNode was fixed, the cases from bug 17020 were also
fixed without trying to treat bracket nodes like dot nodes. That wasn't needed.
The reason we handle numbers before dot nodes specially is that the dot is a
legal character in a number. The same is not true of a bracket. Eventually we
could get smarter, and only add the parentheses when there is actual ambiguity.
There is none if the string form of the number already has a dot in it, or if
it's a number with a alphabetic name like infinity or NAN.

  • kjs/nodes.h: Renamed back from ObjectAccess to DotExpr. (KJS::NumberNode::precedence): Return PrecUnary for negative numbers, since they serialize as a unary operator, not a primary expression.
  • kjs/nodes2string.cpp: (KJS::SourceStream::operator<<): Clear m_numberNeedsParens if this adds parens; one set is enough. (KJS::bracketNodeStreamTo): Remove unneeded special flag here. Normal operator precedence suffices. (KJS::NewExprNode::streamTo): Ditto.

LayoutTests:

Reviewed by Oliver.

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