]>
git.saurik.com Git - cycript.git/blob - Output.cpp
f8885247ca89d867ef62e9bfb5e6ee81ba87add3
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
& ~CYNoDangle
;
29 _finline CYFlags
CYRight(CYFlags flags
) {
30 return flags
& ~CYNoBF
;
33 _finline CYFlags
CYCenter(CYFlags flags
) {
34 return CYLeft(CYRight(flags
));
39 void CYOutput::Terminate() {
44 CYOutput
&CYOutput::operator <<(char rhs
) {
45 if (rhs
== ' ' || rhs
== '\n')
51 for (unsigned i(0); i
!= indent_
; ++i
)
60 if (mode_
== Terminated
&& rhs
!= '}')
70 } else if (rhs
== '-') {
71 if (mode_
== NoHyphen
)
74 } else if (WordEndRange_
[rhs
]) {
75 if (mode_
== NoLetter
)
86 CYOutput
&CYOutput::operator <<(const char *rhs
) {
87 size_t size(strlen(rhs
));
92 if (mode_
== Terminated
)
95 mode_
== NoHyphen
&& *rhs
== '-' ||
96 mode_
== NoLetter
&& WordEndRange_
[*rhs
]
100 if (WordEndRange_
[rhs
[size
- 1]])
109 void OutputBody(CYOutput
&out
, CYStatement
*body
) {
110 out
<< ' ' << '{' << '\n';
118 void CYAddressOf::Output(CYOutput
&out
, CYFlags flags
) const {
119 rhs_
->Output(out
, 1, CYLeft(flags
));
123 void CYArgument::Output(CYOutput
&out
) const {
130 value_
->Output(out
, CYPA
, CYNoFlags
);
132 if (next_
->name_
== NULL
)
134 out
<< ' ' << *next_
;
138 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
139 out
<< '[' << elements_
<< ']';
142 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
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())
150 comprehensions_
->Output(out
);
152 expression_
->Output(out
, CYPA
, CYNoFlags
);
154 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
155 comprehension
->End_(out
);
156 out
<< "return $cyv;";
160 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
161 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
162 out
<< ' ' << Operator() << ' ';
163 rhs_
->Output(out
, Precedence(), CYRight(flags
));
166 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
167 statements_
->Single(out
, flags
);
170 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
171 out
<< (Value() ? "true" : "false");
174 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
177 out
<< ' ' << *label_
;
181 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
182 bool protect((flags
& CYNoCall
) != 0);
185 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
186 out
<< '(' << arguments_
<< ')';
191 void CYCatch::Output(CYOutput
&out
) const {
192 out
<< "catch" << ' ' << '(' << *name_
<< ')' << ' ' << '{';
194 code_
->Multiple(out
);
198 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
199 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
200 out
<< "$cyp=object_getClass($cys);";
202 if (messages_
!= NULL
)
203 messages_
->Output(out
, true);
205 name_
->ClassName(out
, true);
210 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
211 // XXX: I don't necc. need the ()s
212 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
213 out
<< "$cyp=object_getClass($cys);";
214 out
<< "$cyc=objc_allocateClassPair($cys,";
216 name_
->ClassName(out
, false);
218 out
<< "$cyq(\"CY$\")";
220 out
<< "$cym=object_getClass($cyc);";
222 fields_
->Output(out
);
223 if (messages_
!= NULL
)
224 messages_
->Output(out
, false);
225 out
<< "objc_registerClassPair($cyc);";
226 out
<< "return $cyc;";
229 super_
->Output(out
, CYPA
, CYNoFlags
);
235 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
236 CYClass::Output(out
, flags
);
239 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
240 CYClass::Output(out
, flags
);
243 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
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
) {
251 next
= expression
->next_
;
252 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
253 expression
->Output(out
, right
);
256 expression
->Output(out
, flags
);
259 void CYComprehension::Output(CYOutput
&out
) const {
264 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
265 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
266 out
<< ' ' << '?' << ' ';
268 true_
->Output(out
, CYPA
, CYNoFlags
);
269 out
<< ' ' << ':' << ' ';
270 false_
->Output(out
, CYPA
, CYRight(flags
));
273 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
276 out
<< ' ' << *label_
;
280 void CYClause::Output(CYOutput
&out
) const {
282 out
<< "case" << ' ' << *case_
;
287 code_
->Multiple(out
, CYNoFlags
);
291 const char *CYDeclaration::ForEachIn() const {
292 return identifier_
->Value();
295 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
297 Output(out
, CYRight(flags
));
300 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
304 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
306 if (initialiser_
!= NULL
) {
307 out
<< ' ' << '=' << ' ';
308 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
312 void CYDeclarations::For(CYOutput
&out
) const {
317 void CYDeclarations::Output(CYOutput
&out
) const {
318 Output(out
, CYNoFlags
);
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
);
337 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
338 object_
->Output(out
, Precedence(), CYLeft(flags
));
339 if (const char *word
= property_
->Word())
342 out
<< '[' << *property_
<< ']';
345 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
347 code_
->Single(out
, CYCenter(flags
));
348 out
<< "while" << ' ' << '(' << *test_
<< ')';
351 void CYElement::Output(CYOutput
&out
) const {
353 value_
->Output(out
, CYPA
, CYNoFlags
);
354 if (next_
!= NULL
|| value_
== NULL
) {
356 if (next_
!= NULL
&& next_
->value_
!= NULL
)
363 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
367 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
368 expression_
->Output(out
, flags
| CYNoBF
);
372 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
373 Output(out
, CYPA
, CYNoFlags
);
376 const char *CYExpression::ForEachIn() const {
380 void CYExpression::For(CYOutput
&out
) const {
384 void CYExpression::ForEachIn(CYOutput
&out
) const {
385 Output(out
, CYPA
, CYNoRightHand
);
388 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
389 Output(out
, flags
| CYNoRightHand
);
392 void CYExpression::Output(CYOutput
&out
) const {
393 Output(out
, CYNoFlags
);
396 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
397 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
398 out
<< '(' << *this << ')';
403 void CYField::Output(CYOutput
&out
) const {
407 void CYFinally::Output(CYOutput
&out
) const {
408 out
<< "finally" << ' ' << '{';
410 code_
->Multiple(out
);
414 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
415 out
<< "for" << ' ' << '(';
416 if (initialiser_
!= NULL
)
417 initialiser_
->For(out
);
423 code_
->Single(out
, CYRight(flags
));
426 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
427 out
<< "with({$cys:0,$cyt:0}){";
430 set_
->Output(out
, CYPA
, CYNoFlags
);
433 out
<< "for($cyt in $cys){";
435 initialiser_
->ForEachIn(out
);
436 out
<< "=$cys[$cyt];";
438 code_
->Multiple(out
);
445 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
446 out
<< "(function($cys){";
448 set_
->Output(out
, CYPA
, CYNoFlags
);
451 out
<< "for(" << *name_
<< " in $cys){";
452 out
<< *name_
<< "=$cys[" << *name_
<< "];";
455 void CYForEachInComprehension::End_(CYOutput
&out
) const {
459 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
460 out
<< "for" << ' ' << '(';
461 initialiser_
->ForIn(out
, CYNoIn
);
462 out
<< "in" << *set_
<< ')';
463 code_
->Single(out
, CYRight(flags
));
466 void CYForInComprehension::Begin_(CYOutput
&out
) const {
467 out
<< "for" << ' ' << '(' << *name_
<< "in" << *set_
<< ')';
470 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
471 // XXX: one could imagine using + here to save a byte
472 bool protect((flags
& CYNoFunction
) != 0);
477 out
<< ' ' << *name_
;
478 out
<< '(' << parameters_
<< ')';
479 OutputBody(out
, body_
);
484 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
485 CYFunction::Output(out
, flags
);
488 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
489 CYFunction::Output(out
, flags
);
492 void CYFunctionParameter::Output(CYOutput
&out
) const {
495 out
<< ',' << ' ' << *next_
;
498 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
500 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
505 out
<< "if" << ' ' << '(' << *test_
<< ')';
507 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
509 CYFlags
jacks(CYNoDangle
);
513 jacks
|= protect
? CYNoFlags
: CYCenter(flags
);
515 bool single(true_
->Single(out
, jacks
));
517 if (false_
!= NULL
) {
518 out
<< (single
? '\t' : ' ');
520 false_
->Single(out
, right
);
527 void CYIfComprehension::Begin_(CYOutput
&out
) const {
528 out
<< "if" << '(' << *test_
<< ')';
531 void CYIndirect::Output(CYOutput
&out
, CYFlags flags
) const {
532 rhs_
->Output(out
, 1, CYLeft(flags
));
536 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
537 object_
->Output(out
, Precedence(), CYLeft(flags
));
539 if (const char *word
= property_
->Word())
542 out
<< '[' << *property_
<< ']';
545 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
546 const char *name(Operator());
547 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in"));
550 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
551 lhs_
->Output(out
, Precedence(), left
);
552 out
<< ' ' << name
<< ' ';
553 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
554 rhs_
->Output(out
, Precedence() - 1, right
);
559 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
560 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << '{';
561 if (statements_
!= NULL
)
562 statements_
->Multiple(out
);
566 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
568 next_
->Output(out
, replace
);
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
)
577 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ");";
578 out
<< "class_" << (replace
? "replace" : "add") << "Method($cy" << (instance_
? 'c' : 'm') << ",$cyn,";
579 out
<< "new Functor(function(self,_cmd";
580 for (CYMessageParameter
*parameter(parameter_
); parameter
!= NULL
; parameter
= parameter
->next_
)
581 if (parameter
->name_
!= NULL
)
582 out
<< ',' << *parameter
->name_
;
583 out
<< "){return function(){";
585 body_
->Multiple(out
);
586 out
<< "}.call(self);},$cyt),$cyt);";
589 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
591 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
592 constructor_
->Output(out
, Precedence(), jacks
);
593 if (arguments_
!= NULL
)
594 out
<< '(' << *arguments_
<< ')';
597 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
601 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
603 sprintf(value
, "%.17g", Value());
607 void CYNumber::PropertyName(CYOutput
&out
) const {
608 Output(out
, CYNoFlags
);
611 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
612 bool protect((flags
& CYNoBrace
) != 0);
622 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
623 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
627 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
628 const char *name(Operator());
632 rhs_
->Output(out
, Precedence(), CYRight(flags
));
635 void CYProperty::Output(CYOutput
&out
) const {
636 name_
->PropertyName(out
);
638 value_
->Output(out
, CYPA
, CYNoFlags
);
640 out
<< ',' << ' ' << *next_
;
643 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
647 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
648 out
<< "return" << value_
<< ';';
651 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
652 out
<< "new Selector(\"";
658 void CYSelectorPart::Output(CYOutput
&out
) const {
665 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
666 out
<< "objc_msgSend(";
667 self_
->Output(out
, CYPA
, CYNoFlags
);
669 std::ostringstream name
;
670 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
671 if (argument
->name_
!= NULL
) {
672 name
<< *argument
->name_
;
673 if (argument
->value_
!= NULL
)
676 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
677 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
678 if (argument
->value_
!= NULL
) {
680 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
685 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
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
));
692 next
->Output(out
, jacks
);
697 bool CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
699 out
<< ' ' << '{' << '\n';
706 for (CYLabel
*label(labels_
); label
!= NULL
; label
= label
->next_
)
707 out
<< ' ' << *label
->name_
<< ':';
718 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
719 unsigned quot(0), apos(0);
720 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
723 else if (*value
== '\'')
726 bool single(quot
> apos
);
728 std::ostringstream str
;
730 str
<< (single
? '\'' : '"');
731 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
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;
754 if (*value
< 0x20 || *value
>= 0x7f)
755 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
759 str
<< (single
? '\'' : '"');
761 out
<< str
.str().c_str();
764 void CYString::PropertyName(CYOutput
&out
) const {
765 if (const char *word
= Word())
771 const char *CYString::Word() const {
772 if (size_
== 0 || !WordStartRange_
[value_
[0]])
774 for (size_t i(1); i
!= size_
; ++i
)
775 if (!WordEndRange_
[value_
[i
]])
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)
786 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
787 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
792 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
796 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
797 out
<< "throw" << value_
<< ';';
800 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
801 out
<< "try" << ' ' << '{';
803 code_
->Multiple(out
);
809 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
811 declarations_
->Output(out
, flags
);
815 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
819 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
820 out
<< "while" << '(' << *test_
<< ')';
821 code_
->Single(out
, CYRight(flags
));
824 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
825 out
<< "with" << '(' << *scope_
<< ')';
826 code_
->Single(out
, CYRight(flags
));
829 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
831 out
<< "objc_getClass(";
832 out
<< '"' << Value() << '"';
837 void CYWord::Output(CYOutput
&out
) const {
841 void CYWord::PropertyName(CYOutput
&out
) const {