]> git.saurik.com Git - cycript.git/blame - Output.cpp
Fixed some corner cases in flags propogation.
[cycript.git] / Output.cpp
CommitLineData
5999c315
JF
1#include "Parser.hpp"
2
3#include <iostream>
4#include <iomanip>
5
4afefdd9
JF
6#include <objc/runtime.h>
7#include <sstream>
8
b09da87b
JF
9_finline CYFlags operator ~(CYFlags rhs) {
10 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
11}
12
13_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
14 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
15}
16
17_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
18 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
19}
20
21_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
22 return lhs = lhs | rhs;
23}
24
25_finline CYFlags CYLeft(CYFlags flags) {
d29365ce 26 return flags & ~CYNoDangle;
b09da87b
JF
27}
28
96a7e5c2
JF
29_finline CYFlags CYRight(CYFlags flags) {
30 return flags & ~CYNoBF;
b09da87b
JF
31}
32
96a7e5c2 33_finline CYFlags CYCenter(CYFlags flags) {
d29365ce 34 return CYLeft(CYRight(flags));
b09da87b
JF
35}
36
11c1cc16 37#define CYPA 16
b09da87b 38
1fdca2fa
JF
39void CYOutput::Terminate() {
40 out_ << ';';
41 mode_ = NoMode;
42}
43
96a7e5c2 44CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
45 if (rhs == ' ' || rhs == '\n')
46 if (pretty_)
47 out_ << rhs;
48 else goto done;
49 else if (rhs == '\t')
50 if (pretty_)
51 for (unsigned i(0); i != indent_; ++i)
52 out_ << " ";
53 else goto done;
54 else goto work;
55
56 mode_ = NoMode;
57 goto done;
96a7e5c2 58
1fdca2fa 59 work:
96a7e5c2
JF
60 if (mode_ == Terminated && rhs != '}')
61 out_ << ';';
62
63 if (rhs == ';') {
64 if (pretty_)
65 goto none;
66 else {
67 mode_ = Terminated;
68 goto done;
69 }
70 } else if (rhs == '-') {
71 if (mode_ == NoHyphen)
72 out_ << ' ';
73 mode_ = NoHyphen;
74 } else if (WordEndRange_[rhs]) {
75 if (mode_ == NoLetter)
76 out_ << ' ';
77 mode_ = NoLetter;
78 } else none:
79 mode_ = NoMode;
80
81 out_ << rhs;
82 done:
83 return *this;
84}
85
86CYOutput &CYOutput::operator <<(const char *rhs) {
87 size_t size(strlen(rhs));
88
89 if (size == 1)
90 return *this << *rhs;
91
92 if (mode_ == Terminated)
93 out_ << ';';
94 else if (
95 mode_ == NoHyphen && *rhs == '-' ||
96 mode_ == NoLetter && WordEndRange_[*rhs]
97 )
98 out_ << ' ';
99
100 if (WordEndRange_[rhs[size - 1]])
101 mode_ = NoLetter;
102 else
103 mode_ = NoMode;
104
105 out_ << rhs;
106 return *this;
107}
108
11c1cc16 109void OutputBody(CYOutput &out, CYStatement *body) {
1fdca2fa 110 out << ' ' << '{' << '\n';
11c1cc16
JF
111 ++out.indent_;
112 if (body != NULL)
113 body->Multiple(out);
114 --out.indent_;
1fdca2fa 115 out << '\t' << '}';
b09da87b
JF
116}
117
652ec1ba 118void CYAddressOf::Output(CYOutput &out, CYFlags flags) const {
b09da87b 119 rhs_->Output(out, 1, CYLeft(flags));
9b5527f0 120 out << ".$cya()";
5999c315
JF
121}
122
652ec1ba 123void CYArgument::Output(CYOutput &out) const {
d35a3b07 124 if (name_ != NULL) {
5999c315 125 out << *name_;
96a7e5c2
JF
126 if (value_ != NULL)
127 out << ':' << ' ';
5999c315 128 }
d35a3b07 129 if (value_ != NULL)
b09da87b 130 value_->Output(out, CYPA, CYNoFlags);
5999c315 131 if (next_ != NULL) {
96a7e5c2 132 if (next_->name_ == NULL)
11c1cc16 133 out << ',';
96a7e5c2 134 out << ' ' << *next_;
5999c315
JF
135 }
136}
137
652ec1ba 138void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 139 out << '[' << elements_ << ']';
5befe15e
JF
140}
141
652ec1ba 142void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
75b0a457
JF
143 // XXX: I don't necc. need the ()s
144 out << "(function($cyv";
145 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
146 if (const char *name = comprehension->Name())
147 out << ',' << name;
148 out << "){";
dc81e1c2 149 out << "$cyv=[];";
75b0a457 150 comprehensions_->Output(out);
dc81e1c2 151 out << "$cyv.push(";
75b0a457
JF
152 expression_->Output(out, CYPA, CYNoFlags);
153 out << ");";
154 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
155 comprehension->End_(out);
dc81e1c2 156 out << "return $cyv;";
75b0a457
JF
157 out << "}())";
158}
159
652ec1ba 160void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 161 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 162 out << ' ' << Operator() << ' ';
b09da87b 163 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
164}
165
fb98ac0c
JF
166void CYBlock::Output(CYOutput &out, CYFlags flags) const {
167 statements_->Single(out, flags);
9e562cfc
JF
168}
169
652ec1ba 170void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
171 out << (Value() ? "true" : "false");
172}
173
fb98ac0c 174void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
175 out << "break";
176 if (label_ != NULL)
177 out << ' ' << *label_;
96a7e5c2 178 out << ';';
5999c315
JF
179}
180
652ec1ba 181void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
182 bool protect((flags & CYNoCall) != 0);
183 if (protect)
184 out << '(';
185 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 186 out << '(' << arguments_ << ')';
fb98ac0c
JF
187 if (protect)
188 out << ')';
5999c315
JF
189}
190
652ec1ba 191void CYCatch::Output(CYOutput &out) const {
96a7e5c2 192 out << "catch" << ' ' << '(' << *name_ << ')' << ' ' << '{';
b10bd496 193 if (code_ != NULL)
fb98ac0c 194 code_->Multiple(out);
11c1cc16 195 out << '}';
5999c315
JF
196}
197
fb98ac0c 198void CYCategory::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
199 out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
200 out << "$cyp=object_getClass($cys);";
201 out << "$cyc=$cys;";
202 if (messages_ != NULL)
203 messages_->Output(out, true);
204 out << "})(";
367eebb1 205 name_->ClassName(out, true);
fb98ac0c 206 out << ')';
96a7e5c2 207 out << ';';
365abb0a
JF
208}
209
652ec1ba 210void CYClass::Output(CYOutput &out, CYFlags flags) const {
367eebb1 211 // XXX: I don't necc. need the ()s
e5bc40db
JF
212 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
213 out << "$cyp=object_getClass($cys);";
367eebb1
JF
214 out << "$cyc=objc_allocateClassPair($cys,";
215 if (name_ != NULL)
216 name_->ClassName(out, false);
217 else
218 out << "$cyq(\"CY$\")";
219 out << ",0);";
b09da87b
JF
220 out << "$cym=object_getClass($cyc);";
221 if (fields_ != NULL)
222 fields_->Output(out);
223 if (messages_ != NULL)
e5bc40db 224 messages_->Output(out, false);
b09da87b 225 out << "objc_registerClassPair($cyc);";
367eebb1
JF
226 out << "return $cyc;";
227 out << "}(";
b09da87b
JF
228 if (super_ != NULL)
229 super_->Output(out, CYPA, CYNoFlags);
230 else
231 out << "null";
367eebb1 232 out << "))";
b09da87b
JF
233}
234
fb98ac0c
JF
235void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
236 CYClass::Output(out, flags);
237}
238
239void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
240 CYClass::Output(out, flags);
241}
242
652ec1ba 243void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
244 if (CYExpression *expression = expressions_)
245 if (CYExpression *next = expression->next_) {
246 expression->Output(out, CYLeft(flags));
247 CYFlags center(CYCenter(flags));
248 while (next != NULL) {
249 expression = next;
96a7e5c2 250 out << ',' << ' ';
e5bc40db
JF
251 next = expression->next_;
252 CYFlags right(next != NULL ? center : CYRight(flags));
253 expression->Output(out, right);
254 }
255 } else
256 expression->Output(out, flags);
257}
258
652ec1ba 259void CYComprehension::Output(CYOutput &out) const {
75b0a457 260 Begin_(out);
96a7e5c2 261 out << next_;
75b0a457
JF
262}
263
652ec1ba 264void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 265 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 266 out << ' ' << '?' << ' ';
5999c315 267 if (true_ != NULL)
b09da87b 268 true_->Output(out, CYPA, CYNoFlags);
96a7e5c2 269 out << ' ' << ':' << ' ';
b09da87b 270 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
271}
272
fb98ac0c 273void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
274 out << "continue";
275 if (label_ != NULL)
276 out << ' ' << *label_;
96a7e5c2 277 out << ';';
5999c315
JF
278}
279
652ec1ba 280void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
281 if (case_ != NULL)
282 out << "case" << ' ' << *case_;
283 else
5999c315 284 out << "default";
1fdca2fa 285 out << ':' << '\n';
5999c315 286 if (code_ != NULL)
96a7e5c2
JF
287 code_->Multiple(out, CYNoFlags);
288 out << next_;
cac61857
JF
289}
290
291const char *CYDeclaration::ForEachIn() const {
292 return identifier_->Value();
5999c315
JF
293}
294
652ec1ba 295void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 296 out << "var";
96a7e5c2 297 Output(out, CYRight(flags));
75b0a457
JF
298}
299
652ec1ba 300void CYDeclaration::ForEachIn(CYOutput &out) const {
75b0a457 301 out << *identifier_;
5999c315
JF
302}
303
652ec1ba 304void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 305 out << *identifier_;
d35a3b07 306 if (initialiser_ != NULL) {
96a7e5c2 307 out << ' ' << '=' << ' ';
75b0a457 308 initialiser_->Output(out, CYPA, CYRight(flags));
96a7e5c2 309 }
5999c315
JF
310}
311
652ec1ba 312void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 313 out << "var";
96a7e5c2
JF
314 Output(out, CYNoIn);
315}
316
317void CYDeclarations::Output(CYOutput &out) const {
318 Output(out, CYNoFlags);
cac61857 319}
d35a3b07 320
652ec1ba 321void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 322 const CYDeclarations *declaration(this);
fb98ac0c 323 bool first(true);
d35a3b07 324 output:
75b0a457 325 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
326 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
327 first = false;
328 declaration->declaration_->Output(out, jacks);
d35a3b07 329
75b0a457 330 if (next != NULL) {
96a7e5c2 331 out << ',' << ' ';
75b0a457 332 declaration = next;
d35a3b07
JF
333 goto output;
334 }
5999c315
JF
335}
336
652ec1ba 337void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
338 object_->Output(out, Precedence(), CYLeft(flags));
339 if (const char *word = property_->Word())
340 out << '.' << word;
96a7e5c2
JF
341 else
342 out << '[' << *property_ << ']';
9b5527f0
JF
343}
344
fb98ac0c 345void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 346 out << "do";
d29365ce 347 code_->Single(out, CYCenter(flags));
96a7e5c2 348 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
349}
350
652ec1ba 351void CYElement::Output(CYOutput &out) const {
5999c315 352 if (value_ != NULL)
b09da87b 353 value_->Output(out, CYPA, CYNoFlags);
11c1cc16 354 if (next_ != NULL || value_ == NULL) {
5999c315 355 out << ',';
96a7e5c2 356 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
357 out << ' ';
358 }
5befe15e
JF
359 if (next_ != NULL)
360 next_->Output(out);
5999c315
JF
361}
362
fb98ac0c 363void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 364 out.Terminate();
5999c315
JF
365}
366
fb98ac0c 367void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
368 expression_->Output(out, flags | CYNoBF);
369 out << ';';
5999c315
JF
370}
371
652ec1ba 372void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
373 Output(out, CYPA, CYNoFlags);
374}
375
cac61857
JF
376const char *CYExpression::ForEachIn() const {
377 return NULL;
378}
379
652ec1ba 380void CYExpression::For(CYOutput &out) const {
cac61857
JF
381 Output(out, CYNoIn);
382}
383
652ec1ba 384void CYExpression::ForEachIn(CYOutput &out) const {
fb98ac0c 385 Output(out, CYPA, CYNoRightHand);
75b0a457
JF
386}
387
652ec1ba 388void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 389 Output(out, flags | CYNoRightHand);
d35a3b07
JF
390}
391
96a7e5c2
JF
392void CYExpression::Output(CYOutput &out) const {
393 Output(out, CYNoFlags);
394}
395
652ec1ba 396void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
397 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
398 out << '(' << *this << ')';
399 else
b09da87b
JF
400 Output(out, flags);
401}
402
652ec1ba 403void CYField::Output(CYOutput &out) const {
b09da87b 404 // XXX: implement!
5999c315
JF
405}
406
b10bd496 407void CYFinally::Output(CYOutput &out) const {
96a7e5c2 408 out << "finally" << ' ' << '{';
b10bd496 409 if (code_ != NULL)
fb98ac0c 410 code_->Multiple(out);
11c1cc16 411 out << '}';
b10bd496
JF
412}
413
fb98ac0c 414void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 415 out << "for" << ' ' << '(';
5999c315 416 if (initialiser_ != NULL)
cac61857 417 initialiser_->For(out);
1fdca2fa 418 out.Terminate();
96a7e5c2 419 out << test_;
1fdca2fa 420 out.Terminate();
96a7e5c2 421 out << increment_;
5999c315 422 out << ')';
d29365ce 423 code_->Single(out, CYRight(flags));
5999c315
JF
424}
425
fb98ac0c 426void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
6f926cee 427 out << "with({$cys:0,$cyt:0}){";
75b0a457 428
75b0a457
JF
429 out << "$cys=";
430 set_->Output(out, CYPA, CYNoFlags);
11c1cc16 431 out << ';';
75b0a457
JF
432
433 out << "for($cyt in $cys){";
434
435 initialiser_->ForEachIn(out);
436 out << "=$cys[$cyt];";
437
fb98ac0c 438 code_->Multiple(out);
75b0a457 439
6f926cee 440 out << '}';
75b0a457 441
6f926cee 442 out << '}';
75b0a457
JF
443}
444
652ec1ba 445void CYForEachInComprehension::Begin_(CYOutput &out) const {
75b0a457
JF
446 out << "(function($cys){";
447 out << "$cys=";
448 set_->Output(out, CYPA, CYNoFlags);
11c1cc16 449 out << ';';
75b0a457
JF
450
451 out << "for(" << *name_ << " in $cys){";
452 out << *name_ << "=$cys[" << *name_ << "];";
453}
454
652ec1ba 455void CYForEachInComprehension::End_(CYOutput &out) const {
75b0a457
JF
456 out << "}}());";
457}
458
fb98ac0c 459void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
460 out << "for" << ' ' << '(';
461 initialiser_->ForIn(out, CYNoIn);
462 out << "in" << *set_ << ')';
fb98ac0c 463 code_->Single(out, CYRight(flags));
5999c315
JF
464}
465
652ec1ba 466void CYForInComprehension::Begin_(CYOutput &out) const {
96a7e5c2 467 out << "for" << ' ' << '(' << *name_ << "in" << *set_ << ')';
75b0a457
JF
468}
469
fb98ac0c 470void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 471 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
472 bool protect((flags & CYNoFunction) != 0);
473 if (protect)
474 out << '(';
fb98ac0c
JF
475 out << "function";
476 if (name_ != NULL)
477 out << ' ' << *name_;
1fdca2fa 478 out << '(' << parameters_ << ')';
11c1cc16 479 OutputBody(out, body_);
fb98ac0c
JF
480 if (protect)
481 out << ')';
482}
483
484void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
485 CYFunction::Output(out, flags);
486}
487
488void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
489 CYFunction::Output(out, flags);
b09da87b
JF
490}
491
652ec1ba 492void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 493 out << *name_;
96a7e5c2
JF
494 if (next_ != NULL)
495 out << ',' << ' ' << *next_;
5999c315
JF
496}
497
fb98ac0c
JF
498void CYIf::Output(CYOutput &out, CYFlags flags) const {
499 bool protect(false);
500 if (false_ == NULL && (flags & CYNoDangle) != 0) {
501 protect = true;
502 out << '{';
96a7e5c2 503 }
1fdca2fa
JF
504
505 out << "if" << ' ' << '(' << *test_ << ')';
506
fb98ac0c 507 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 508
fb98ac0c 509 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
510 if (false_ == NULL)
511 jacks |= right;
d29365ce
JF
512 else
513 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa
JF
514
515 bool single(true_->Single(out, jacks));
516
5999c315 517 if (false_ != NULL) {
1fdca2fa 518 out << (single ? '\t' : ' ');
fb98ac0c 519 out << "else";
96a7e5c2 520 false_->Single(out, right);
5999c315 521 }
1fdca2fa 522
fb98ac0c
JF
523 if (protect)
524 out << '}';
5999c315
JF
525}
526
652ec1ba 527void CYIfComprehension::Begin_(CYOutput &out) const {
96a7e5c2 528 out << "if" << '(' << *test_ << ')';
75b0a457
JF
529}
530
652ec1ba 531void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
b09da87b 532 rhs_->Output(out, 1, CYLeft(flags));
9b5527f0
JF
533 out << ".$cyi";
534}
535
652ec1ba 536void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
537 object_->Output(out, Precedence(), CYLeft(flags));
538 out << ".$cyi";
539 if (const char *word = property_->Word())
540 out << '.' << word;
96a7e5c2
JF
541 else
542 out << '[' << *property_ << ']';
5999c315
JF
543}
544
652ec1ba 545void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
546 const char *name(Operator());
547 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
548 if (protect)
549 out << '(';
b09da87b 550 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 551 lhs_->Output(out, Precedence(), left);
96a7e5c2 552 out << ' ' << name << ' ';
b09da87b 553 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
554 rhs_->Output(out, Precedence() - 1, right);
555 if (protect)
556 out << ')';
5999c315
JF
557}
558
fb98ac0c 559void CYLet::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 560 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << '{';
cac61857 561 if (statements_ != NULL)
fb98ac0c 562 statements_->Multiple(out);
11c1cc16 563 out << '}';
cac61857
JF
564}
565
652ec1ba 566void CYMessage::Output(CYOutput &out, bool replace) const {
4e8c99fb 567 if (next_ != NULL)
e5bc40db 568 next_->Output(out, replace);
b09da87b
JF
569 out << "$cyn=new Selector(\"";
570 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
571 if (parameter->tag_ != NULL) {
572 out << *parameter->tag_;
573 if (parameter->name_ != NULL)
5999c315
JF
574 out << ':';
575 }
b09da87b 576 out << "\");";
e5bc40db
JF
577 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
578 out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
478d4ed0 579 out << "new Functor(function(self,_cmd";
b09da87b 580 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
581 if (parameter->name_ != NULL)
582 out << ',' << *parameter->name_;
583 out << "){return function(){";
b09da87b 584 if (body_ != NULL)
fb98ac0c 585 body_->Multiple(out);
478d4ed0 586 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
587}
588
652ec1ba 589void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 590 out << "new" << ' ';
11c1cc16 591 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 592 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
593 if (arguments_ != NULL)
594 out << '(' << *arguments_ << ')';
5999c315
JF
595}
596
652ec1ba 597void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
598 CYWord::Output(out);
599}
600
652ec1ba 601void CYNumber::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
602 char value[32];
603 sprintf(value, "%.17g", Value());
604 out << value;
5999c315
JF
605}
606
652ec1ba 607void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 608 Output(out, CYNoFlags);
e5bc40db
JF
609}
610
652ec1ba 611void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
612 bool protect((flags & CYNoBrace) != 0);
613 if (protect)
614 out << '(';
693d501b 615 out << '{';
96a7e5c2 616 out << property_;
693d501b 617 out << '}';
b09da87b
JF
618 if (protect)
619 out << ')';
693d501b
JF
620}
621
652ec1ba 622void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 623 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 624 out << Operator();
5999c315
JF
625}
626
652ec1ba 627void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 628 const char *name(Operator());
1ef7d061 629 out << name;
96a7e5c2 630 if (Alphabetic())
11c1cc16 631 out << ' ';
96a7e5c2 632 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
633}
634
652ec1ba 635void CYProperty::Output(CYOutput &out) const {
e5bc40db 636 name_->PropertyName(out);
96a7e5c2 637 out << ':' << ' ';
b09da87b 638 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2
JF
639 if (next_ != NULL)
640 out << ',' << ' ' << *next_;
5999c315
JF
641}
642
63cd45c9
JF
643void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
644 out << Value();
63cd45c9
JF
645}
646
fb98ac0c 647void CYReturn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 648 out << "return" << value_ << ';';
5999c315
JF
649}
650
652ec1ba 651void CYSelector::Output(CYOutput &out, CYFlags flags) const {
b09da87b 652 out << "new Selector(\"";
62014ea9
JF
653 if (name_ != NULL)
654 name_->Output(out);
dea834b0 655 out << "\")";
e7ed5354
JF
656}
657
652ec1ba 658void CYSelectorPart::Output(CYOutput &out) const {
96a7e5c2 659 out << name_;
62014ea9
JF
660 if (value_)
661 out << ':';
96a7e5c2 662 out << next_;
62014ea9
JF
663}
664
652ec1ba 665void CYSend::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
666 out << "objc_msgSend(";
667 self_->Output(out, CYPA, CYNoFlags);
11c1cc16 668 out << ',';
4afefdd9 669 std::ostringstream name;
b09da87b
JF
670 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
671 if (argument->name_ != NULL) {
4afefdd9 672 name << *argument->name_;
b09da87b 673 if (argument->value_ != NULL)
4afefdd9 674 name << ':';
b09da87b 675 }
652ec1ba 676 out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
b09da87b
JF
677 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
678 if (argument->value_ != NULL) {
11c1cc16 679 out << ',';
b09da87b
JF
680 argument->value_->Output(out, CYPA, CYNoFlags);
681 }
682 out << ')';
683}
684
fb98ac0c
JF
685void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
686 bool first(true);
687 for (const CYStatement *next(this); next != NULL; next = next->next_) {
688 bool last(next->next_ == NULL);
689 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 690 first = false;
1fdca2fa 691 out << '\t';
fb98ac0c 692 next->Output(out, jacks);
1fdca2fa 693 out << '\n';
fb98ac0c 694 }
5999c315
JF
695}
696
1fdca2fa 697bool CYStatement::Single(CYOutput &out, CYFlags flags) const {
fb98ac0c 698 if (next_ != NULL) {
1fdca2fa 699 out << ' ' << '{' << '\n';
11c1cc16 700 ++out.indent_;
fb98ac0c 701 Multiple(out);
11c1cc16 702 --out.indent_;
1fdca2fa
JF
703 out << '\t' << '}';
704 return false;
fb98ac0c 705 } else {
96a7e5c2 706 for (CYLabel *label(labels_); label != NULL; label = label->next_)
1fdca2fa
JF
707 out << ' ' << *label->name_ << ':';
708 out << '\n';
11c1cc16 709 ++out.indent_;
1fdca2fa 710 out << '\t';
96a7e5c2 711 Output(out, flags);
1fdca2fa 712 out << '\n';
11c1cc16 713 --out.indent_;
1fdca2fa 714 return true;
5999c315
JF
715 }
716}
717
652ec1ba 718void CYString::Output(CYOutput &out, CYFlags flags) const {
b4aa79af
JF
719 unsigned quot(0), apos(0);
720 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
721 if (*value == '"')
722 ++quot;
723 else if (*value == '\'')
724 ++apos;
725
726 bool single(quot > apos);
727
96a7e5c2
JF
728 std::ostringstream str;
729
730 str << (single ? '\'' : '"');
5999c315
JF
731 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
732 switch (*value) {
96a7e5c2
JF
733 case '\\': str << "\\\\"; break;
734 case '\b': str << "\\b"; break;
735 case '\f': str << "\\f"; break;
736 case '\n': str << "\\n"; break;
737 case '\r': str << "\\r"; break;
738 case '\t': str << "\\t"; break;
739 case '\v': str << "\\v"; break;
5999c315 740
b4aa79af
JF
741 case '"':
742 if (!single)
96a7e5c2 743 str << "\\\"";
b4aa79af
JF
744 else goto simple;
745 break;
746
747 case '\'':
748 if (single)
96a7e5c2 749 str << "\\'";
b4aa79af
JF
750 else goto simple;
751 break;
752
5999c315
JF
753 default:
754 if (*value < 0x20 || *value >= 0x7f)
96a7e5c2 755 str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
b4aa79af 756 else simple:
96a7e5c2 757 str << *value;
5999c315 758 }
96a7e5c2
JF
759 str << (single ? '\'' : '"');
760
761 out << str.str().c_str();
5999c315
JF
762}
763
652ec1ba 764void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
765 if (const char *word = Word())
766 out << word;
767 else
96a7e5c2 768 out << *this;
e5bc40db
JF
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());
778 // XXX: we should probably include the full ECMAScript3+5 list.
779 static const char *reserveds[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL};
780 for (const char **reserved(reserveds); *reserved != NULL; ++reserved)
781 if (strcmp(*reserved, value) == 0)
782 return NULL;
783 return value;
784}
785
fb98ac0c 786void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
787 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
788 out << clauses_;
5999c315
JF
789 out << '}';
790}
791
652ec1ba 792void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
793 CYWord::Output(out);
794}
795
fb98ac0c 796void CYThrow::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 797 out << "throw" << value_ << ';';
5999c315
JF
798}
799
fb98ac0c 800void CYTry::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 801 out << "try" << ' ' << '{';
b10bd496 802 if (code_ != NULL)
fb98ac0c 803 code_->Multiple(out);
11c1cc16 804 out << '}';
96a7e5c2
JF
805 out << catch_;
806 out << finally_;
5999c315
JF
807}
808
fb98ac0c 809void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 810 out << "var";
96a7e5c2
JF
811 declarations_->Output(out, flags);
812 out << ';';
cac61857
JF
813}
814
652ec1ba 815void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
816 out << *name_;
817}
818
fb98ac0c 819void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 820 out << "while" << '(' << *test_ << ')';
fb98ac0c 821 code_->Single(out, CYRight(flags));
5999c315
JF
822}
823
fb98ac0c 824void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 825 out << "with" << '(' << *scope_ << ')';
fb98ac0c 826 code_->Single(out, CYRight(flags));
5999c315
JF
827}
828
652ec1ba 829void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
830 if (object)
831 out << "objc_getClass(";
832 out << '"' << Value() << '"';
833 if (object)
834 out << ')';
e5bc40db
JF
835}
836
652ec1ba 837void CYWord::Output(CYOutput &out) const {
5999c315
JF
838 out << Value();
839}
e5bc40db 840
652ec1ba 841void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
842 Output(out);
843}