]> git.saurik.com Git - cycript.git/blame - Output.cpp
Provide a new ?destroy to release the JSContext.
[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 {
e5bc40db
JF
197 if (CYExpression *expression = expressions_)
198 if (CYExpression *next = expression->next_) {
199 expression->Output(out, CYLeft(flags));
200 CYFlags center(CYCenter(flags));
201 while (next != NULL) {
202 expression = next;
96a7e5c2 203 out << ',' << ' ';
e5bc40db
JF
204 next = expression->next_;
205 CYFlags right(next != NULL ? center : CYRight(flags));
206 expression->Output(out, right);
207 }
208 } else
209 expression->Output(out, flags);
210}
211
652ec1ba 212void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 213 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 214 out << ' ' << '?' << ' ';
5999c315 215 if (true_ != NULL)
8351aa30 216 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 217 out << ' ' << ':' << ' ';
8351aa30 218 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
219}
220
fb98ac0c 221void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
222 out << "continue";
223 if (label_ != NULL)
224 out << ' ' << *label_;
96a7e5c2 225 out << ';';
5999c315
JF
226}
227
652ec1ba 228void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
229 if (case_ != NULL)
230 out << "case" << ' ' << *case_;
231 else
5999c315 232 out << "default";
1fdca2fa 233 out << ':' << '\n';
3b52fd1a
JF
234 if (statements_ != NULL)
235 statements_->Multiple(out);
96a7e5c2 236 out << next_;
cac61857
JF
237}
238
c8a0500b
JF
239void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
240 out << "debugger" << ';';
241}
242
652ec1ba 243void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 244 out << "var";
96a7e5c2 245 Output(out, CYRight(flags));
75b0a457
JF
246}
247
652ec1ba 248void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 249 out << *identifier_;
e013809d 250 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 251 if (initialiser_ != NULL) {
96a7e5c2 252 out << ' ' << '=' << ' ';
8351aa30 253 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 254 }
5999c315
JF
255}
256
15b88a33 257void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 258 out << "var";
15b88a33 259 Output(out, CYRight(flags));
96a7e5c2
JF
260}
261
262void CYDeclarations::Output(CYOutput &out) const {
263 Output(out, CYNoFlags);
cac61857 264}
d35a3b07 265
652ec1ba 266void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 267 const CYDeclarations *declaration(this);
fb98ac0c 268 bool first(true);
d35a3b07 269
c8a0500b
JF
270 for (;;) {
271 CYDeclarations *next(declaration->next_);
272
273 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
274 first = false;
275 declaration->declaration_->Output(out, jacks);
276
277 if (next == NULL)
278 break;
279
96a7e5c2 280 out << ',' << ' ';
75b0a457 281 declaration = next;
d35a3b07 282 }
5999c315
JF
283}
284
652ec1ba 285void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 286 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
287 if (const char *word = property_->Word())
288 out << '.' << word;
96a7e5c2
JF
289 else
290 out << '[' << *property_ << ']';
9b5527f0
JF
291}
292
fb98ac0c 293void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 294 out << "do";
d29365ce 295 code_->Single(out, CYCenter(flags));
96a7e5c2 296 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
297}
298
652ec1ba 299void CYElement::Output(CYOutput &out) const {
5999c315 300 if (value_ != NULL)
8351aa30 301 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 302 if (next_ != NULL || value_ == NULL) {
5999c315 303 out << ',';
96a7e5c2 304 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
305 out << ' ';
306 }
5befe15e
JF
307 if (next_ != NULL)
308 next_->Output(out);
5999c315
JF
309}
310
fb98ac0c 311void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 312 out.Terminate();
5999c315
JF
313}
314
fb98ac0c 315void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
316 expression_->Output(out, flags | CYNoBF);
317 out << ';';
5999c315
JF
318}
319
652ec1ba 320void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 321 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
322}
323
652ec1ba 324void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 325 Output(out, flags | CYNoRightHand);
d35a3b07
JF
326}
327
96a7e5c2
JF
328void CYExpression::Output(CYOutput &out) const {
329 Output(out, CYNoFlags);
330}
331
9a39f705 332void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
96a7e5c2
JF
333 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
334 out << '(' << *this << ')';
335 else
b09da87b
JF
336 Output(out, flags);
337}
338
a0be43fc
JF
339void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
340 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << code_;
341}
342
b10bd496 343void CYFinally::Output(CYOutput &out) const {
3b52fd1a 344 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
345}
346
fb98ac0c 347void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 348 out << "for" << ' ' << '(';
5999c315 349 if (initialiser_ != NULL)
15b88a33 350 initialiser_->Output(out, CYNoIn);
1fdca2fa 351 out.Terminate();
e661185c
JF
352 if (test_ != NULL)
353 out << ' ';
96a7e5c2 354 out << test_;
1fdca2fa 355 out.Terminate();
e661185c
JF
356 if (increment_ != NULL)
357 out << ' ';
96a7e5c2 358 out << increment_;
5999c315 359 out << ')';
d29365ce 360 code_->Single(out, CYRight(flags));
5999c315
JF
361}
362
d5618df7 363void CYForOf::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
364 out << "for" << ' ' << "each" << ' ' << '(';
365 initialiser_->ForIn(out, CYNoIn);
366 out << "in" << *set_ << ')';
367 code_->Single(out, CYRight(flags));
75b0a457
JF
368}
369
d5618df7 370void CYForOfComprehension::Output(CYOutput &out) const {
4644480a 371 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
372}
373
fb98ac0c 374void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 375 out << "for" << ' ' << '(';
029bc65b
JF
376 if (initialiser_ != NULL)
377 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 378 out << "in" << *set_ << ')';
fb98ac0c 379 code_->Single(out, CYRight(flags));
5999c315
JF
380}
381
4644480a
JF
382void CYForInComprehension::Output(CYOutput &out) const {
383 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
384}
385
fb98ac0c 386void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 387 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
388 bool protect((flags & CYNoFunction) != 0);
389 if (protect)
390 out << '(';
fb98ac0c
JF
391 out << "function";
392 if (name_ != NULL)
393 out << ' ' << *name_;
1fdca2fa 394 out << '(' << parameters_ << ')';
3b52fd1a 395 out << ' ' << code_;
fb98ac0c
JF
396 if (protect)
397 out << ')';
398}
399
400void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
401 CYFunction::Output(out, flags);
402}
403
404void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
405 CYFunction::Output(out, flags);
b09da87b
JF
406}
407
652ec1ba 408void CYFunctionParameter::Output(CYOutput &out) const {
c8a0500b 409 initialiser_->Output(out, CYNoFlags);
96a7e5c2
JF
410 if (next_ != NULL)
411 out << ',' << ' ' << *next_;
5999c315
JF
412}
413
029bc65b
JF
414const char *CYIdentifier::Word() const {
415 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
416}
417
fb98ac0c
JF
418void CYIf::Output(CYOutput &out, CYFlags flags) const {
419 bool protect(false);
420 if (false_ == NULL && (flags & CYNoDangle) != 0) {
421 protect = true;
422 out << '{';
96a7e5c2 423 }
1fdca2fa
JF
424
425 out << "if" << ' ' << '(' << *test_ << ')';
426
fb98ac0c 427 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 428
fb98ac0c 429 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
430 if (false_ == NULL)
431 jacks |= right;
d29365ce
JF
432 else
433 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 434
3b52fd1a 435 true_->Single(out, jacks);
1fdca2fa 436
5999c315 437 if (false_ != NULL) {
e661185c 438 out << '\t' << "else";
96a7e5c2 439 false_->Single(out, right);
5999c315 440 }
1fdca2fa 441
fb98ac0c
JF
442 if (protect)
443 out << '}';
5999c315
JF
444}
445
4644480a
JF
446void CYIfComprehension::Output(CYOutput &out) const {
447 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
448}
449
652ec1ba 450void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 451 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 452 if (const char *word = property_->Word())
3b52fd1a 453 out << "->" << word;
96a7e5c2 454 else
3b52fd1a 455 out << "->" << '[' << *property_ << ']';
5999c315
JF
456}
457
652ec1ba 458void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 459 const char *name(Operator());
d09e527c 460 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
461 if (protect)
462 out << '(';
b09da87b 463 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 464 lhs_->Output(out, Precedence(), left);
96a7e5c2 465 out << ' ' << name << ' ';
b09da87b 466 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
467 rhs_->Output(out, Precedence() - 1, right);
468 if (protect)
469 out << ')';
5999c315
JF
470}
471
3b52fd1a
JF
472void CYLabel::Output(CYOutput &out, CYFlags flags) const {
473 out << *name_ << ':' << ' ';
474 statement_->Single(out, CYRight(flags));
475}
476
9a39f705
JF
477void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
478 next_->Output(out, Precedence(), identifier);
479 out << '[';
480 out << size_;
481 out << ']';
482}
483
3fe16be7
JF
484void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
485 out << '(' << '^';
486 next_->Output(out, Precedence(), identifier);
487 out << ')' << '(' << parameters_ << ')';
488}
489
9a39f705
JF
490void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
491 out << "const";
492 next_->Output(out, Precedence(), identifier);
493}
494
495void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
496 next_->Output(out, Precedence(), identifier);
497 out << '(' << parameters_ << ')';
498}
499
500void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
501 out << '*';
502 next_->Output(out, Precedence(), identifier);
503}
504
505void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
506 out << "volatile";
507 next_->Output(out, Precedence(), identifier);
508}
509
510void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
511 if (this == NULL) {
512 out << identifier;
513 return;
514 }
515
516 bool protect(precedence > Precedence());
517
518 if (protect)
519 out << '(';
520 Output(out, identifier);
521 if (protect)
522 out << ')';
523}
524
60097023 525void CYTypedIdentifier::Output(CYOutput &out) const {
9a39f705
JF
526 type_->Output(out, 0, CYNoFlags);
527 modifier_->Output(out, 0, identifier_);
528}
529
530void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
531 out << "@encode(" << typed_ << ")";
532}
533
534void CYTypedParameter::Output(CYOutput &out) const {
535 out << typed_;
536 if (next_ != NULL)
537 out << ',' << ' ' << next_;
60097023
JF
538}
539
690cf1a8
JF
540void CYLambda::Output(CYOutput &out, CYFlags flags) const {
541 // XXX: this is seriously wrong
542 out << "[](";
543 out << ")->";
544 out << "{";
545 out << "}";
546}
547
60097023
JF
548void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
549 out << "typedef" << *typed_;
550}
551
c8a0500b 552void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
15b88a33
JF
553 out << "let" << ' ' << '(' << *declarations_ << ')';
554 code_->Single(out, CYRight(flags));
cac61857
JF
555}
556
2eb8215d
JF
557namespace cy {
558namespace Syntax {
559
560void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 561 out << "new" << ' ';
11c1cc16 562 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 563 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
564 if (arguments_ != NULL)
565 out << '(' << *arguments_ << ')';
5999c315
JF
566}
567
2eb8215d
JF
568} }
569
652ec1ba 570void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
571 CYWord::Output(out);
572}
573
652ec1ba 574void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
575 std::ostringstream str;
576 CYNumerify(str, Value());
9561f209
JF
577 std::string value(str.str());
578 out << value.c_str();
579 // XXX: this should probably also handle hex conversions and exponents
580 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
581 out << '.';
5999c315
JF
582}
583
652ec1ba 584void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 585 Output(out, CYNoFlags);
e5bc40db
JF
586}
587
652ec1ba 588void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
589 bool protect((flags & CYNoBrace) != 0);
590 if (protect)
591 out << '(';
c0bc320e
JF
592 out << '{' << '\n';
593 ++out.indent_;
3b52fd1a 594 out << properties_;
c0bc320e
JF
595 --out.indent_;
596 out << '\t' << '}';
b09da87b
JF
597 if (protect)
598 out << ')';
693d501b
JF
599}
600
652ec1ba 601void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 602 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 603 out << Operator();
5999c315
JF
604}
605
652ec1ba 606void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 607 const char *name(Operator());
1ef7d061 608 out << name;
96a7e5c2 609 if (Alphabetic())
11c1cc16 610 out << ' ';
96a7e5c2 611 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
612}
613
3b52fd1a
JF
614void CYProgram::Output(CYOutput &out) const {
615 if (statements_ != NULL)
616 statements_->Multiple(out);
617}
618
652ec1ba 619void CYProperty::Output(CYOutput &out) const {
c0bc320e 620 out << '\t';
e5bc40db 621 name_->PropertyName(out);
96a7e5c2 622 out << ':' << ' ';
8351aa30 623 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 624 if (next_ != NULL)
c0bc320e
JF
625 out << ',' << '\n' << *next_;
626 else
627 out << '\n';
5999c315
JF
628}
629
63cd45c9
JF
630void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
631 out << Value();
63cd45c9
JF
632}
633
fb98ac0c 634void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
635 out << "return";
636 if (value_ != NULL)
637 out << ' ' << *value_;
638 out << ';';
5999c315
JF
639}
640
6c093cce
JF
641void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
642 call_->Output(out, CYLeft(flags));
643 out << ' ';
644 proc_->Output(out, CYRight(flags));
645}
646
647void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
648 // XXX: this is not outputting the parameters
649 out << code_;
650}
651
fb98ac0c
JF
652void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
653 bool first(true);
c2c9f509 654 CYForEach (next, this) {
fb98ac0c 655 bool last(next->next_ == NULL);
7bf4a0cd 656 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 657 first = false;
1fdca2fa 658 out << '\t';
fb98ac0c 659 next->Output(out, jacks);
1fdca2fa 660 out << '\n';
fb98ac0c 661 }
5999c315
JF
662}
663
3b52fd1a 664void CYStatement::Single(CYOutput &out, CYFlags flags) const {
0f37eca9
JF
665 if (this == NULL)
666 return out.Terminate();
667
3b52fd1a
JF
668 _assert(next_ == NULL);
669 out << '\n';
670 ++out.indent_;
671 out << '\t';
672 Output(out, flags);
673 out << '\n';
674 --out.indent_;
5999c315
JF
675}
676
652ec1ba 677void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 678 std::ostringstream str;
520c130f 679 CYStringify(str, value_, size_);
96a7e5c2 680 out << str.str().c_str();
5999c315
JF
681}
682
652ec1ba 683void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
684 if (const char *word = Word())
685 out << word;
686 else
96a7e5c2 687 out << *this;
e5bc40db
JF
688}
689
c0bc320e
JF
690static const char *Reserved_[] = {
691 "false", "null", "true",
692
693 "break", "case", "catch", "continue", "default",
694 "delete", "do", "else", "finally", "for", "function",
695 "if", "in", "instanceof", "new", "return", "switch",
696 "this", "throw", "try", "typeof", "var", "void",
697 "while", "with",
698
699 "debugger", "const",
700
701 "class", "enum", "export", "extends", "import", "super",
702
703 "abstract", "boolean", "byte", "char", "double", "final",
704 "float", "goto", "int", "long", "native", "short",
705 "synchronized", "throws", "transient", "volatile",
706
707 "let", "yield",
708
c0bc320e
JF
709 NULL
710};
711
11c1cc16
JF
712const char *CYString::Word() const {
713 if (size_ == 0 || !WordStartRange_[value_[0]])
714 return NULL;
715 for (size_t i(1); i != size_; ++i)
716 if (!WordEndRange_[value_[i]])
717 return NULL;
718 const char *value(Value());
c0bc320e 719 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
720 if (strcmp(*reserved, value) == 0)
721 return NULL;
722 return value;
723}
724
fb98ac0c 725void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
726 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
727 out << clauses_;
5999c315
JF
728 out << '}';
729}
730
652ec1ba 731void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
732 CYWord::Output(out);
733}
734
37954781
JF
735namespace cy {
736namespace Syntax {
737
738void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
739 out << "throw";
740 if (value_ != NULL)
741 out << ' ' << *value_;
742 out << ';';
5999c315
JF
743}
744
37954781 745void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 746 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
747}
748
37954781
JF
749} }
750
fb98ac0c 751void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 752 out << "var";
96a7e5c2
JF
753 declarations_->Output(out, flags);
754 out << ';';
cac61857
JF
755}
756
652ec1ba 757void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
758 out << *name_;
759}
760
fb98ac0c 761void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 762 out << "while" << '(' << *test_ << ')';
fb98ac0c 763 code_->Single(out, CYRight(flags));
5999c315
JF
764}
765
fb98ac0c 766void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 767 out << "with" << '(' << *scope_ << ')';
fb98ac0c 768 code_->Single(out, CYRight(flags));
5999c315
JF
769}
770
652ec1ba 771void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
772 if (object)
773 out << "objc_getClass(";
029bc65b 774 out << '"' << Word() << '"';
367eebb1
JF
775 if (object)
776 out << ')';
e5bc40db
JF
777}
778
652ec1ba 779void CYWord::Output(CYOutput &out) const {
029bc65b
JF
780 out << Word();
781 if (out.options_.verbose_)
782 out.out_ << '@' << this;
5999c315 783}
e5bc40db 784
652ec1ba 785void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
786 Output(out);
787}
029bc65b
JF
788
789const char *CYWord::Word() const {
790 return word_;
791}