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

Last change on this file since 27695 was 27695, checked in by eseidel, 18 years ago

2007-11-10 Eric Seidel <[email protected]>

Reviewed by darin.

Add simple type inferencing to the parser, and create custom
AddNode and LessNode subclasses based on inferred types.
http://bugs.webkit.org/show_bug.cgi?id=15884

SunSpider claims this is at least a 0.5% speedup.

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