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