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