1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2013 Jay Freeman (saurik)
5 /* GNU General Public License, Version 3 {{{ */
7 * Cycript is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
12 * Cycript is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
23 #include "Replace.hpp"
27 CYFunctionExpression
*CYNonLocalize(CYContext
&context
, CYFunctionExpression
*function
) {
28 function
->nonlocal_
= context
.nextlocal_
;
32 CYExpression
*CYAdd::Replace(CYContext
&context
) {
33 CYInfix::Replace(context
);
35 CYExpression
*lhp(lhs_
->Primitive(context
));
36 CYExpression
*rhp(rhs_
->Primitive(context
));
38 CYString
*lhs(dynamic_cast<CYString
*>(lhp
));
39 CYString
*rhs(dynamic_cast<CYString
*>(rhp
));
41 if (lhs
!= NULL
|| rhs
!= NULL
) {
43 lhs
= lhp
->String(context
);
46 } else if (rhs
== NULL
) {
47 rhs
= rhp
->String(context
);
52 return lhs
->Concat(context
, rhs
);
55 if (CYNumber
*lhn
= lhp
->Number(context
))
56 if (CYNumber
*rhn
= rhp
->Number(context
))
57 return $
D(lhn
->Value() + rhn
->Value());
62 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
63 return $
C0($
M(rhs_
, $
S("$cya")));
66 CYArgument
*CYArgument::Replace(CYContext
&context
) { $
T(NULL
)
67 context
.Replace(value_
);
68 next_
= next_
->Replace(context
);
80 CYExpression
*CYArray::Replace(CYContext
&context
) {
81 elements_
->Replace(context
);
85 CYExpression
*CYArrayComprehension::Replace(CYContext
&context
) {
86 CYVariable
*cyv($
V("$cyv"));
88 return $
C0($
F(NULL
, $
P1($
L("$cyv"), comprehensions_
->Parameters(context
)), $$
->*
89 $
E($
CYAssign(cyv
, $
CYArray()))->*
90 comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->*
95 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
96 context
.Replace(lhs_
);
97 context
.Replace(rhs_
);
101 CYStatement
*CYBlock::Replace(CYContext
&context
) {
102 context
.ReplaceAll(statements_
);
103 if (statements_
== NULL
)
108 CYStatement
*CYBreak::Replace(CYContext
&context
) {
112 CYExpression
*CYCall::AddArgument(CYContext
&context
, CYExpression
*value
) {
113 CYArgument
**argument(&arguments_
);
114 while (*argument
!= NULL
)
115 argument
= &(*argument
)->next_
;
116 *argument
= $
CYArgument(value
);
120 CYExpression
*CYCall::Replace(CYContext
&context
) {
121 context
.Replace(function_
);
122 arguments_
->Replace(context
);
129 void Catch::Replace(CYContext
&context
) { $
T()
130 CYScope
scope(true, context
, code_
.statements_
);
132 context
.Replace(name_
);
133 context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
);
135 code_
.Replace(context
);
141 void CYClause::Replace(CYContext
&context
) { $
T()
142 context
.Replace(case_
);
143 context
.ReplaceAll(statements_
);
144 next_
->Replace(context
);
147 CYStatement
*CYComment::Replace(CYContext
&context
) {
151 CYExpression
*CYCompound::Replace(CYContext
&context
) {
152 context
.ReplaceAll(expressions_
);
153 if (expressions_
== NULL
)
158 CYExpression
*CYCompound::Primitive(CYContext
&context
) {
159 CYExpression
*expression(expressions_
);
160 if (expression
== NULL
)
162 while (expression
->next_
!= NULL
)
163 expression
= expression
->next_
;
164 return expression
->Primitive(context
);
167 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
168 CYFunctionParameter
*next(next_
->Parameters(context
));
169 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
170 parameter
->SetNext(next
);
176 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
177 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
180 CYExpression
*CYCondition::Replace(CYContext
&context
) {
181 context
.Replace(test_
);
182 context
.Replace(true_
);
183 context
.Replace(false_
);
187 void CYContext::NonLocal(CYStatement
*&statements
) {
188 CYContext
&context(*this);
190 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
191 CYIdentifier
*cye($
I("$cye")->Replace(context
));
192 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
));
194 CYStatement
*declare(
195 $
CYVar($
L1($
CYDeclaration(unique
, $
CYObject()))));
197 cy::Syntax::Catch
*rescue(
198 $
cy::Syntax::Catch(cye
, $$
->*
199 $
CYIf($
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->*
200 $
CYReturn($
M($
V(cye
), $
S("$cyv"))))->*
201 $
cy::Syntax::Throw($
V(cye
))));
203 context
.Replace(declare
);
204 rescue
->Replace(context
);
208 $
cy::Syntax::Try(statements
, rescue
, NULL
);
212 CYIdentifier
*CYContext::Unique() {
213 return $
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
));
216 CYStatement
*CYContinue::Replace(CYContext
&context
) {
220 CYStatement
*CYDebugger::Replace(CYContext
&context
) {
224 CYAssignment
*CYDeclaration::Assignment(CYContext
&context
) {
225 if (initialiser_
== NULL
)
228 CYAssignment
*value($
CYAssign(Variable(context
), initialiser_
));
233 CYVariable
*CYDeclaration::Variable(CYContext
&context
) {
234 return $
V(identifier_
);
237 CYStatement
*CYDeclaration::ForEachIn(CYContext
&context
, CYExpression
*value
) {
238 return $
CYVar($
L1($
CYDeclaration(identifier_
, value
)));
241 CYExpression
*CYDeclaration::Replace(CYContext
&context
) {
242 context
.Replace(identifier_
);
243 context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
);
244 return Variable(context
);
247 void CYDeclarations::Replace(CYContext
&context
) { $
T()
248 declaration_
->Replace(context
);
249 next_
->Replace(context
);
252 CYProperty
*CYDeclarations::Property(CYContext
&context
) { $
T(NULL
)
253 return $
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
, next_
->Property(context
));
256 CYFunctionParameter
*CYDeclarations::Parameter(CYContext
&context
) { $
T(NULL
)
257 return $
CYFunctionParameter($
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
));
260 CYArgument
*CYDeclarations::Argument(CYContext
&context
) { $
T(NULL
)
261 return $
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
));
264 CYCompound
*CYDeclarations::Compound(CYContext
&context
) { $
T(NULL
)
265 CYCompound
*compound(next_
->Compound(context
) ?: $
CYCompound());
266 if (CYAssignment
*assignment
= declaration_
->Assignment(context
))
267 compound
->AddPrev(assignment
);
271 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
272 context
.Replace(object_
);
273 context
.Replace(property_
);
277 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
278 context
.Replace(test_
);
279 context
.Replace(code_
);
283 void CYElement::Replace(CYContext
&context
) { $
T()
284 context
.Replace(value_
);
285 next_
->Replace(context
);
288 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
292 CYStatement
*CYExpress::Replace(CYContext
&context
) {
293 while (CYExpress
*express
= dynamic_cast<CYExpress
*>(next_
)) {
294 CYCompound
*compound(dynamic_cast<CYCompound
*>(express
->expression_
));
295 if (compound
== NULL
)
296 compound
= $
CYCompound(express
->expression_
);
297 compound
->AddPrev(expression_
);
298 expression_
= compound
;
299 SetNext(express
->next_
);
302 context
.Replace(expression_
);
303 if (expression_
== NULL
)
309 CYExpression
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
310 return $
C1(this, value
);
313 CYExpression
*CYExpression::ClassName(CYContext
&context
, bool object
) {
317 CYStatement
*CYExpression::ForEachIn(CYContext
&context
, CYExpression
*value
) {
318 return $
E($
CYAssign(this, value
));
321 CYAssignment
*CYExpression::Assignment(CYContext
&context
) {
325 CYNumber
*CYFalse::Number(CYContext
&context
) {
329 CYString
*CYFalse::String(CYContext
&context
) {
333 CYExpression
*CYFatArrow::Replace(CYContext
&context
) {
334 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
335 function
->this_
.SetNext(context
.this_
);
339 void CYFinally::Replace(CYContext
&context
) { $
T()
340 code_
.Replace(context
);
343 CYStatement
*CYFor::Replace(CYContext
&context
) {
344 context
.Replace(initialiser_
);
345 context
.Replace(test_
);
346 context
.Replace(increment_
);
347 context
.Replace(code_
);
351 CYCompound
*CYForDeclarations::Replace(CYContext
&context
) {
352 declarations_
->Replace(context
);
353 return declarations_
->Compound(context
);
356 // XXX: this still feels highly suboptimal
357 CYStatement
*CYForIn::Replace(CYContext
&context
) {
358 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
359 return $
CYBlock($$
->*
364 context
.Replace(initialiser_
);
365 context
.Replace(set_
);
366 context
.Replace(code_
);
370 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
371 return $
CYFunctionParameter($
CYDeclaration(name_
));
374 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
375 return $
CYForIn($
V(name_
), set_
, CYComprehension::Replace(context
, statement
));
378 CYStatement
*CYForOf::Replace(CYContext
&context
) {
379 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
380 return $
CYBlock($$
->*
385 CYIdentifier
*cys($
I("$cys")), *cyt($
I("$cyt"));
387 return $
CYLetStatement($
L2($
CYDeclaration(cys
, set_
), $
CYDeclaration(cyt
)), $$
->*
388 $
CYForIn($
V(cyt
), $
V(cys
), $
CYBlock($$
->*
389 initialiser_
->ForEachIn(context
, $
M($
V(cys
), $
V(cyt
)))->*
395 CYFunctionParameter
*CYForOfComprehension::Parameter(CYContext
&context
) const {
396 return $
CYFunctionParameter($
CYDeclaration(name_
));
399 CYStatement
*CYForOfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
400 CYIdentifier
*cys($
I("cys"));
402 return $
E($
C0($
F(NULL
, $
P1($
L("$cys")), $$
->*
403 $
E($
CYAssign($
V(cys
), set_
))->*
404 $
CYForIn($
V(name_
), $
V(cys
), $
CYBlock($$
->*
405 $
E($
CYAssign($
V(name_
), $
M($
V(cys
), $
V(name_
))))->*
406 CYComprehension::Replace(context
, statement
)
411 void CYFunction::Inject(CYContext
&context
) {
412 context
.Replace(name_
);
413 context
.scope_
->Declare(context
, name_
, CYIdentifierOther
);
416 void CYFunction::Replace_(CYContext
&context
, bool outer
) {
420 CYThisScope
*_this(context
.this_
);
421 context
.this_
= CYGetLast(&this_
);
423 CYNonLocal
*nonlocal(context
.nonlocal_
);
424 CYNonLocal
*nextlocal(context
.nextlocal_
);
427 if (nonlocal_
!= NULL
) {
429 context
.nonlocal_
= nonlocal_
;
432 nonlocal_
= $
CYNonLocal();
433 context
.nextlocal_
= nonlocal_
;
436 CYScope
scope(!localize
, context
, code_
.statements_
);
438 if (!outer
&& name_
!= NULL
)
441 parameters_
->Replace(context
, code_
);
442 code_
.Replace(context
);
444 if (CYIdentifier
*identifier
= this_
.identifier_
)
445 code_
.statements_
= $$
->*
446 $
CYVar($
L1($
CYDeclaration(identifier
, $
CYThis())))->*
450 context
.NonLocal(code_
.statements_
);
452 context
.nextlocal_
= nextlocal
;
453 context
.nonlocal_
= nonlocal
;
455 context
.this_
= _this
;
460 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
461 Replace_(context
, false);
465 void CYFunctionParameter::Replace(CYContext
&context
, CYBlock
&code
) { $
T()
466 CYAssignment
*assignment(initialiser_
->Assignment(context
));
467 context
.Replace(initialiser_
);
469 next_
->Replace(context
, code
);
471 if (assignment
!= NULL
)
472 // XXX: this cast is quite incorrect
473 code
.AddPrev($
CYIf($
CYIdentical($
CYTypeOf(dynamic_cast<CYExpression
*>(initialiser_
)), $
S("undefined")), $$
->*
478 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
479 Replace_(context
, true);
483 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
) {
484 if (replace_
!= NULL
&& replace_
!= this)
485 return replace_
->Replace(context
);
486 replace_
= context
.scope_
->Lookup(context
, this);
490 CYStatement
*CYIf::Replace(CYContext
&context
) {
491 context
.Replace(test_
);
492 context
.Replace(true_
);
493 context
.Replace(false_
);
497 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
501 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
502 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
505 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
506 return $
M(rhs_
, $
S("$cyi"));
509 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
510 return $
M($
CYIndirect(object_
), property_
);
513 CYExpression
*CYInfix::Replace(CYContext
&context
) {
514 context
.Replace(lhs_
);
515 context
.Replace(rhs_
);
519 CYStatement
*CYLabel::Replace(CYContext
&context
) {
520 context
.Replace(statement_
);
524 CYExpression
*CYLambda::Replace(CYContext
&context
) {
525 return $
N2($
V("Functor"), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), statements_
), parameters_
->TypeSignature(context
, type_
->Replace(context
)));
528 CYStatement
*CYLetStatement::Replace(CYContext
&context
) {
529 return $
E($
CYCall(CYNonLocalize(context
, $
CYFunctionExpression(NULL
, declarations_
->Parameter(context
), code_
)), declarations_
->Argument(context
)));
535 CYExpression
*New::AddArgument(CYContext
&context
, CYExpression
*value
) {
536 CYSetLast(arguments_
) = $
CYArgument(value
);
540 CYExpression
*New::Replace(CYContext
&context
) {
541 context
.Replace(constructor_
);
542 arguments_
->Replace(context
);
548 CYNumber
*CYNull::Number(CYContext
&context
) {
552 CYString
*CYNull::String(CYContext
&context
) {
556 CYNumber
*CYNumber::Number(CYContext
&context
) {
560 CYString
*CYNumber::String(CYContext
&context
) {
561 // XXX: there is a precise algorithm for this
562 return $
S($pool
.sprintf(24, "%.17g", Value()));
565 CYExpression
*CYObject::Replace(CYContext
&context
) {
566 properties_
->Replace(context
);
570 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
571 context
.Replace(lhs_
);
575 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
576 context
.Replace(rhs_
);
580 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
581 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
582 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
585 struct IdentifierUsageLess
:
586 std::binary_function
<CYIdentifier
*, CYIdentifier
*, bool>
588 _finline
bool operator ()(CYIdentifier
*lhs
, CYIdentifier
*rhs
) const {
589 if (lhs
->usage_
!= rhs
->usage_
)
590 return lhs
->usage_
> rhs
->usage_
;
595 typedef std::set
<CYIdentifier
*, IdentifierUsageLess
> IdentifierUsages
;
598 void CYProgram::Replace(CYContext
&context
) {
599 CYScope
scope(true, context
, statements_
);
601 context
.nextlocal_
= $
CYNonLocal();
602 context
.ReplaceAll(statements_
);
603 context
.NonLocal(statements_
);
609 CYCStringSet external
;
610 for (CYIdentifierValueSet::const_iterator
i(scope
.identifiers_
.begin()); i
!= scope
.identifiers_
.end(); ++i
)
611 external
.insert((*i
)->Word());
613 IdentifierUsages usages
;
615 if (offset
< context
.rename_
.size())
616 CYForEach (i
, context
.rename_
[offset
].identifier_
)
619 // XXX: totalling the probable occurrences and sorting by them would improve the result
620 for (CYIdentifierUsageVector::const_iterator
i(context
.rename_
.begin()); i
!= context
.rename_
.end(); ++i
, ++offset
) {
621 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
625 if (context
.options_
.verbose_
)
626 name
= $pool
.strcat("$", $pool
.itoa(offset
), NULL
);
632 unsigned position(7), local(offset
+ 1);
635 unsigned index(local
% (sizeof(MappingSet
) - 1));
636 local
/= sizeof(MappingSet
) - 1;
637 id
[--position
] = MappingSet
[index
];
638 } while (local
!= 0);
640 if (external
.find(id
+ position
) != external
.end()) {
645 name
= $pool
.strmemdup(id
+ position
, 7 - position
);
646 // XXX: at some point, this could become a keyword
649 CYForEach (identifier
, i
->identifier_
)
650 identifier
->Set(name
);
654 void CYProperty::Replace(CYContext
&context
) { $
T()
655 context
.Replace(value_
);
656 next_
->Replace(context
);
661 CYStatement
*CYReturn::Replace(CYContext
&context
) {
662 if (context
.nonlocal_
!= NULL
) {
663 CYProperty
*value(value_
== NULL
? NULL
: $
CYProperty($
S("$cyv"), value_
));
664 return $
cy::Syntax::Throw($
CYObject(
665 $
CYProperty($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
)
669 context
.Replace(value_
);
673 CYExpression
*CYRubyBlock::Replace(CYContext
&context
) {
674 // XXX: this needs to do something much more epic to handle return
675 return call_
->AddArgument(context
, proc_
->Replace(context
));
678 CYExpression
*CYRubyProc::Replace(CYContext
&context
) {
679 return CYNonLocalize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
));
682 CYScope::CYScope(bool transparent
, CYContext
&context
, CYStatement
*&statements
) :
683 transparent_(transparent
),
685 statements_(statements
),
686 parent_(context
.scope_
)
688 context_
.scope_
= this;
691 CYScope::~CYScope() {
694 void CYScope::Close() {
695 context_
.scope_
= parent_
;
696 Scope(context_
, statements_
);
699 void CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierFlags flags
) {
700 if (!transparent_
|| flags
== CYIdentifierArgument
|| flags
== CYIdentifierCatch
)
701 internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
));
702 else if (parent_
!= NULL
)
703 parent_
->Declare(context
, identifier
, flags
);
706 CYIdentifier
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
707 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
708 return *insert
.first
;
711 void CYScope::Merge(CYContext
&context
, CYIdentifier
*identifier
) {
712 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
713 if (!insert
.second
) {
714 if ((*insert
.first
)->offset_
< identifier
->offset_
)
715 (*insert
.first
)->offset_
= identifier
->offset_
;
716 identifier
->replace_
= *insert
.first
;
717 (*insert
.first
)->usage_
+= identifier
->usage_
+ 1;
722 struct IdentifierOffset
{
724 CYIdentifierFlags flags_
;
726 CYIdentifier
*identifier_
;
728 IdentifierOffset(CYIdentifier
*identifier
, CYIdentifierFlags flags
) :
729 offset_(identifier
->offset_
),
731 usage_(identifier
->usage_
),
732 identifier_(identifier
)
737 struct IdentifierOffsetLess
:
738 std::binary_function
<const IdentifierOffset
&, const IdentifierOffset
&, bool>
740 _finline
bool operator ()(const IdentifierOffset
&lhs
, const IdentifierOffset
&rhs
) const {
741 if (lhs
.offset_
!= rhs
.offset_
)
742 return lhs
.offset_
< rhs
.offset_
;
743 if (lhs
.flags_
!= rhs
.flags_
)
744 return lhs
.flags_
< rhs
.flags_
;
745 /*if (lhs.usage_ != rhs.usage_)
746 return lhs.usage_ < rhs.usage_;*/
747 return lhs
.identifier_
< rhs
.identifier_
;
751 typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
;
754 void CYScope::Scope(CYContext
&context
, CYStatement
*&statements
) {
758 CYDeclarations
*last(NULL
), *curr(NULL
);
760 IdentifierOffsets offsets
;
762 for (CYIdentifierAddressFlagsMap::const_iterator
i(internal_
.begin()); i
!= internal_
.end(); ++i
)
763 if (i
->second
!= CYIdentifierMagic
)
764 offsets
.insert(IdentifierOffset(i
->first
, i
->second
));
768 for (IdentifierOffsets::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
769 if (i
->flags_
== CYIdentifierVariable
) {
770 CYDeclarations
*next($
CYDeclarations($
CYDeclaration(i
->identifier_
)));
778 if (offset
< i
->offset_
)
780 if (context
.rename_
.size() <= offset
)
781 context
.rename_
.resize(offset
+ 1);
783 CYIdentifierUsage
&rename(context
.rename_
[offset
++]);
784 i
->identifier_
->SetNext(rename
.identifier_
);
785 rename
.identifier_
= i
->identifier_
;
786 rename
.usage_
+= i
->identifier_
->usage_
+ 1;
790 CYVar
*var($
CYVar(last
));
791 var
->SetNext(statements
);
795 for (CYIdentifierValueSet::const_iterator
i(identifiers_
.begin()); i
!= identifiers_
.end(); ++i
)
796 if (internal_
.find(*i
) == internal_
.end()) {
797 //std::cout << *i << '=' << offset << std::endl;
798 if ((*i
)->offset_
< offset
)
799 (*i
)->offset_
= offset
;
800 parent_
->Merge(context
, *i
);
804 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
805 size_t size(size_
+ rhs
->size_
);
806 char *value($
char[size
+ 1]);
807 memcpy(value
, value_
, size_
);
808 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
810 return $
S(value
, size
);
813 CYNumber
*CYString::Number(CYContext
&context
) {
814 // XXX: there is a precise algorithm for this
818 CYString
*CYString::String(CYContext
&context
) {
822 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
823 context
.Replace(value_
);
824 clauses_
->Replace(context
);
828 CYExpression
*CYThis::Replace(CYContext
&context
) {
829 if (context
.this_
!= NULL
)
830 return $
V(context
.this_
->Identifier(context
));
837 CYStatement
*Throw::Replace(CYContext
&context
) {
838 context
.Replace(value_
);
844 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
848 CYNumber
*CYTrue::Number(CYContext
&context
) {
852 CYString
*CYTrue::String(CYContext
&context
) {
859 CYStatement
*Try::Replace(CYContext
&context
) {
860 code_
.Replace(context
);
861 catch_
->Replace(context
);
862 finally_
->Replace(context
);
868 CYExpression
*CYTypeArrayOf::Replace(CYContext
&context
) {
869 return $
CYCall($
CYDirectMember(next_
->Replace(context
), $
CYString("arrayOf")), $
CYArgument(size_
));
872 CYExpression
*CYTypeConstant::Replace(CYContext
&context
) {
873 return $
CYCall($
CYDirectMember(next_
->Replace(context
), $
CYString("constant")));
876 CYStatement
*CYTypeDefinition::Replace(CYContext
&context
) {
877 return $
E($
CYAssign($
V(typed_
->identifier_
), typed_
->type_
->Replace(context
)));
880 CYExpression
*CYTypeFunctionWith::Replace(CYContext
&context
) {
881 return $
CYCall($
CYDirectMember(next_
->Replace(context
), $
CYString("functionWith")), parameters_
->Argument(context
));
884 CYExpression
*CYTypePointerTo::Replace(CYContext
&context
) {
885 return $
CYCall($
CYDirectMember(next_
->Replace(context
), $
CYString("pointerTo")));
888 CYExpression
*CYTypeVariable::Replace(CYContext
&context
) {
892 CYArgument
*CYTypedParameter::Argument(CYContext
&context
) { $
T(NULL
)
893 return $
CYArgument(typed_
->type_
->Replace(context
), next_
->Argument(context
));
896 CYFunctionParameter
*CYTypedParameter::Parameters(CYContext
&context
) { $
T(NULL
)
897 return $
CYFunctionParameter($
CYDeclaration(typed_
->identifier_
?: context
.Unique()), next_
->Parameters(context
));
900 CYExpression
*CYTypedParameter::TypeSignature(CYContext
&context
, CYExpression
*prefix
) { $
T(prefix
)
901 return next_
->TypeSignature(context
, $
CYAdd(prefix
, typed_
->type_
->Replace(context
)));
904 CYStatement
*CYVar::Replace(CYContext
&context
) {
905 declarations_
->Replace(context
);
906 return $
E(declarations_
->Compound(context
));
909 CYExpression
*CYVariable::Replace(CYContext
&context
) {
910 context
.Replace(name_
);
914 CYStatement
*CYWhile::Replace(CYContext
&context
) {
915 context
.Replace(test_
);
916 context
.Replace(code_
);
920 CYStatement
*CYWith::Replace(CYContext
&context
) {
921 context
.Replace(scope_
);
922 context
.Replace(code_
);
926 CYExpression
*CYWord::ClassName(CYContext
&context
, bool object
) {
927 CYString
*name($
S(this));
929 return $
C1($
V("objc_getClass"), name
);