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/>.
24 #include "Replace.hpp"
27 CYFunctionExpression
*CYNonLocalize(CYContext
&context
, CYFunctionExpression
*function
) {
28 function
->nonlocal_
= context
.nextlocal_
;
32 CYFunctionExpression
*CYSuperize(CYContext
&context
, CYFunctionExpression
*function
) {
33 function
->super_
= context
.super_
;
37 CYStatement
*CYDefineProperty(CYExpression
*object
, CYExpression
*name
, bool configurable
, bool enumerable
, CYProperty
*descriptor
) {
38 return $
E($
C3($
M($
V("Object"), $
S("defineProperty")), object
, name
, $
CYObject(CYList
<CYProperty
>()
39 ->* (configurable
? $
CYPropertyValue($
S("configurable"), $
CYTrue()) : NULL
)
40 ->* (enumerable
? $
CYPropertyValue($
S("enumerable"), $
CYTrue()) : NULL
)
44 static void CYImplicitReturn(CYStatement
*&code
) {
45 if (CYStatement
*&last
= CYGetLast(code
))
46 last
= last
->Return();
49 CYExpression
*CYAdd::Replace(CYContext
&context
) {
50 CYInfix::Replace(context
);
52 CYString
*lhs(dynamic_cast<CYString
*>(lhs_
));
53 CYString
*rhs(dynamic_cast<CYString
*>(rhs_
));
55 if (lhs
!= NULL
|| rhs
!= NULL
) {
57 lhs
= lhs_
->String(context
);
60 } else if (rhs
== NULL
) {
61 rhs
= rhs_
->String(context
);
66 return lhs
->Concat(context
, rhs
);
69 if (CYNumber
*lhn
= lhs_
->Number(context
))
70 if (CYNumber
*rhn
= rhs_
->Number(context
))
71 return $
D(lhn
->Value() + rhn
->Value());
76 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
77 return $
C0($
M(rhs_
, $
S("$cya")));
80 CYArgument
*CYArgument::Replace(CYContext
&context
) { $
T(NULL
)
81 context
.Replace(value_
);
82 next_
= next_
->Replace(context
);
94 CYExpression
*CYArray::Replace(CYContext
&context
) {
95 if (elements_
!= NULL
)
96 elements_
->Replace(context
);
100 CYExpression
*CYArrayComprehension::Replace(CYContext
&context
) {
101 CYVariable
*cyv($
V("$cyv"));
103 return $
C0($
F(NULL
, $
P1($
L($
I("$cyv")), comprehensions_
->Parameters(context
)), $$
->*
104 $
E($
CYAssign(cyv
, $
CYArray()))->*
105 comprehensions_
->Replace(context
, $
E($
C1($
M(cyv
, $
S("push")), expression_
)))->*
110 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
111 context
.Replace(lhs_
);
112 context
.Replace(rhs_
);
116 CYStatement
*CYBlock::Return() {
117 CYImplicitReturn(code_
);
121 CYStatement
*CYBlock::Replace(CYContext
&context
) {
122 context
.ReplaceAll(code_
);
128 CYStatement
*CYBreak::Replace(CYContext
&context
) {
132 CYExpression
*CYCall::AddArgument(CYContext
&context
, CYExpression
*value
) {
133 CYArgument
**argument(&arguments_
);
134 while (*argument
!= NULL
)
135 argument
= &(*argument
)->next_
;
136 *argument
= $
CYArgument(value
);
140 CYExpression
*CYCall::Replace(CYContext
&context
) {
141 context
.Replace(function_
);
142 arguments_
->Replace(context
);
149 void Catch::Replace(CYContext
&context
) { $
T()
150 CYScope
scope(true, context
);
152 context
.Replace(name_
);
153 context
.scope_
->Declare(context
, name_
, CYIdentifierCatch
);
155 context
.ReplaceAll(code_
);
156 scope
.Close(context
, code_
);
161 CYExpression
*CYClassExpression::Replace(CYContext
&context
) {
164 CYIdentifier
*super(context
.Unique());
166 CYIdentifier
*old(context
.super_
);
167 context
.super_
= super
;
169 CYIdentifier
*constructor(context
.Unique());
170 CYForEach (member
, tail_
->static_
)
171 member
->Replace(context
, builder
, $
V(constructor
), true);
173 CYIdentifier
*prototype(context
.Unique());
174 CYForEach (member
, tail_
->instance_
)
175 member
->Replace(context
, builder
, $
V(prototype
), true);
177 if (tail_
->constructor_
== NULL
)
178 tail_
->constructor_
= $
CYFunctionExpression(NULL
, NULL
, NULL
);
179 tail_
->constructor_
= CYSuperize(context
, tail_
->constructor_
);
181 context
.super_
= old
;
183 return $
C1($
CYFunctionExpression(NULL
, $
P($
L(super
)), $$
184 ->* $
CYVar($
L1($
L(constructor
, tail_
->constructor_
)))
185 ->* $
CYVar($
L1($
L(prototype
, $
CYFunctionExpression(NULL
, NULL
, NULL
))))
186 ->* $
E($
CYAssign($
M($
V(prototype
), $
S("prototype")), $
M($
V(super
), $
S("prototype"))))
187 ->* $
E($
CYAssign($
V(prototype
), $
N($
V(prototype
))))
188 ->* CYDefineProperty($
V(prototype
), $
S("constructor"), false, false, $
CYPropertyValue($
S("value"), $
V(constructor
)))
189 ->* $
CYVar(builder
.declarations_
)
190 ->* builder
.statements_
191 ->* CYDefineProperty($
V(constructor
), $
S("prototype"), false, false, $
CYPropertyValue($
S("value"), $
V(prototype
)))
192 ->* $
CYReturn($
V(constructor
))
193 ), tail_
->extends_
?: $
V($
I("Object")));
196 CYStatement
*CYClassStatement::Replace(CYContext
&context
) {
197 return $
CYVar($
L1($
L(name_
, $
CYClassExpression(name_
, tail_
))));
200 void CYClause::Replace(CYContext
&context
) { $
T()
201 context
.Replace(case_
);
202 context
.ReplaceAll(code_
);
203 next_
->Replace(context
);
206 CYExpression
*CYCompound::Replace(CYContext
&context
) {
207 context
.Replace(expression_
);
208 context
.Replace(next_
);
210 if (CYCompound
*compound
= dynamic_cast<CYCompound
*>(expression_
)) {
211 expression_
= compound
->expression_
;
212 compound
->expression_
= compound
->next_
;
213 compound
->next_
= next_
;
220 CYFunctionParameter
*CYCompound::Parameter() const {
221 CYFunctionParameter
*next(next_
->Parameter());
225 CYFunctionParameter
*parameter(expression_
->Parameter());
226 if (parameter
== NULL
)
229 parameter
->SetNext(next
);
233 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
234 CYFunctionParameter
*next(next_
->Parameters(context
));
235 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
236 parameter
->SetNext(next
);
242 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
243 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
246 CYExpression
*CYComputed::PropertyName(CYContext
&context
) {
250 CYExpression
*CYCondition::Replace(CYContext
&context
) {
251 context
.Replace(test_
);
252 context
.Replace(true_
);
253 context
.Replace(false_
);
257 void CYContext::NonLocal(CYStatement
*&statements
) {
258 CYContext
&context(*this);
260 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
261 CYIdentifier
*cye($
I("$cye")->Replace(context
));
262 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
));
264 CYStatement
*declare(
265 $
CYVar($
L1($
L(unique
, $
CYObject()))));
267 cy::Syntax::Catch
*rescue(
268 $
cy::Syntax::Catch(cye
, $$
->*
269 $
CYIf($
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
->*
270 $
CYReturn($
M($
V(cye
), $
S("$cyv"))))->*
271 $
cy::Syntax::Throw($
V(cye
))));
273 // XXX: I don't understand any of this
274 context
.Replace(declare
);
275 rescue
->Replace(context
);
279 $
cy::Syntax::Try(statements
, rescue
, NULL
);
283 CYIdentifier
*CYContext::Unique() {
284 return $
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
));
287 CYStatement
*CYContinue::Replace(CYContext
&context
) {
291 CYStatement
*CYDebugger::Replace(CYContext
&context
) {
295 CYAssignment
*CYDeclaration::Assignment(CYContext
&context
) {
296 if (initialiser_
== NULL
)
299 CYAssignment
*value($
CYAssign(Variable(context
), initialiser_
));
304 CYVariable
*CYDeclaration::Variable(CYContext
&context
) {
305 return $
V(identifier_
);
308 CYStatement
*CYDeclaration::ForEachIn(CYContext
&context
, CYExpression
*value
) {
309 return $
CYVar($
L1($
CYDeclaration(identifier_
, value
)));
312 CYExpression
*CYDeclaration::Replace(CYContext
&context
) {
313 context
.Replace(identifier_
);
314 context
.scope_
->Declare(context
, identifier_
, CYIdentifierVariable
);
315 return Variable(context
);
318 void CYDeclarations::Replace(CYContext
&context
) { $
T()
319 declaration_
->Replace(context
);
320 next_
->Replace(context
);
323 CYFunctionParameter
*CYDeclarations::Parameter(CYContext
&context
) { $
T(NULL
)
324 return $
CYFunctionParameter($
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
));
327 CYArgument
*CYDeclarations::Argument(CYContext
&context
) { $
T(NULL
)
328 return $
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
));
331 CYExpression
*CYDeclarations::Expression(CYContext
&context
) { $
T(NULL
)
332 CYExpression
*compound(next_
->Expression(context
));
333 if (CYAssignment
*assignment
= declaration_
->Assignment(context
))
334 if (compound
== NULL
)
335 compound
= assignment
;
337 compound
= $
CYCompound(assignment
, compound
);
341 CYExpression
*CYDirectMember::Replace(CYContext
&context
) {
342 context
.Replace(object_
);
343 context
.Replace(property_
);
347 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
348 context
.Replace(test_
);
349 context
.ReplaceAll(code_
);
353 void CYElementSpread::Replace(CYContext
&context
) {
354 context
.Replace(value_
);
357 void CYElementValue::Replace(CYContext
&context
) {
358 context
.Replace(value_
);
360 next_
->Replace(context
);
363 CYStatement
*CYEmpty::Replace(CYContext
&context
) {
367 CYExpression
*CYEncodedType::Replace(CYContext
&context
) {
368 return typed_
->Replace(context
);
371 CYStatement
*CYExpress::Return() {
372 return $
CYReturn(expression_
);
375 CYStatement
*CYExpress::Replace(CYContext
&context
) {
376 context
.Replace(expression_
);
380 CYExpression
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
381 return $
C1(this, value
);
384 CYStatement
*CYExpression::ForEachIn(CYContext
&context
, CYExpression
*value
) {
385 return $
E($
CYAssign(this, value
));
388 CYAssignment
*CYExpression::Assignment(CYContext
&context
) {
392 CYFunctionParameter
*CYExpression::Parameter() const {
396 CYStatement
*CYExternal::Replace(CYContext
&context
) {
397 return $
E($
CYAssign($
V(typed_
->identifier_
), $
C1(typed_
->Replace(context
), $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), $
S(typed_
->identifier_
->Word())))));
400 CYNumber
*CYFalse::Number(CYContext
&context
) {
404 CYString
*CYFalse::String(CYContext
&context
) {
408 CYExpression
*CYFatArrow::Replace(CYContext
&context
) {
409 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
410 function
->this_
.SetNext(context
.this_
);
414 void CYFinally::Replace(CYContext
&context
) { $
T()
415 context
.ReplaceAll(code_
);
418 CYStatement
*CYFor::Replace(CYContext
&context
) {
419 context
.Replace(initialiser_
);
420 context
.Replace(test_
);
421 context
.Replace(increment_
);
422 context
.ReplaceAll(code_
);
426 CYExpression
*CYForDeclarations::Replace(CYContext
&context
) {
427 declarations_
->Replace(context
);
428 return declarations_
->Expression(context
);
431 // XXX: this still feels highly suboptimal
432 CYStatement
*CYForIn::Replace(CYContext
&context
) {
433 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
434 return $
CYBlock($$
->*
439 context
.Replace(initialiser_
);
440 context
.Replace(set_
);
441 context
.ReplaceAll(code_
);
445 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
446 return $
CYFunctionParameter(declaration_
);
449 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
450 return $
CYForIn(declaration_
->Variable(context
), set_
, CYComprehension::Replace(context
, statement
));
453 CYStatement
*CYForOf::Replace(CYContext
&context
) {
454 if (CYAssignment
*assignment
= initialiser_
->Assignment(context
))
455 return $
CYBlock($$
->*
460 CYIdentifier
*cys(context
.Unique()), *cyt(context
.Unique());
463 ->* $
CYLet($
L2($
L(cys
, set_
), $
L(cyt
)))
464 ->* $
CYForIn($
V(cyt
), $
V(cys
), $
CYBlock($$
465 ->* initialiser_
->ForEachIn(context
, $
M($
V(cys
), $
V(cyt
)))
470 CYFunctionParameter
*CYForOfComprehension::Parameter(CYContext
&context
) const {
471 return $
CYFunctionParameter(declaration_
);
474 CYStatement
*CYForOfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
475 CYIdentifier
*cys($
I("$cys"));
477 return $
E($
C0($
F(NULL
, $
P1($
L($
I("$cys"))), $$
->*
478 $
E($
CYAssign($
V(cys
), set_
))->*
479 $
CYForIn(declaration_
->Variable(context
), $
V(cys
), $
CYBlock($$
->*
480 $
E($
CYAssign(declaration_
->Variable(context
), $
M($
V(cys
), declaration_
->Variable(context
))))->*
481 CYComprehension::Replace(context
, statement
)
486 void CYFunction::Replace(CYContext
&context
) {
487 CYThisScope
*_this(context
.this_
);
488 context
.this_
= &this_
;
489 context
.this_
= CYGetLast(context
.this_
);
491 CYIdentifier
*super(context
.super_
);
492 context
.super_
= super_
;
494 CYNonLocal
*nonlocal(context
.nonlocal_
);
495 CYNonLocal
*nextlocal(context
.nextlocal_
);
498 if (nonlocal_
!= NULL
) {
500 context
.nonlocal_
= nonlocal_
;
503 nonlocal_
= $
CYNonLocal();
504 context
.nextlocal_
= nonlocal_
;
507 CYScope
scope(!localize
, context
);
509 parameters_
->Replace(context
, code_
);
511 context
.ReplaceAll(code_
);
514 CYImplicitReturn(code_
);
516 if (CYIdentifier
*identifier
= this_
.identifier_
) {
517 context
.scope_
->Declare(context
, identifier
, CYIdentifierVariable
);
519 ->*$
E($
CYAssign($
V(identifier
), $
CYThis()))
525 context
.NonLocal(code_
);
527 context
.nextlocal_
= nextlocal
;
528 context
.nonlocal_
= nonlocal
;
530 context
.super_
= super
;
531 context
.this_
= _this
;
533 scope
.Close(context
, code_
);
536 CYExpression
*CYFunctionExpression::Replace(CYContext
&context
) {
537 CYScope
scope(false, context
);
539 context
.scope_
->Declare(context
, name_
, CYIdentifierOther
);
540 CYFunction::Replace(context
);
541 scope
.Close(context
, code_
);
545 void CYFunctionParameter::Replace(CYContext
&context
, CYStatement
*&statements
) { $
T()
546 CYAssignment
*assignment(initialiser_
->Assignment(context
));
547 context
.Replace(initialiser_
);
549 next_
->Replace(context
, statements
);
551 if (assignment
!= NULL
)
553 // XXX: this cast is quite incorrect
554 $
CYIf($
CYIdentical($
CYTypeOf(dynamic_cast<CYExpression
*>(initialiser_
)), $
S("undefined")), $$
->*
560 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
561 context
.scope_
->Declare(context
, name_
, CYIdentifierOther
);
562 CYFunction::Replace(context
);
566 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
) {
567 if (replace_
!= NULL
&& replace_
!= this)
568 return replace_
->Replace(context
);
569 replace_
= context
.scope_
->Lookup(context
, this);
573 CYStatement
*CYIf::Return() {
574 CYImplicitReturn(true_
);
575 CYImplicitReturn(false_
);
579 CYStatement
*CYIf::Replace(CYContext
&context
) {
580 context
.Replace(test_
);
581 context
.ReplaceAll(true_
);
582 context
.ReplaceAll(false_
);
586 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
590 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
591 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
594 CYStatement
*CYImport::Replace(CYContext
&context
) {
595 return $
CYVar($
L1($
L($
I(module_
->part_
->Word()), $
C1($
V("require"), module_
->Replace(context
, "/")))));
598 CYExpression
*CYIndirect::Replace(CYContext
&context
) {
599 return $
M(rhs_
, $
S("$cyi"));
602 CYExpression
*CYIndirectMember::Replace(CYContext
&context
) {
603 return $
M($
CYIndirect(object_
), property_
);
606 CYExpression
*CYInfix::Replace(CYContext
&context
) {
607 context
.Replace(lhs_
);
608 context
.Replace(rhs_
);
612 CYStatement
*CYLabel::Replace(CYContext
&context
) {
613 context
.Replace(statement_
);
617 CYExpression
*CYLambda::Replace(CYContext
&context
) {
618 return $
N2($
V("Functor"), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
)));
621 CYStatement
*CYLet::Replace(CYContext
&context
) {
622 declarations_
->Replace(context
);
623 if (CYExpression
*expression
= declarations_
->Expression(context
))
624 return $
E(expression
);
628 CYFunctionExpression
*CYMethod::Constructor() {
632 void CYMethod::Replace(CYContext
&context
) {
633 CYFunction::Replace(context
);
636 CYString
*CYModule::Replace(CYContext
&context
, const char *separator
) const {
638 return $
CYString(part_
);
639 return $
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
));
642 CYExpression
*CYMultiply::Replace(CYContext
&context
) {
643 CYInfix::Replace(context
);
645 if (CYNumber
*lhn
= lhs_
->Number(context
))
646 if (CYNumber
*rhn
= rhs_
->Number(context
))
647 return $
D(lhn
->Value() * rhn
->Value());
655 CYExpression
*New::AddArgument(CYContext
&context
, CYExpression
*value
) {
656 CYSetLast(arguments_
) = $
CYArgument(value
);
660 CYExpression
*New::Replace(CYContext
&context
) {
661 context
.Replace(constructor_
);
662 arguments_
->Replace(context
);
668 CYNumber
*CYNull::Number(CYContext
&context
) {
672 CYString
*CYNull::String(CYContext
&context
) {
676 CYNumber
*CYNumber::Number(CYContext
&context
) {
680 CYString
*CYNumber::String(CYContext
&context
) {
681 // XXX: there is a precise algorithm for this
682 return $
S($pool
.sprintf(24, "%.17g", Value()));
685 CYExpression
*CYNumber::PropertyName(CYContext
&context
) {
686 return String(context
);
689 CYExpression
*CYObject::Replace(CYContext
&context
) {
691 if (properties_
!= NULL
)
692 properties_
= properties_
->ReplaceAll(context
, builder
, $
CYThis(), false);
695 return $
C1($
M($
CYFunctionExpression(NULL
, builder
.declarations_
->Parameter(context
),
696 builder
.statements_
->*
697 $
CYReturn($
CYThis())
698 ), $
S("call")), this, builder
.declarations_
->Argument(context
));
701 CYForEach (property
, properties_
)
702 property
->Replace(context
);
706 CYExpression
*CYParenthetical::Replace(CYContext
&context
) {
710 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
711 context
.Replace(lhs_
);
715 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
716 context
.Replace(rhs_
);
720 CYProperty
*CYProperty::ReplaceAll(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool update
) {
721 update
|= name_
->Computed();
723 Replace(context
, builder
, self
, false);
725 next_
= next_
->ReplaceAll(context
, builder
, self
, update
);
726 return update
? next_
: this;
729 void CYProperty::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool protect
) {
730 CYExpression
*name(name_
->PropertyName(context
));
731 if (name_
->Computed()) {
732 CYIdentifier
*unique(context
.Unique());
733 builder
.declarations_
->*$
L1($
L(unique
, name
));
737 Replace(context
, builder
, self
, name
, protect
);
740 void CYPropertyGetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
741 CYIdentifier
*unique(context
.Unique());
742 builder
.declarations_
743 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
745 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("get"), $
V(unique
)));
748 CYFunctionExpression
*CYPropertyMethod::Constructor() {
749 return name_
->Constructor() ? $
CYFunctionExpression(NULL
, parameters_
, code_
) : NULL
;
752 void CYPropertyMethod::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
753 CYIdentifier
*unique(context
.Unique());
754 builder
.declarations_
755 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
757 ->* (!protect
? $
E($
CYAssign($
M(self
, name
), $
V(unique
))) :
758 CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("value"), $
V(unique
), $
CYPropertyValue($
S("writable"), $
CYTrue()))));
761 void CYPropertySetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
762 CYIdentifier
*unique(context
.Unique());
763 builder
.declarations_
764 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
766 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("set"), $
V(unique
)));
769 void CYPropertyValue::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
771 CYIdentifier
*unique(context
.Unique());
772 builder
.declarations_
773 ->* $
L1($
L(unique
, value_
));
775 ->* $
E($
CYAssign($
M(self
, name
), $
V(unique
)));
778 void CYPropertyValue::Replace(CYContext
&context
) {
779 context
.Replace(value_
);
782 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
783 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
784 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
787 struct IdentifierUsageLess
:
788 std::binary_function
<CYIdentifier
*, CYIdentifier
*, bool>
790 _finline
bool operator ()(CYIdentifier
*lhs
, CYIdentifier
*rhs
) const {
791 if (lhs
->usage_
!= rhs
->usage_
)
792 return lhs
->usage_
> rhs
->usage_
;
797 typedef std::set
<CYIdentifier
*, IdentifierUsageLess
> IdentifierUsages
;
800 void CYScript::Replace(CYContext
&context
) {
801 CYScope
scope(true, context
);
803 context
.nextlocal_
= $
CYNonLocal();
804 context
.ReplaceAll(code_
);
805 context
.NonLocal(code_
);
807 scope
.Close(context
, code_
);
811 CYCStringSet external
;
812 for (CYIdentifierValueSet::const_iterator
i(scope
.identifiers_
.begin()); i
!= scope
.identifiers_
.end(); ++i
)
813 external
.insert((*i
)->Word());
815 IdentifierUsages usages
;
817 if (offset
< context
.rename_
.size())
818 CYForEach (i
, context
.rename_
[offset
].identifier_
)
821 // XXX: totalling the probable occurrences and sorting by them would improve the result
822 for (CYIdentifierUsageVector::const_iterator
i(context
.rename_
.begin()); i
!= context
.rename_
.end(); ++i
, ++offset
) {
823 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
827 if (context
.options_
.verbose_
)
828 name
= $pool
.strcat("$", $pool
.itoa(offset
), NULL
);
834 unsigned position(7), local(offset
+ 1);
837 unsigned index(local
% (sizeof(MappingSet
) - 1));
838 local
/= sizeof(MappingSet
) - 1;
839 id
[--position
] = MappingSet
[index
];
840 } while (local
!= 0);
842 if (external
.find(id
+ position
) != external
.end()) {
847 name
= $pool
.strmemdup(id
+ position
, 7 - position
);
848 // XXX: at some point, this could become a keyword
851 CYForEach (identifier
, i
->identifier_
)
852 identifier
->Set(name
);
856 CYStatement
*CYReturn::Replace(CYContext
&context
) {
857 if (context
.nonlocal_
!= NULL
) {
858 CYProperty
*value(value_
== NULL
? NULL
: $
CYPropertyValue($
S("$cyv"), value_
));
859 return $
cy::Syntax::Throw($
CYObject(
860 $
CYPropertyValue($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
)
864 context
.Replace(value_
);
868 CYExpression
*CYRubyBlock::Replace(CYContext
&context
) {
869 return call_
->AddArgument(context
, proc_
->Replace(context
));
872 CYExpression
*CYRubyBlock::AddArgument(CYContext
&context
, CYExpression
*value
) {
873 return Replace(context
)->AddArgument(context
, value
);
876 CYExpression
*CYRubyProc::Replace(CYContext
&context
) {
877 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
878 function
= CYNonLocalize(context
, function
);
879 function
->implicit_
= true;
883 CYScope::CYScope(bool transparent
, CYContext
&context
) :
884 transparent_(transparent
),
885 parent_(context
.scope_
)
887 context
.scope_
= this;
890 void CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierFlags flags
) {
891 if (!transparent_
|| flags
== CYIdentifierArgument
|| flags
== CYIdentifierCatch
)
892 internal_
.insert(CYIdentifierAddressFlagsMap::value_type(identifier
, flags
));
893 else if (parent_
!= NULL
)
894 parent_
->Declare(context
, identifier
, flags
);
897 CYIdentifier
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
898 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
899 return *insert
.first
;
902 void CYScope::Merge(CYContext
&context
, CYIdentifier
*identifier
) {
903 std::pair
<CYIdentifierValueSet::iterator
, bool> insert(identifiers_
.insert(identifier
));
904 if (!insert
.second
) {
905 if ((*insert
.first
)->offset_
< identifier
->offset_
)
906 (*insert
.first
)->offset_
= identifier
->offset_
;
907 identifier
->replace_
= *insert
.first
;
908 (*insert
.first
)->usage_
+= identifier
->usage_
+ 1;
913 struct IdentifierOffset
{
915 CYIdentifierFlags flags_
;
917 CYIdentifier
*identifier_
;
919 IdentifierOffset(CYIdentifier
*identifier
, CYIdentifierFlags flags
) :
920 offset_(identifier
->offset_
),
922 usage_(identifier
->usage_
),
923 identifier_(identifier
)
928 struct IdentifierOffsetLess
:
929 std::binary_function
<const IdentifierOffset
&, const IdentifierOffset
&, bool>
931 _finline
bool operator ()(const IdentifierOffset
&lhs
, const IdentifierOffset
&rhs
) const {
932 if (lhs
.offset_
!= rhs
.offset_
)
933 return lhs
.offset_
< rhs
.offset_
;
934 if (lhs
.flags_
!= rhs
.flags_
)
935 return lhs
.flags_
< rhs
.flags_
;
936 /*if (lhs.usage_ != rhs.usage_)
937 return lhs.usage_ < rhs.usage_;*/
938 return lhs
.identifier_
< rhs
.identifier_
;
942 typedef std::set
<IdentifierOffset
, IdentifierOffsetLess
> IdentifierOffsets
;
945 void CYScope::Close(CYContext
&context
, CYStatement
*&statements
) {
946 context
.scope_
= parent_
;
951 CYDeclarations
*last(NULL
), *curr(NULL
);
953 IdentifierOffsets offsets
;
955 for (CYIdentifierAddressFlagsMap::const_iterator
i(internal_
.begin()); i
!= internal_
.end(); ++i
)
956 if (i
->second
!= CYIdentifierMagic
)
957 offsets
.insert(IdentifierOffset(i
->first
, i
->second
));
961 for (IdentifierOffsets::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
962 if (i
->flags_
== CYIdentifierVariable
) {
963 CYDeclarations
*next($
CYDeclarations($
CYDeclaration(i
->identifier_
)));
971 if (offset
< i
->offset_
)
973 if (context
.rename_
.size() <= offset
)
974 context
.rename_
.resize(offset
+ 1);
976 CYIdentifierUsage
&rename(context
.rename_
[offset
++]);
977 i
->identifier_
->SetNext(rename
.identifier_
);
978 rename
.identifier_
= i
->identifier_
;
979 rename
.usage_
+= i
->identifier_
->usage_
+ 1;
983 CYVar
*var($
CYVar(last
));
984 var
->SetNext(statements
);
988 for (CYIdentifierValueSet::const_iterator
i(identifiers_
.begin()); i
!= identifiers_
.end(); ++i
)
989 if (internal_
.find(*i
) == internal_
.end()) {
990 //std::cout << *i << '=' << offset << std::endl;
991 if ((*i
)->offset_
< offset
)
992 (*i
)->offset_
= offset
;
993 parent_
->Merge(context
, *i
);
997 CYElementValue
*CYSpan::Replace(CYContext
&context
) { $
T(NULL
)
998 return $
CYElementValue(expression_
, $
CYElementValue(string_
, next_
->Replace(context
)));
1001 CYStatement
*CYStatement::Return() {
1005 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
1006 size_t size(size_
+ rhs
->size_
);
1007 char *value($
char[size
+ 1]);
1008 memcpy(value
, value_
, size_
);
1009 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
1011 return $
S(value
, size
);
1014 CYNumber
*CYString::Number(CYContext
&context
) {
1015 // XXX: there is a precise algorithm for this
1019 CYExpression
*CYString::PropertyName(CYContext
&context
) {
1023 CYString
*CYString::String(CYContext
&context
) {
1027 CYExpression
*CYSuperAccess::Replace(CYContext
&context
) {
1028 return $
C1($
M($
M($
M($
V(context
.super_
), $
S("prototype")), property_
), $
S("bind")), $
CYThis());
1031 CYExpression
*CYSuperCall::Replace(CYContext
&context
) {
1032 return $
C($
C1($
M($
V(context
.super_
), $
S("bind")), $
CYThis()), arguments_
);
1035 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
1036 context
.Replace(value_
);
1037 clauses_
->Replace(context
);
1041 CYExpression
*CYTemplate::Replace(CYContext
&context
) {
1042 return $
C2($
M($
M($
M($
V("String"), $
S("prototype")), $
S("concat")), $
S("apply")), $
S(""), $
CYArray($
CYElementValue(string_
, spans_
->Replace(context
))));
1045 CYExpression
*CYThis::Replace(CYContext
&context
) {
1046 if (context
.this_
!= NULL
)
1047 return $
V(context
.this_
->Identifier(context
));
1054 CYStatement
*Throw::Replace(CYContext
&context
) {
1055 context
.Replace(value_
);
1061 CYExpression
*CYTrivial::Replace(CYContext
&context
) {
1065 CYNumber
*CYTrue::Number(CYContext
&context
) {
1069 CYString
*CYTrue::String(CYContext
&context
) {
1076 CYStatement
*Try::Replace(CYContext
&context
) {
1077 context
.ReplaceAll(code_
);
1078 catch_
->Replace(context
);
1079 finally_
->Replace(context
);
1085 CYExpression
*CYTypeArrayOf::Replace_(CYContext
&context
, CYExpression
*type
) {
1086 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("arrayOf")), $
CYArgument(size_
)));
1089 CYExpression
*CYTypeBlockWith::Replace_(CYContext
&context
, CYExpression
*type
) {
1090 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("blockWith")), parameters_
->Argument(context
)));
1093 CYExpression
*CYTypeConstant::Replace_(CYContext
&context
, CYExpression
*type
) {
1094 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("constant"))));
1097 CYStatement
*CYTypeDefinition::Replace(CYContext
&context
) {
1098 return $
E($
CYAssign($
V(typed_
->identifier_
), typed_
->Replace(context
)));
1101 CYExpression
*CYTypeError::Replace(CYContext
&context
) {
1106 CYExpression
*CYTypeModifier::Replace(CYContext
&context
, CYExpression
*type
) { $
T(type
)
1107 return Replace_(context
, type
);
1110 CYExpression
*CYTypeFunctionWith::Replace_(CYContext
&context
, CYExpression
*type
) {
1111 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("functionWith")), parameters_
->Argument(context
)));
1114 CYExpression
*CYTypeLong::Replace(CYContext
&context
) {
1115 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("long")));
1118 CYExpression
*CYTypePointerTo::Replace_(CYContext
&context
, CYExpression
*type
) {
1119 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("pointerTo"))));
1122 CYExpression
*CYTypeShort::Replace(CYContext
&context
) {
1123 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("short")));
1126 CYExpression
*CYTypeSigned::Replace(CYContext
&context
) {
1127 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("signed")));
1130 CYExpression
*CYTypeUnsigned::Replace(CYContext
&context
) {
1131 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("unsigned")));
1134 CYExpression
*CYTypeVariable::Replace(CYContext
&context
) {
1138 CYExpression
*CYTypeVoid::Replace(CYContext
&context
) {
1139 return $
N1($
V("Type"), $
CYString("v"));
1142 CYExpression
*CYTypeVolatile::Replace_(CYContext
&context
, CYExpression
*type
) {
1143 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("volatile"))));
1146 CYExpression
*CYTypedIdentifier::Replace(CYContext
&context
) {
1147 return modifier_
->Replace(context
, specifier_
->Replace(context
));
1150 CYTypeFunctionWith
*CYTypedIdentifier::Function() {
1151 CYTypeModifier
**modifier(&modifier_
);
1152 if (*modifier
== NULL
)
1154 while ((*modifier
)->next_
!= NULL
)
1155 modifier
= &(*modifier
)->next_
;
1156 CYTypeFunctionWith
*function((*modifier
)->Function());
1157 if (function
== NULL
)
1163 CYArgument
*CYTypedParameter::Argument(CYContext
&context
) { $
T(NULL
)
1164 return $
CYArgument(typed_
->Replace(context
), next_
->Argument(context
));
1167 CYFunctionParameter
*CYTypedParameter::Parameters(CYContext
&context
) { $
T(NULL
)
1168 return $
CYFunctionParameter($
CYDeclaration(typed_
->identifier_
?: context
.Unique()), next_
->Parameters(context
));
1171 CYExpression
*CYTypedParameter::TypeSignature(CYContext
&context
, CYExpression
*prefix
) { $
T(prefix
)
1172 return next_
->TypeSignature(context
, $
CYAdd(prefix
, typed_
->Replace(context
)));
1175 CYStatement
*CYVar::Replace(CYContext
&context
) {
1176 declarations_
->Replace(context
);
1177 if (CYExpression
*expression
= declarations_
->Expression(context
))
1178 return $
E(expression
);
1182 CYExpression
*CYVariable::Replace(CYContext
&context
) {
1183 context
.Replace(name_
);
1187 CYFunctionParameter
*CYVariable::Parameter() const {
1188 return $
CYFunctionParameter($
CYDeclaration(name_
));
1191 CYStatement
*CYWhile::Replace(CYContext
&context
) {
1192 context
.Replace(test_
);
1193 context
.ReplaceAll(code_
);
1197 CYStatement
*CYWith::Replace(CYContext
&context
) {
1198 context
.Replace(scope_
);
1199 context
.ReplaceAll(code_
);
1203 CYExpression
*CYWord::PropertyName(CYContext
&context
) {