]> git.saurik.com Git - cycript.git/blame - Output.cpp
Allow extern "C" {} and limit semicolon insertion.
[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
c5b15840
JF
187void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
188 bool protect((flags & CYNoClass) != 0);
189 if (protect)
190 out << '(';
191 out << "class";
192 if (name_ != NULL)
193 out << ' ' << *name_;
194 out << *tail_;;
195 if (protect)
196 out << ')';
197}
198
199void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
200 out << "class" << ' ' << *name_ << *tail_;
201}
202
203void CYClassTail::Output(CYOutput &out) const {
204 if (extends_ == NULL)
205 out << ' ';
206 else {
207 out << '\n';
208 ++out.indent_;
209 out << "extends" << ' ';
210 extends_->Output(out, CYAssign::Precedence_ - 1, CYNoFlags);
211 out << '\n';
212 --out.indent_;
213 }
214
215 out << '{' << '\n';
216 ++out.indent_;
217
218 --out.indent_;
219 out << '}';
220}
221
652ec1ba 222void CYCompound::Output(CYOutput &out, CYFlags flags) const {
fd5cdf97
JF
223 if (next_ == NULL)
224 expression_->Output(out, flags);
225 else {
226 expression_->Output(out, CYLeft(flags));
227 out << ',' << ' ';
228 next_->Output(out, CYRight(flags));
229 }
e5bc40db
JF
230}
231
c5b15840
JF
232void CYComputed::PropertyName(CYOutput &out) const {
233 out << '[';
234 expression_->Output(out, CYAssign::Precedence_, CYNoFlags);
235 out << ']';
236}
237
652ec1ba 238void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 239 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 240 out << ' ' << '?' << ' ';
5999c315 241 if (true_ != NULL)
8351aa30 242 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 243 out << ' ' << ':' << ' ';
8351aa30 244 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
245}
246
fb98ac0c 247void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
248 out << "continue";
249 if (label_ != NULL)
250 out << ' ' << *label_;
96a7e5c2 251 out << ';';
5999c315
JF
252}
253
652ec1ba 254void CYClause::Output(CYOutput &out) const {
efd689d8 255 out << '\t';
09fc3efb
JF
256 if (value_ != NULL)
257 out << "case" << ' ' << *value_;
96a7e5c2 258 else
5999c315 259 out << "default";
1fdca2fa 260 out << ':' << '\n';
efd689d8 261 ++out.indent_;
b0385401 262 out << code_;
efd689d8 263 --out.indent_;
96a7e5c2 264 out << next_;
cac61857
JF
265}
266
c8a0500b
JF
267void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
268 out << "debugger" << ';';
269}
270
09fc3efb 271void CYBinding::Output(CYOutput &out, CYFlags flags) const {
5999c315 272 out << *identifier_;
e013809d 273 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
09fc3efb 274 if (initializer_ != NULL) {
96a7e5c2 275 out << ' ' << '=' << ' ';
09fc3efb 276 initializer_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 277 }
5999c315
JF
278}
279
09fc3efb 280void CYBindings::Output(CYOutput &out) const {
96a7e5c2 281 Output(out, CYNoFlags);
cac61857 282}
d35a3b07 283
09fc3efb
JF
284void CYBindings::Output(CYOutput &out, CYFlags flags) const {
285 const CYBindings *binding(this);
fb98ac0c 286 bool first(true);
d35a3b07 287
c8a0500b 288 for (;;) {
09fc3efb 289 CYBindings *next(binding->next_);
c8a0500b
JF
290
291 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
292 first = false;
09fc3efb 293 binding->binding_->Output(out, jacks);
c8a0500b
JF
294
295 if (next == NULL)
296 break;
297
96a7e5c2 298 out << ',' << ' ';
09fc3efb 299 binding = next;
d35a3b07 300 }
5999c315
JF
301}
302
652ec1ba 303void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 304 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
305 if (const char *word = property_->Word())
306 out << '.' << word;
96a7e5c2
JF
307 else
308 out << '[' << *property_ << ']';
9b5527f0
JF
309}
310
fb98ac0c 311void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 312 out << "do";
efd689d8
JF
313
314 unsigned line(out.position_.line);
315 unsigned indent(out.indent_);
316 code_->Single(out, CYCenter(flags), CYCompactLong);
317
318 if (out.position_.line != line && out.recent_ == indent)
319 out << ' ';
320 else
321 out << '\n' << '\t';
322
96a7e5c2 323 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
324}
325
fc8fc33d
JF
326void CYElementSpread::Output(CYOutput &out) const {
327 out << "..." << value_;
328}
329
330void CYElementValue::Output(CYOutput &out) const {
5999c315 331 if (value_ != NULL)
8351aa30 332 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 333 if (next_ != NULL || value_ == NULL) {
5999c315 334 out << ',';
fc8fc33d 335 if (next_ != NULL && !next_->Elision())
11c1cc16
JF
336 out << ' ';
337 }
5befe15e
JF
338 if (next_ != NULL)
339 next_->Output(out);
5999c315
JF
340}
341
fb98ac0c 342void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 343 out.Terminate();
5999c315
JF
344}
345
7085e1ab
JF
346void CYEval::Output(CYOutput &out, CYFlags flags) const {
347 _assert(false);
348}
349
fb98ac0c 350void CYExpress::Output(CYOutput &out, CYFlags flags) const {
c5b15840 351 expression_->Output(out, flags | CYNoBFC);
96a7e5c2 352 out << ';';
5999c315
JF
353}
354
96a7e5c2
JF
355void CYExpression::Output(CYOutput &out) const {
356 Output(out, CYNoFlags);
357}
358
9a39f705 359void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
96a7e5c2
JF
360 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
361 out << '(' << *this << ')';
362 else
b09da87b
JF
363 Output(out, flags);
364}
365
c5587ed7 366void CYExternal::Output(CYOutput &out, CYFlags flags) const {
ffc2d225
JF
367 out << "extern" << abi_ << typed_;
368 out.Terminate();
c5587ed7
JF
369}
370
a0be43fc 371void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
b0385401 372 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
a0be43fc
JF
373}
374
b10bd496 375void CYFinally::Output(CYOutput &out) const {
b0385401
JF
376 out << ' ' << "finally" << ' ';
377 out << '{' << '\n';
378 ++out.indent_;
379 out << code_;
380 --out.indent_;
381 out << '\t' << '}';
b10bd496
JF
382}
383
fb98ac0c 384void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 385 out << "for" << ' ' << '(';
09fc3efb
JF
386 if (initializer_ != NULL)
387 initializer_->Output(out, CYNoIn);
1fdca2fa 388 out.Terminate();
e661185c
JF
389 if (test_ != NULL)
390 out << ' ';
96a7e5c2 391 out << test_;
1fdca2fa 392 out.Terminate();
e661185c
JF
393 if (increment_ != NULL)
394 out << ' ';
96a7e5c2 395 out << increment_;
5999c315 396 out << ')';
efd689d8 397 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315 398}
75b0a457 399
7085e1ab
JF
400void CYForLexical::Output(CYOutput &out, CYFlags flags) const {
401 out << (constant_ ? "const" : "let") << ' ';
09fc3efb 402 binding_->Output(out, CYRight(flags));
75b0a457
JF
403}
404
fb98ac0c 405void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 406 out << "for" << ' ' << '(';
09fc3efb
JF
407 initializer_->Output(out, CYNoIn | CYNoRightHand);
408 out << ' ' << "in" << ' ' << *iterable_ << ')';
efd689d8 409 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
410}
411
23111dca
JF
412void CYForInitialized::Output(CYOutput &out, CYFlags flags) const {
413 out << "for" << ' ' << '(' << "var" << ' ';
09fc3efb
JF
414 binding_->Output(out, CYNoIn | CYNoRightHand);
415 out << ' ' << "in" << ' ' << *iterable_ << ')';
23111dca
JF
416 code_->Single(out, CYRight(flags), CYCompactShort);
417}
418
4644480a 419void CYForInComprehension::Output(CYOutput &out) const {
4e3c9056 420 out << "for" << ' ' << '(';
09fc3efb
JF
421 binding_->Output(out, CYNoIn | CYNoRightHand);
422 out << ' ' << "in" << ' ' << *iterable_ << ')';
75b0a457
JF
423}
424
7085e1ab
JF
425void CYForOf::Output(CYOutput &out, CYFlags flags) const {
426 out << "for" << ' ' << '(';
09fc3efb
JF
427 initializer_->Output(out, CYNoRightHand);
428 out << ' ' << "of" << ' ' << *iterable_ << ')';
7085e1ab
JF
429 code_->Single(out, CYRight(flags), CYCompactShort);
430}
431
432void CYForOfComprehension::Output(CYOutput &out) const {
433 out << "for" << ' ' << '(';
09fc3efb
JF
434 binding_->Output(out, CYNoRightHand);
435 out << ' ' << "of" << ' ' << *iterable_ << ')' << next_;
7085e1ab
JF
436}
437
438void CYForVariable::Output(CYOutput &out, CYFlags flags) const {
439 out << "var" << ' ';
09fc3efb 440 binding_->Output(out, CYRight(flags));
7085e1ab
JF
441}
442
c5b15840 443void CYFunction::Output(CYOutput &out) const {
b0385401
JF
444 out << '(' << parameters_ << ')' << ' ';
445 out << '{' << '\n';
446 ++out.indent_;
447 out << code_;
448 --out.indent_;
449 out << '\t' << '}';
fb98ac0c
JF
450}
451
452void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
c5b15840
JF
453 // XXX: one could imagine using + here to save a byte
454 bool protect((flags & CYNoFunction) != 0);
455 if (protect)
456 out << '(';
457 out << "function";
458 if (name_ != NULL)
459 out << ' ' << *name_;
460 CYFunction::Output(out);
461 if (protect)
462 out << ')';
fb98ac0c
JF
463}
464
465void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
c5b15840
JF
466 out << "function" << ' ' << *name_;
467 CYFunction::Output(out);
b09da87b
JF
468}
469
652ec1ba 470void CYFunctionParameter::Output(CYOutput &out) const {
09fc3efb 471 binding_->Output(out, CYNoFlags);
96a7e5c2
JF
472 if (next_ != NULL)
473 out << ',' << ' ' << *next_;
5999c315
JF
474}
475
029bc65b 476const char *CYIdentifier::Word() const {
7085e1ab 477 return next_ == NULL || next_ == this ? CYWord::Word() : next_->Word();
029bc65b
JF
478}
479
fb98ac0c
JF
480void CYIf::Output(CYOutput &out, CYFlags flags) const {
481 bool protect(false);
482 if (false_ == NULL && (flags & CYNoDangle) != 0) {
483 protect = true;
484 out << '{';
96a7e5c2 485 }
1fdca2fa
JF
486
487 out << "if" << ' ' << '(' << *test_ << ')';
488
fb98ac0c 489 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 490
fb98ac0c 491 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
492 if (false_ == NULL)
493 jacks |= right;
d29365ce
JF
494 else
495 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 496
efd689d8
JF
497 unsigned line(out.position_.line);
498 unsigned indent(out.indent_);
499 true_->Single(out, jacks, CYCompactShort);
1fdca2fa 500
5999c315 501 if (false_ != NULL) {
efd689d8
JF
502 if (out.position_.line != line && out.recent_ == indent)
503 out << ' ';
504 else
505 out << '\n' << '\t';
506
507 out << "else";
508 false_->Single(out, right, CYCompactLong);
5999c315 509 }
1fdca2fa 510
fb98ac0c
JF
511 if (protect)
512 out << '}';
5999c315
JF
513}
514
4644480a
JF
515void CYIfComprehension::Output(CYOutput &out) const {
516 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
517}
518
7b750785
JF
519void CYImport::Output(CYOutput &out, CYFlags flags) const {
520 out << "@import";
521}
522
7085e1ab
JF
523void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
524 out << "*";
525 rhs_->Output(out, Precedence(), CYRight(flags));
526}
527
652ec1ba 528void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 529 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 530 if (const char *word = property_->Word())
3b52fd1a 531 out << "->" << word;
96a7e5c2 532 else
3b52fd1a 533 out << "->" << '[' << *property_ << ']';
5999c315
JF
534}
535
652ec1ba 536void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 537 const char *name(Operator());
d09e527c 538 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
539 if (protect)
540 out << '(';
b09da87b 541 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 542 lhs_->Output(out, Precedence(), left);
96a7e5c2 543 out << ' ' << name << ' ';
b09da87b 544 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
545 rhs_->Output(out, Precedence() - 1, right);
546 if (protect)
547 out << ')';
5999c315
JF
548}
549
3b52fd1a 550void CYLabel::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
551 out << *name_ << ':';
552 statement_->Single(out, CYRight(flags), CYCompactShort);
3b52fd1a
JF
553}
554
b0385401
JF
555void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
556 out << '(';
557 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
558 out << ')';
559}
560
561void CYStatement::Output(CYOutput &out) const {
562 Multiple(out);
563}
564
b900e1a4
JF
565void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
566 _assert(false);
567}
568
9a39f705
JF
569void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
570 next_->Output(out, Precedence(), identifier);
571 out << '[';
572 out << size_;
573 out << ']';
574}
575
3fe16be7
JF
576void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
577 out << '(' << '^';
578 next_->Output(out, Precedence(), identifier);
579 out << ')' << '(' << parameters_ << ')';
580}
581
9a39f705 582void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
efd689d8 583 out << "const" << ' ';
9a39f705
JF
584 next_->Output(out, Precedence(), identifier);
585}
586
587void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
588 next_->Output(out, Precedence(), identifier);
589 out << '(' << parameters_ << ')';
590}
591
592void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
593 out << '*';
594 next_->Output(out, Precedence(), identifier);
595}
596
597void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
598 out << "volatile";
599 next_->Output(out, Precedence(), identifier);
600}
601
602void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
603 if (this == NULL) {
604 out << identifier;
605 return;
606 }
607
608 bool protect(precedence > Precedence());
609
610 if (protect)
611 out << '(';
612 Output(out, identifier);
613 if (protect)
614 out << ')';
615}
616
60097023 617void CYTypedIdentifier::Output(CYOutput &out) const {
3fe283c5 618 specifier_->Output(out);
9a39f705
JF
619 modifier_->Output(out, 0, identifier_);
620}
621
622void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
623 out << "@encode(" << typed_ << ")";
624}
625
626void CYTypedParameter::Output(CYOutput &out) const {
627 out << typed_;
628 if (next_ != NULL)
629 out << ',' << ' ' << next_;
60097023
JF
630}
631
690cf1a8
JF
632void CYLambda::Output(CYOutput &out, CYFlags flags) const {
633 // XXX: this is seriously wrong
634 out << "[](";
635 out << ")->";
636 out << "{";
637 out << "}";
638}
639
60097023 640void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
efd689d8 641 out << "typedef" << ' ' << *typed_;
ffc2d225 642 out.Terminate();
60097023
JF
643}
644
64a505ff
JF
645void CYTypeExpression::Output(CYOutput &out, CYFlags flags) const {
646 out << '(' << "typedef" << ' ' << *typed_ << ')';
647}
648
09fc3efb 649void CYLexical::Output(CYOutput &out, CYFlags flags) const {
ca6a1b2b 650 out << "let" << ' ';
09fc3efb 651 bindings_->Output(out, flags); // XXX: flags
ca6a1b2b 652 out << ';';
cac61857
JF
653}
654
7b750785
JF
655void CYModule::Output(CYOutput &out) const {
656 out << part_;
657 if (next_ != NULL)
658 out << '.' << next_;
659}
660
2eb8215d
JF
661namespace cy {
662namespace Syntax {
663
664void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 665 out << "new" << ' ';
11c1cc16 666 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 667 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
668 if (arguments_ != NULL)
669 out << '(' << *arguments_ << ')';
5999c315
JF
670}
671
2eb8215d
JF
672} }
673
652ec1ba 674void CYNull::Output(CYOutput &out, CYFlags flags) const {
8f56307d 675 out << "null";
5999c315
JF
676}
677
652ec1ba 678void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
679 std::ostringstream str;
680 CYNumerify(str, Value());
9561f209
JF
681 std::string value(str.str());
682 out << value.c_str();
683 // XXX: this should probably also handle hex conversions and exponents
684 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
685 out << '.';
5999c315
JF
686}
687
652ec1ba 688void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 689 Output(out, CYNoFlags);
e5bc40db
JF
690}
691
652ec1ba 692void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
693 bool protect((flags & CYNoBrace) != 0);
694 if (protect)
695 out << '(';
c0bc320e
JF
696 out << '{' << '\n';
697 ++out.indent_;
3b52fd1a 698 out << properties_;
c0bc320e
JF
699 --out.indent_;
700 out << '\t' << '}';
b09da87b
JF
701 if (protect)
702 out << ')';
693d501b
JF
703}
704
652ec1ba 705void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 706 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 707 out << Operator();
5999c315
JF
708}
709
652ec1ba 710void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 711 const char *name(Operator());
1ef7d061 712 out << name;
96a7e5c2 713 if (Alphabetic())
11c1cc16 714 out << ' ';
96a7e5c2 715 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
716}
717
a7d8b413 718void CYScript::Output(CYOutput &out) const {
b0385401 719 out << code_;
3b52fd1a
JF
720}
721
652ec1ba 722void CYProperty::Output(CYOutput &out) const {
c5b15840
JF
723 if (next_ != NULL || out.pretty_)
724 out << ',';
725 out << '\n' << next_;
726}
727
728void CYPropertyGetter::Output(CYOutput &out) const {
729 out << "get" << ' ';
730 name_->PropertyName(out);
731 CYFunction::Output(out);
732 CYProperty::Output(out);
733}
734
735void CYPropertyMethod::Output(CYOutput &out) const {
736 name_->PropertyName(out);
737 CYFunction::Output(out);
738 CYProperty::Output(out);
739}
740
741void CYPropertySetter::Output(CYOutput &out) const {
742 out << "set" << ' ';
743 name_->PropertyName(out);
744 CYFunction::Output(out);
745 CYProperty::Output(out);
746}
747
748void CYPropertyValue::Output(CYOutput &out) const {
c0bc320e 749 out << '\t';
e5bc40db 750 name_->PropertyName(out);
96a7e5c2 751 out << ':' << ' ';
8351aa30 752 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
c5b15840 753 CYProperty::Output(out);
5999c315
JF
754}
755
63cd45c9
JF
756void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
757 out << Value();
63cd45c9
JF
758}
759
fb98ac0c 760void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
761 out << "return";
762 if (value_ != NULL)
763 out << ' ' << *value_;
764 out << ';';
5999c315
JF
765}
766
6c093cce
JF
767void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
768 call_->Output(out, CYLeft(flags));
769 out << ' ';
770 proc_->Output(out, CYRight(flags));
771}
772
773void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
0da459fc 774 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
b0385401 775 ++out.indent_;
6c093cce 776 out << code_;
b0385401
JF
777 --out.indent_;
778 out << '\t' << '}';
6c093cce
JF
779}
780
fb98ac0c
JF
781void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
782 bool first(true);
c2c9f509 783 CYForEach (next, this) {
fb98ac0c 784 bool last(next->next_ == NULL);
7bf4a0cd 785 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 786 first = false;
1fdca2fa 787 out << '\t';
fb98ac0c 788 next->Output(out, jacks);
1fdca2fa 789 out << '\n';
fb98ac0c 790 }
5999c315
JF
791}
792
efd689d8 793void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
0f37eca9
JF
794 if (this == NULL)
795 return out.Terminate();
796
3b52fd1a 797 _assert(next_ == NULL);
efd689d8
JF
798
799 CYCompactType compact(Compact());
800
801 if (compact >= request)
802 out << ' ';
803 else {
804 out << '\n';
805 ++out.indent_;
806 out << '\t';
807 }
808
3b52fd1a 809 Output(out, flags);
efd689d8
JF
810
811 if (compact < request)
812 --out.indent_;
5999c315
JF
813}
814
652ec1ba 815void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 816 std::ostringstream str;
520c130f 817 CYStringify(str, value_, size_);
96a7e5c2 818 out << str.str().c_str();
5999c315
JF
819}
820
652ec1ba 821void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
822 if (const char *word = Word())
823 out << word;
824 else
96a7e5c2 825 out << *this;
e5bc40db
JF
826}
827
c0bc320e
JF
828static const char *Reserved_[] = {
829 "false", "null", "true",
830
831 "break", "case", "catch", "continue", "default",
832 "delete", "do", "else", "finally", "for", "function",
833 "if", "in", "instanceof", "new", "return", "switch",
834 "this", "throw", "try", "typeof", "var", "void",
835 "while", "with",
836
837 "debugger", "const",
838
839 "class", "enum", "export", "extends", "import", "super",
840
841 "abstract", "boolean", "byte", "char", "double", "final",
842 "float", "goto", "int", "long", "native", "short",
843 "synchronized", "throws", "transient", "volatile",
844
845 "let", "yield",
846
c0bc320e
JF
847 NULL
848};
849
11c1cc16
JF
850const char *CYString::Word() const {
851 if (size_ == 0 || !WordStartRange_[value_[0]])
852 return NULL;
853 for (size_t i(1); i != size_; ++i)
854 if (!WordEndRange_[value_[i]])
855 return NULL;
856 const char *value(Value());
c0bc320e 857 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
858 if (strcmp(*reserved, value) == 0)
859 return NULL;
860 return value;
861}
862
c5b15840
JF
863void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
864 out << "super";
865 if (const char *word = property_->Word())
866 out << '.' << word;
867 else
868 out << '[' << *property_ << ']';
869}
870
871void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
872 out << "super" << '(' << arguments_ << ')';
873}
874
fb98ac0c 875void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
876 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
877 ++out.indent_;
96a7e5c2 878 out << clauses_;
efd689d8
JF
879 --out.indent_;
880 out << '\t' << '}';
5999c315
JF
881}
882
652ec1ba 883void CYThis::Output(CYOutput &out, CYFlags flags) const {
8f56307d 884 out << "this";
5999c315
JF
885}
886
37954781
JF
887namespace cy {
888namespace Syntax {
889
890void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
891 out << "throw";
892 if (value_ != NULL)
893 out << ' ' << *value_;
894 out << ';';
5999c315
JF
895}
896
37954781 897void Try::Output(CYOutput &out, CYFlags flags) const {
b0385401
JF
898 out << "try" << ' ';
899 out << '{' << '\n';
900 ++out.indent_;
901 out << code_;
902 --out.indent_;
903 out << '\t' << '}';
904 out << catch_ << finally_;
5999c315
JF
905}
906
37954781
JF
907} }
908
03db6a67
JF
909void CYTypeError::Output(CYOutput &out) const {
910 out << "@error";
911}
912
3fe283c5
JF
913void CYTypeLong::Output(CYOutput &out) const {
914 out << "long" << specifier_;
915}
916
917void CYTypeShort::Output(CYOutput &out) const {
918 out << "short" << specifier_;
919}
920
921void CYTypeSigned::Output(CYOutput &out) const {
922 out << "signed" << specifier_;
923}
924
b3c38c5f
JF
925void CYTypeStruct::Output(CYOutput &out) const {
926 out << "struct" << ' ';
927 if (name_ != NULL)
928 out << *name_ << ' ';
929 out << '{' << '\n';
930 ++out.indent_;
931 CYForEach (field, fields_) {
932 out << '\t' << *field->typed_;
933 out.Terminate();
934 out << '\n';
935 }
936 --out.indent_;
937 out << '}';
938}
939
3fe283c5
JF
940void CYTypeUnsigned::Output(CYOutput &out) const {
941 out << "unsigned" << specifier_;
942}
943
944void CYTypeVariable::Output(CYOutput &out) const {
945 out << *name_;
946}
947
948void CYTypeVoid::Output(CYOutput &out) const {
949 out << "void";
950}
951
fb98ac0c 952void CYVar::Output(CYOutput &out, CYFlags flags) const {
efd689d8 953 out << "var" << ' ';
09fc3efb 954 bindings_->Output(out, flags); // XXX: flags
96a7e5c2 955 out << ';';
cac61857
JF
956}
957
652ec1ba 958void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
959 out << *name_;
960}
961
fb98ac0c 962void CYWhile::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
963 out << "while" << ' ' << '(' << *test_ << ')';
964 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
965}
966
fb98ac0c 967void CYWith::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
968 out << "with" << ' ' << '(' << *scope_ << ')';
969 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
970}
971
652ec1ba 972void CYWord::Output(CYOutput &out) const {
029bc65b 973 out << Word();
efd689d8
JF
974 if (out.options_.verbose_) {
975 out('@');
976 char number[32];
977 sprintf(number, "%p", this);
978 out(number);
979 }
5999c315 980}
e5bc40db 981
652ec1ba 982void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
983 Output(out);
984}
029bc65b
JF
985
986const char *CYWord::Word() const {
987 return word_;
988}