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