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/>.
25 #include "Replace.hpp"
28 CYFunctionExpression
*CYNonLocalize(CYContext
&context
, CYFunctionExpression
*function
) {
29 function
->nonlocal_
= context
.nextlocal_
;
33 CYFunctionExpression
*CYSuperize(CYContext
&context
, CYFunctionExpression
*function
) {
34 function
->super_
= context
.super_
;
38 CYStatement
*CYDefineProperty(CYExpression
*object
, CYExpression
*name
, bool configurable
, bool enumerable
, CYProperty
*descriptor
) {
39 return $
E($
C3($
M($
V("Object"), $
S("defineProperty")), object
, name
, $
CYObject(CYList
<CYProperty
>()
40 ->* (configurable
? $
CYPropertyValue($
S("configurable"), $
CYTrue()) : NULL
)
41 ->* (enumerable
? $
CYPropertyValue($
S("enumerable"), $
CYTrue()) : NULL
)
45 static void CYImplicitReturn(CYStatement
*&code
) {
46 if (CYStatement
*&last
= CYGetLast(code
))
47 last
= last
->Return();
50 CYExpression
*CYAdd::Replace(CYContext
&context
) {
51 CYInfix::Replace(context
);
53 CYString
*lhs(dynamic_cast<CYString
*>(lhs_
));
54 CYString
*rhs(dynamic_cast<CYString
*>(rhs_
));
56 if (lhs
!= NULL
|| rhs
!= NULL
) {
58 lhs
= lhs_
->String(context
);
61 } else if (rhs
== NULL
) {
62 rhs
= rhs_
->String(context
);
67 return lhs
->Concat(context
, rhs
);
70 if (CYNumber
*lhn
= lhs_
->Number(context
))
71 if (CYNumber
*rhn
= rhs_
->Number(context
))
72 return $
D(lhn
->Value() + rhn
->Value());
77 CYExpression
*CYAddressOf::Replace(CYContext
&context
) {
78 return $
C0($
M(rhs_
, $
S("$cya")));
81 CYTarget
*CYApply::AddArgument(CYContext
&context
, CYExpression
*value
) {
82 CYArgument
**argument(&arguments_
);
83 while (*argument
!= NULL
)
84 argument
= &(*argument
)->next_
;
85 *argument
= $
CYArgument(value
);
89 CYArgument
*CYArgument::Replace(CYContext
&context
) { $
T(NULL
)
90 context
.Replace(value_
);
91 next_
= next_
->Replace(context
);
103 CYTarget
*CYArray::Replace(CYContext
&context
) {
104 if (elements_
!= NULL
)
105 elements_
->Replace(context
);
109 CYTarget
*CYArrayComprehension::Replace(CYContext
&context
) {
110 CYIdentifier
*cyv(context
.Unique());
112 return $
C0($
F(NULL
, $
P1($
L(cyv
), comprehensions_
->Parameters(context
)), $$
113 ->* $
E($
CYAssign($
V(cyv
), $
CYArray()))
114 ->* comprehensions_
->Replace(context
, $
E($
C1($
M($
V(cyv
), $
S("push")), expression_
)))
115 ->* $
CYReturn($
V(cyv
))
119 CYExpression
*CYAssignment::Replace(CYContext
&context
) {
120 context
.Replace(lhs_
);
121 context
.Replace(rhs_
);
125 CYStatement
*CYBlock::Return() {
126 CYImplicitReturn(code_
);
130 CYStatement
*CYBlock::Replace(CYContext
&context
) {
131 CYScope
scope(true, context
);
132 context
.ReplaceAll(code_
);
133 scope
.Close(context
);
140 CYStatement
*CYBreak::Replace(CYContext
&context
) {
144 CYTarget
*CYCall::Replace(CYContext
&context
) {
145 context
.Replace(function_
);
146 arguments_
->Replace(context
);
153 void Catch::Replace(CYContext
&context
) { $
T()
154 CYScope
scope(true, context
);
156 name_
= name_
->Replace(context
, CYIdentifierCatch
);
158 context
.ReplaceAll(code_
);
159 scope
.Close(context
);
164 CYTarget
*CYClassExpression::Replace(CYContext
&context
) {
167 CYIdentifier
*super(context
.Unique());
169 CYIdentifier
*old(context
.super_
);
170 context
.super_
= super
;
172 CYIdentifier
*constructor(context
.Unique());
173 CYForEach (member
, tail_
->static_
)
174 member
->Replace(context
, builder
, $
V(constructor
), true);
176 CYIdentifier
*prototype(context
.Unique());
177 CYForEach (member
, tail_
->instance_
)
178 member
->Replace(context
, builder
, $
V(prototype
), true);
180 if (tail_
->constructor_
== NULL
)
181 tail_
->constructor_
= $
CYFunctionExpression(NULL
, NULL
, NULL
);
182 tail_
->constructor_
= CYSuperize(context
, tail_
->constructor_
);
184 context
.super_
= old
;
186 return $
C1($
CYFunctionExpression(NULL
, $
P($
L(super
)), $$
187 ->* $
CYVar($
L1($
L(constructor
, tail_
->constructor_
)))
188 ->* $
CYVar($
L1($
L(prototype
, $
CYFunctionExpression(NULL
, NULL
, NULL
))))
189 ->* $
E($
CYAssign($
M($
V(prototype
), $
S("prototype")), $
M($
V(super
), $
S("prototype"))))
190 ->* $
E($
CYAssign($
V(prototype
), $
N($
V(prototype
))))
191 ->* CYDefineProperty($
V(prototype
), $
S("constructor"), false, false, $
CYPropertyValue($
S("value"), $
V(constructor
)))
192 ->* $
CYVar(builder
.declarations_
)
193 ->* builder
.statements_
194 ->* CYDefineProperty($
V(constructor
), $
S("prototype"), false, false, $
CYPropertyValue($
S("value"), $
V(prototype
)))
195 ->* $
CYReturn($
V(constructor
))
196 ), tail_
->extends_
?: $
V($
I("Object")));
199 CYStatement
*CYClassStatement::Replace(CYContext
&context
) {
200 return $
CYVar($
L1($
L(name_
, $
CYClassExpression(name_
, tail_
))));
203 void CYClause::Replace(CYContext
&context
) { $
T()
204 context
.Replace(case_
);
205 context
.ReplaceAll(code_
);
206 next_
->Replace(context
);
209 CYExpression
*CYCompound::Replace(CYContext
&context
) {
210 context
.Replace(expression_
);
211 context
.Replace(next_
);
213 if (CYCompound
*compound
= dynamic_cast<CYCompound
*>(expression_
)) {
214 expression_
= compound
->expression_
;
215 compound
->expression_
= compound
->next_
;
216 compound
->next_
= next_
;
223 CYFunctionParameter
*CYCompound::Parameter() const {
224 CYFunctionParameter
*next(next_
->Parameter());
228 CYFunctionParameter
*parameter(expression_
->Parameter());
229 if (parameter
== NULL
)
232 parameter
->SetNext(next
);
236 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
237 CYFunctionParameter
*next(next_
->Parameters(context
));
238 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
239 parameter
->SetNext(next
);
245 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
246 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
249 CYExpression
*CYComputed::PropertyName(CYContext
&context
) {
253 CYExpression
*CYCondition::Replace(CYContext
&context
) {
254 context
.Replace(test_
);
255 context
.Replace(true_
);
256 context
.Replace(false_
);
260 void CYContext::NonLocal(CYStatement
*&statements
) {
261 CYContext
&context(*this);
263 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
264 CYIdentifier
*cye($
I("$cye")->Replace(context
, CYIdentifierGlobal
));
265 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
, CYIdentifierGlobal
));
267 CYStatement
*declare(
268 $
CYVar($
L1($
L(unique
, $
CYObject()))));
270 cy::Syntax::Catch
*rescue(
271 $
cy::Syntax::Catch(cye
, $$
272 ->* $
CYIf($
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
273 ->* $
CYReturn($
M($
V(cye
), $
S("$cyv"))))
274 ->* $
cy::Syntax::Throw($
V(cye
))));
276 context
.Replace(declare
);
277 rescue
->Replace(context
);
281 ->* $
cy::Syntax::Try(statements
, rescue
, NULL
);
285 CYIdentifier
*CYContext::Unique() {
286 return $
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
));
289 CYStatement
*CYContinue::Replace(CYContext
&context
) {
293 CYStatement
*CYDebugger::Replace(CYContext
&context
) {
297 CYTarget
*CYDeclaration::Target(CYContext
&context
) {
298 return $
V(identifier_
);
301 CYAssignment
*CYDeclaration::Replace(CYContext
&context
, CYIdentifierKind kind
) {
302 identifier_
= identifier_
->Replace(context
, kind
);
304 if (initialiser_
== NULL
)
307 CYAssignment
*value($
CYAssign(Target(context
), initialiser_
));
312 CYExpression
*CYDeclarations::Replace(CYContext
&context
, CYIdentifierKind kind
) { $
T(NULL
)
313 CYAssignment
*assignment(declaration_
->Replace(context
, kind
));
314 CYExpression
*compound(next_
->Replace(context
, kind
));
316 if (assignment
!= NULL
)
317 if (compound
== NULL
)
318 compound
= assignment
;
320 compound
= $
CYCompound(assignment
, compound
);
324 CYFunctionParameter
*CYDeclarations::Parameter(CYContext
&context
) { $
T(NULL
)
325 return $
CYFunctionParameter($
CYDeclaration(declaration_
->identifier_
), next_
->Parameter(context
));
328 CYArgument
*CYDeclarations::Argument(CYContext
&context
) { $
T(NULL
)
329 return $
CYArgument(declaration_
->initialiser_
, next_
->Argument(context
));
332 CYTarget
*CYDirectMember::Replace(CYContext
&context
) {
333 context
.Replace(object_
);
334 context
.Replace(property_
);
338 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
339 context
.Replace(test_
);
340 context
.ReplaceAll(code_
);
344 void CYElementSpread::Replace(CYContext
&context
) {
345 context
.Replace(value_
);
348 void CYElementValue::Replace(CYContext
&context
) {
349 context
.Replace(value_
);
351 next_
->Replace(context
);
354 CYForInitializer
*CYEmpty::Replace(CYContext
&context
) {
358 CYTarget
*CYEncodedType::Replace(CYContext
&context
) {
359 return typed_
->Replace(context
);
362 CYTarget
*CYEval::Replace(CYContext
&context
) {
363 context
.scope_
->Damage();
364 if (arguments_
!= NULL
)
365 arguments_
->value_
= $
C1($
M($
V("Cycript"), $
S("compile")), arguments_
->value_
);
366 return $
C($
V("eval"), arguments_
);
369 CYStatement
*CYExpress::Return() {
370 return $
CYReturn(expression_
);
373 CYForInitializer
*CYExpress::Replace(CYContext
&context
) {
374 context
.Replace(expression_
);
378 CYTarget
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
379 return $
C1(this, value
);
382 CYFunctionParameter
*CYExpression::Parameter() const {
386 CYStatement
*CYExternal::Replace(CYContext
&context
) {
387 return $
E($
CYAssign($
V(typed_
->identifier_
), $
C1(typed_
->Replace(context
), $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), $
S(typed_
->identifier_
->Word())))));
390 CYNumber
*CYFalse::Number(CYContext
&context
) {
394 CYString
*CYFalse::String(CYContext
&context
) {
398 CYExpression
*CYFatArrow::Replace(CYContext
&context
) {
399 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
400 function
->this_
.SetNext(context
.this_
);
404 void CYFinally::Replace(CYContext
&context
) { $
T()
405 CYScope
scope(true, context
);
406 context
.ReplaceAll(code_
);
407 scope
.Close(context
);
410 CYStatement
*CYFor::Replace(CYContext
&context
) {
411 CYScope
outer(true, context
);
412 context
.Replace(initialiser_
);
414 context
.Replace(test_
);
417 CYScope
inner(true, context
);
418 context
.ReplaceAll(code_
);
419 inner
.Close(context
);
422 context
.Replace(increment_
);
424 outer
.Close(context
);
428 CYStatement
*CYForLexical::Initialize(CYContext
&context
, CYExpression
*value
) {
430 if (declaration_
->initialiser_
== NULL
)
432 value
= declaration_
->initialiser_
;
435 return $
CYLet(constant_
, $
L1($
CYDeclaration(declaration_
->identifier_
, value
)));
438 CYTarget
*CYForLexical::Replace(CYContext
&context
) {
439 _assert(declaration_
->Replace(context
, CYIdentifierLexical
) == NULL
);
440 return declaration_
->Target(context
);
443 CYStatement
*CYForIn::Replace(CYContext
&context
) {
444 CYScope
scope(true, context
);
445 context
.Replace(initialiser_
);
446 context
.Replace(set_
);
447 context
.ReplaceAll(code_
);
448 scope
.Close(context
);
452 CYStatement
*CYForInitialized::Replace(CYContext
&context
) {
453 CYAssignment
*assignment(declaration_
->Replace(context
, CYIdentifierVariable
));
455 ->* (assignment
== NULL
? NULL
: $
CYExpress(assignment
))
456 ->* $
CYForIn(declaration_
->Target(context
), set_
, code_
));
459 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
460 return $
CYFunctionParameter(declaration_
);
463 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
464 return $
CYForIn(declaration_
->Target(context
), set_
, CYComprehension::Replace(context
, statement
));
467 CYStatement
*CYForOf::Replace(CYContext
&context
) {
468 CYIdentifier
*item(context
.Unique()), *list(context
.Unique());
471 ->* initialiser_
->Initialize(context
, NULL
)
472 ->* $
CYLet(false, $
L2($
L(list
, set_
), $
L(item
)))
473 ->* $
CYForIn($
V(item
), $
V(list
), $
CYBlock($$
474 ->* initialiser_
->Initialize(context
, $
M($
V(list
), $
V(item
)))
479 CYFunctionParameter
*CYForOfComprehension::Parameter(CYContext
&context
) const {
480 return $
CYFunctionParameter(declaration_
);
483 CYStatement
*CYForOfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
484 CYIdentifier
*cys(context
.Unique());
487 ->* $
CYLet(false, $
L1($
L(cys
, set_
)))
488 ->* $
CYForIn(declaration_
->Target(context
), $
V(cys
), $
CYBlock($$
489 ->* $
E($
CYAssign(declaration_
->Target(context
), $
M($
V(cys
), declaration_
->Target(context
))))
490 ->* CYComprehension::Replace(context
, statement
)
494 CYStatement
*CYForVariable::Initialize(CYContext
&context
, CYExpression
*value
) {
496 if (declaration_
->initialiser_
== NULL
)
498 value
= declaration_
->initialiser_
;
501 return $
CYVar($
L1($
CYDeclaration(declaration_
->identifier_
, value
)));
504 CYTarget
*CYForVariable::Replace(CYContext
&context
) {
505 _assert(declaration_
->Replace(context
, CYIdentifierVariable
) == NULL
);
506 return declaration_
->Target(context
);
509 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
510 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
511 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
513 void CYFunction::Replace(CYContext
&context
) {
514 CYThisScope
*_this(context
.this_
);
515 context
.this_
= &this_
;
516 context
.this_
= CYGetLast(context
.this_
);
518 CYIdentifier
*super(context
.super_
);
519 context
.super_
= super_
;
521 CYNonLocal
*nonlocal(context
.nonlocal_
);
522 CYNonLocal
*nextlocal(context
.nextlocal_
);
525 if (nonlocal_
!= NULL
) {
527 context
.nonlocal_
= nonlocal_
;
530 nonlocal_
= $
CYNonLocal();
531 context
.nextlocal_
= nonlocal_
;
534 CYScope
scope(!localize
, context
);
536 $
I("arguments")->Replace(context
, CYIdentifierMagic
);
538 parameters_
->Replace(context
, code_
);
540 context
.ReplaceAll(code_
);
543 CYImplicitReturn(code_
);
545 if (CYIdentifier
*identifier
= this_
.identifier_
) {
546 context
.scope_
->Declare(context
, identifier
, CYIdentifierVariable
);
548 ->* $
E($
CYAssign($
V(identifier
), $
CYThis()))
553 context
.NonLocal(code_
);
555 context
.nextlocal_
= nextlocal
;
556 context
.nonlocal_
= nonlocal
;
558 context
.super_
= super
;
559 context
.this_
= _this
;
561 scope
.Close(context
, code_
);
564 CYTarget
*CYFunctionExpression::Replace(CYContext
&context
) {
565 CYScope
scope(false, context
);
567 name_
= name_
->Replace(context
, CYIdentifierOther
);
569 CYFunction::Replace(context
);
570 scope
.Close(context
);
574 void CYFunctionParameter::Replace(CYContext
&context
, CYStatement
*&statements
) { $
T()
575 CYAssignment
*assignment(initialiser_
->Replace(context
, CYIdentifierArgument
));
577 next_
->Replace(context
, statements
);
579 if (assignment
!= NULL
)
581 ->* $
CYIf($
CYIdentical($
CYTypeOf(initialiser_
->Target(context
)), $
S("undefined")), $$
586 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
587 name_
= name_
->Replace(context
, CYIdentifierOther
);
588 CYFunction::Replace(context
);
592 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
, CYIdentifierKind kind
) {
596 return next_
->Replace(context
, kind
);
597 next_
= context
.scope_
->Declare(context
, this, kind
)->identifier_
;
601 CYStatement
*CYIf::Return() {
602 CYImplicitReturn(true_
);
603 CYImplicitReturn(false_
);
607 CYStatement
*CYIf::Replace(CYContext
&context
) {
608 context
.Replace(test_
);
609 context
.ReplaceAll(true_
);
610 context
.ReplaceAll(false_
);
614 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
618 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
619 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
622 CYStatement
*CYImport::Replace(CYContext
&context
) {
623 return $
CYVar($
L1($
L($
I(module_
->part_
->Word()), $
C1($
V("require"), module_
->Replace(context
, "/")))));
626 CYTarget
*CYIndirect::Replace(CYContext
&context
) {
627 return $
M(rhs_
, $
S("$cyi"));
630 CYTarget
*CYIndirectMember::Replace(CYContext
&context
) {
631 return $
M($
CYIndirect(object_
), property_
);
634 CYExpression
*CYInfix::Replace(CYContext
&context
) {
635 context
.Replace(lhs_
);
636 context
.Replace(rhs_
);
640 CYStatement
*CYLabel::Replace(CYContext
&context
) {
641 context
.Replace(statement_
);
645 CYTarget
*CYLambda::Replace(CYContext
&context
) {
646 return $
N2($
V("Functor"), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
)));
649 CYForInitializer
*CYLet::Replace(CYContext
&context
) {
650 if (CYExpression
*expression
= declarations_
->Replace(context
, CYIdentifierLexical
))
651 return $
E(expression
);
655 CYFunctionExpression
*CYMethod::Constructor() {
659 void CYMethod::Replace(CYContext
&context
) {
660 CYFunction::Replace(context
);
663 CYString
*CYModule::Replace(CYContext
&context
, const char *separator
) const {
665 return $
CYString(part_
);
666 return $
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
));
669 CYExpression
*CYMultiply::Replace(CYContext
&context
) {
670 CYInfix::Replace(context
);
672 if (CYNumber
*lhn
= lhs_
->Number(context
))
673 if (CYNumber
*rhn
= rhs_
->Number(context
))
674 return $
D(lhn
->Value() * rhn
->Value());
682 CYTarget
*New::AddArgument(CYContext
&context
, CYExpression
*value
) {
683 CYSetLast(arguments_
) = $
CYArgument(value
);
687 CYTarget
*New::Replace(CYContext
&context
) {
688 context
.Replace(constructor_
);
689 arguments_
->Replace(context
);
695 CYNumber
*CYNull::Number(CYContext
&context
) {
699 CYString
*CYNull::String(CYContext
&context
) {
703 CYNumber
*CYNumber::Number(CYContext
&context
) {
707 CYString
*CYNumber::String(CYContext
&context
) {
708 // XXX: there is a precise algorithm for this
709 return $
S($pool
.sprintf(24, "%.17g", Value()));
712 CYExpression
*CYNumber::PropertyName(CYContext
&context
) {
713 return String(context
);
716 CYTarget
*CYObject::Replace(CYContext
&context
) {
718 if (properties_
!= NULL
)
719 properties_
= properties_
->ReplaceAll(context
, builder
, $
CYThis(), false);
722 return $
C1($
M($
CYFunctionExpression(NULL
, builder
.declarations_
->Parameter(context
),
724 ->* $
CYReturn($
CYThis())
725 ), $
S("call")), this, builder
.declarations_
->Argument(context
));
728 CYForEach (property
, properties_
)
729 property
->Replace(context
);
733 CYTarget
*CYParenthetical::Replace(CYContext
&context
) {
734 // XXX: return expression_;
735 context
.Replace(expression_
);
739 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
740 context
.Replace(lhs_
);
744 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
745 context
.Replace(rhs_
);
749 CYProperty
*CYProperty::ReplaceAll(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool update
) {
752 Replace(context
, builder
, self
, false);
754 next_
= next_
->ReplaceAll(context
, builder
, self
, update
);
755 return update
? next_
: this;
758 void CYProperty::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool protect
) {
759 CYExpression
*name(name_
->PropertyName(context
));
760 if (name_
->Computed()) {
761 CYIdentifier
*unique(context
.Unique());
762 builder
.declarations_
763 ->* $
L1($
L(unique
, name
));
767 Replace(context
, builder
, self
, name
, protect
);
770 bool CYProperty::Update() const {
771 return name_
->Computed();
774 void CYPropertyGetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
775 CYIdentifier
*unique(context
.Unique());
776 builder
.declarations_
777 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
779 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("get"), $
V(unique
)));
782 CYFunctionExpression
*CYPropertyMethod::Constructor() {
783 return name_
->Constructor() ? $
CYFunctionExpression(NULL
, parameters_
, code_
) : NULL
;
786 void CYPropertyMethod::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
787 CYIdentifier
*unique(context
.Unique());
788 builder
.declarations_
789 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
791 ->* (!protect
? $
E($
CYAssign($
M(self
, name
), $
V(unique
))) :
792 CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("value"), $
V(unique
), $
CYPropertyValue($
S("writable"), $
CYTrue()))));
795 bool CYPropertyMethod::Update() const {
799 void CYPropertySetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
800 CYIdentifier
*unique(context
.Unique());
801 builder
.declarations_
802 ->* $
L1($
L(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
804 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("set"), $
V(unique
)));
807 void CYPropertyValue::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
809 CYIdentifier
*unique(context
.Unique());
810 builder
.declarations_
811 ->* $
L1($
L(unique
, value_
));
813 ->* $
E($
CYAssign($
M(self
, name
), $
V(unique
)));
816 void CYPropertyValue::Replace(CYContext
&context
) {
817 context
.Replace(value_
);
820 void CYScript::Replace(CYContext
&context
) {
821 CYScope
scope(false, context
);
822 context
.scope_
->Damage();
824 context
.nextlocal_
= $
CYNonLocal();
825 context
.ReplaceAll(code_
);
826 context
.NonLocal(code_
);
828 scope
.Close(context
, code_
);
832 for (std::vector
<CYIdentifier
*>::const_iterator
i(context
.replace_
.begin()); i
!= context
.replace_
.end(); ++i
) {
834 if (context
.options_
.verbose_
)
835 name
= $pool
.strcat("$", $pool
.itoa(offset
++), NULL
);
841 unsigned position(7), local(offset
++ + 1);
844 unsigned index(local
% (sizeof(MappingSet
) - 1));
845 local
/= sizeof(MappingSet
) - 1;
846 id
[--position
] = MappingSet
[index
];
847 } while (local
!= 0);
849 if (scope
.Lookup(context
, id
+ position
) != NULL
)
851 // XXX: at some point, this could become a keyword
853 name
= $pool
.strmemdup(id
+ position
, 7 - position
);
856 CYIdentifier
*identifier(*i
);
857 _assert(identifier
->next_
== identifier
);
858 identifier
->next_
= $
I(name
);
862 CYStatement
*CYReturn::Replace(CYContext
&context
) {
863 if (context
.nonlocal_
!= NULL
) {
864 CYProperty
*value(value_
== NULL
? NULL
: $
CYPropertyValue($
S("$cyv"), value_
));
865 return $
cy::Syntax::Throw($
CYObject(
866 $
CYPropertyValue($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
)
870 context
.Replace(value_
);
874 CYTarget
*CYRubyBlock::Replace(CYContext
&context
) {
875 return call_
->AddArgument(context
, proc_
->Replace(context
));
878 CYTarget
*CYRubyBlock::AddArgument(CYContext
&context
, CYExpression
*value
) {
879 return Replace(context
)->AddArgument(context
, value
);
882 CYTarget
*CYRubyProc::Replace(CYContext
&context
) {
883 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
884 function
= CYNonLocalize(context
, function
);
885 function
->implicit_
= true;
889 CYScope::CYScope(bool transparent
, CYContext
&context
) :
890 transparent_(transparent
),
891 parent_(context
.scope_
),
896 _assert(!transparent_
|| parent_
!= NULL
);
897 context
.scope_
= this;
900 void CYScope::Damage() {
906 CYIdentifierFlags
*CYScope::Lookup(CYContext
&context
, const char *word
) {
907 CYForEach (i
, internal_
)
908 if (strcmp(i
->identifier_
->Word(), word
) == 0)
913 CYIdentifierFlags
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
914 return Lookup(context
, identifier
->Word());
917 CYIdentifierFlags
*CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierKind kind
) {
918 _assert(identifier
->next_
== NULL
|| identifier
->next_
== identifier
);
920 CYIdentifierFlags
*existing(Lookup(context
, identifier
));
921 if (existing
== NULL
)
922 internal_
= $
CYIdentifierFlags(identifier
, kind
, internal_
);
924 if (existing
== NULL
)
927 if (kind
== CYIdentifierGlobal
);
928 else if (existing
->kind_
== CYIdentifierGlobal
|| existing
->kind_
== CYIdentifierMagic
)
929 existing
->kind_
= kind
;
930 else if (existing
->kind_
== CYIdentifierLexical
|| kind
== CYIdentifierLexical
)
931 _assert(false); // XXX: throw new SyntaxError()
936 void CYScope::Merge(CYContext
&context
, const CYIdentifierFlags
*flags
) {
937 _assert(flags
->identifier_
->next_
== flags
->identifier_
);
938 CYIdentifierFlags
*existing(Declare(context
, flags
->identifier_
, flags
->kind_
));
939 flags
->identifier_
->next_
= existing
->identifier_
;
941 existing
->count_
+= flags
->count_
;
942 if (existing
->offset_
< flags
->offset_
)
943 existing
->offset_
= flags
->offset_
;
946 void CYScope::Close(CYContext
&context
, CYStatement
*&statements
) {
949 CYList
<CYDeclarations
> declarations
;
951 CYForEach (i
, internal_
)
952 if (i
->kind_
== CYIdentifierVariable
)
954 ->* $
CYDeclarations($
CYDeclaration(i
->identifier_
));
957 CYVar
*var($
CYVar(declarations
));
958 var
->SetNext(statements
);
963 void CYScope::Close(CYContext
&context
) {
964 context
.scope_
= parent_
;
966 CYForEach (i
, internal_
) {
967 _assert(i
->identifier_
->next_
== i
->identifier_
);
969 case CYIdentifierArgument
: {
970 _assert(!transparent_
);
973 case CYIdentifierLexical
: {
975 CYIdentifier
*replace(context
.Unique());
976 replace
->next_
= replace
;
977 i
->identifier_
->next_
= replace
;
978 i
->identifier_
= replace
;
982 i
->kind_
= CYIdentifierVariable
;
984 parent_
->Declare(context
, i
->identifier_
, CYIdentifierVariable
);
987 case CYIdentifierVariable
: {
989 parent_
->Declare(context
, i
->identifier_
, i
->kind_
);
990 i
->kind_
= CYIdentifierGlobal
;
998 typedef std::multimap
<unsigned, CYIdentifier
*> CYIdentifierOffsetMap
;
999 CYIdentifierOffsetMap offsets
;
1001 CYForEach (i
, internal_
) {
1002 _assert(i
->identifier_
->next_
== i
->identifier_
);
1004 case CYIdentifierArgument
:
1005 case CYIdentifierVariable
:
1006 offsets
.insert(CYIdentifierOffsetMap::value_type(i
->offset_
, i
->identifier_
));
1012 for (CYIdentifierOffsetMap::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
1013 if (offset
< i
->first
)
1015 CYIdentifier
*identifier(i
->second
);
1017 if (offset
>= context
.replace_
.size())
1018 context
.replace_
.resize(offset
+ 1, NULL
);
1019 CYIdentifier
*&replace(context
.replace_
[offset
++]);
1021 if (replace
== NULL
)
1022 replace
= identifier
;
1024 _assert(replace
->next_
== replace
);
1025 identifier
->next_
= replace
;
1029 if (parent_
== NULL
)
1032 CYForEach (i
, internal_
) {
1034 case CYIdentifierGlobal
: {
1035 if (i
->offset_
< offset
)
1036 i
->offset_
= offset
;
1037 parent_
->Merge(context
, i
);
1042 CYElementValue
*CYSpan::Replace(CYContext
&context
) { $
T(NULL
)
1043 return $
CYElementValue(expression_
, $
CYElementValue(string_
, next_
->Replace(context
)));
1046 CYStatement
*CYStatement::Return() {
1050 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
1051 size_t size(size_
+ rhs
->size_
);
1052 char *value($
char[size
+ 1]);
1053 memcpy(value
, value_
, size_
);
1054 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
1056 return $
S(value
, size
);
1059 CYNumber
*CYString::Number(CYContext
&context
) {
1060 // XXX: there is a precise algorithm for this
1064 CYExpression
*CYString::PropertyName(CYContext
&context
) {
1068 CYString
*CYString::String(CYContext
&context
) {
1072 CYTarget
*CYSuperAccess::Replace(CYContext
&context
) {
1073 return $
C1($
M($
M($
M($
V(context
.super_
), $
S("prototype")), property_
), $
S("bind")), $
CYThis());
1076 CYTarget
*CYSuperCall::Replace(CYContext
&context
) {
1077 return $
C($
C1($
M($
V(context
.super_
), $
S("bind")), $
CYThis()), arguments_
);
1080 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
1081 context
.Replace(value_
);
1082 clauses_
->Replace(context
);
1086 CYStatement
*CYTarget::Initialize(CYContext
&context
, CYExpression
*value
) {
1089 return $
E($
CYAssign(this, value
));
1092 CYTarget
*CYTemplate::Replace(CYContext
&context
) {
1093 return $
C2($
M($
M($
M($
V("String"), $
S("prototype")), $
S("concat")), $
S("apply")), $
S(""), $
CYArray($
CYElementValue(string_
, spans_
->Replace(context
))));
1096 CYTarget
*CYThis::Replace(CYContext
&context
) {
1097 if (context
.this_
!= NULL
)
1098 return $
V(context
.this_
->Identifier(context
));
1105 CYStatement
*Throw::Replace(CYContext
&context
) {
1106 context
.Replace(value_
);
1112 CYTarget
*CYTrivial::Replace(CYContext
&context
) {
1116 CYNumber
*CYTrue::Number(CYContext
&context
) {
1120 CYString
*CYTrue::String(CYContext
&context
) {
1127 CYStatement
*Try::Replace(CYContext
&context
) {
1128 CYScope
scope(true, context
);
1129 context
.ReplaceAll(code_
);
1130 scope
.Close(context
);
1132 catch_
->Replace(context
);
1133 finally_
->Replace(context
);
1139 CYTarget
*CYTypeArrayOf::Replace_(CYContext
&context
, CYTarget
*type
) {
1140 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("arrayOf")), $
CYArgument(size_
)));
1143 CYTarget
*CYTypeBlockWith::Replace_(CYContext
&context
, CYTarget
*type
) {
1144 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("blockWith")), parameters_
->Argument(context
)));
1147 CYTarget
*CYTypeConstant::Replace_(CYContext
&context
, CYTarget
*type
) {
1148 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("constant"))));
1151 CYStatement
*CYTypeDefinition::Replace(CYContext
&context
) {
1152 return $
E($
CYAssign($
V(typed_
->identifier_
), typed_
->Replace(context
)));
1155 CYTarget
*CYTypeError::Replace(CYContext
&context
) {
1160 CYTarget
*CYTypeModifier::Replace(CYContext
&context
, CYTarget
*type
) { $
T(type
)
1161 return Replace_(context
, type
);
1164 CYTarget
*CYTypeFunctionWith::Replace_(CYContext
&context
, CYTarget
*type
) {
1165 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("functionWith")), parameters_
->Argument(context
)));
1168 CYTarget
*CYTypeLong::Replace(CYContext
&context
) {
1169 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("long")));
1172 CYTarget
*CYTypePointerTo::Replace_(CYContext
&context
, CYTarget
*type
) {
1173 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("pointerTo"))));
1176 CYTarget
*CYTypeShort::Replace(CYContext
&context
) {
1177 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("short")));
1180 CYTarget
*CYTypeSigned::Replace(CYContext
&context
) {
1181 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("signed")));
1184 CYTarget
*CYTypeUnsigned::Replace(CYContext
&context
) {
1185 return $
CYCall($
CYDirectMember(specifier_
->Replace(context
), $
CYString("unsigned")));
1188 CYTarget
*CYTypeVariable::Replace(CYContext
&context
) {
1192 CYTarget
*CYTypeVoid::Replace(CYContext
&context
) {
1193 return $
N1($
V("Type"), $
CYString("v"));
1196 CYTarget
*CYTypeVolatile::Replace_(CYContext
&context
, CYTarget
*type
) {
1197 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("volatile"))));
1200 CYTarget
*CYTypedIdentifier::Replace(CYContext
&context
) {
1201 return modifier_
->Replace(context
, specifier_
->Replace(context
));
1204 CYTypeFunctionWith
*CYTypedIdentifier::Function() {
1205 CYTypeModifier
**modifier(&modifier_
);
1206 if (*modifier
== NULL
)
1208 while ((*modifier
)->next_
!= NULL
)
1209 modifier
= &(*modifier
)->next_
;
1210 CYTypeFunctionWith
*function((*modifier
)->Function());
1211 if (function
== NULL
)
1217 CYArgument
*CYTypedParameter::Argument(CYContext
&context
) { $
T(NULL
)
1218 return $
CYArgument(typed_
->Replace(context
), next_
->Argument(context
));
1221 CYFunctionParameter
*CYTypedParameter::Parameters(CYContext
&context
) { $
T(NULL
)
1222 return $
CYFunctionParameter($
CYDeclaration(typed_
->identifier_
?: context
.Unique()), next_
->Parameters(context
));
1225 CYExpression
*CYTypedParameter::TypeSignature(CYContext
&context
, CYExpression
*prefix
) { $
T(prefix
)
1226 return next_
->TypeSignature(context
, $
CYAdd(prefix
, typed_
->Replace(context
)));
1229 CYForInitializer
*CYVar::Replace(CYContext
&context
) {
1230 if (CYExpression
*expression
= declarations_
->Replace(context
, CYIdentifierVariable
))
1231 return $
E(expression
);
1235 CYTarget
*CYVariable::Replace(CYContext
&context
) {
1236 name_
= name_
->Replace(context
, CYIdentifierGlobal
);
1240 CYFunctionParameter
*CYVariable::Parameter() const {
1241 return $
CYFunctionParameter($
CYDeclaration(name_
));
1244 CYStatement
*CYWhile::Replace(CYContext
&context
) {
1245 context
.Replace(test_
);
1246 context
.ReplaceAll(code_
);
1250 CYStatement
*CYWith::Replace(CYContext
&context
) {
1251 context
.Replace(scope_
);
1252 CYScope
scope(true, context
);
1254 context
.ReplaceAll(code_
);
1255 scope
.Close(context
);
1259 CYExpression
*CYWord::PropertyName(CYContext
&context
) {