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

Last change on this file since 21406 was 21406, checked in by bdash, 18 years ago

2007-05-11 Kimmo Kinnunen <Kimmo Kinnunen>

Reviewed by Darin.

  • kjs/nodes2string.cpp: (KJS::SourceStream::): Add boolean flag to indicate that if next item is a number, it should be grouped. Add new formatting enum which turns on the boolean flag. (KJS::SourceStream::SourceStream): Added. Initialize the flag. (SourceStream::operator<<): Added. New overloaded operator with double value as parameter. (NumberNode::streamTo): Use the double operator (ArrayNode::streamTo): (DotAccessorNode::streamTo): (FunctionCallDotNode::streamTo): (FunctionCallParenDotNode::streamTo): (PostfixDotNode::streamTo): (DeleteDotNode::streamTo): (PrefixDotNode::streamTo): (AssignDotNode::streamTo): Use the new formatting enum to turn on the grouping flag.

2007-05-11 Kimmo Kinnunen <Kimmo Kinnunen>

Reviewed by Darin.

Tests for http://bugs.webkit.org/show_bug.cgi?id=10878
Bug 10878: Incorrect decompilation for "4..x"

  • fast/js/resources/toString-number-dot-expr.js: Added.
  • fast/js/toString-number-dot-expr-expected.txt: Added.
  • fast/js/toString-number-dot-expr.html: Added.
  • Property svn:eol-style set to native
File size: 15.6 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2002 Harri Porten ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
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#include "function.h"
26
27namespace KJS {
28 /**
29 * A simple text streaming class that helps with code indentation.
30 */
31 class SourceStream {
32 public:
33 enum Format {
34 Endl, Indent, Unindent, DotExpr
35 };
36 SourceStream() : m_groupIfNumber(false) {}
37 UString toString() const { return str; }
38 SourceStream& operator<<(const Identifier &);
39 SourceStream& operator<<(const UString &);
40 SourceStream& operator<<(const char *);
41 SourceStream& operator<<(double);
42 SourceStream& operator<<(char);
43 SourceStream& operator<<(Format f);
44 SourceStream& operator<<(const Node *);
45 template <typename T> SourceStream& operator<<(RefPtr<T> n) { return this->operator<<(n.get()); }
46
47 private:
48 UString str; /* TODO: buffer */
49 UString ind;
50 bool m_groupIfNumber;
51 };
52}
53
54using namespace KJS;
55
56SourceStream& SourceStream::operator<<(char c)
57{
58 m_groupIfNumber = false;
59 UChar ch(c);
60 str += UString(&ch, 1);
61 return *this;
62}
63
64SourceStream& SourceStream::operator<<(const char *s)
65{
66 m_groupIfNumber = false;
67 str += UString(s);
68 return *this;
69}
70
71SourceStream& SourceStream::operator<<(double value)
72{
73 if (m_groupIfNumber)
74 str.append("(");
75
76 str += UString::from(value);
77
78 if (m_groupIfNumber)
79 str.append(")");
80
81 m_groupIfNumber = false;
82 return *this;
83}
84
85SourceStream& SourceStream::operator<<(const UString &s)
86{
87 m_groupIfNumber = false;
88 str += s;
89 return *this;
90}
91
92SourceStream& SourceStream::operator<<(const Identifier &s)
93{
94 m_groupIfNumber = false;
95 str += s.ustring();
96 return *this;
97}
98
99SourceStream& SourceStream::operator<<(const Node *n)
100{
101 if (n)
102 n->streamTo(*this);
103 m_groupIfNumber = false;
104 return *this;
105}
106
107SourceStream& SourceStream::operator<<(Format f)
108{
109 m_groupIfNumber = false;
110 switch (f) {
111 case Endl:
112 str += "\n" + ind;
113 break;
114 case Indent:
115 ind += " ";
116 break;
117 case Unindent:
118 ind = ind.substr(0, ind.size() - 2);
119 break;
120 case DotExpr:
121 m_groupIfNumber = true;
122 break;
123 }
124
125 return *this;
126}
127
128UString Node::toString() const
129{
130 SourceStream str;
131 streamTo(str);
132
133 return str.toString();
134}
135
136void NullNode::streamTo(SourceStream &s) const { s << "null"; }
137
138void BooleanNode::streamTo(SourceStream &s) const
139{
140 s << (value ? "true" : "false");
141}
142
143void NumberNode::streamTo(SourceStream &s) const { s << value; }
144
145void StringNode::streamTo(SourceStream &s) const
146{
147 s << '"' << escapeStringForPrettyPrinting(value) << '"';
148}
149
150void RegExpNode::streamTo(SourceStream &s) const
151{
152 s << "/" << pattern << "/" << flags;
153}
154
155void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
156
157void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
158
159void GroupNode::streamTo(SourceStream &s) const
160{
161 s << "(" << group << ")";
162}
163
164void ElementNode::streamTo(SourceStream &s) const
165{
166 for (const ElementNode *n = this; n; n = n->next.get()) {
167 for (int i = 0; i < n->elision; i++)
168 s << ",";
169 s << n->node;
170 if (n->next)
171 s << ",";
172 }
173}
174
175void ArrayNode::streamTo(SourceStream &s) const
176{
177 s << "[" << element;
178 for (int i = 0; i < elision; i++)
179 s << ",";
180 s << "]";
181}
182
183void ObjectLiteralNode::streamTo(SourceStream &s) const
184{
185 if (list)
186 s << "{ " << list << " }";
187 else
188 s << "{ }";
189}
190
191void PropertyListNode::streamTo(SourceStream &s) const
192{
193 s << node;
194
195 for (const PropertyListNode *n = next.get(); n; n = n->next.get())
196 s << ", " << n->node;
197}
198
199void PropertyNode::streamTo(SourceStream &s) const
200{
201 switch (type) {
202 case Constant:
203 s << name << ": " << assign;
204 break;
205 case Getter:
206 case Setter: {
207 const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
208 if (type == Getter)
209 s << "get ";
210 else
211 s << "set ";
212
213 s << name << "(" << func->param << ")" << func->body;
214 break;
215 }
216 }
217}
218
219void PropertyNameNode::streamTo(SourceStream &s) const
220{
221 if (str.isNull())
222 s << UString::from(numeric);
223 else
224 s << '"' << escapeStringForPrettyPrinting(str.ustring()) << '"';
225}
226
227void BracketAccessorNode::streamTo(SourceStream &s) const
228{
229 s << expr1 << "[" << expr2 << "]";
230}
231
232void DotAccessorNode::streamTo(SourceStream &s) const
233{
234 s << SourceStream::DotExpr << expr << "." << ident;
235}
236
237void ArgumentListNode::streamTo(SourceStream &s) const
238{
239 s << expr;
240 for (ArgumentListNode *n = next.get(); n; n = n->next.get())
241 s << ", " << n->expr;
242}
243
244void ArgumentsNode::streamTo(SourceStream &s) const
245{
246 s << "(" << list << ")";
247}
248
249void NewExprNode::streamTo(SourceStream &s) const
250{
251 s << "new " << expr << args;
252}
253
254void FunctionCallValueNode::streamTo(SourceStream &s) const
255{
256 s << expr << args;
257}
258
259void FunctionCallResolveNode::streamTo(SourceStream &s) const
260{
261 s << ident << args;
262}
263
264void FunctionCallBracketNode::streamTo(SourceStream &s) const
265{
266 s << base << "[" << subscript << "]" << args;
267}
268
269void FunctionCallParenBracketNode::streamTo(SourceStream &s) const
270{
271 s << "(" << base << "[" << subscript << "])" << args;
272}
273
274void FunctionCallDotNode::streamTo(SourceStream &s) const
275{
276 s << SourceStream::DotExpr << base << "." << ident << args;
277}
278
279void FunctionCallParenDotNode::streamTo(SourceStream &s) const
280{
281 s << "(" << SourceStream::DotExpr << base << "." << ident << ")" << args;
282}
283
284void PostfixResolveNode::streamTo(SourceStream &s) const
285{
286 s << m_ident;
287 if (m_oper == OpPlusPlus)
288 s << "++";
289 else
290 s << "--";
291}
292
293void PostfixBracketNode::streamTo(SourceStream &s) const
294{
295 s << m_base << "[" << m_subscript << "]";
296 if (m_oper == OpPlusPlus)
297 s << "++";
298 else
299 s << "--";
300}
301
302void PostfixDotNode::streamTo(SourceStream &s) const
303{
304 s << SourceStream::DotExpr << m_base << "." << m_ident;
305 if (m_oper == OpPlusPlus)
306 s << "++";
307 else
308 s << "--";
309}
310
311void PostfixErrorNode::streamTo(SourceStream& s) const
312{
313 s << m_expr;
314 if (m_oper == OpPlusPlus)
315 s << "++";
316 else
317 s << "--";
318}
319
320void DeleteResolveNode::streamTo(SourceStream &s) const
321{
322 s << "delete " << m_ident;
323}
324
325void DeleteBracketNode::streamTo(SourceStream &s) const
326{
327 s << "delete " << m_base << "[" << m_subscript << "]";
328}
329
330void DeleteDotNode::streamTo(SourceStream &s) const
331{
332 s << "delete " << SourceStream::DotExpr << m_base << "." << m_ident;
333}
334
335void DeleteValueNode::streamTo(SourceStream &s) const
336{
337 s << "delete " << m_expr;
338}
339
340void VoidNode::streamTo(SourceStream &s) const
341{
342 s << "void " << expr;
343}
344
345void TypeOfValueNode::streamTo(SourceStream &s) const
346{
347 s << "typeof " << m_expr;
348}
349
350void TypeOfResolveNode::streamTo(SourceStream &s) const
351{
352 s << "typeof " << m_ident;
353}
354
355void PrefixResolveNode::streamTo(SourceStream &s) const
356{
357 if (m_oper == OpPlusPlus)
358 s << "++";
359 else
360 s << "--";
361 s << m_ident;
362}
363
364void PrefixBracketNode::streamTo(SourceStream &s) const
365{
366 if (m_oper == OpPlusPlus)
367 s << "++";
368 else
369 s << "--";
370 s << m_base << "[" << m_subscript << "]";
371}
372
373void PrefixDotNode::streamTo(SourceStream &s) const
374{
375 if (m_oper == OpPlusPlus)
376 s << "++";
377 else
378 s << "--";
379 s << SourceStream::DotExpr << m_base << "." << m_ident;
380}
381
382void PrefixErrorNode::streamTo(SourceStream& s) const
383{
384 if (m_oper == OpPlusPlus)
385 s << "++";
386 else
387 s << "--";
388 s << m_expr;
389}
390
391void UnaryPlusNode::streamTo(SourceStream &s) const
392{
393 s << "+" << expr;
394}
395
396void NegateNode::streamTo(SourceStream &s) const
397{
398 s << "-" << expr;
399}
400
401void BitwiseNotNode::streamTo(SourceStream &s) const
402{
403 s << "~" << expr;
404}
405
406void LogicalNotNode::streamTo(SourceStream &s) const
407{
408 s << "!" << expr;
409}
410
411void MultNode::streamTo(SourceStream &s) const
412{
413 s << term1 << oper << term2;
414}
415
416void AddNode::streamTo(SourceStream &s) const
417{
418 s << term1 << oper << term2;
419}
420
421void ShiftNode::streamTo(SourceStream &s) const
422{
423 s << term1;
424 if (oper == OpLShift)
425 s << "<<";
426 else if (oper == OpRShift)
427 s << ">>";
428 else
429 s << ">>>";
430 s << term2;
431}
432
433void RelationalNode::streamTo(SourceStream &s) const
434{
435 s << expr1;
436 switch (oper) {
437 case OpLess:
438 s << " < ";
439 break;
440 case OpGreater:
441 s << " > ";
442 break;
443 case OpLessEq:
444 s << " <= ";
445 break;
446 case OpGreaterEq:
447 s << " >= ";
448 break;
449 case OpInstanceOf:
450 s << " instanceof ";
451 break;
452 case OpIn:
453 s << " in ";
454 break;
455 default:
456 ;
457 }
458 s << expr2;
459}
460
461void EqualNode::streamTo(SourceStream &s) const
462{
463 s << expr1;
464 switch (oper) {
465 case OpEqEq:
466 s << " == ";
467 break;
468 case OpNotEq:
469 s << " != ";
470 break;
471 case OpStrEq:
472 s << " === ";
473 break;
474 case OpStrNEq:
475 s << " !== ";
476 break;
477 default:
478 ;
479 }
480 s << expr2;
481}
482
483void BitOperNode::streamTo(SourceStream &s) const
484{
485 s << expr1;
486 if (oper == OpBitAnd)
487 s << " & ";
488 else if (oper == OpBitXOr)
489 s << " ^ ";
490 else
491 s << " | ";
492 s << expr2;
493}
494
495void BinaryLogicalNode::streamTo(SourceStream &s) const
496{
497 s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
498}
499
500void ConditionalNode::streamTo(SourceStream &s) const
501{
502 s << logical << " ? " << expr1 << " : " << expr2;
503}
504
505static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
506{
507 const char *opStr;
508 switch (oper) {
509 case OpEqual:
510 opStr = " = ";
511 break;
512 case OpMultEq:
513 opStr = " *= ";
514 break;
515 case OpDivEq:
516 opStr = " /= ";
517 break;
518 case OpPlusEq:
519 opStr = " += ";
520 break;
521 case OpMinusEq:
522 opStr = " -= ";
523 break;
524 case OpLShift:
525 opStr = " <<= ";
526 break;
527 case OpRShift:
528 opStr = " >>= ";
529 break;
530 case OpURShift:
531 opStr = " >>>= ";
532 break;
533 case OpAndEq:
534 opStr = " &= ";
535 break;
536 case OpXOrEq:
537 opStr = " ^= ";
538 break;
539 case OpOrEq:
540 opStr = " |= ";
541 break;
542 case OpModEq:
543 opStr = " %= ";
544 break;
545 default:
546 opStr = " ?= ";
547 }
548 s << opStr;
549}
550
551void AssignResolveNode::streamTo(SourceStream &s) const
552{
553 s << m_ident;
554 streamAssignmentOperatorTo(s, m_oper);
555 s << m_right;
556}
557
558void AssignBracketNode::streamTo(SourceStream &s) const
559{
560 s << m_base << "[" << m_subscript << "]";
561 streamAssignmentOperatorTo(s, m_oper);
562 s << m_right;
563}
564
565void AssignDotNode::streamTo(SourceStream &s) const
566{
567 s << SourceStream::DotExpr << m_base << "." << m_ident;
568 streamAssignmentOperatorTo(s, m_oper);
569 s << m_right;
570}
571
572void AssignErrorNode::streamTo(SourceStream& s) const
573{
574 s << m_left;
575 streamAssignmentOperatorTo(s, m_oper);
576 s << m_right;
577}
578
579void CommaNode::streamTo(SourceStream &s) const
580{
581 s << expr1 << ", " << expr2;
582}
583
584void AssignExprNode::streamTo(SourceStream &s) const
585{
586 s << " = " << expr;
587}
588
589void VarDeclNode::streamTo(SourceStream &s) const
590{
591 s << ident << init;
592}
593
594void VarDeclListNode::streamTo(SourceStream &s) const
595{
596 s << var;
597 for (VarDeclListNode *n = next.get(); n; n = n->next.get())
598 s << ", " << n->var;
599}
600
601void VarStatementNode::streamTo(SourceStream &s) const
602{
603 s << SourceStream::Endl << "var " << next << ";";
604}
605
606void BlockNode::streamTo(SourceStream &s) const
607{
608 s << SourceStream::Endl << "{" << SourceStream::Indent
609 << source << SourceStream::Unindent << SourceStream::Endl << "}";
610}
611
612void EmptyStatementNode::streamTo(SourceStream &s) const
613{
614 s << SourceStream::Endl << ";";
615}
616
617void ExprStatementNode::streamTo(SourceStream &s) const
618{
619 s << SourceStream::Endl << expr << ";";
620}
621
622void IfNode::streamTo(SourceStream &s) const
623{
624 s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
625 << statement1 << SourceStream::Unindent;
626 if (statement2)
627 s << SourceStream::Endl << "else" << SourceStream::Indent
628 << statement2 << SourceStream::Unindent;
629}
630
631void DoWhileNode::streamTo(SourceStream &s) const
632{
633 s << SourceStream::Endl << "do " << SourceStream::Indent
634 << statement << SourceStream::Unindent << SourceStream::Endl
635 << "while (" << expr << ");";
636}
637
638void WhileNode::streamTo(SourceStream &s) const
639{
640 s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
641 << statement << SourceStream::Unindent;
642}
643
644void ForNode::streamTo(SourceStream &s) const
645{
646 s << SourceStream::Endl << "for ("
647 << expr1 // TODO: doesn't properly do "var i = 0"
648 << "; " << expr2
649 << "; " << expr3
650 << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
651}
652
653void ForInNode::streamTo(SourceStream &s) const
654{
655 s << SourceStream::Endl << "for (";
656 if (varDecl)
657 s << "var " << varDecl;
658 else
659 s << lexpr;
660
661 if (init)
662 s << " = " << init;
663 s << " in " << expr << ")" << SourceStream::Indent
664 << statement << SourceStream::Unindent;
665}
666
667void ContinueNode::streamTo(SourceStream &s) const
668{
669 s << SourceStream::Endl << "continue";
670 if (!ident.isNull())
671 s << " " << ident;
672 s << ";";
673}
674
675void BreakNode::streamTo(SourceStream &s) const
676{
677 s << SourceStream::Endl << "break";
678 if (!ident.isNull())
679 s << " " << ident;
680 s << ";";
681}
682
683void ReturnNode::streamTo(SourceStream &s) const
684{
685 s << SourceStream::Endl << "return";
686 if (value)
687 s << " " << value;
688 s << ";";
689}
690
691void WithNode::streamTo(SourceStream &s) const
692{
693 s << SourceStream::Endl << "with (" << expr << ") "
694 << statement;
695}
696
697void CaseClauseNode::streamTo(SourceStream &s) const
698{
699 s << SourceStream::Endl;
700 if (expr)
701 s << "case " << expr;
702 else
703 s << "default";
704 s << ":" << SourceStream::Indent;
705 if (source)
706 s << source;
707 s << SourceStream::Unindent;
708}
709
710void ClauseListNode::streamTo(SourceStream &s) const
711{
712 for (const ClauseListNode *n = this; n; n = n->getNext())
713 s << n->getClause();
714}
715
716void CaseBlockNode::streamTo(SourceStream &s) const
717{
718 for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
719 s << n->getClause();
720 if (def)
721 s << def;
722 for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
723 s << n->getClause();
724}
725
726void SwitchNode::streamTo(SourceStream &s) const
727{
728 s << SourceStream::Endl << "switch (" << expr << ") {"
729 << SourceStream::Indent << block << SourceStream::Unindent
730 << SourceStream::Endl << "}";
731}
732
733void LabelNode::streamTo(SourceStream &s) const
734{
735 s << SourceStream::Endl << label << ":" << SourceStream::Indent
736 << statement << SourceStream::Unindent;
737}
738
739void ThrowNode::streamTo(SourceStream &s) const
740{
741 s << SourceStream::Endl << "throw " << expr << ";";
742}
743
744void TryNode::streamTo(SourceStream &s) const
745{
746 s << "try " << tryBlock;
747 if (catchBlock)
748 s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
749 if (finallyBlock)
750 s << SourceStream::Endl << "finally " << finallyBlock;
751}
752
753void ParameterNode::streamTo(SourceStream &s) const
754{
755 s << id;
756 for (ParameterNode *n = next.get(); n; n = n->next.get())
757 s << ", " << n->id;
758}
759
760void FuncDeclNode::streamTo(SourceStream &s) const
761{
762 s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
763}
764
765void FuncExprNode::streamTo(SourceStream &s) const
766{
767 s << "function " << ident << "(" << param << ")" << body;
768}
769
770void SourceElementsNode::streamTo(SourceStream &s) const
771{
772 for (const SourceElementsNode *n = this; n; n = n->next.get())
773 s << n->node;
774}
Note: See TracBrowser for help on using the repository browser.