]> git.saurik.com Git - cycript.git/blame - Output.cpp
As FunctionInstance is different, it must be last.
[cycript.git] / Output.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c15969fd 2 * Copyright (C) 2009-2013 Jay Freeman (saurik)
4644480a
JF
3*/
4
c15969fd 5/* GNU General Public License, Version 3 {{{ */
4644480a 6/*
c15969fd
JF
7 * Cycript is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
4644480a 11 *
c15969fd
JF
12 * Cycript is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
4644480a 16 *
c15969fd 17 * You should have received a copy of the GNU General Public License
b3378a02
JF
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
4644480a
JF
20/* }}} */
21
520c130f 22#include "cycript.hpp"
5999c315
JF
23#include "Parser.hpp"
24
4afefdd9
JF
25#include <sstream>
26
1fdca2fa
JF
27void CYOutput::Terminate() {
28 out_ << ';';
29 mode_ = NoMode;
30}
31
96a7e5c2 32CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
33 if (rhs == ' ' || rhs == '\n')
34 if (pretty_)
35 out_ << rhs;
36 else goto done;
37 else if (rhs == '\t')
38 if (pretty_)
39 for (unsigned i(0); i != indent_; ++i)
40 out_ << " ";
41 else goto done;
320ce753
JF
42 else if (rhs == '\r') {
43 if (right_) {
44 out_ << '\n';
45 right_ = false;
14ec9e00 46 } goto done;
320ce753 47 } else goto work;
1fdca2fa 48
320ce753 49 right_ = true;
1fdca2fa
JF
50 mode_ = NoMode;
51 goto done;
96a7e5c2 52
1fdca2fa 53 work:
320ce753
JF
54 if (mode_ == Terminated && rhs != '}') {
55 right_ = true;
96a7e5c2 56 out_ << ';';
320ce753 57 }
96a7e5c2
JF
58
59 if (rhs == ';') {
60 if (pretty_)
61 goto none;
62 else {
63 mode_ = Terminated;
64 goto done;
65 }
c0bc320e
JF
66 } else if (rhs == '+') {
67 if (mode_ == NoPlus)
68 out_ << ' ';
69 mode_ = NoPlus;
96a7e5c2
JF
70 } else if (rhs == '-') {
71 if (mode_ == NoHyphen)
72 out_ << ' ';
73 mode_ = NoHyphen;
74 } else if (WordEndRange_[rhs]) {
75 if (mode_ == NoLetter)
76 out_ << ' ';
77 mode_ = NoLetter;
78 } else none:
79 mode_ = NoMode;
80
320ce753 81 right_ = true;
96a7e5c2
JF
82 out_ << rhs;
83 done:
84 return *this;
85}
86
87CYOutput &CYOutput::operator <<(const char *rhs) {
88 size_t size(strlen(rhs));
89
90 if (size == 1)
91 return *this << *rhs;
92
93 if (mode_ == Terminated)
94 out_ << ';';
95 else if (
c0bc320e 96 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
97 mode_ == NoHyphen && *rhs == '-' ||
98 mode_ == NoLetter && WordEndRange_[*rhs]
99 )
100 out_ << ' ';
101
102 if (WordEndRange_[rhs[size - 1]])
103 mode_ = NoLetter;
104 else
105 mode_ = NoMode;
106
320ce753 107 right_ = true;
96a7e5c2
JF
108 out_ << rhs;
109 return *this;
110}
111
652ec1ba 112void CYArgument::Output(CYOutput &out) const {
d35a3b07 113 if (name_ != NULL) {
5999c315 114 out << *name_;
96a7e5c2
JF
115 if (value_ != NULL)
116 out << ':' << ' ';
5999c315 117 }
d35a3b07 118 if (value_ != NULL)
8351aa30 119 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
5999c315 120 if (next_ != NULL) {
96a7e5c2 121 if (next_->name_ == NULL)
11c1cc16 122 out << ',';
96a7e5c2 123 out << ' ' << *next_;
5999c315
JF
124 }
125}
126
652ec1ba 127void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 128 out << '[' << elements_ << ']';
5befe15e
JF
129}
130
652ec1ba 131void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 132 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
133}
134
652ec1ba 135void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 136 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 137 out << ' ' << Operator() << ' ';
b09da87b 138 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
139}
140
3b52fd1a
JF
141void CYBlock::Output(CYOutput &out) const {
142 out << '{' << '\n';
143 ++out.indent_;
144 if (statements_ != NULL)
145 statements_->Multiple(out);
146 --out.indent_;
147 out << '\t' << '}';
148}
149
fb98ac0c 150void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
151 if (statements_ == NULL)
152 out.Terminate();
153 else if (statements_->next_ == NULL)
154 statements_->Single(out, flags);
155 else
156 Output(out);
9e562cfc
JF
157}
158
652ec1ba 159void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
160 out << (Value() ? "true" : "false");
161}
162
fb98ac0c 163void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
164 out << "break";
165 if (label_ != NULL)
166 out << ' ' << *label_;
96a7e5c2 167 out << ';';
5999c315
JF
168}
169
652ec1ba 170void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
171 bool protect((flags & CYNoCall) != 0);
172 if (protect)
173 out << '(';
174 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 175 out << '(' << arguments_ << ')';
fb98ac0c
JF
176 if (protect)
177 out << ')';
5999c315
JF
178}
179
37954781
JF
180namespace cy {
181namespace Syntax {
182
183void Catch::Output(CYOutput &out) const {
3b52fd1a 184 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
185}
186
37954781
JF
187} }
188
320ce753
JF
189void CYComment::Output(CYOutput &out, CYFlags flags) const {
190 out << '\r';
14ec9e00
JF
191 out.out_ << value_;
192 out.right_ = true;
320ce753
JF
193 out << '\r';
194}
195
652ec1ba 196void CYCompound::Output(CYOutput &out, CYFlags flags) const {
fd5cdf97
JF
197 if (next_ == NULL)
198 expression_->Output(out, flags);
199 else {
200 expression_->Output(out, CYLeft(flags));
201 out << ',' << ' ';
202 next_->Output(out, CYRight(flags));
203 }
e5bc40db
JF
204}
205
652ec1ba 206void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 207 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 208 out << ' ' << '?' << ' ';
5999c315 209 if (true_ != NULL)
8351aa30 210 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 211 out << ' ' << ':' << ' ';
8351aa30 212 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
213}
214
fb98ac0c 215void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
216 out << "continue";
217 if (label_ != NULL)
218 out << ' ' << *label_;
96a7e5c2 219 out << ';';
5999c315
JF
220}
221
652ec1ba 222void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
223 if (case_ != NULL)
224 out << "case" << ' ' << *case_;
225 else
5999c315 226 out << "default";
1fdca2fa 227 out << ':' << '\n';
3b52fd1a
JF
228 if (statements_ != NULL)
229 statements_->Multiple(out);
96a7e5c2 230 out << next_;
cac61857
JF
231}
232
c8a0500b
JF
233void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
234 out << "debugger" << ';';
235}
236
652ec1ba 237void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 238 out << "var";
96a7e5c2 239 Output(out, CYRight(flags));
75b0a457
JF
240}
241
652ec1ba 242void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 243 out << *identifier_;
e013809d 244 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 245 if (initialiser_ != NULL) {
96a7e5c2 246 out << ' ' << '=' << ' ';
8351aa30 247 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 248 }
5999c315
JF
249}
250
15b88a33 251void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 252 out << "var";
15b88a33 253 Output(out, CYRight(flags));
96a7e5c2
JF
254}
255
256void CYDeclarations::Output(CYOutput &out) const {
257 Output(out, CYNoFlags);
cac61857 258}
d35a3b07 259
652ec1ba 260void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 261 const CYDeclarations *declaration(this);
fb98ac0c 262 bool first(true);
d35a3b07 263
c8a0500b
JF
264 for (;;) {
265 CYDeclarations *next(declaration->next_);
266
267 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
268 first = false;
269 declaration->declaration_->Output(out, jacks);
270
271 if (next == NULL)
272 break;
273
96a7e5c2 274 out << ',' << ' ';
75b0a457 275 declaration = next;
d35a3b07 276 }
5999c315
JF
277}
278
652ec1ba 279void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 280 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
281 if (const char *word = property_->Word())
282 out << '.' << word;
96a7e5c2
JF
283 else
284 out << '[' << *property_ << ']';
9b5527f0
JF
285}
286
fb98ac0c 287void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 288 out << "do";
d29365ce 289 code_->Single(out, CYCenter(flags));
96a7e5c2 290 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
291}
292
652ec1ba 293void CYElement::Output(CYOutput &out) const {
5999c315 294 if (value_ != NULL)
8351aa30 295 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 296 if (next_ != NULL || value_ == NULL) {
5999c315 297 out << ',';
96a7e5c2 298 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
299 out << ' ';
300 }
5befe15e
JF
301 if (next_ != NULL)
302 next_->Output(out);
5999c315
JF
303}
304
fb98ac0c 305void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 306 out.Terminate();
5999c315
JF
307}
308
fb98ac0c 309void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
310 expression_->Output(out, flags | CYNoBF);
311 out << ';';
5999c315
JF
312}
313
652ec1ba 314void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 315 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
316}
317
652ec1ba 318void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 319 Output(out, flags | CYNoRightHand);
d35a3b07
JF
320}
321
96a7e5c2
JF
322void CYExpression::Output(CYOutput &out) const {
323 Output(out, CYNoFlags);
324}
325
9a39f705 326void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
96a7e5c2
JF
327 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
328 out << '(' << *this << ')';
329 else
b09da87b
JF
330 Output(out, flags);
331}
332
a0be43fc
JF
333void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
334 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_;
335}
336
b10bd496 337void CYFinally::Output(CYOutput &out) const {
3b52fd1a 338 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
339}
340
fb98ac0c 341void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 342 out << "for" << ' ' << '(';
5999c315 343 if (initialiser_ != NULL)
15b88a33 344 initialiser_->Output(out, CYNoIn);
1fdca2fa 345 out.Terminate();
e661185c
JF
346 if (test_ != NULL)
347 out << ' ';
96a7e5c2 348 out << test_;
1fdca2fa 349 out.Terminate();
e661185c
JF
350 if (increment_ != NULL)
351 out << ' ';
96a7e5c2 352 out << increment_;
5999c315 353 out << ')';
d29365ce 354 code_->Single(out, CYRight(flags));
5999c315
JF
355}
356
d5618df7 357void CYForOf::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
358 out << "for" << ' ' << "each" << ' ' << '(';
359 initialiser_->ForIn(out, CYNoIn);
360 out << "in" << *set_ << ')';
361 code_->Single(out, CYRight(flags));
75b0a457
JF
362}
363
d5618df7 364void CYForOfComprehension::Output(CYOutput &out) const {
4644480a 365 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
366}
367
fb98ac0c 368void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 369 out << "for" << ' ' << '(';
029bc65b
JF
370 if (initialiser_ != NULL)
371 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 372 out << "in" << *set_ << ')';
fb98ac0c 373 code_->Single(out, CYRight(flags));
5999c315
JF
374}
375
4644480a
JF
376void CYForInComprehension::Output(CYOutput &out) const {
377 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
378}
379
fb98ac0c 380void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 381 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
382 bool protect((flags & CYNoFunction) != 0);
383 if (protect)
384 out << '(';
fb98ac0c
JF
385 out << "function";
386 if (name_ != NULL)
387 out << ' ' << *name_;
1fdca2fa 388 out << '(' << parameters_ << ')';
3b52fd1a 389 out << ' ' << code_;
fb98ac0c
JF
390 if (protect)
391 out << ')';
392}
393
394void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
395 CYFunction::Output(out, flags);
396}
397
398void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
399 CYFunction::Output(out, flags);
b09da87b
JF
400}
401
652ec1ba 402void CYFunctionParameter::Output(CYOutput &out) const {
c8a0500b 403 initialiser_->Output(out, CYNoFlags);
96a7e5c2
JF
404 if (next_ != NULL)
405 out << ',' << ' ' << *next_;
5999c315
JF
406}
407
029bc65b
JF
408const char *CYIdentifier::Word() const {
409 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
410}
411
fb98ac0c
JF
412void CYIf::Output(CYOutput &out, CYFlags flags) const {
413 bool protect(false);
414 if (false_ == NULL && (flags & CYNoDangle) != 0) {
415 protect = true;
416 out << '{';
96a7e5c2 417 }
1fdca2fa
JF
418
419 out << "if" << ' ' << '(' << *test_ << ')';
420
fb98ac0c 421 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 422
fb98ac0c 423 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
424 if (false_ == NULL)
425 jacks |= right;
d29365ce
JF
426 else
427 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 428
3b52fd1a 429 true_->Single(out, jacks);
1fdca2fa 430
5999c315 431 if (false_ != NULL) {
e661185c 432 out << '\t' << "else";
96a7e5c2 433 false_->Single(out, right);
5999c315 434 }
1fdca2fa 435
fb98ac0c
JF
436 if (protect)
437 out << '}';
5999c315
JF
438}
439
4644480a
JF
440void CYIfComprehension::Output(CYOutput &out) const {
441 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
442}
443
652ec1ba 444void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 445 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 446 if (const char *word = property_->Word())
3b52fd1a 447 out << "->" << word;
96a7e5c2 448 else
3b52fd1a 449 out << "->" << '[' << *property_ << ']';
5999c315
JF
450}
451
652ec1ba 452void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 453 const char *name(Operator());
d09e527c 454 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
455 if (protect)
456 out << '(';
b09da87b 457 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 458 lhs_->Output(out, Precedence(), left);
96a7e5c2 459 out << ' ' << name << ' ';
b09da87b 460 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
461 rhs_->Output(out, Precedence() - 1, right);
462 if (protect)
463 out << ')';
5999c315
JF
464}
465
3b52fd1a
JF
466void CYLabel::Output(CYOutput &out, CYFlags flags) const {
467 out << *name_ << ':' << ' ';
468 statement_->Single(out, CYRight(flags));
469}
470
9a39f705
JF
471void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
472 next_->Output(out, Precedence(), identifier);
473 out << '[';
474 out << size_;
475 out << ']';
476}
477
3fe16be7
JF
478void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
479 out << '(' << '^';
480 next_->Output(out, Precedence(), identifier);
481 out << ')' << '(' << parameters_ << ')';
482}
483
9a39f705
JF
484void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
485 out << "const";
486 next_->Output(out, Precedence(), identifier);
487}
488
489void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
490 next_->Output(out, Precedence(), identifier);
491 out << '(' << parameters_ << ')';
492}
493
494void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
495 out << '*';
496 next_->Output(out, Precedence(), identifier);
497}
498
499void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
500 out << "volatile";
501 next_->Output(out, Precedence(), identifier);
502}
503
504void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
505 if (this == NULL) {
506 out << identifier;
507 return;
508 }
509
510 bool protect(precedence > Precedence());
511
512 if (protect)
513 out << '(';
514 Output(out, identifier);
515 if (protect)
516 out << ')';
517}
518
60097023 519void CYTypedIdentifier::Output(CYOutput &out) const {
3fe283c5 520 specifier_->Output(out);
9a39f705
JF
521 modifier_->Output(out, 0, identifier_);
522}
523
524void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
525 out << "@encode(" << typed_ << ")";
526}
527
528void CYTypedParameter::Output(CYOutput &out) const {
529 out << typed_;
530 if (next_ != NULL)
531 out << ',' << ' ' << next_;
60097023
JF
532}
533
690cf1a8
JF
534void CYLambda::Output(CYOutput &out, CYFlags flags) const {
535 // XXX: this is seriously wrong
536 out << "[](";
537 out << ")->";
538 out << "{";
539 out << "}";
540}
541
60097023
JF
542void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
543 out << "typedef" << *typed_;
544}
545
c8a0500b 546void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
15b88a33
JF
547 out << "let" << ' ' << '(' << *declarations_ << ')';
548 code_->Single(out, CYRight(flags));
cac61857
JF
549}
550
2eb8215d
JF
551namespace cy {
552namespace Syntax {
553
554void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 555 out << "new" << ' ';
11c1cc16 556 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 557 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
558 if (arguments_ != NULL)
559 out << '(' << *arguments_ << ')';
5999c315
JF
560}
561
2eb8215d
JF
562} }
563
652ec1ba 564void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
565 CYWord::Output(out);
566}
567
652ec1ba 568void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
569 std::ostringstream str;
570 CYNumerify(str, Value());
9561f209
JF
571 std::string value(str.str());
572 out << value.c_str();
573 // XXX: this should probably also handle hex conversions and exponents
574 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
575 out << '.';
5999c315
JF
576}
577
652ec1ba 578void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 579 Output(out, CYNoFlags);
e5bc40db
JF
580}
581
652ec1ba 582void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
583 bool protect((flags & CYNoBrace) != 0);
584 if (protect)
585 out << '(';
c0bc320e
JF
586 out << '{' << '\n';
587 ++out.indent_;
3b52fd1a 588 out << properties_;
c0bc320e
JF
589 --out.indent_;
590 out << '\t' << '}';
b09da87b
JF
591 if (protect)
592 out << ')';
693d501b
JF
593}
594
652ec1ba 595void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 596 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 597 out << Operator();
5999c315
JF
598}
599
652ec1ba 600void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 601 const char *name(Operator());
1ef7d061 602 out << name;
96a7e5c2 603 if (Alphabetic())
11c1cc16 604 out << ' ';
96a7e5c2 605 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
606}
607
3b52fd1a
JF
608void CYProgram::Output(CYOutput &out) const {
609 if (statements_ != NULL)
610 statements_->Multiple(out);
611}
612
652ec1ba 613void CYProperty::Output(CYOutput &out) const {
c0bc320e 614 out << '\t';
e5bc40db 615 name_->PropertyName(out);
96a7e5c2 616 out << ':' << ' ';
8351aa30 617 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 618 if (next_ != NULL)
c0bc320e
JF
619 out << ',' << '\n' << *next_;
620 else
621 out << '\n';
5999c315
JF
622}
623
63cd45c9
JF
624void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
625 out << Value();
63cd45c9
JF
626}
627
fb98ac0c 628void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
629 out << "return";
630 if (value_ != NULL)
631 out << ' ' << *value_;
632 out << ';';
5999c315
JF
633}
634
6c093cce
JF
635void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
636 call_->Output(out, CYLeft(flags));
637 out << ' ';
638 proc_->Output(out, CYRight(flags));
639}
640
641void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
642 // XXX: this is not outputting the parameters
643 out << code_;
644}
645
fb98ac0c
JF
646void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
647 bool first(true);
c2c9f509 648 CYForEach (next, this) {
fb98ac0c 649 bool last(next->next_ == NULL);
7bf4a0cd 650 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 651 first = false;
1fdca2fa 652 out << '\t';
fb98ac0c 653 next->Output(out, jacks);
1fdca2fa 654 out << '\n';
fb98ac0c 655 }
5999c315
JF
656}
657
3b52fd1a 658void CYStatement::Single(CYOutput &out, CYFlags flags) const {
0f37eca9
JF
659 if (this == NULL)
660 return out.Terminate();
661
3b52fd1a
JF
662 _assert(next_ == NULL);
663 out << '\n';
664 ++out.indent_;
665 out << '\t';
666 Output(out, flags);
667 out << '\n';
668 --out.indent_;
5999c315
JF
669}
670
652ec1ba 671void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 672 std::ostringstream str;
520c130f 673 CYStringify(str, value_, size_);
96a7e5c2 674 out << str.str().c_str();
5999c315
JF
675}
676
652ec1ba 677void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
678 if (const char *word = Word())
679 out << word;
680 else
96a7e5c2 681 out << *this;
e5bc40db
JF
682}
683
c0bc320e
JF
684static const char *Reserved_[] = {
685 "false", "null", "true",
686
687 "break", "case", "catch", "continue", "default",
688 "delete", "do", "else", "finally", "for", "function",
689 "if", "in", "instanceof", "new", "return", "switch",
690 "this", "throw", "try", "typeof", "var", "void",
691 "while", "with",
692
693 "debugger", "const",
694
695 "class", "enum", "export", "extends", "import", "super",
696
697 "abstract", "boolean", "byte", "char", "double", "final",
698 "float", "goto", "int", "long", "native", "short",
699 "synchronized", "throws", "transient", "volatile",
700
701 "let", "yield",
702
c0bc320e
JF
703 NULL
704};
705
11c1cc16
JF
706const char *CYString::Word() const {
707 if (size_ == 0 || !WordStartRange_[value_[0]])
708 return NULL;
709 for (size_t i(1); i != size_; ++i)
710 if (!WordEndRange_[value_[i]])
711 return NULL;
712 const char *value(Value());
c0bc320e 713 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
714 if (strcmp(*reserved, value) == 0)
715 return NULL;
716 return value;
717}
718
fb98ac0c 719void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
720 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
721 out << clauses_;
5999c315
JF
722 out << '}';
723}
724
652ec1ba 725void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
726 CYWord::Output(out);
727}
728
37954781
JF
729namespace cy {
730namespace Syntax {
731
732void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
733 out << "throw";
734 if (value_ != NULL)
735 out << ' ' << *value_;
736 out << ';';
5999c315
JF
737}
738
37954781 739void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 740 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
741}
742
37954781
JF
743} }
744
03db6a67
JF
745void CYTypeError::Output(CYOutput &out) const {
746 out << "@error";
747}
748
3fe283c5
JF
749void CYTypeLong::Output(CYOutput &out) const {
750 out << "long" << specifier_;
751}
752
753void CYTypeShort::Output(CYOutput &out) const {
754 out << "short" << specifier_;
755}
756
757void CYTypeSigned::Output(CYOutput &out) const {
758 out << "signed" << specifier_;
759}
760
761void CYTypeUnsigned::Output(CYOutput &out) const {
762 out << "unsigned" << specifier_;
763}
764
765void CYTypeVariable::Output(CYOutput &out) const {
766 out << *name_;
767}
768
769void CYTypeVoid::Output(CYOutput &out) const {
770 out << "void";
771}
772
fb98ac0c 773void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 774 out << "var";
96a7e5c2
JF
775 declarations_->Output(out, flags);
776 out << ';';
cac61857
JF
777}
778
652ec1ba 779void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
780 out << *name_;
781}
782
fb98ac0c 783void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 784 out << "while" << '(' << *test_ << ')';
fb98ac0c 785 code_->Single(out, CYRight(flags));
5999c315
JF
786}
787
fb98ac0c 788void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 789 out << "with" << '(' << *scope_ << ')';
fb98ac0c 790 code_->Single(out, CYRight(flags));
5999c315
JF
791}
792
652ec1ba 793void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
794 if (object)
795 out << "objc_getClass(";
029bc65b 796 out << '"' << Word() << '"';
367eebb1
JF
797 if (object)
798 out << ')';
e5bc40db
JF
799}
800
652ec1ba 801void CYWord::Output(CYOutput &out) const {
029bc65b
JF
802 out << Word();
803 if (out.options_.verbose_)
804 out.out_ << '@' << this;
5999c315 805}
e5bc40db 806
652ec1ba 807void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
808 Output(out);
809}
029bc65b
JF
810
811const char *CYWord::Word() const {
812 return word_;
813}