1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
5 /* GNU Affero General Public License, Version 3 {{{ */
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. 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 static void CYImplicitReturn(CYStatement
*&code
) {
33 if (CYStatement
*&last
= CYGetLast(code
))
34 last
= last
->Return();
37 CYExpression
*CYAdd::Replace(CYContext
&context
) {
38 CYInfix::Replace(context
);
40 CYString
*lhs(dynamic_cast<CYString
*>(lhs_
));
41 CYString
*rhs(dynamic_cast<CYString
*>(rhs_
));
43 if (lhs
!= NULL
|| rhs
!= NULL
) {
45 lhs
= lhs_
->String(context
);
48 } else if (rhs
== NULL
) {
49 rhs
= rhs_
->String(context
);
54 return lhs
->Concat(context
, rhs
);
57 if (CYNumber
*lhn
= lhs_
->Number(context
))
58 if (CYNumber
*rhn
= rhs_
->Number(context
))
59 return $
D(lhn
->Value() + rhn
->Value());
64 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
65 return $
C0($
M(rhs_
, $
S("$cya")));
68 CYArgument
*CYArgument::Replace(CYContext
&context
) { $
T(NULL
)
69 context
.Replace(value_
);
70 next_
= next_
->Replace(context
);
82 CYExpression
*CYArray::Replace(CYContext
&context
) {
83 if (elements_
!= NULL
)
84 elements_
->Replace(context
);
88 CYExpression
*CYArrayComprehension::Replace(CYContext
&context
) {
89 CYVariable
*cyv($
V("$cyv"));
91 return $
C0($
F(NULL
, $
P1($
L("$cyv"), comprehensions_
->Parameters(context
)), $$
->*
92 $
E($
CYAssign(cyv
, $
CYArray()))->*
93 comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->*
98 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
99 context
.Replace(lhs_
);
100 context
.Replace(rhs_
);
104 CYStatement
*CYBlock::Return() {
105 CYImplicitReturn(code_
);
109 CYStatement
*CYBlock::Replace(CYContext
&context
) {
110 context
.ReplaceAll(code_
);
116 CYStatement
*CYBreak::Replace(CYContext
&context
) {
120 CYExpression
*CYCall::AddArgument(CYContext
&context
, CYExpression
*value
) {
121 CYArgument
**argument(&arguments_
);
122 while (*argument
!= NULL
)
123 argument
= &(*argument
)->next_
;
124 *argument
= $
CYArgument(value
);
128 CYExpression
*CYCall::Replace(CYContext
&context
) {
129 context
.Replace(function_
);
130 arguments_
->Replace(context
);
137 void Catch::Replace(CYContext
&context
) { $
T()
138 CYScope
scope(true, context
);
140 context
.Replace(name_
);
141 context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
);
143 context
.ReplaceAll(code_
);
144 scope
.Close(context
, code_
);
149 void CYClause::Replace(CYContext
&context
) { $
T()
150 context
.Replace(case_
);
151 context
.ReplaceAll(code_
);
152 next_
->Replace(context
);
155 CYExpression
*CYCompound::Replace(CYContext
&context
) {
156 context
.Replace(expression_
);
157 context
.Replace(next_
);
159 if (CYCompound
*compound
= dynamic_cast<CYCompound
*>(expression_
)) {
160 expression_
= compound
->expression_
;
161 compound
->expression_
= compound
->next_
;
162 compound
->next_
= next_
;
169 CYFunctionParameter
*CYCompound::Parameter() const {
170 CYFunctionParameter
*next(next_
->Parameter());
174 CYFunctionParameter
*parameter(expression_
->Parameter());
175 if (parameter
== NULL
)
178 parameter
->SetNext(next
);
182 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
183 CYFunctionParameter
*next(next_
->Parameters(context
));
184 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
185 parameter
->SetNext(next
);
191 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
192 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
195 CYExpression
*CYCondition::Replace(CYContext
&context
) {
196 context
.Replace(test_
);
197 context
.Replace(true_
);
198 context
.Replace(false_
);
202 void CYContext::NonLocal(CYStatement
*&statements
) {
203 CYContext
&context(*this);
205 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
206 CYIdentifier
*cye($
I("$cye")->Replace(context
));
207 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
));
209 CYStatement
*declare(
210 $
CYVar($
L1($
CYDeclaration(unique
, $
CYObject()))));
212 cy::Syntax::Catch
*rescue(
213 $
cy::Syntax::Catch(cye
, $$
->*
214 $
CYIf($
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->*
215 $
CYReturn($
M($
V(cye
), $
S("$cyv"))))->*
216 $
cy::Syntax::Throw($
V(cye
))));
218 // XXX: I don't understand any of this
219 context
.Replace(declare
);
220 rescue
->Replace(context
);
224 $
cy::Syntax::Try(statements
, rescue
, NULL
);
228 CYIdentifier
*CYContext::Unique() {
229 return $
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
));
232 CYStatement
*CYContinue::Replace(CYContext
&context
) {
236 CYStatement
*CYDebugger::Replace(CYContext
&context
) {
240 CYAssignment
*CYDeclaration::Assignment(CYContext
&context
) {
241 if (initialiser_
== NULL
)
244 CYAssignment
*value($
CYAssign(Variable(context
), initialiser_
));
249 CYVariable
*CYDeclaration::Variable(CYContext
&context
) {
250 return $
V(identifier_
);
253 CYStatement
*CYDeclaration::ForEachIn(CYContext
&context
, CYExpression
*value
) {
254 return $
CYVar($
L1($
CYDeclaration(identifier_
, value
)));
257 CYExpression
*CYDeclaration::Replace(CYContext
&context
) {
258 context
.Replace(identifier_
);
259 context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
);
260 return Variable(context
);
263 void CYDeclarations::Replace(CYContext
&context
) { $
T()
264 declaration_
->Replace(context
);
265 next_
->Replace(context
);
268 CYProperty
*CYDeclarations::Property(CYContext
&context
) { $
T(NULL
)
269 return $
CYProperty(declaration_
->identifier_
, declaration_
->initialiser_
, next_
->Property(context
));
272 CYFunctionParameter
*CYDeclarations::Parameter(CYContext
&context
) { $
T(NULL
)
273 return $
CYFunctionParameter($
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
));
276 CYArgument
*CYDeclarations::Argument(CYContext
&context
) { $
T(NULL
)
277 return $
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
));
280 CYExpression
*CYDeclarations::Expression(CYContext
&context
) { $
T(NULL
)
281 CYExpression
*compound(next_
->Expression(context
));
282 if (CYAssignment
*assignment
= declaration_
->Assignment(context
))
283 if (compound
== NULL
)
284 compound
= assignment
;
286 compound
= $
CYCompound(assignment
, compound
);
290 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
291 context
.Replace(object_
);
292 context
.Replace(property_
);
296 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
297 context
.Replace(test_
);
298 context
.ReplaceAll(code_
);
302 void CYElementSpread::Replace(CYContext
&context
) {
303 context
.Replace(value_
);
306 void CYElementValue::Replace(CYContext
&context
) {
307 context
.Replace(value_
);
309 next_
->Replace(context
);
312 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
316 CYExpression
*CYEncodedType::Replace(CYContext
&context
) {
317 return typed_
->Replace(context
);
320 CYStatement
*CYExpress::Return() {
321 return $
CYReturn(expression_
);
324 CYStatement
*CYExpress::Replace(CYContext
&context
) {
325 context
.Replace(expression_
);
329 CYExpression
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
330 return $
C1(this, value
);
333 CYExpression
*CYExpression::ClassName(CYContext
&context
, bool object
) {
337 CYStatement
*CYExpression::ForEachIn(CYContext
&context
, CYExpression
*value
) {
338 return $
E($
CYAssign(this, value
));
341 CYAssignment
*CYExpression::Assignment(CYContext
&context
) {
345 CYFunctionParameter
*CYExpression::Parameter() const {
349 CYStatement
*CYExternal::Replace(CYContext
&context
) {
350 return $
E($
CYAssign($
V(typed_
->identifier_
), $
C1(typed_
->Replace(context
), $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), $
S(typed_
->identifier_
->Word())))));
353 CYNumber
*CYFalse::Number(CYContext
&context
) {
357 CYString
*CYFalse::String(CYContext
&context
) {
361 CYExpression
*CYFatArrow::Replace(CYContext
&context
) {
362 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
363 function
->this_
.SetNext(context
.this_
);
367 void CYFinally::Replace(CYContext
&context
) { $
T()
368 context
.ReplaceAll(code_
);
371 CYStatement
*CYFor::Replace(CYContext
&context
) {
372 context
.Replace(initialiser_
);
373 context
.Replace(test_
);
374 context
.Replace(increment_
);
375 context
.ReplaceAll(code_
);
379 CYExpression
*CYForDeclarations::Replace(CYContext
&context
) {
380 declarations_
->Replace(context
);
381 return declarations_
->Expression(context
);
384 // XXX: this still feels highly suboptimal
385 CYStatement
*CYForIn::Replace(CYContext
&context
) {
386 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
387 return $
CYBlock($$
->*
392 context
.Replace(initialiser_
);
393 context
.Replace(set_
);
394 context
.ReplaceAll(code_
);
398 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
399 return $
CYFunctionParameter($
CYDeclaration(name_
));
402 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
403 return $
CYForIn($
V(name_
), set_
, CYComprehension::Replace(context
, statement
));
406 CYStatement
*CYForOf::Replace(CYContext
&context
) {
407 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
408 return $
CYBlock($$
->*
413 CYIdentifier
*cys($
I("$cys")), *cyt($
I("$cyt"));
415 return $
CYLetStatement($
L2($
CYDeclaration(cys
, set_
), $
CYDeclaration(cyt
)), $$
->*
416 $
CYForIn($
V(cyt
), $
V(cys
), $
CYBlock($$
->*
417 initialiser_
->ForEachIn(context
, $
M($
V(cys
), $
V(cyt
)))->*
423 CYFunctionParameter
*CYForOfComprehension::Parameter(CYContext
&context
) const {
424 return $
CYFunctionParameter($
CYDeclaration(name_
));
427 CYStatement
*CYForOfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
428 CYIdentifier
*cys($
I("$cys"));
430 return $
E($
C0($
F(NULL
, $
P1($
L("$cys")), $$
->*
431 $
E($
CYAssign($
V(cys
), set_
))->*
432 $
CYForIn($
V(name_
), $
V(cys
), $
CYBlock($$
->*
433 $
E($
CYAssign($
V(name_
), $
M($
V(cys
), $
V(name_
))))->*
434 CYComprehension::Replace(context
, statement
)
439 void CYFunction::Inject(CYContext
&context
) {
440 context
.Replace(name_
);
441 context
.scope_
->Declare(context
, name_
, CYIdentifierOther
);
444 void CYFunction::Replace_(CYContext
&context
, bool outer
) {
448 CYThisScope
*_this(context
.this_
);
449 context
.this_
= &this_
;
450 context
.this_
= CYGetLast(context
.this_
);
452 CYNonLocal
*nonlocal(context
.nonlocal_
);
453 CYNonLocal
*nextlocal(context
.nextlocal_
);
456 if (nonlocal_
!= NULL
) {
458 context
.nonlocal_
= nonlocal_
;
461 nonlocal_
= $
CYNonLocal();
462 context
.nextlocal_
= nonlocal_
;
465 CYScope
scope(!localize
, context
);
467 if (!outer
&& name_
!= NULL
)
470 parameters_
->Replace(context
, code_
);
471 context
.ReplaceAll(code_
);
474 CYImplicitReturn(code_
);
476 if (CYIdentifier
*identifier
= this_
.identifier_
)
478 $
CYVar($
L1($
CYDeclaration(identifier
, $
CYThis())))->*
482 context
.NonLocal(code_
);
484 context
.nextlocal_
= nextlocal
;
485 context
.nonlocal_
= nonlocal
;
487 context
.this_
= _this
;
489 scope
.Close(context
, code_
);
492 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
493 Replace_(context
, false);
497 void CYFunctionParameter::Replace(CYContext
&context
, CYStatement
*&statements
) { $
T()
498 CYAssignment
*assignment(initialiser_
->Assignment(context
));
499 context
.Replace(initialiser_
);
501 next_
->Replace(context
, statements
);
503 if (assignment
!= NULL
)
505 // XXX: this cast is quite incorrect
506 $
CYIf($
CYIdentical($
CYTypeOf(dynamic_cast<CYExpression
*>(initialiser_
)), $
S("undefined")), $$
->*
512 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
513 Replace_(context
, true);
517 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
) {
518 if (replace_
!= NULL
&& replace_
!= this)
519 return replace_
->Replace(context
);
520 replace_
= context
.scope_
->Lookup(context
, this);
524 CYStatement
*CYIf::Return() {
525 CYImplicitReturn(true_
);
526 CYImplicitReturn(false_
);
530 CYStatement
*CYIf::Replace(CYContext
&context
) {
531 context
.Replace(test_
);
532 context
.ReplaceAll(true_
);
533 context
.ReplaceAll(false_
);
537 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
541 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
542 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
545 CYStatement
*CYImport::Replace(CYContext
&context
) {
546 return $
CYVar($
L1($
L(module_
->part_
->Word(), $
C1($
V("require"), module_
->Replace(context
, "/")))));
549 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
550 return $
M(rhs_
, $
S("$cyi"));
553 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
554 return $
M($
CYIndirect(object_
), property_
);
557 CYExpression
*CYInfix::Replace(CYContext
&context
) {
558 context
.Replace(lhs_
);
559 context
.Replace(rhs_
);
563 CYStatement
*CYLabel::Replace(CYContext
&context
) {
564 context
.Replace(statement_
);
568 CYExpression
*CYLambda::Replace(CYContext
&context
) {
569 return $
N2($
V("Functor"), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
)));
572 CYStatement
*CYLetStatement::Replace(CYContext
&context
) {
573 return $
E($
CYCall(CYNonLocalize(context
, $
CYFunctionExpression(NULL
, declarations_
->Parameter(context
), code_
)), declarations_
->Argument(context
)));
576 CYString
*CYModule::Replace(CYContext
&context
, const char *separator
) const {
578 return $
CYString(part_
);
579 return $
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
));
582 CYExpression
*CYMultiply::Replace(CYContext
&context
) {
583 CYInfix::Replace(context
);
585 if (CYNumber
*lhn
= lhs_
->Number(context
))
586 if (CYNumber
*rhn
= rhs_
->Number(context
))
587 return $
D(lhn
->Value() * rhn
->Value());
595 CYExpression
*New::AddArgument(CYContext
&context
, CYExpression
*value
) {
596 CYSetLast(arguments_
) = $
CYArgument(value
);
600 CYExpression
*New::Replace(CYContext
&context
) {
601 context
.Replace(constructor_
);
602 arguments_
->Replace(context
);
608 CYNumber
*CYNull::Number(CYContext
&context
) {
612 CYString
*CYNull::String(CYContext
&context
) {
616 CYNumber
*CYNumber::Number(CYContext
&context
) {
620 CYString
*CYNumber::String(CYContext
&context
) {
621 // XXX: there is a precise algorithm for this
622 return $
S($pool
.sprintf(24, "%.17g", Value()));
625 CYExpression
*CYObject::Replace(CYContext
&context
) {
626 properties_
->Replace(context
);
630 CYExpression
*CYParenthetical::Replace(CYContext
&context
) {
634 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
635 context
.Replace(lhs_
);
639 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
640 context
.Replace(rhs_
);
644 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
645 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
646 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
649 struct IdentifierUsageLess
:
650 std::binary_function
<CYIdentifier
*, CYIdentifier
*, bool>
652 _finline
bool operator ()(CYIdentifier
*lhs
, CYIdentifier
*rhs
) const {
653 if (lhs
->usage_
!= rhs
->usage_
)
654 return lhs
->usage_
> rhs
->usage_
;
659 typedef std::set
<CYIdentifier
*, IdentifierUsageLess
> IdentifierUsages
;
662 void CYScript::Replace(CYContext
&context
) {
663 CYScope
scope(true, context
);
665 context
.nextlocal_
= $
CYNonLocal();
666 context
.ReplaceAll(code_
);
667 context
.NonLocal(code_
);
669 scope
.Close(context
, code_
);
673 CYCStringSet external
;
674 for (CYIdentifierValueSet::const_iterator
i(scope
.identifiers_
.begin()); i
!= scope
.identifiers_
.end(); ++i
)
675 external
.insert((*i
)->Word());
677 IdentifierUsages usages
;
679 if (offset
< context
.rename_
.size())
680 CYForEach (i
, context
.rename_
[offset
].identifier_
)
683 // XXX: totalling the probable occurrences and sorting by them would improve the result
684 for (CYIdentifierUsageVector::const_iterator
i(context
.rename_
.begin()); i
!= context
.rename_
.end(); ++i
, ++offset
) {
685 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
689 if (context
.options_
.verbose_
)
690 name
= $pool
.strcat("$", $pool
.itoa(offset
), NULL
);
696 unsigned position(7), local(offset
+ 1);
699 unsigned index(local
% (sizeof(MappingSet
) - 1));
700 local
/= sizeof(MappingSet
) - 1;
701 id
[--position
] = MappingSet
[index
];
702 } while (local
!= 0);
704 if (external
.find(id
+ position
) != external
.end()) {
709 name
= $pool
.strmemdup(id
+ position
, 7 - position
);
710 // XXX: at some point, this could become a keyword
713 CYForEach (identifier
, i
->identifier_
)
714 identifier
->Set(name
);
718 void CYProperty::Replace(CYContext
&context
) { $
T()
719 context
.Replace(value_
);
720 next_
->Replace(context
);
725 CYStatement
*CYReturn::Replace(CYContext
&context
) {
726 if (context
.nonlocal_
!= NULL
) {
727 CYProperty
*value(value_
== NULL
? NULL
: $
CYProperty($
S("$cyv"), value_
));
728 return $
cy::Syntax::Throw($
CYObject(
729 $
CYProperty($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
)
733 context
.Replace(value_
);
737 CYExpression
*CYRubyBlock::Replace(CYContext
&context
) {
738 return call_
->AddArgument(context
, proc_
->Replace(context
));
741 CYExpression
*CYRubyProc::Replace(CYContext
&context
) {
742 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
743 function
= CYNonLocalize(context
, function
);
744 function
->implicit_
= true;
748 CYScope::CYScope(bool transparent
, CYContext
&context
) :
749 transparent_(transparent
),
750 parent_(context
.scope_
)
752 context
.scope_
= this;
755 void CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierFlags flags
) {
756 if (!transparent_
|| flags
== CYIdentifierArgument
|| flags
== CYIdentifierCatch
)
757 internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
));
758 else if (parent_
!= NULL
)
759 parent_
->Declare(context
, identifier
, flags
);
762 CYIdentifier
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
763 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
764 return *insert
.first
;
767 void CYScope::Merge(CYContext
&context
, CYIdentifier
*identifier
) {
768 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
769 if (!insert
.second
) {
770 if ((*insert
.first
)->offset_
< identifier
->offset_
)
771 (*insert
.first
)->offset_
= identifier
->offset_
;
772 identifier
->replace_
= *insert
.first
;
773 (*insert
.first
)->usage_
+= identifier
->usage_
+ 1;
778 struct IdentifierOffset
{
780 CYIdentifierFlags flags_
;
782 CYIdentifier
*identifier_
;
784 IdentifierOffset(CYIdentifier
*identifier
, CYIdentifierFlags flags
) :
785 offset_(identifier
->offset_
),
787 usage_(identifier
->usage_
),
788 identifier_(identifier
)
793 struct IdentifierOffsetLess
:
794 std::binary_function
<const IdentifierOffset
&, const IdentifierOffset
&, bool>
796 _finline
bool operator ()(const IdentifierOffset
&lhs
, const IdentifierOffset
&rhs
) const {
797 if (lhs
.offset_
!= rhs
.offset_
)
798 return lhs
.offset_
< rhs
.offset_
;
799 if (lhs
.flags_
!= rhs
.flags_
)
800 return lhs
.flags_
< rhs
.flags_
;
801 /*if (lhs.usage_ != rhs.usage_)
802 return lhs.usage_ < rhs.usage_;*/
803 return lhs
.identifier_
< rhs
.identifier_
;
807 typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
;
810 void CYScope::Close(CYContext
&context
, CYStatement
*&statements
) {
811 context
.scope_
= parent_
;
816 CYDeclarations
*last(NULL
), *curr(NULL
);
818 IdentifierOffsets offsets
;
820 for (CYIdentifierAddressFlagsMap::const_iterator
i(internal_
.begin()); i
!= internal_
.end(); ++i
)
821 if (i
->second
!= CYIdentifierMagic
)
822 offsets
.insert(IdentifierOffset(i
->first
, i
->second
));
826 for (IdentifierOffsets::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
827 if (i
->flags_
== CYIdentifierVariable
) {
828 CYDeclarations
*next($
CYDeclarations($
CYDeclaration(i
->identifier_
)));
836 if (offset
< i
->offset_
)
838 if (context
.rename_
.size() <= offset
)
839 context
.rename_
.resize(offset
+ 1);
841 CYIdentifierUsage
&rename(context
.rename_
[offset
++]);
842 i
->identifier_
->SetNext(rename
.identifier_
);
843 rename
.identifier_
= i
->identifier_
;
844 rename
.usage_
+= i
->identifier_
->usage_
+ 1;
848 CYVar
*var($
CYVar(last
));
849 var
->SetNext(statements
);
853 for (CYIdentifierValueSet::const_iterator
i(identifiers_
.begin()); i
!= identifiers_
.end(); ++i
)
854 if (internal_
.find(*i
) == internal_
.end()) {
855 //std::cout << *i << '=' << offset << std::endl;
856 if ((*i
)->offset_
< offset
)
857 (*i
)->offset_
= offset
;
858 parent_
->Merge(context
, *i
);
862 CYElementValue
*CYSpan::Replace(CYContext
&context
) { $
T(NULL
)
863 return $
CYElementValue(expression_
, $
CYElementValue(string_
, next_
->Replace(context
)));
866 CYStatement
*CYStatement::Return() {
870 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
871 size_t size(size_
+ rhs
->size_
);
872 char *value($
char[size
+ 1]);
873 memcpy(value
, value_
, size_
);
874 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
876 return $
S(value
, size
);
879 CYNumber
*CYString::Number(CYContext
&context
) {
880 // XXX: there is a precise algorithm for this
884 CYString
*CYString::String(CYContext
&context
) {
888 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
889 context
.Replace(value_
);
890 clauses_
->Replace(context
);
894 CYExpression
*CYTemplate::Replace(CYContext
&context
) {
895 return $
C2($
M($
M($
M($
V("String"), $
S("prototype")), $
S("concat")), $
S("apply")), $
S(""), $
CYArray($
CYElementValue(string_
, spans_
->Replace(context
))));
898 CYExpression
*CYThis::Replace(CYContext
&context
) {
899 if (context
.this_
!= NULL
)
900 return $
V(context
.this_
->Identifier(context
));
907 CYStatement
*Throw::Replace(CYContext
&context
) {
908 context
.Replace(value_
);
914 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
918 CYNumber
*CYTrue::Number(CYContext
&context
) {
922 CYString
*CYTrue::String(CYContext
&context
) {
929 CYStatement
*Try::Replace(CYContext
&context
) {
930 context
.ReplaceAll(code_
);
931 catch_
->Replace(context
);
932 finally_
->Replace(context
);
938 CYExpression
*CYTypeArrayOf::Replace_(CYContext
&context
, CYExpression
*type
) {
939 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("arrayOf")), $
CYArgument(size_
)));
942 CYExpression
*CYTypeBlockWith::Replace_(CYContext
&context
, CYExpression
*type
) {
943 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("blockWith")), parameters_
->Argument(context
)));
946 CYExpression
*CYTypeConstant::Replace_(CYContext
&context
, CYExpression
*type
) {
947 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("constant"))));
950 CYStatement
*CYTypeDefinition::Replace(CYContext
&context
) {
951 return $
E($
CYAssign($
V(typed_
->identifier_
), typed_
->Replace(context
)));
954 CYExpression
*CYTypeError::Replace(CYContext
&context
) {
959 CYExpression
*CYTypeModifier::Replace(CYContext
&context
, CYExpression
*type
) { $
T(type
)
960 return Replace_(context
, type
);
963 CYExpression
*CYTypeFunctionWith::Replace_(CYContext
&context
, CYExpression
*type
) {
964 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("functionWith")), parameters_
->Argument(context
)));
967 CYExpression
*CYTypeLong::Replace(CYContext
&context
) {
968 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("long")));
971 CYExpression
*CYTypePointerTo::Replace_(CYContext
&context
, CYExpression
*type
) {
972 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("pointerTo"))));
975 CYExpression
*CYTypeShort::Replace(CYContext
&context
) {
976 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("short")));
979 CYExpression
*CYTypeSigned::Replace(CYContext
&context
) {
980 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("signed")));
983 CYExpression
*CYTypeUnsigned::Replace(CYContext
&context
) {
984 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("unsigned")));
987 CYExpression
*CYTypeVariable::Replace(CYContext
&context
) {
991 CYExpression
*CYTypeVoid::Replace(CYContext
&context
) {
992 return $
N1($
V("Type"), $
CYString("v"));
995 CYExpression
*CYTypeVolatile::Replace_(CYContext
&context
, CYExpression
*type
) {
996 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("volatile"))));
999 CYExpression
*CYTypedIdentifier::Replace(CYContext
&context
) {
1000 return modifier_
->Replace(context
, specifier_
->Replace(context
));
1003 CYTypeFunctionWith
*CYTypedIdentifier::Function() {
1004 CYTypeModifier
**modifier(&modifier_
);
1005 if (*modifier
== NULL
)
1007 while ((*modifier
)->next_
!= NULL
)
1008 modifier
= &(*modifier
)->next_
;
1009 CYTypeFunctionWith
*function((*modifier
)->Function());
1010 if (function
== NULL
)
1016 CYArgument
*CYTypedParameter::Argument(CYContext
&context
) { $
T(NULL
)
1017 return $
CYArgument(typed_
->Replace(context
), next_
->Argument(context
));
1020 CYFunctionParameter
*CYTypedParameter::Parameters(CYContext
&context
) { $
T(NULL
)
1021 return $
CYFunctionParameter($
CYDeclaration(typed_
->identifier_
?: context
.Unique()), next_
->Parameters(context
));
1024 CYExpression
*CYTypedParameter::TypeSignature(CYContext
&context
, CYExpression
*prefix
) { $
T(prefix
)
1025 return next_
->TypeSignature(context
, $
CYAdd(prefix
, typed_
->Replace(context
)));
1028 CYStatement
*CYVar::Replace(CYContext
&context
) {
1029 declarations_
->Replace(context
);
1030 if (CYExpression
*expression
= declarations_
->Expression(context
))
1031 return $
E(expression
);
1035 CYExpression
*CYVariable::Replace(CYContext
&context
) {
1036 context
.Replace(name_
);
1040 CYFunctionParameter
*CYVariable::Parameter() const {
1041 return $
CYFunctionParameter($
CYDeclaration(name_
));
1044 CYStatement
*CYWhile::Replace(CYContext
&context
) {
1045 context
.Replace(test_
);
1046 context
.ReplaceAll(code_
);
1050 CYStatement
*CYWith::Replace(CYContext
&context
) {
1051 context
.Replace(scope_
);
1052 context
.ReplaceAll(code_
);
1056 CYExpression
*CYWord::ClassName(CYContext
&context
, bool object
) {
1057 CYString
*name($
S(this));
1059 return $
C1($
V("objc_getClass"), name
);