]>
git.saurik.com Git - cycript.git/blob - Output.cpp
b8780687a8edf6eddc88bd1b86431bc38267a494
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
);
39 void OutputBody(CYOutput
&out
, CYStatement
*body
) {
53 void CYOutput::Indent() {
55 for (unsigned i(0); i
!= indent_
; ++i
)
59 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
60 rhs_
->Output(out
, 1, CYLeft(flags
));
64 void CYArgument::Output(CYOutput
&out
) const {
74 value_
->Output(out
, CYPA
, CYNoFlags
);
76 if (next_
->name_
!= NULL
)
87 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
89 if (elements_
!= NULL
)
90 elements_
->Output(out
);
94 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
95 // XXX: I don't necc. need the ()s
96 out
<< "(function($cyv";
97 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
98 if (const char *name
= comprehension
->Name())
102 comprehensions_
->Output(out
);
104 expression_
->Output(out
, CYPA
, CYNoFlags
);
106 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
107 comprehension
->End_(out
);
108 out
<< "return $cyv;";
112 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
113 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
119 rhs_
->Output(out
, Precedence(), CYRight(flags
));
122 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
123 statements_
->Single(out
, flags
);
126 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
127 if ((flags
& CYNoLeader
) != 0)
129 out
<< (Value() ? "true" : "false");
130 if ((flags
& CYNoTrailer
) != 0)
134 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
135 if ((flags
& CYNoLeader
) != 0)
139 out
<< ' ' << *label_
;
140 if ((flags
& CYNoTerminator
) == 0)
142 else if ((flags
& CYNoTrailer
) != 0)
146 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
147 bool protect((flags
& CYNoCall
) != 0);
150 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
152 if (arguments_
!= NULL
)
153 arguments_
->Output(out
);
159 void CYCatch::Output(CYOutput
&out
) const {
163 out
<< '(' << *name_
<< ')';
168 code_
->Multiple(out
);
172 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
173 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
174 out
<< "$cyp=object_getClass($cys);";
176 if (messages_
!= NULL
)
177 messages_
->Output(out
, true);
179 name_
->ClassName(out
, true);
181 if ((flags
& CYNoTerminator
) == 0)
185 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
186 // XXX: I don't necc. need the ()s
187 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
188 out
<< "$cyp=object_getClass($cys);";
189 out
<< "$cyc=objc_allocateClassPair($cys,";
191 name_
->ClassName(out
, false);
193 out
<< "$cyq(\"CY$\")";
195 out
<< "$cym=object_getClass($cyc);";
197 fields_
->Output(out
);
198 if (messages_
!= NULL
)
199 messages_
->Output(out
, false);
200 out
<< "objc_registerClassPair($cyc);";
201 out
<< "return $cyc;";
204 super_
->Output(out
, CYPA
, CYNoFlags
);
210 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
211 CYClass::Output(out
, flags
);
214 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
215 CYClass::Output(out
, flags
);
218 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
219 if (CYExpression
*expression
= expressions_
)
220 if (CYExpression
*next
= expression
->next_
) {
221 expression
->Output(out
, CYLeft(flags
));
222 CYFlags
center(CYCenter(flags
));
223 while (next
!= NULL
) {
228 next
= expression
->next_
;
229 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
230 expression
->Output(out
, right
);
233 expression
->Output(out
, flags
);
236 void CYComprehension::Output(CYOutput
&out
) const {
242 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
243 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
250 true_
->Output(out
, CYPA
, CYNoFlags
);
256 false_
->Output(out
, CYPA
, CYRight(flags
));
259 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
260 if ((flags
& CYNoLeader
) != 0)
264 out
<< ' ' << *label_
;
265 if ((flags
& CYNoTerminator
) == 0)
267 else if ((flags
& CYNoTrailer
) != 0)
271 void CYClause::Output(CYOutput
&out
) const {
274 case_
->Output(out
, CYNoLeader
);
281 code_
->Multiple(out
, next_
== NULL
? CYNoFlags
: CYNoTrailer
);
286 const char *CYDeclaration::ForEachIn() const {
287 return identifier_
->Value();
290 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
291 if ((flags
& CYNoLeader
) != 0)
294 Output(out
, CYRight(flags
) | CYNoLeader
);
297 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
301 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
302 if ((flags
& CYNoLeader
) != 0)
305 if (initialiser_
!= NULL
) {
311 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
312 } else if ((flags
& CYNoTrailer
) != 0)
316 void CYDeclarations::For(CYOutput
&out
) const {
318 Output(out
, CYNoIn
| CYNoLeader
);
321 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
322 const CYDeclarations
*declaration(this);
325 CYDeclarations
*next(declaration
->next_
);
326 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
328 declaration
->declaration_
->Output(out
, jacks
);
339 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
340 object_
->Output(out
, Precedence(), CYLeft(flags
));
341 if (const char *word
= property_
->Word())
345 property_
->Output(out
, CYNoFlags
);
350 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
351 if ((flags
& CYNoLeader
) != 0)
354 code_
->Single(out
, CYNoLeader
| CYNoTrailer
);
359 test_
->Output(out
, CYNoFlags
);
363 void CYElement::Output(CYOutput
&out
) const {
365 value_
->Output(out
, CYPA
, CYNoFlags
);
366 if (next_
!= NULL
|| value_
== NULL
) {
368 if (out
.pretty_
&& next_
!= NULL
&& next_
->value_
!= NULL
)
375 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
379 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
380 bool terminator((flags
& CYNoTerminator
) == 0);
381 expression_
->Output(out
, (terminator
? CYLeft(flags
) : flags
) | CYNoBF
);
386 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
387 Output(out
, CYPA
, CYNoFlags
);
390 const char *CYExpression::ForEachIn() const {
394 void CYExpression::For(CYOutput
&out
) const {
398 void CYExpression::ForEachIn(CYOutput
&out
) const {
399 Output(out
, CYPA
, CYNoRightHand
);
402 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
403 Output(out
, flags
| CYNoRightHand
);
406 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
407 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand()) {
409 Output(out
, CYNoFlags
);
415 void CYField::Output(CYOutput
&out
) const {
419 void CYFinally::Output(CYOutput
&out
) const {
425 code_
->Multiple(out
);
429 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
430 if ((flags
& CYNoLeader
) != 0)
436 if (initialiser_
!= NULL
)
437 initialiser_
->For(out
);
440 test_
->Output(out
, CYNoFlags
);
442 if (increment_
!= NULL
)
443 increment_
->Output(out
, CYNoFlags
);
445 code_
->Single(out
, CYNoFlags
);
448 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
449 if ((flags
& CYNoLeader
) != 0)
452 out
<< "with({$cys:0,$cyt:0}){";
455 set_
->Output(out
, CYPA
, CYNoFlags
);
458 out
<< "for($cyt in $cys){";
460 initialiser_
->ForEachIn(out
);
461 out
<< "=$cys[$cyt];";
463 code_
->Multiple(out
);
470 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
471 out
<< "(function($cys){";
473 set_
->Output(out
, CYPA
, CYNoFlags
);
476 out
<< "for(" << *name_
<< " in $cys){";
477 out
<< *name_
<< "=$cys[" << *name_
<< "];";
480 void CYForEachInComprehension::End_(CYOutput
&out
) const {
484 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
485 if ((flags
& CYNoLeader
) != 0)
491 initialiser_
->ForIn(out
, CYNoIn
| CYNoTrailer
);
493 set_
->Output(out
, CYNoLeader
);
495 code_
->Single(out
, CYRight(flags
));
498 void CYForInComprehension::Begin_(CYOutput
&out
) const {
502 out
<< '(' << *name_
<< " in";
503 set_
->Output(out
, CYNoLeader
);
507 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
508 bool protect((flags
& CYNoFunction
) != 0);
511 else if ((flags
& CYNoLeader
) != 0)
515 out
<< ' ' << *name_
;
517 if (parameters_
!= NULL
)
520 OutputBody(out
, body_
);
525 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
526 CYFunction::Output(out
, flags
);
529 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
530 CYFunction::Output(out
, flags
);
533 void CYFunctionParameter::Output(CYOutput
&out
) const {
543 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
545 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
548 } else if ((flags
& CYNoLeader
) != 0)
554 test_
->Output(out
, CYNoFlags
);
556 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
557 CYFlags
jacks(CYNoDangle
);
558 jacks
|= false_
== NULL
? right
: CYNoTrailer
;
559 true_
->Single(out
, jacks
);
560 if (false_
!= NULL
) {
563 right
|= CYNoTerminator
;
564 false_
->Single(out
, CYNoLeader
| right
);
570 void CYIfComprehension::Begin_(CYOutput
&out
) const {
572 test_
->Output(out
, CYNoFlags
);
576 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
577 rhs_
->Output(out
, 1, CYLeft(flags
));
579 if ((flags
& CYNoTrailer
) != 0)
583 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
584 object_
->Output(out
, Precedence(), CYLeft(flags
));
586 if (const char *word
= property_
->Word())
590 property_
->Output(out
, CYNoFlags
);
595 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
596 const char *name(Operator());
597 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
600 bool alphabetic(Alphabetic());
601 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
604 lhs_
->Output(out
, Precedence(), left
);
610 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
613 if (strcmp(name
, "-") == 0)
615 rhs_
->Output(out
, Precedence() - 1, right
);
620 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
621 if ((flags
& CYNoLeader
) != 0)
627 declarations_
->Output(out
, CYNoFlags
);
632 if (statements_
!= NULL
)
633 statements_
->Multiple(out
);
637 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
639 next_
->Output(out
, replace
);
640 out
<< "$cyn=new Selector(\"";
641 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
642 if (parameter
->tag_
!= NULL
) {
643 out
<< *parameter
->tag_
;
644 if (parameter
->name_
!= NULL
)
648 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
649 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
650 out
<< "new Functor(function(self,_cmd";
651 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
652 if (parameter
->name_
!= NULL
)
653 out
<< ',' << *parameter
->name_
;
654 out
<< "){return function(){";
656 body_
->Multiple(out
);
657 out
<< "}.call(self);},$cyt),$cyt);";
660 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
661 if ((flags
& CYNoLeader
) != 0)
666 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
669 constructor_
->Output(out
, Precedence(), jacks
);
670 if (arguments_
!= NULL
) {
672 arguments_
->Output(out
);
677 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
678 if ((flags
& CYNoLeader
) != 0)
681 if ((flags
& CYNoTrailer
) != 0)
685 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
686 double value(Value());
687 if ((flags
& CYNoLeader
) != 0 || value
< 0 && (flags
& CYNoHyphen
) != 0)
689 // XXX: decide on correct precision
690 out
.out_
<< std::setprecision(9) << value
;
691 if ((flags
& CYNoTrailer
) != 0)
695 void CYNumber::PropertyName(CYOutput
&out
) const {
696 Output(out
, CYNoFlags
);
699 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
700 bool protect((flags
& CYNoBrace
) != 0);
704 if (property_
!= NULL
)
705 property_
->Output(out
);
711 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
712 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
716 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
717 const char *name(Operator());
718 bool alphabetic(Alphabetic());
719 if (alphabetic
&& (flags
& CYNoLeader
) != 0 || name
[0] == '-' && (flags
& CYNoHyphen
) != 0)
722 if (alphabetic
&& out
.pretty_
)
724 CYFlags
right(CYRight(flags
));
727 rhs_
->Output(out
, Precedence(), right
);
730 void CYProperty::Output(CYOutput
&out
) const {
731 name_
->PropertyName(out
);
735 value_
->Output(out
, CYPA
, CYNoFlags
);
744 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
746 if ((flags
& CYNoTrailer
) != 0)
750 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
751 bool terminator((flags
& CYNoTerminator
) == 0);
752 if ((flags
& CYNoLeader
) != 0)
756 value_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
761 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
762 if ((flags
& CYNoLeader
) != 0)
764 out
<< "new Selector(\"";
770 void CYSelectorPart::Output(CYOutput
&out
) const {
779 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
780 if ((flags
& CYNoLeader
) != 0)
782 out
<< "objc_msgSend(";
783 self_
->Output(out
, CYPA
, CYNoFlags
);
785 std::ostringstream name
;
786 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
787 if (argument
->name_
!= NULL
) {
788 name
<< *argument
->name_
;
789 if (argument
->value_
!= NULL
)
792 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
793 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
794 if (argument
->value_
!= NULL
) {
796 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
801 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
803 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
804 bool last(next
->next_
== NULL
);
805 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
807 jacks
|= CYNoTerminator
;
810 next
->Output(out
, jacks
);
816 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
832 if (labels_
!= NULL
&& (flags
& CYNoLeader
) != 0)
836 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
) {
837 out
<< *label
->name_
<< ':';
843 Output(out
, protect
? CYRight(flags
) : flags
);
850 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
851 unsigned quot(0), apos(0);
852 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
855 else if (*value
== '\'')
858 bool single(quot
> apos
);
860 out
<< (single
? '\'' : '"');
861 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
863 case '\\': out
<< "\\\\"; break;
864 case '\b': out
<< "\\b"; break;
865 case '\f': out
<< "\\f"; break;
866 case '\n': out
<< "\\n"; break;
867 case '\r': out
<< "\\r"; break;
868 case '\t': out
<< "\\t"; break;
869 case '\v': out
<< "\\v"; break;
884 if (*value
< 0x20 || *value
>= 0x7f)
885 out
.out_
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
889 out
<< (single
? '\'' : '"');
892 void CYString::PropertyName(CYOutput
&out
) const {
893 if (const char *word
= Word())
896 Output(out
, CYNoFlags
);
899 const char *CYString::Word() const {
900 if (size_
== 0 || !WordStartRange_
[value_
[0]])
902 for (size_t i(1); i
!= size_
; ++i
)
903 if (!WordEndRange_
[value_
[i
]])
905 const char *value(Value());
906 // XXX: we should probably include the full ECMAScript3+5 list.
907 static const char *reserveds
[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL
};
908 for (const char **reserved(reserveds
); *reserved
!= NULL
; ++reserved
)
909 if (strcmp(*reserved
, value
) == 0)
914 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
915 if ((flags
& CYNoLeader
) != 0)
921 value_
->Output(out
, CYNoFlags
);
926 if (clauses_
!= NULL
)
931 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
932 if ((flags
& CYNoLeader
) != 0)
935 if ((flags
& CYNoTrailer
) != 0)
939 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
940 bool terminator((flags
& CYNoTerminator
) == 0);
941 if ((flags
& CYNoLeader
) != 0)
945 value_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
950 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
951 if ((flags
& CYNoLeader
) != 0)
958 code_
->Multiple(out
);
962 if (finally_
!= NULL
)
963 finally_
->Output(out
);
966 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
967 bool terminator((flags
& CYNoTerminator
) == 0);
968 if ((flags
& CYNoLeader
) != 0)
971 declarations_
->Output(out
, (terminator
? CYCenter(flags
) : flags
) | CYNoLeader
);
976 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
977 if ((flags
& CYNoLeader
) != 0)
980 if ((flags
& CYNoTrailer
) != 0)
984 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
985 if ((flags
& CYNoLeader
) != 0)
988 test_
->Output(out
, CYNoFlags
);
990 code_
->Single(out
, CYRight(flags
));
993 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
994 if ((flags
& CYNoLeader
) != 0)
997 scope_
->Output(out
, CYNoFlags
);
999 code_
->Single(out
, CYRight(flags
));
1002 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
1004 out
<< "objc_getClass(";
1005 out
<< '"' << Value() << '"';
1010 void CYWord::Output(CYOutput
&out
) const {
1014 void CYWord::PropertyName(CYOutput
&out
) const {