]>
git.saurik.com Git - cycript.git/blob - Replace.cpp
1 /* Cycript - Inlining/Optimizing JavaScript Compiler
2 * Copyright (C) 2009 Jay Freeman (saurik)
5 /* Modified BSD License {{{ */
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 #include "Replace.hpp"
46 CYExpression
*CYAdd::Replace(CYContext
&context
) {
47 CYInfix::Replace(context
);
49 CYExpression
*lhp(lhs_
->Primitive(context
));
50 CYExpression
*rhp(rhs_
->Primitive(context
));
52 CYString
*lhs(dynamic_cast<CYString
*>(lhp
));
53 CYString
*rhs(dynamic_cast<CYString
*>(rhp
));
55 if (lhs
!= NULL
|| rhs
!= NULL
) {
57 lhs
= lhp
->String(context
);
60 } else if (rhs
== NULL
) {
61 rhs
= rhp
->String(context
);
66 return lhs
->Concat(context
, rhs
);
69 if (CYNumber
*lhn
= lhp
->Number(context
))
70 if (CYNumber
*rhn
= rhp
->Number(context
))
71 return $
D(lhn
->Value() + rhn
->Value());
76 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
77 CYPrefix::Replace(context
);
78 return $
C0($
M(rhs_
, $
S("$cya")));
81 void CYArgument::Replace(CYContext
&context
) { $
T()
82 context
.Replace(value_
);
83 next_
->Replace(context
);
86 CYExpression
*CYArray::Replace(CYContext
&context
) {
87 elements_
->Replace(context
);
91 CYExpression
*CYArrayComprehension::Replace(CYContext
&context
) {
92 CYVariable
*cyv($
V("$cyv"));
94 return $
C0($
F(NULL
, $
P1("$cyv", comprehensions_
->Parameters(context
)), $$
->*
95 $
E($
CYAssign(cyv
, $
CYArray()))->*
96 comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->*
101 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
102 context
.Replace(lhs_
);
103 context
.Replace(rhs_
);
107 CYStatement
*CYBlock::Replace(CYContext
&context
) {
108 statements_
= statements_
->ReplaceAll(context
);
112 CYStatement
*CYBreak::Replace(CYContext
&context
) {
116 CYExpression
*CYCall::Replace(CYContext
&context
) {
117 context
.Replace(function_
);
118 arguments_
->Replace(context
);
125 void Catch::Replace(CYContext
&context
) { $
T()
126 code_
.Replace(context
);
131 void CYClause::Replace(CYContext
&context
) { $
T()
132 context
.Replace(case_
);
133 statements_
= statements_
->ReplaceAll(context
);
134 next_
->Replace(context
);
137 CYExpression
*CYCompound::Replace(CYContext
&context
) {
138 expressions_
= expressions_
->ReplaceAll(context
);
142 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
143 CYFunctionParameter
*next(next_
->Parameters(context
));
144 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
145 parameter
->SetNext(next
);
151 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
152 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
155 CYExpression
*CYCondition::Replace(CYContext
&context
) {
156 context
.Replace(test_
);
157 context
.Replace(true_
);
158 context
.Replace(false_
);
162 CYStatement
*CYContinue::Replace(CYContext
&context
) {
166 CYExpression
*CYDeclaration::ForEachIn(CYContext
&context
) {
167 return $
CYVariable(identifier_
);
170 void CYDeclaration::Replace(CYContext
&context
) {
171 context
.Replace(initialiser_
);
174 CYProperty
*CYDeclarations::Property(CYContext
&context
) { $
T(NULL
)
175 return $
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
?: $U
, next_
->Property(context
));
178 void CYDeclarations::Replace(CYContext
&context
) { $
T()
179 declaration_
->Replace(context
);
180 next_
->Replace(context
);
183 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
188 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
189 context
.Replace(test_
);
190 context
.Replace(code_
);
194 void CYElement::Replace(CYContext
&context
) { $
T()
195 context
.Replace(value_
);
196 next_
->Replace(context
);
199 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
203 CYStatement
*CYExpress::Replace(CYContext
&context
) {
204 context
.Replace(expression_
);
208 CYExpression
*CYExpression::ClassName(CYContext
&context
, bool object
) {
212 CYExpression
*CYExpression::ForEachIn(CYContext
&context
) {
216 CYExpression
*CYExpression::ReplaceAll(CYContext
&context
) { $
T(NULL
)
217 CYExpression
*replace(this);
218 context
.Replace(replace
);
220 if (CYExpression
*next
= next_
->ReplaceAll(context
))
221 replace
->SetNext(next
);
223 replace
->SetNext(next_
);
228 CYNumber
*CYFalse::Number(CYContext
&context
) {
232 CYString
*CYFalse::String(CYContext
&context
) {
236 void CYFinally::Replace(CYContext
&context
) { $
T()
237 code_
.Replace(context
);
240 CYStatement
*CYFor::Replace(CYContext
&context
) {
242 context
.Replace(test_
);
243 context
.Replace(increment_
);
244 context
.Replace(code_
);
248 CYStatement
*CYForIn::Replace(CYContext
&context
) {
250 context
.Replace(set_
);
251 context
.Replace(code_
);
255 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
256 return $
CYFunctionParameter(name_
);
259 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
260 return $
CYForIn($
CYVariable(name_
), set_
, CYComprehension::Replace(context
, statement
));
263 CYStatement
*CYForEachIn::Replace(CYContext
&context
) {
264 CYVariable
*cys($
V("$cys")), *cyt($
V("$cyt"));
266 return $
CYLet($
L2($
L($
I("$cys"), set_
), $
L($
I("$cyt"))), $$
->*
267 $
CYForIn(cyt
, cys
, $
CYBlock($$
->*
268 $
E($
CYAssign(initialiser_
->ForEachIn(context
), $
M(cys
, cyt
)))->*
274 CYFunctionParameter
*CYForEachInComprehension::Parameter(CYContext
&context
) const {
275 return $
CYFunctionParameter(name_
);
278 CYStatement
*CYForEachInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
279 CYVariable
*cys($
V("$cys")), *name($
CYVariable(name_
));
281 return $
E($
C0($
F(NULL
, $
P1("$cys"), $$
->*
282 $
E($
CYAssign(cys
, set_
))->*
283 $
CYForIn(name
, cys
, $
CYBlock($$
->*
284 $
E($
CYAssign(name
, $
M(cys
, name
)))->*
285 CYComprehension::Replace(context
, statement
)
290 void CYFunction::Replace_(CYContext
&context
) {
291 code_
.Replace(context
);
294 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
299 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
304 CYStatement
*CYIf::Replace(CYContext
&context
) {
305 context
.Replace(test_
);
306 context
.Replace(true_
);
307 context
.Replace(false_
);
311 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
315 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
316 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
319 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
320 CYPrefix::Replace(context
);
321 return $
M(rhs_
, $
S("$cyi"));
324 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
326 return $
M($
CYIndirect(object_
), property_
);
329 CYExpression
*CYInfix::Replace(CYContext
&context
) {
330 context
.Replace(lhs_
);
331 context
.Replace(rhs_
);
335 CYStatement
*CYLabel::Replace(CYContext
&context
) {
336 context
.Replace(statement_
);
340 CYStatement
*CYLet::Replace(CYContext
&context
) {
341 return $
CYWith($
CYObject(declarations_
->Property(context
)), &code_
);
344 void CYMember::Replace_(CYContext
&context
) {
345 context
.Replace(object_
);
346 context
.Replace(property_
);
349 CYExpression
*CYNew::Replace(CYContext
&context
) {
350 context
.Replace(constructor_
);
351 arguments_
->Replace(context
);
355 CYNumber
*CYNull::Number(CYContext
&context
) {
359 CYString
*CYNull::String(CYContext
&context
) {
363 CYNumber
*CYNumber::Number(CYContext
&context
) {
367 CYString
*CYNumber::String(CYContext
&context
) {
368 // XXX: there is a precise algorithm for this
369 return $
S(apr_psprintf(context
.pool_
, "%.17g", Value()));
372 CYExpression
*CYObject::Replace(CYContext
&context
) {
373 properties_
->Replace(context
);
377 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
378 context
.Replace(lhs_
);
382 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
383 context
.Replace(rhs_
);
387 void CYProgram::Replace(CYContext
&context
) {
388 statements_
= statements_
->ReplaceAll(context
);
391 void CYProperty::Replace(CYContext
&context
) { $
T()
392 context
.Replace(value_
);
393 next_
->Replace(context
);
396 CYStatement
*CYReturn::Replace(CYContext
&context
) {
397 context
.Replace(value_
);
401 CYStatement
*CYStatement::ReplaceAll(CYContext
&context
) { $
T(NULL
)
402 CYStatement
*replace(this);
403 context
.Replace(replace
);
405 if (CYStatement
*next
= next_
->ReplaceAll(context
))
406 replace
->SetNext(next
);
408 replace
->SetNext(next_
);
413 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
414 size_t size(size_
+ rhs
->size_
);
415 char *value(new(context
.pool_
) char[size
+ 1]);
416 memcpy(value
, value_
, size_
);
417 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
419 return $
S(value
, size
);
422 CYNumber
*CYString::Number(CYContext
&context
) {
423 // XXX: there is a precise algorithm for this
427 CYString
*CYString::String(CYContext
&context
) {
431 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
432 context
.Replace(value_
);
433 clauses_
->Replace(context
);
437 CYExpression
*CYThis::Replace(CYContext
&context
) {
444 CYStatement
*Throw::Replace(CYContext
&context
) {
445 context
.Replace(value_
);
451 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
455 CYNumber
*CYTrue::Number(CYContext
&context
) {
459 CYString
*CYTrue::String(CYContext
&context
) {
466 CYStatement
*Try::Replace(CYContext
&context
) {
467 code_
.Replace(context
);
468 catch_
->Replace(context
);
469 finally_
->Replace(context
);
475 CYStatement
*CYVar::Replace(CYContext
&context
) {
476 declarations_
->Replace(context
);
480 CYExpression
*CYVariable::Replace(CYContext
&context
) {
484 CYStatement
*CYWhile::Replace(CYContext
&context
) {
485 context
.Replace(test_
);
486 context
.Replace(code_
);
490 CYStatement
*CYWith::Replace(CYContext
&context
) {
491 context
.Replace(scope_
);
492 context
.Replace(code_
);
496 CYExpression
*CYWord::ClassName(CYContext
&context
, bool object
) {
497 CYString
*name($
S(this));
499 return $
C1($
V("objc_getClass"), name
);