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

Last change on this file since 10135 was 10135, checked in by mjs, 20 years ago

JavaScriptCore:

Reviewed by Geoff.

Refactor assignment grammar to avoid Reference type, and to later
be able to take advantage of writeable PropertySlots, when those
are added. I also fixed a minor bug, turning a function to a
string lost parentheses, I made sure they are printed at least
where semantically significant.

Test cases: see WebCore

  • kjs/grammar.y: Change grammar so that assignment expressions are parsed directly to nodes that know how to set the kind of location being assigned, instead of having a generic assign node that counts on evaluateReference.
  • kjs/lexer.cpp: Include grammar_types.h.
  • kjs/nodes.cpp: (BracketAccessorNode): Renamed from AccessorNode1 for clarity. (DotAccessorNode): Renamed from AccessorNode2 for clarity. (combineForAssignment): Inline function for doing the proper kind of operation for various update assignments like += or *=. (AssignResolveNode): Node that handles assignment to a bare identifier. (AssignDotNode): Node that handles assignments of the form EXPR . IDENT = EXPR (AssignBracketNode): EXPR [ IDENT ] = EXPR
  • kjs/nodes.h: Updated for declarations/renames of new classes.
  • kjs/nodes2string.cpp: (GroupNode::streamTo): Fixed to print parens around the expression. (BracketAccessorNode::streamTo): Renamed. (DotAccessorNode::streamTo): Renamed. (AssignResolveNode::streamTo): Added. (AssignBracketNode::streamTo): Added. (AssignDotNode::streamTo): Added. (streamAssignmentOperatorTo): helper function for the above
  • kjs/property_slot.h: (KJS::PropertySlot::isSet): Made this const.

WebCore:

Reviewed by Geoff.

Test cases added:

  • layout-tests/fast/js/assign.html: Added. Test case for assignment to make sure I didn't break anything.
  • layout-tests/fast/js/code-serialize-paren.html: Added, test case for a minor bug I fixed where parens were not getting serialized at all when turning a function into a string.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 2002 Harri Porten ([email protected])
5 * Copyright (C) 2003 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "nodes.h"
25
26namespace KJS {
27 /**
28 * A simple text streaming class that helps with code indentation.
29 */
30 class SourceStream {
31 public:
32 enum Format {
33 Endl, Indent, Unindent
34 };
35
36 UString toString() const { return str; }
37 SourceStream& operator<<(const Identifier &);
38 SourceStream& operator<<(const UString &);
39 SourceStream& operator<<(const char *);
40 SourceStream& operator<<(char);
41 SourceStream& operator<<(Format f);
42 SourceStream& operator<<(const Node *);
43 private:
44 UString str; /* TODO: buffer */
45 UString ind;
46 };
47};
48
49using namespace KJS;
50
51SourceStream& SourceStream::operator<<(char c)
52{
53 str += UString(c);
54 return *this;
55}
56
57SourceStream& SourceStream::operator<<(const char *s)
58{
59 str += UString(s);
60 return *this;
61}
62
63SourceStream& SourceStream::operator<<(const UString &s)
64{
65 str += s;
66 return *this;
67}
68
69SourceStream& SourceStream::operator<<(const Identifier &s)
70{
71 str += s.ustring();
72 return *this;
73}
74
75SourceStream& SourceStream::operator<<(const Node *n)
76{
77 if (n)
78 n->streamTo(*this);
79 return *this;
80}
81
82SourceStream& SourceStream::operator<<(Format f)
83{
84 switch (f) {
85 case Endl:
86 str += "\n" + ind;
87 break;
88 case Indent:
89 ind += " ";
90 break;
91 case Unindent:
92 ind = ind.substr(0, ind.size() - 2);
93 break;
94 }
95
96 return *this;
97}
98
99UString Node::toString() const
100{
101 SourceStream str;
102 streamTo(str);
103
104 return str.toString();
105}
106
107void NullNode::streamTo(SourceStream &s) const { s << "null"; }
108
109void BooleanNode::streamTo(SourceStream &s) const
110{
111 s << (value ? "true" : "false");
112}
113
114void NumberNode::streamTo(SourceStream &s) const { s << UString::from(value); }
115
116void StringNode::streamTo(SourceStream &s) const
117{
118 s << '"' << value << '"';
119}
120
121void RegExpNode::streamTo(SourceStream &s) const { s << pattern; }
122
123void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
124
125void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
126
127void GroupNode::streamTo(SourceStream &s) const
128{
129 s << "(" << group << ")";
130}
131
132void ElementNode::streamTo(SourceStream &s) const
133{
134 for (const ElementNode *n = this; n; n = n->list) {
135 for (int i = 0; i < n->elision; i++)
136 s << ",";
137 s << n->node;
138 }
139}
140
141void ArrayNode::streamTo(SourceStream &s) const
142{
143 s << "[" << element;
144 for (int i = 0; i < elision; i++)
145 s << ",";
146 s << "]";
147}
148
149void ObjectLiteralNode::streamTo(SourceStream &s) const
150{
151 if (list)
152 s << "{ " << list << " }";
153 else
154 s << "{ }";
155}
156
157void PropertyValueNode::streamTo(SourceStream &s) const
158{
159 for (const PropertyValueNode *n = this; n; n = n->list)
160 s << n->name << ": " << n->assign;
161}
162
163void PropertyNode::streamTo(SourceStream &s) const
164{
165 if (str.isNull())
166 s << UString::from(numeric);
167 else
168 s << str;
169}
170
171void BracketAccessorNode::streamTo(SourceStream &s) const
172{
173 s << expr1 << "[" << expr2 << "]";
174}
175
176void DotAccessorNode::streamTo(SourceStream &s) const
177{
178 s << expr << "." << ident;
179}
180
181void ArgumentListNode::streamTo(SourceStream &s) const
182{
183 s << expr;
184 for (ArgumentListNode *n = list; n; n = n->list)
185 s << ", " << n->expr;
186}
187
188void ArgumentsNode::streamTo(SourceStream &s) const
189{
190 s << "(" << list << ")";
191}
192
193void NewExprNode::streamTo(SourceStream &s) const
194{
195 s << "new " << expr << args;
196}
197
198void FunctionCallNode::streamTo(SourceStream &s) const
199{
200 s << expr << args;
201}
202
203void PostfixNode::streamTo(SourceStream &s) const
204{
205 s << expr;
206 if (oper == OpPlusPlus)
207 s << "++";
208 else
209 s << "--";
210}
211
212void DeleteNode::streamTo(SourceStream &s) const
213{
214 s << "delete " << expr;
215}
216
217void VoidNode::streamTo(SourceStream &s) const
218{
219 s << "void " << expr;
220}
221
222void TypeOfNode::streamTo(SourceStream &s) const
223{
224 s << "typeof " << expr;
225}
226
227void PrefixNode::streamTo(SourceStream &s) const
228{
229 s << expr << (oper == OpPlusPlus ? "++" : "--");
230}
231
232void UnaryPlusNode::streamTo(SourceStream &s) const
233{
234 s << "+" << expr;
235}
236
237void NegateNode::streamTo(SourceStream &s) const
238{
239 s << "-" << expr;
240}
241
242void BitwiseNotNode::streamTo(SourceStream &s) const
243{
244 s << "~" << expr;
245}
246
247void LogicalNotNode::streamTo(SourceStream &s) const
248{
249 s << "!" << expr;
250}
251
252void MultNode::streamTo(SourceStream &s) const
253{
254 s << term1 << oper << term2;
255}
256
257void AddNode::streamTo(SourceStream &s) const
258{
259 s << term1 << oper << term2;
260}
261
262void ShiftNode::streamTo(SourceStream &s) const
263{
264 s << term1;
265 if (oper == OpLShift)
266 s << "<<";
267 else if (oper == OpRShift)
268 s << ">>";
269 else
270 s << ">>>";
271 s << term2;
272}
273
274void RelationalNode::streamTo(SourceStream &s) const
275{
276 s << expr1;
277 switch (oper) {
278 case OpLess:
279 s << " < ";
280 break;
281 case OpGreater:
282 s << " > ";
283 break;
284 case OpLessEq:
285 s << " <= ";
286 break;
287 case OpGreaterEq:
288 s << " >= ";
289 break;
290 case OpInstanceOf:
291 s << " instanceof ";
292 break;
293 case OpIn:
294 s << " in ";
295 break;
296 default:
297 ;
298 }
299 s << expr2;
300}
301
302void EqualNode::streamTo(SourceStream &s) const
303{
304 s << expr1;
305 switch (oper) {
306 case OpEqEq:
307 s << " == ";
308 break;
309 case OpNotEq:
310 s << " != ";
311 break;
312 case OpStrEq:
313 s << " === ";
314 break;
315 case OpStrNEq:
316 s << " !== ";
317 break;
318 default:
319 ;
320 }
321 s << expr2;
322}
323
324void BitOperNode::streamTo(SourceStream &s) const
325{
326 s << expr1;
327 if (oper == OpBitAnd)
328 s << " & ";
329 else if (oper == OpBitXOr)
330 s << " ^ ";
331 else
332 s << " | ";
333 s << expr2;
334}
335
336void BinaryLogicalNode::streamTo(SourceStream &s) const
337{
338 s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
339}
340
341void ConditionalNode::streamTo(SourceStream &s) const
342{
343 s << logical << " ? " << expr1 << " : " << expr2;
344}
345
346void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
347{
348 const char *opStr;
349 switch (oper) {
350 case OpEqual:
351 opStr = " = ";
352 break;
353 case OpMultEq:
354 opStr = " *= ";
355 break;
356 case OpDivEq:
357 opStr = " /= ";
358 break;
359 case OpPlusEq:
360 opStr = " += ";
361 break;
362 case OpMinusEq:
363 opStr = " -= ";
364 break;
365 case OpLShift:
366 opStr = " <<= ";
367 break;
368 case OpRShift:
369 opStr = " >>= ";
370 break;
371 case OpURShift:
372 opStr = " >>>= ";
373 break;
374 case OpAndEq:
375 opStr = " &= ";
376 break;
377 case OpXOrEq:
378 opStr = " ^= ";
379 break;
380 case OpOrEq:
381 opStr = " |= ";
382 break;
383 case OpModEq:
384 opStr = " %= ";
385 break;
386 default:
387 opStr = " ?= ";
388 }
389 s << opStr;
390}
391
392void AssignResolveNode::streamTo(SourceStream &s) const
393{
394 s << m_ident;
395 streamAssignmentOperatorTo(s, m_oper);
396 s << m_right;
397}
398
399void AssignBracketNode::streamTo(SourceStream &s) const
400{
401 s << m_base << "[" << m_subscript << "]";
402 streamAssignmentOperatorTo(s, m_oper);
403 s << m_right;
404}
405
406void AssignDotNode::streamTo(SourceStream &s) const
407{
408 s << m_base << "." << m_ident;
409 streamAssignmentOperatorTo(s, m_oper);
410 s << m_right;
411}
412
413void CommaNode::streamTo(SourceStream &s) const
414{
415 s << expr1 << ", " << expr2;
416}
417
418void StatListNode::streamTo(SourceStream &s) const
419{
420 for (const StatListNode *n = this; n; n = n->list)
421 s << n->statement;
422}
423
424void AssignExprNode::streamTo(SourceStream &s) const
425{
426 s << " = " << expr;
427}
428
429void VarDeclNode::streamTo(SourceStream &s) const
430{
431 s << ident << init;
432}
433
434void VarDeclListNode::streamTo(SourceStream &s) const
435{
436 s << var;
437 for (VarDeclListNode *n = list; n; n = n->list)
438 s << ", " << n->var;
439}
440
441void VarStatementNode::streamTo(SourceStream &s) const
442{
443 s << SourceStream::Endl << "var " << list << ";";
444}
445
446void BlockNode::streamTo(SourceStream &s) const
447{
448 s << SourceStream::Endl << "{" << SourceStream::Indent
449 << source << SourceStream::Unindent << SourceStream::Endl << "}";
450}
451
452void EmptyStatementNode::streamTo(SourceStream &s) const
453{
454 s << SourceStream::Endl << ";";
455}
456
457void ExprStatementNode::streamTo(SourceStream &s) const
458{
459 s << SourceStream::Endl << expr << ";";
460}
461
462void IfNode::streamTo(SourceStream &s) const
463{
464 s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
465 << statement1 << SourceStream::Unindent;
466 if (statement2)
467 s << SourceStream::Endl << "else" << SourceStream::Indent
468 << statement2 << SourceStream::Unindent;
469}
470
471void DoWhileNode::streamTo(SourceStream &s) const
472{
473 s << SourceStream::Endl << "do " << SourceStream::Indent
474 << statement << SourceStream::Unindent << SourceStream::Endl
475 << "while (" << expr << ");";
476}
477
478void WhileNode::streamTo(SourceStream &s) const
479{
480 s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
481 << statement << SourceStream::Unindent;
482}
483
484void ForNode::streamTo(SourceStream &s) const
485{
486 s << SourceStream::Endl << "for ("
487 << expr1 // TODO: doesn't properly do "var i = 0"
488 << "; " << expr2
489 << "; " << expr3
490 << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
491}
492
493void ForInNode::streamTo(SourceStream &s) const
494{
495 s << SourceStream::Endl << "for (";
496 if (varDecl)
497 s << "var " << varDecl;
498 if (init)
499 s << " = " << init;
500 s << " in " << expr << ")" << SourceStream::Indent
501 << statement << SourceStream::Unindent;
502}
503
504void ContinueNode::streamTo(SourceStream &s) const
505{
506 s << SourceStream::Endl << "continue";
507 if (!ident.isNull())
508 s << " " << ident;
509 s << ";";
510}
511
512void BreakNode::streamTo(SourceStream &s) const
513{
514 s << SourceStream::Endl << "break";
515 if (!ident.isNull())
516 s << " " << ident;
517 s << ";";
518}
519
520void ReturnNode::streamTo(SourceStream &s) const
521{
522 s << SourceStream::Endl << "return";
523 if (value)
524 s << " " << value;
525 s << ";";
526}
527
528void WithNode::streamTo(SourceStream &s) const
529{
530 s << SourceStream::Endl << "with (" << expr << ") "
531 << statement;
532}
533
534void CaseClauseNode::streamTo(SourceStream &s) const
535{
536 s << SourceStream::Endl;
537 if (expr)
538 s << "case " << expr;
539 else
540 s << "default";
541 s << ":" << SourceStream::Indent;
542 if (list)
543 s << list;
544 s << SourceStream::Unindent;
545}
546
547void ClauseListNode::streamTo(SourceStream &s) const
548{
549 for (const ClauseListNode *n = this; n; n = n->next())
550 s << n->clause();
551}
552
553void CaseBlockNode::streamTo(SourceStream &s) const
554{
555 for (const ClauseListNode *n = list1; n; n = n->next())
556 s << n->clause();
557 if (def)
558 s << def;
559 for (const ClauseListNode *n = list2; n; n = n->next())
560 s << n->clause();
561}
562
563void SwitchNode::streamTo(SourceStream &s) const
564{
565 s << SourceStream::Endl << "switch (" << expr << ") {"
566 << SourceStream::Indent << block << SourceStream::Unindent
567 << SourceStream::Endl << "}";
568}
569
570void LabelNode::streamTo(SourceStream &s) const
571{
572 s << SourceStream::Endl << label << ":" << SourceStream::Indent
573 << statement << SourceStream::Unindent;
574}
575
576void ThrowNode::streamTo(SourceStream &s) const
577{
578 s << SourceStream::Endl << "throw " << expr << ";";
579}
580
581void CatchNode::streamTo(SourceStream &s) const
582{
583 s << SourceStream::Endl << "catch (" << ident << ")" << block;
584}
585
586void FinallyNode::streamTo(SourceStream &s) const
587{
588 s << SourceStream::Endl << "finally " << block;
589}
590
591void TryNode::streamTo(SourceStream &s) const
592{
593 s << "try " << block
594 << _catch
595 << _final;
596}
597
598void ParameterNode::streamTo(SourceStream &s) const
599{
600 s << id;
601 for (ParameterNode *n = next; n; n = n->next)
602 s << ", " << n->id;
603}
604
605void FuncDeclNode::streamTo(SourceStream &s) const {
606 s << "function " << ident << "(";
607 if (param)
608 s << param;
609 s << ")" << body;
610}
611
612void FuncExprNode::streamTo(SourceStream &s) const
613{
614 s << "function " << "("
615 << param
616 << ")" << body;
617}
618
619void SourceElementsNode::streamTo(SourceStream &s) const
620{
621 for (const SourceElementsNode *n = this; n; n = n->elements)
622 s << n->element;
623}
624
Note: See TracBrowser for help on using the repository browser.