]> git.saurik.com Git - cycript.git/blob - Output.cpp
Drastic modifications to exception handling that required temporarily bringing back...
[cycript.git] / Output.cpp
1 #include "Parser.hpp"
2
3 #include <iostream>
4 #include <iomanip>
5
6 _finline CYFlags operator ~(CYFlags rhs) {
7 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
8 }
9
10 _finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
11 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
12 }
13
14 _finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
15 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
16 }
17
18 _finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
19 return lhs = lhs | rhs;
20 }
21
22 _finline CYFlags CYLeft(CYFlags flags) {
23 return flags & ~CYNoTrailer;
24 }
25
26 _finline CYFlags CYCenter(CYFlags flags) {
27 return flags & CYNoIn;
28 }
29
30 _finline CYFlags CYRight(CYFlags flags) {
31 return flags & (CYNoIn | CYNoTrailer);
32 }
33
34 bool CYFalse::Value() const {
35 return false;
36 }
37
38 bool CYTrue::Value() const {
39 return true;
40 }
41
42 #define CYPA 16
43
44 void CYAddressOf::Output(std::ostream &out, CYFlags flags) const {
45 rhs_->Output(out, 1, CYLeft(flags));
46 out << ".$()";
47 }
48
49 void CYArgument::Output(std::ostream &out) const {
50 if (name_ != NULL) {
51 out << *name_;
52 if (value_ != NULL)
53 out << ":";
54 }
55 if (value_ != NULL)
56 value_->Output(out, CYPA, CYNoFlags);
57 if (next_ != NULL) {
58 if (next_->name_ == NULL)
59 out << ',';
60 else
61 out << ' ';
62 next_->Output(out);
63 }
64 }
65
66 void CYArray::Output(std::ostream &out, CYFlags flags) const {
67 out << '[';
68 if (elements_ != NULL)
69 elements_->Output(out);
70 out << ']';
71 }
72
73 void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
74 lhs_->Output(out, Precedence() - 1, CYLeft(flags));
75 out << Operator();
76 rhs_->Output(out, Precedence(), CYRight(flags));
77 }
78
79 void CYBoolean::Output(std::ostream &out, CYFlags flags) const {
80 if ((flags & CYNoLeader) != 0)
81 out << ' ';
82 out << (Value() ? "true" : "false");
83 if ((flags & CYNoTrailer) != 0)
84 out << ' ';
85 }
86
87 void CYBreak::Output(std::ostream &out) const {
88 out << "break";
89 if (label_ != NULL)
90 out << ' ' << *label_;
91 out << ';';
92 }
93
94 void CYCall::Output(std::ostream &out, CYFlags flags) const {
95 function_->Output(out, Precedence(), CYLeft(flags));
96 out << '(';
97 if (arguments_ != NULL)
98 arguments_->Output(out);
99 out << ')';
100 }
101
102 void CYCatch::Output(std::ostream &out) const {
103 out << "catch(" << *name_ << ')';
104 code_->Output(out, true);
105 }
106
107 void CYClass::Output(std::ostream &out) const {
108 out << "(function($cys,$cyc,$cym,$cyn,$cyt){";
109 out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);";
110 out << "$cym=object_getClass($cyc);";
111 if (fields_ != NULL)
112 fields_->Output(out);
113 if (messages_ != NULL)
114 messages_->Output(out);
115 out << "objc_registerClassPair($cyc);";
116 out << "})(";
117 if (super_ != NULL)
118 super_->Output(out, CYPA, CYNoFlags);
119 else
120 out << "null";
121 out << ");";
122 }
123
124 void CYCondition::Output(std::ostream &out, CYFlags flags) const {
125 test_->Output(out, Precedence() - 1, CYLeft(flags));
126 out << '?';
127 if (true_ != NULL)
128 true_->Output(out, CYPA, CYNoFlags);
129 out << ':';
130 false_->Output(out, CYPA, CYRight(flags));
131 }
132
133 void CYContinue::Output(std::ostream &out) const {
134 out << "continue";
135 if (label_ != NULL)
136 out << ' ' << *label_;
137 out << ';';
138 }
139
140 void CYClause::Output(std::ostream &out) const {
141 if (case_ != NULL) {
142 out << "case";
143 case_->Output(out, CYNoFlags);
144 } else
145 out << "default";
146 out << ':';
147 if (code_ != NULL)
148 code_->Output(out, false);
149 out << *next_;
150 }
151
152 // XXX: deal with NoIn
153 void CYDeclaration::Part(std::ostream &out) const {
154 out << "var ";
155 Output(out);
156 }
157
158 void CYDeclaration::Output(std::ostream &out) const {
159 out << *identifier_;
160 if (initialiser_ != NULL) {
161 out << '=';
162 initialiser_->Output(out, CYPA, CYNoFlags);
163 }
164 }
165
166 // XXX: deal with NoIn
167 void CYDeclarations::Part(std::ostream &out) const {
168 out << "var ";
169
170 const CYDeclarations *declaration(this);
171 output:
172 out << *declaration->declaration_;
173 declaration = declaration->next_;
174
175 if (declaration != NULL) {
176 out << ',';
177 goto output;
178 }
179 }
180
181 void CYDeclarations::Output(std::ostream &out) const {
182 Part(out);
183 out << ';';
184 }
185
186 void CYDoWhile::Output(std::ostream &out) const {
187 // XXX: extra space character!
188 out << "do ";
189 code_->Output(out, false);
190 out << "while(";
191 test_->Output(out, CYNoFlags);
192 out << ')';
193 }
194
195 void CYElement::Output(std::ostream &out) const {
196 if (value_ != NULL)
197 value_->Output(out, CYPA, CYNoFlags);
198 if (next_ != NULL || value_ == NULL)
199 out << ',';
200 if (next_ != NULL)
201 next_->Output(out);
202 }
203
204 void CYEmpty::Output(std::ostream &out) const {
205 out << ';';
206 }
207
208 void CYEmpty::Output(std::ostream &out, bool block) const {
209 if (next_ != NULL)
210 CYSource::Output(out, block);
211 else
212 out << "{}";
213 }
214
215 void CYExpress::Output(std::ostream &out) const {
216 expression_->Output(out, CYNoFunction | CYNoBrace);
217 out << ';';
218 }
219
220 void CYExpression::Part(std::ostream &out) const {
221 // XXX: this should handle LeftHandSideExpression
222 Output(out, CYNoIn);
223 }
224
225 void CYCompound::Output(std::ostream &out, CYFlags flags) const {
226 if (CYExpression *expression = expressions_)
227 if (CYExpression *next = expression->next_) {
228 expression->Output(out, CYLeft(flags));
229 CYFlags center(CYCenter(flags));
230 while (next != NULL) {
231 expression = next;
232 out << ',';
233 next = expression->next_;
234 CYFlags right(next != NULL ? center : CYRight(flags));
235 expression->Output(out, right);
236 }
237 } else
238 expression->Output(out, flags);
239 }
240
241 void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
242 if (precedence < Precedence()) {
243 out << '(';
244 Output(out, CYNoFlags);
245 out << ')';
246 } else
247 Output(out, flags);
248 }
249
250 void CYField::Output(std::ostream &out) const {
251 // XXX: implement!
252 }
253
254 void CYFor::Output(std::ostream &out) const {
255 out << "for(";
256 if (initialiser_ != NULL)
257 initialiser_->Part(out);
258 out << ';';
259 if (test_ != NULL)
260 test_->Output(out, CYNoFlags);
261 out << ';';
262 if (increment_ != NULL)
263 increment_->Output(out, CYNoFlags);
264 out << ')';
265 code_->Output(out, false);
266 }
267
268 void CYForIn::Output(std::ostream &out) const {
269 out << "for(";
270 initialiser_->Part(out);
271 // XXX: deal with this space character!
272 out << ' ';
273 out << "in";
274 set_->Output(out, CYNoLeader);
275 out << ')';
276 code_->Output(out, false);
277 }
278
279 void CYFunction::Output(std::ostream &out) const {
280 CYLambda::Output(out, CYNoFlags);
281 }
282
283 void CYFunctionParameter::Output(std::ostream &out) const {
284 out << *name_;
285 if (next_ != NULL) {
286 out << ',';
287 out << *next_;
288 }
289 }
290
291 void CYIf::Output(std::ostream &out) const {
292 out << "if(";
293 test_->Output(out, CYNoFlags);
294 out << ')';
295 true_->Output(out, true);
296 if (false_ != NULL) {
297 out << "else ";
298 false_->Output(out, false);
299 }
300 }
301
302 void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
303 rhs_->Output(out, 1, CYLeft(flags));
304 out << "[0]";
305 }
306
307 void CYInfix::Output(std::ostream &out, CYFlags flags) const {
308 const char *name(Operator());
309 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
310 if (protect)
311 out << '(';
312 bool alphabetic(Alphabetic());
313 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
314 if (alphabetic)
315 left |= CYNoTrailer;
316 lhs_->Output(out, Precedence(), left);
317 out << name;
318 CYFlags right(protect ? CYNoFlags : CYRight(flags));
319 if (alphabetic)
320 right |= CYNoLeader;
321 rhs_->Output(out, Precedence() - 1, right);
322 if (protect)
323 out << ')';
324 }
325
326 void CYLambda::Output(std::ostream &out, CYFlags flags) const {
327 bool protect((flags & CYNoFunction) != 0);
328 if (protect)
329 out << '(';
330 out << "function";
331 if (name_ != NULL)
332 out << ' ' << *name_;
333 out << '(';
334 if (parameters_ != NULL)
335 out << *parameters_;
336 out << "){";
337 if (body_ != NULL)
338 body_->Show(out);
339 out << '}';
340 if (protect)
341 out << ')';
342 }
343
344 void CYMember::Output(std::ostream &out, CYFlags flags) const {
345 object_->Output(out, Precedence(), CYLeft(flags));
346 if (const char *word = property_->Word())
347 out << '.' << word;
348 else {
349 out << '[';
350 property_->Output(out, CYNoFlags);
351 out << ']';
352 }
353 }
354
355 void CYMessage::Output(std::ostream &out) const {
356 out << "$cyn=new Selector(\"";
357 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
358 if (parameter->tag_ != NULL) {
359 out << *parameter->tag_;
360 if (parameter->name_ != NULL)
361 out << ':';
362 }
363 out << "\");";
364 out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");";
365 out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
366 out << "new Functor(function(self,_cmd";
367 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
368 if (parameter->name_ != NULL)
369 out << ',' << *parameter->name_;
370 out << "){return function(){";
371 if (body_ != NULL)
372 body_->Show(out);
373 out << "}.call(self);},$cyt),$cyt);";
374 }
375
376 void CYNew::Output(std::ostream &out, CYFlags flags) const {
377 out << "new";
378 constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader);
379 out << '(';
380 if (arguments_ != NULL)
381 arguments_->Output(out);
382 out << ')';
383 }
384
385 void CYNull::Output(std::ostream &out, CYFlags flags) const {
386 if ((flags & CYNoLeader) != 0)
387 out << ' ';
388 CYWord::Output(out);
389 if ((flags & CYNoTrailer) != 0)
390 out << ' ';
391 }
392
393 void CYNumber::Output(std::ostream &out, CYFlags flags) const {
394 if ((flags & CYNoLeader) != 0)
395 out << ' ';
396 // XXX: this is not a useful formatting
397 out << Value();
398 if ((flags & CYNoTrailer) != 0)
399 out << ' ';
400 }
401
402 void CYObject::Output(std::ostream &out, CYFlags flags) const {
403 bool protect((flags & CYNoBrace) != 0);
404 if (protect)
405 out << '(';
406 out << '{';
407 if (property_ != NULL)
408 property_->Output(out);
409 out << '}';
410 if (protect)
411 out << ')';
412 }
413
414 void CYPostfix::Output(std::ostream &out, CYFlags flags) const {
415 lhs_->Output(out, Precedence(), CYLeft(flags));
416 out << Operator();
417 }
418
419 void CYPrefix::Output(std::ostream &out, CYFlags flags) const {
420 bool alphabetic(Alphabetic());
421 out << Operator();
422 CYFlags right(CYRight(flags));
423 if (alphabetic)
424 right |= CYNoLeader;
425 rhs_->Output(out, Precedence(), right);
426 }
427
428 void CYProperty::Output(std::ostream &out) const {
429 out << *name_ << ':';
430 value_->Output(out, CYPA, CYNoFlags);
431 if (next_ != NULL) {
432 out << ',';
433 next_->Output(out);
434 }
435 }
436
437 void CYReturn::Output(std::ostream &out) const {
438 out << "return";
439 if (value_ != NULL)
440 value_->Output(out, CYNoLeader);
441 out << ';';
442 }
443
444 void CYSelector::Output(std::ostream &out, CYFlags flags) const {
445 out << "new Selector(\"";
446 if (name_ != NULL)
447 name_->Output(out);
448 out << "\")";
449 }
450
451 void CYSelectorPart::Output(std::ostream &out) const {
452 if (name_ != NULL)
453 out << *name_;
454 if (value_)
455 out << ':';
456 if (next_ != NULL)
457 next_->Output(out);
458 }
459
460 void CYSend::Output(std::ostream &out, CYFlags flags) const {
461 out << "objc_msgSend(";
462 self_->Output(out, CYPA, CYNoFlags);
463 out << ",\"";
464 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
465 if (argument->name_ != NULL) {
466 out << *argument->name_;
467 if (argument->value_ != NULL)
468 out << ':';
469 }
470 out << "\"";
471 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
472 if (argument->value_ != NULL) {
473 out << ",";
474 argument->value_->Output(out, CYPA, CYNoFlags);
475 }
476 out << ')';
477 }
478
479 void CYSource::Show(std::ostream &out) const {
480 for (const CYSource *next(this); next != NULL; next = next->next_)
481 next->Output(out);
482 }
483
484 void CYSource::Output(std::ostream &out, bool block) const {
485 if (!block && next_ == NULL)
486 Output(out);
487 else {
488 out << '{';
489 Show(out);
490 out << '}';
491 }
492 }
493
494 void CYString::Output(std::ostream &out, CYFlags flags) const {
495 out << '\"';
496 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
497 switch (*value) {
498 case '"': out << "\\\""; break;
499 case '\\': out << "\\\\"; break;
500 case '\b': out << "\\b"; break;
501 case '\f': out << "\\f"; break;
502 case '\n': out << "\\n"; break;
503 case '\r': out << "\\r"; break;
504 case '\t': out << "\\t"; break;
505 case '\v': out << "\\v"; break;
506
507 default:
508 if (*value < 0x20 || *value >= 0x7f)
509 out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
510 else
511 out << *value;
512 }
513 out << '\"';
514 }
515
516 void CYSwitch::Output(std::ostream &out) const {
517 out << "switch(";
518 value_->Output(out, CYNoFlags);
519 out << "){";
520 if (clauses_ != NULL)
521 out << *clauses_;
522 out << '}';
523 }
524
525 void CYThis::Output(std::ostream &out, CYFlags flags) const {
526 if ((flags & CYNoLeader) != 0)
527 out << ' ';
528 CYWord::Output(out);
529 if ((flags & CYNoTrailer) != 0)
530 out << ' ';
531 }
532
533 void CYThrow::Output(std::ostream &out) const {
534 out << "throw";
535 if (value_ != NULL)
536 value_->Output(out, CYNoLeader);
537 out << ';';
538 }
539
540 void CYTry::Output(std::ostream &out) const {
541 out << "try";
542 try_->Output(out, true);
543 if (catch_ != NULL)
544 out << catch_;
545 if (finally_ != NULL) {
546 out << "finally";
547 finally_->Output(out, true);
548 }
549 }
550
551 void CYVariable::Output(std::ostream &out, CYFlags flags) const {
552 if ((flags & CYNoLeader) != 0)
553 out << ' ';
554 out << *name_;
555 if ((flags & CYNoTrailer) != 0)
556 out << ' ';
557 }
558
559 void CYWhile::Output(std::ostream &out) const {
560 out << "while(";
561 test_->Output(out, CYNoFlags);
562 out << ')';
563 code_->Output(out, false);
564 }
565
566 void CYWith::Output(std::ostream &out) const {
567 out << "with(";
568 scope_->Output(out, CYNoFlags);
569 out << ')';
570 code_->Output(out, false);
571 }
572
573 void CYWord::Output(std::ostream &out) const {
574 out << Value();
575 }