]>
git.saurik.com Git - cycript.git/blob - Output.cpp
be38f058810a777740663362d0fe01ffac3aae38
6 #include <objc/runtime.h>
9 _finline CYFlags
operator ~(CYFlags rhs
) {
10 return static_cast<CYFlags
>(~static_cast<unsigned>(rhs
));
13 _finline CYFlags
operator &(CYFlags lhs
, CYFlags rhs
) {
14 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) & static_cast<unsigned>(rhs
));
17 _finline CYFlags
operator |(CYFlags lhs
, CYFlags rhs
) {
18 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) | static_cast<unsigned>(rhs
));
21 _finline CYFlags
&operator |=(CYFlags
&lhs
, CYFlags rhs
) {
22 return lhs
= lhs
| rhs
;
25 _finline CYFlags
CYLeft(CYFlags flags
) {
26 return flags
& ~CYNoTrailer
;
29 _finline CYFlags
CYCenter(CYFlags flags
) {
30 return flags
& CYNoIn
;
33 _finline CYFlags
CYRight(CYFlags flags
) {
34 return flags
& (CYNoIn
| CYNoTrailer
| CYNoTerminator
);
37 bool CYFalse::Value() const {
41 bool CYTrue::Value() const {
47 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
48 rhs_
->Output(out
, 1, CYLeft(flags
));
52 void CYArgument::Output(CYOutput
&out
) const {
59 value_
->Output(out
, CYPA
, CYNoFlags
);
61 if (next_
->name_
== NULL
)
69 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
71 if (elements_
!= NULL
)
72 elements_
->Output(out
);
76 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
77 // XXX: I don't necc. need the ()s
78 out
<< "(function($cyv";
79 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
80 if (const char *name
= comprehension
->Name())
84 comprehensions_
->Output(out
);
86 expression_
->Output(out
, CYPA
, CYNoFlags
);
88 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
89 comprehension
->End_(out
);
90 out
<< "return $cyv;";
94 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
95 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
97 rhs_
->Output(out
, Precedence(), CYRight(flags
));
100 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
101 statements_
->Single(out
, flags
);
104 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
105 if ((flags
& CYNoLeader
) != 0)
107 out
<< (Value() ? "true" : "false");
108 if ((flags
& CYNoTrailer
) != 0)
112 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
113 if ((flags
& CYNoLeader
) != 0)
117 out
<< ' ' << *label_
;
118 if ((flags
& CYNoTerminator
) == 0)
120 else if ((flags
& CYNoTrailer
) != 0)
124 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
125 bool protect((flags
& CYNoCall
) != 0);
128 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
130 if (arguments_
!= NULL
)
131 arguments_
->Output(out
);
137 void CYCatch::Output(CYOutput
&out
) const {
138 out
<< "catch(" << *name_
<< "){";
140 code_
->Multiple(out
);
144 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
145 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
146 out
<< "$cyp=object_getClass($cys);";
148 if (messages_
!= NULL
)
149 messages_
->Output(out
, true);
151 name_
->ClassName(out
, true);
153 if ((flags
& CYNoTerminator
) == 0)
157 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
158 // XXX: I don't necc. need the ()s
159 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
160 out
<< "$cyp=object_getClass($cys);";
161 out
<< "$cyc=objc_allocateClassPair($cys,";
163 name_
->ClassName(out
, false);
165 out
<< "$cyq(\"CY$\")";
167 out
<< "$cym=object_getClass($cyc);";
169 fields_
->Output(out
);
170 if (messages_
!= NULL
)
171 messages_
->Output(out
, false);
172 out
<< "objc_registerClassPair($cyc);";
173 out
<< "return $cyc;";
176 super_
->Output(out
, CYPA
, CYNoFlags
);
182 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
183 CYClass::Output(out
, flags
);
186 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
187 CYClass::Output(out
, flags
);
190 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
191 if (CYExpression
*expression
= expressions_
)
192 if (CYExpression
*next
= expression
->next_
) {
193 expression
->Output(out
, CYLeft(flags
));
194 CYFlags
center(CYCenter(flags
));
195 while (next
!= NULL
) {
198 next
= expression
->next_
;
199 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
200 expression
->Output(out
, right
);
203 expression
->Output(out
, flags
);
206 void CYComprehension::Output(CYOutput
&out
) const {
212 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
213 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
216 true_
->Output(out
, CYPA
, CYNoFlags
);
218 false_
->Output(out
, CYPA
, CYRight(flags
));
221 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
222 if ((flags
& CYNoLeader
) != 0)
226 out
<< ' ' << *label_
;
227 if ((flags
& CYNoTerminator
) == 0)
229 else if ((flags
& CYNoTrailer
) != 0)
233 void CYClause::Output(CYOutput
&out
) const {
236 case_
->Output(out
, CYNoLeader
);
241 code_
->Multiple(out
, next_
== NULL
? CYNoFlags
: CYNoTrailer
);
246 const char *CYDeclaration::ForEachIn() const {
247 return identifier_
->Value();
250 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
251 if ((flags
& CYNoLeader
) != 0)
254 Output(out
, CYRight(flags
) | CYNoLeader
);
257 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
261 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
262 if ((flags
& CYNoLeader
) != 0)
265 if (initialiser_
!= NULL
) {
267 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
268 } else if ((flags
& CYNoTrailer
) != 0)
272 void CYDeclarations::For(CYOutput
&out
) const {
274 Output(out
, CYNoIn
| CYNoLeader
);
277 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
278 const CYDeclarations
*declaration(this);
281 CYDeclarations
*next(declaration
->next_
);
282 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
284 declaration
->declaration_
->Output(out
, jacks
);
293 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
294 object_
->Output(out
, Precedence(), CYLeft(flags
));
295 if (const char *word
= property_
->Word())
299 property_
->Output(out
, CYNoFlags
);
304 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
305 if ((flags
& CYNoLeader
) != 0)
308 code_
->Single(out
, CYNoLeader
| CYNoTrailer
);
310 test_
->Output(out
, CYNoFlags
);
314 void CYElement::Output(CYOutput
&out
) const {
316 value_
->Output(out
, CYPA
, CYNoFlags
);
317 if (next_
!= NULL
|| value_
== NULL
)
323 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
327 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
328 bool terminator((flags
& CYNoTerminator
) == 0);
329 expression_
->Output(out
, (terminator
? CYLeft(flags
) : flags
) | CYNoBF
);
334 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
335 Output(out
, CYPA
, CYNoFlags
);
338 const char *CYExpression::ForEachIn() const {
342 void CYExpression::For(CYOutput
&out
) const {
346 void CYExpression::ForEachIn(CYOutput
&out
) const {
347 Output(out
, CYPA
, CYNoRightHand
);
350 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
351 Output(out
, flags
| CYNoRightHand
);
354 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
355 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand()) {
357 Output(out
, CYNoFlags
);
363 void CYField::Output(CYOutput
&out
) const {
367 void CYFinally::Output(CYOutput
&out
) const {
370 code_
->Multiple(out
);
374 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
375 if ((flags
& CYNoLeader
) != 0)
378 if (initialiser_
!= NULL
)
379 initialiser_
->For(out
);
382 test_
->Output(out
, CYNoFlags
);
384 if (increment_
!= NULL
)
385 increment_
->Output(out
, CYNoFlags
);
387 code_
->Single(out
, CYNoFlags
);
390 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
391 if ((flags
& CYNoLeader
) != 0)
394 out
<< "with({$cys:0,$cyt:0}){";
397 set_
->Output(out
, CYPA
, CYNoFlags
);
400 out
<< "for($cyt in $cys){";
402 initialiser_
->ForEachIn(out
);
403 out
<< "=$cys[$cyt];";
405 code_
->Multiple(out
);
412 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
413 out
<< "(function($cys){";
415 set_
->Output(out
, CYPA
, CYNoFlags
);
418 out
<< "for(" << *name_
<< " in $cys){";
419 out
<< *name_
<< "=$cys[" << *name_
<< "];";
422 void CYForEachInComprehension::End_(CYOutput
&out
) const {
426 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
427 if ((flags
& CYNoLeader
) != 0)
430 initialiser_
->ForIn(out
, CYNoIn
| CYNoTrailer
);
432 set_
->Output(out
, CYNoLeader
);
434 code_
->Single(out
, CYRight(flags
));
437 void CYForInComprehension::Begin_(CYOutput
&out
) const {
438 out
<< "for(" << *name_
<< " in";
439 set_
->Output(out
, CYNoLeader
);
443 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
444 bool protect((flags
& CYNoFunction
) != 0);
447 else if ((flags
& CYNoLeader
) != 0)
451 out
<< ' ' << *name_
;
453 if (parameters_
!= NULL
)
457 body_
->Multiple(out
);
463 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
464 CYFunction::Output(out
, flags
);
467 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
468 CYFunction::Output(out
, flags
);
471 void CYFunctionParameter::Output(CYOutput
&out
) const {
479 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
481 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
484 } else if ((flags
& CYNoLeader
) != 0)
487 test_
->Output(out
, CYNoFlags
);
489 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
490 CYFlags
jacks(CYNoDangle
);
491 jacks
|= false_
== NULL
? right
: CYNoTrailer
;
492 true_
->Single(out
, jacks
);
493 if (false_
!= NULL
) {
496 right
|= CYNoTerminator
;
497 false_
->Single(out
, CYNoLeader
| right
);
503 void CYIfComprehension::Begin_(CYOutput
&out
) const {
505 test_
->Output(out
, CYNoFlags
);
509 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
510 rhs_
->Output(out
, 1, CYLeft(flags
));
512 if ((flags
& CYNoTrailer
) != 0)
516 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
517 object_
->Output(out
, Precedence(), CYLeft(flags
));
519 if (const char *word
= property_
->Word())
523 property_
->Output(out
, CYNoFlags
);
528 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
529 const char *name(Operator());
530 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
533 bool alphabetic(Alphabetic());
534 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
537 lhs_
->Output(out
, Precedence(), left
);
539 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
542 if (strcmp(name
, "-") == 0)
544 rhs_
->Output(out
, Precedence() - 1, right
);
549 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
550 if ((flags
& CYNoLeader
) != 0)
553 declarations_
->Output(out
, CYNoFlags
);
555 if (statements_
!= NULL
)
556 statements_
->Multiple(out
);
560 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
562 next_
->Output(out
, replace
);
563 out
<< "$cyn=new Selector(\"";
564 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
565 if (parameter
->tag_
!= NULL
) {
566 out
<< *parameter
->tag_
;
567 if (parameter
->name_
!= NULL
)
571 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
572 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
573 out
<< "new Functor(function(self,_cmd";
574 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
575 if (parameter
->name_
!= NULL
)
576 out
<< ',' << *parameter
->name_
;
577 out
<< "){return function(){";
579 body_
->Multiple(out
);
580 out
<< "}.call(self);},$cyt),$cyt);";
583 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
584 if ((flags
& CYNoLeader
) != 0)
587 constructor_
->Output(out
, Precedence(), CYCenter(flags
) | CYNoLeader
| CYNoCall
);
588 if (arguments_
!= NULL
) {
590 arguments_
->Output(out
);
595 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
596 if ((flags
& CYNoLeader
) != 0)
599 if ((flags
& CYNoTrailer
) != 0)
603 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
604 double value(Value());
605 if ((flags
& CYNoLeader
) != 0 || value
< 0 && (flags
& CYNoHyphen
) != 0)
607 // XXX: decide on correct precision
608 out
.out_
<< std::setprecision(9) << value
;
609 if ((flags
& CYNoTrailer
) != 0)
613 void CYNumber::PropertyName(CYOutput
&out
) const {
614 Output(out
, CYNoFlags
);
617 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
618 bool protect((flags
& CYNoBrace
) != 0);
622 if (property_
!= NULL
)
623 property_
->Output(out
);
629 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
630 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
634 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
635 const char *name(Operator());
636 bool alphabetic(Alphabetic());
637 if (alphabetic
&& (flags
& CYNoLeader
) != 0 || name
[0] == '-' && (flags
& CYNoHyphen
) != 0)
640 CYFlags
right(CYRight(flags
));
643 rhs_
->Output(out
, Precedence(), right
);
646 void CYProperty::Output(CYOutput
&out
) const {
647 name_
->PropertyName(out
);
649 value_
->Output(out
, CYPA
, CYNoFlags
);
656 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
658 if ((flags
& CYNoTrailer
) != 0)
662 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
663 bool terminator((flags
& CYNoTerminator
) == 0);
664 if ((flags
& CYNoLeader
) != 0)
668 value_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
673 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
674 if ((flags
& CYNoLeader
) != 0)
676 out
<< "new Selector(\"";
682 void CYSelectorPart::Output(CYOutput
&out
) const {
691 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
692 if ((flags
& CYNoLeader
) != 0)
694 out
<< "objc_msgSend(";
695 self_
->Output(out
, CYPA
, CYNoFlags
);
697 std::ostringstream name
;
698 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
699 if (argument
->name_
!= NULL
) {
700 name
<< *argument
->name_
;
701 if (argument
->value_
!= NULL
)
704 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
705 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
706 if (argument
->value_
!= NULL
) {
708 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
713 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
715 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
716 bool last(next
->next_
== NULL
);
717 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
719 jacks
|= CYNoTerminator
;
721 next
->Output(out
, jacks
);
725 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
732 if (labels_
!= NULL
&& (flags
& CYNoLeader
) != 0)
736 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
)
737 out
<< *label
->name_
<< ':';
738 Output(out
, protect
? CYRight(flags
) : flags
);
742 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
743 unsigned quot(0), apos(0);
744 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
747 else if (*value
== '\'')
750 bool single(quot
> apos
);
752 out
<< (single
? '\'' : '"');
753 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
755 case '\\': out
<< "\\\\"; break;
756 case '\b': out
<< "\\b"; break;
757 case '\f': out
<< "\\f"; break;
758 case '\n': out
<< "\\n"; break;
759 case '\r': out
<< "\\r"; break;
760 case '\t': out
<< "\\t"; break;
761 case '\v': out
<< "\\v"; break;
776 if (*value
< 0x20 || *value
>= 0x7f)
777 out
.out_
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
781 out
<< (single
? '\'' : '"');
784 void CYString::PropertyName(CYOutput
&out
) const {
785 if (const char *word
= Word())
788 Output(out
, CYNoFlags
);
791 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
792 if ((flags
& CYNoLeader
) != 0)
795 value_
->Output(out
, CYNoFlags
);
797 if (clauses_
!= NULL
)
802 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
803 if ((flags
& CYNoLeader
) != 0)
806 if ((flags
& CYNoTrailer
) != 0)
810 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
811 bool terminator((flags
& CYNoTerminator
) == 0);
812 if ((flags
& CYNoLeader
) != 0)
816 value_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
821 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
822 if ((flags
& CYNoLeader
) != 0)
826 code_
->Multiple(out
);
830 if (finally_
!= NULL
)
831 finally_
->Output(out
);
834 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
835 bool terminator((flags
& CYNoTerminator
) == 0);
836 if ((flags
& CYNoLeader
) != 0)
839 declarations_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
844 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
845 if ((flags
& CYNoLeader
) != 0)
848 if ((flags
& CYNoTrailer
) != 0)
852 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
853 if ((flags
& CYNoLeader
) != 0)
856 test_
->Output(out
, CYNoFlags
);
858 code_
->Single(out
, CYRight(flags
));
861 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
862 if ((flags
& CYNoLeader
) != 0)
865 scope_
->Output(out
, CYNoFlags
);
867 code_
->Single(out
, CYRight(flags
));
870 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
872 out
<< "objc_getClass(";
873 out
<< '"' << Value() << '"';
878 void CYWord::Output(CYOutput
&out
) const {
882 void CYWord::PropertyName(CYOutput
&out
) const {