]>
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 CYStatement
*CYComment::Replace(CYContext
&context
) {
141 CYExpression
*CYCompound::Replace(CYContext
&context
) {
142 expressions_
= expressions_
->ReplaceAll(context
);
146 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
147 CYFunctionParameter
*next(next_
->Parameters(context
));
148 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
149 parameter
->SetNext(next
);
155 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
156 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
159 CYExpression
*CYCondition::Replace(CYContext
&context
) {
160 context
.Replace(test_
);
161 context
.Replace(true_
);
162 context
.Replace(false_
);
166 CYStatement
*CYContinue::Replace(CYContext
&context
) {
170 CYExpression
*CYDeclaration::ForEachIn(CYContext
&context
) {
171 return $
CYVariable(identifier_
);
174 void CYDeclaration::Replace(CYContext
&context
) {
175 context
.Replace(initialiser_
);
178 CYProperty
*CYDeclarations::Property(CYContext
&context
) { $
T(NULL
)
179 return $
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
?: $U
, next_
->Property(context
));
182 void CYDeclarations::Replace(CYContext
&context
) { $
T()
183 declaration_
->Replace(context
);
184 next_
->Replace(context
);
187 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
192 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
193 context
.Replace(test_
);
194 context
.Replace(code_
);
198 void CYElement::Replace(CYContext
&context
) { $
T()
199 context
.Replace(value_
);
200 next_
->Replace(context
);
203 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
207 CYStatement
*CYExpress::Replace(CYContext
&context
) {
208 context
.Replace(expression_
);
212 CYExpression
*CYExpression::ClassName(CYContext
&context
, bool object
) {
216 CYExpression
*CYExpression::ForEachIn(CYContext
&context
) {
220 CYExpression
*CYExpression::ReplaceAll(CYContext
&context
) { $
T(NULL
)
221 CYExpression
*replace(this);
222 context
.Replace(replace
);
224 if (CYExpression
*next
= next_
->ReplaceAll(context
))
225 replace
->SetNext(next
);
227 replace
->SetNext(next_
);
232 CYNumber
*CYFalse::Number(CYContext
&context
) {
236 CYString
*CYFalse::String(CYContext
&context
) {
240 void CYFinally::Replace(CYContext
&context
) { $
T()
241 code_
.Replace(context
);
244 CYStatement
*CYFor::Replace(CYContext
&context
) {
246 context
.Replace(test_
);
247 context
.Replace(increment_
);
248 context
.Replace(code_
);
252 CYStatement
*CYForIn::Replace(CYContext
&context
) {
254 context
.Replace(set_
);
255 context
.Replace(code_
);
259 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
260 return $
CYFunctionParameter(name_
);
263 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
264 return $
CYForIn($
CYVariable(name_
), set_
, CYComprehension::Replace(context
, statement
));
267 CYStatement
*CYForEachIn::Replace(CYContext
&context
) {
268 CYVariable
*cys($
V("$cys")), *cyt($
V("$cyt"));
270 return $
CYLet($
L2($
L($
I("$cys"), set_
), $
L($
I("$cyt"))), $$
->*
271 $
CYForIn(cyt
, cys
, $
CYBlock($$
->*
272 $
E($
CYAssign(initialiser_
->ForEachIn(context
), $
M(cys
, cyt
)))->*
278 CYFunctionParameter
*CYForEachInComprehension::Parameter(CYContext
&context
) const {
279 return $
CYFunctionParameter(name_
);
282 CYStatement
*CYForEachInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
283 CYVariable
*cys($
V("$cys")), *name($
CYVariable(name_
));
285 return $
E($
C0($
F(NULL
, $
P1("$cys"), $$
->*
286 $
E($
CYAssign(cys
, set_
))->*
287 $
CYForIn(name
, cys
, $
CYBlock($$
->*
288 $
E($
CYAssign(name
, $
M(cys
, name
)))->*
289 CYComprehension::Replace(context
, statement
)
294 void CYFunction::Replace_(CYContext
&context
) {
295 code_
.Replace(context
);
298 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
303 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
308 CYStatement
*CYIf::Replace(CYContext
&context
) {
309 context
.Replace(test_
);
310 context
.Replace(true_
);
311 context
.Replace(false_
);
315 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
319 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
320 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
323 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
324 CYPrefix::Replace(context
);
325 return $
M(rhs_
, $
S("$cyi"));
328 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
330 return $
M($
CYIndirect(object_
), property_
);
333 CYExpression
*CYInfix::Replace(CYContext
&context
) {
334 context
.Replace(lhs_
);
335 context
.Replace(rhs_
);
339 CYStatement
*CYLabel::Replace(CYContext
&context
) {
340 context
.Replace(statement_
);
344 CYStatement
*CYLet::Replace(CYContext
&context
) {
345 return $
CYWith($
CYObject(declarations_
->Property(context
)), &code_
);
348 void CYMember::Replace_(CYContext
&context
) {
349 context
.Replace(object_
);
350 context
.Replace(property_
);
353 CYExpression
*CYNew::Replace(CYContext
&context
) {
354 context
.Replace(constructor_
);
355 arguments_
->Replace(context
);
359 CYNumber
*CYNull::Number(CYContext
&context
) {
363 CYString
*CYNull::String(CYContext
&context
) {
367 CYNumber
*CYNumber::Number(CYContext
&context
) {
371 CYString
*CYNumber::String(CYContext
&context
) {
372 // XXX: there is a precise algorithm for this
373 return $
S(apr_psprintf(context
.pool_
, "%.17g", Value()));
376 CYExpression
*CYObject::Replace(CYContext
&context
) {
377 properties_
->Replace(context
);
381 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
382 context
.Replace(lhs_
);
386 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
387 context
.Replace(rhs_
);
391 void CYProgram::Replace(CYContext
&context
) {
392 statements_
= statements_
->ReplaceAll(context
);
395 void CYProperty::Replace(CYContext
&context
) { $
T()
396 context
.Replace(value_
);
397 next_
->Replace(context
);
400 CYStatement
*CYReturn::Replace(CYContext
&context
) {
401 context
.Replace(value_
);
405 CYStatement
*CYStatement::ReplaceAll(CYContext
&context
) { $
T(NULL
)
406 CYStatement
*replace(this);
407 context
.Replace(replace
);
409 if (CYStatement
*next
= next_
->ReplaceAll(context
))
410 replace
->SetNext(next
);
412 replace
->SetNext(next_
);
417 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
418 size_t size(size_
+ rhs
->size_
);
419 char *value(new(context
.pool_
) char[size
+ 1]);
420 memcpy(value
, value_
, size_
);
421 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
423 return $
S(value
, size
);
426 CYNumber
*CYString::Number(CYContext
&context
) {
427 // XXX: there is a precise algorithm for this
431 CYString
*CYString::String(CYContext
&context
) {
435 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
436 context
.Replace(value_
);
437 clauses_
->Replace(context
);
441 CYExpression
*CYThis::Replace(CYContext
&context
) {
448 CYStatement
*Throw::Replace(CYContext
&context
) {
449 context
.Replace(value_
);
455 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
459 CYNumber
*CYTrue::Number(CYContext
&context
) {
463 CYString
*CYTrue::String(CYContext
&context
) {
470 CYStatement
*Try::Replace(CYContext
&context
) {
471 code_
.Replace(context
);
472 catch_
->Replace(context
);
473 finally_
->Replace(context
);
479 CYStatement
*CYVar::Replace(CYContext
&context
) {
480 declarations_
->Replace(context
);
484 CYExpression
*CYVariable::Replace(CYContext
&context
) {
488 CYStatement
*CYWhile::Replace(CYContext
&context
) {
489 context
.Replace(test_
);
490 context
.Replace(code_
);
494 CYStatement
*CYWith::Replace(CYContext
&context
) {
495 context
.Replace(scope_
);
496 context
.Replace(code_
);
500 CYExpression
*CYWord::ClassName(CYContext
&context
, bool object
) {
501 CYString
*name($
S(this));
503 return $
C1($
V("objc_getClass"), name
);