1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 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 CYForEach (element
, elements_
)
105 element
->Replace(context
);
109 CYTarget
*CYArrayComprehension::Replace(CYContext
&context
) {
110 CYIdentifier
*cyv(context
.Unique());
112 return $
C0($
F(NULL
, $
P1($
B(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 // XXX: this is a horrible hack but I'm a month over schedule :(
121 if (CYSubscriptMember
*subscript
= dynamic_cast<CYSubscriptMember
*>(lhs_
))
122 return $
C2($
M(subscript
->object_
, $
S("$cys")), subscript
->property_
, rhs_
);
123 context
.Replace(lhs_
);
124 context
.Replace(rhs_
);
128 CYTarget
*CYAttemptMember::Replace(CYContext
&context
) {
129 CYIdentifier
*value(context
.Unique());
131 return $
C1($
F(NULL
, $
P1($
B(value
)), $$
132 ->* $
CYReturn($
CYCondition($
V(value
), $
M($
V(value
), property_
), $
V(value
)))
136 CYStatement
*CYBlock::Return() {
137 CYImplicitReturn(code_
);
141 CYStatement
*CYBlock::Replace(CYContext
&context
) {
142 CYScope
scope(true, context
);
143 context
.ReplaceAll(code_
);
144 scope
.Close(context
);
151 CYStatement
*CYBreak::Replace(CYContext
&context
) {
155 CYTarget
*CYCall::Replace(CYContext
&context
) {
156 // XXX: this also is a horrible hack but I'm still a month over schedule :(
157 if (CYAttemptMember
*member
= dynamic_cast<CYAttemptMember
*>(function_
)) {
158 CYIdentifier
*value(context
.Unique());
160 return $
C1($
F(NULL
, $
P1($
B(value
)), $$
161 ->* $
CYReturn($
CYCondition($
V(value
), $
C($
M($
V(value
), member
->property_
), arguments_
), $
V(value
)))
165 context
.Replace(function_
);
166 arguments_
->Replace(context
);
173 void Catch::Replace(CYContext
&context
) { $
T()
174 CYScope
scope(true, context
);
176 name_
= name_
->Replace(context
, CYIdentifierCatch
);
178 context
.ReplaceAll(code_
);
179 scope
.Close(context
);
184 CYTarget
*CYClassExpression::Replace(CYContext
&context
) {
187 CYIdentifier
*super(context
.Unique());
189 CYIdentifier
*old(context
.super_
);
190 context
.super_
= super
;
192 CYIdentifier
*constructor(context
.Unique());
193 CYForEach (member
, tail_
->static_
)
194 member
->Replace(context
, builder
, $
V(constructor
), true);
196 CYIdentifier
*prototype(context
.Unique());
197 CYForEach (member
, tail_
->instance_
)
198 member
->Replace(context
, builder
, $
V(prototype
), true);
200 if (tail_
->constructor_
== NULL
)
201 tail_
->constructor_
= $
CYFunctionExpression(NULL
, NULL
, NULL
);
202 tail_
->constructor_
->name_
= name_
;
203 tail_
->constructor_
= CYSuperize(context
, tail_
->constructor_
);
205 context
.super_
= old
;
207 return $
C1($
CYFunctionExpression(NULL
, $
P($
B(super
)), $$
208 ->* $
CYVar($
B1($
B(constructor
, tail_
->constructor_
)))
209 ->* $
CYVar($
B1($
B(prototype
, $
CYFunctionExpression(NULL
, NULL
, NULL
))))
210 ->* $
E($
CYAssign($
M($
V(prototype
), $
S("prototype")), $
M($
V(super
), $
S("prototype"))))
211 ->* $
E($
CYAssign($
V(prototype
), $
N($
V(prototype
))))
212 ->* CYDefineProperty($
V(prototype
), $
S("constructor"), false, false, $
CYPropertyValue($
S("value"), $
V(constructor
)))
213 ->* $
CYVar(builder
.bindings_
)
214 ->* builder
.statements_
215 ->* CYDefineProperty($
V(constructor
), $
S("prototype"), false, false, $
CYPropertyValue($
S("value"), $
V(prototype
)))
216 ->* $
CYReturn($
V(constructor
))
217 ), tail_
->extends_
?: $
V($
I("Object")));
220 CYStatement
*CYClassStatement::Replace(CYContext
&context
) {
221 return $
CYVar($
B1($
B(name_
, $
CYClassExpression(name_
, tail_
))));
224 void CYClause::Replace(CYContext
&context
) { $
T()
225 context
.Replace(value_
);
226 context
.ReplaceAll(code_
);
227 next_
->Replace(context
);
230 CYExpression
*CYCompound::Replace(CYContext
&context
) {
231 context
.Replace(expression_
);
232 context
.Replace(next_
);
234 if (CYCompound
*compound
= dynamic_cast<CYCompound
*>(expression_
)) {
235 expression_
= compound
->expression_
;
236 compound
->expression_
= compound
->next_
;
237 compound
->next_
= next_
;
244 CYFunctionParameter
*CYCompound::Parameter() const {
245 CYFunctionParameter
*next(next_
->Parameter());
249 CYFunctionParameter
*parameter(expression_
->Parameter());
250 if (parameter
== NULL
)
253 parameter
->SetNext(next
);
257 CYFunctionParameter
*CYComprehension::Parameters(CYContext
&context
) const { $
T(NULL
)
258 CYFunctionParameter
*next(next_
->Parameters(context
));
259 if (CYFunctionParameter
*parameter
= Parameter(context
)) {
260 parameter
->SetNext(next
);
266 CYStatement
*CYComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
267 return next_
== NULL
? statement
: next_
->Replace(context
, statement
);
270 CYExpression
*CYComputed::PropertyName(CYContext
&context
) {
274 CYExpression
*CYCondition::Replace(CYContext
&context
) {
275 context
.Replace(test_
);
276 context
.Replace(true_
);
277 context
.Replace(false_
);
281 void CYContext::NonLocal(CYStatement
*&statements
) {
282 CYContext
&context(*this);
284 if (nextlocal_
!= NULL
&& nextlocal_
->identifier_
!= NULL
) {
285 CYIdentifier
*cye($
I("$cye")->Replace(context
, CYIdentifierGlobal
));
286 CYIdentifier
*unique(nextlocal_
->identifier_
->Replace(context
, CYIdentifierGlobal
));
288 CYStatement
*declare(
289 $
CYVar($
B1($
B(unique
, $
CYObject()))));
291 cy::Syntax::Catch
*rescue(
292 $
cy::Syntax::Catch(cye
, $$
293 ->* $
CYIf($
CYIdentical($
M($
V(cye
), $
S("$cyk")), $
V(unique
)), $$
294 ->* $
CYReturn($
M($
V(cye
), $
S("$cyv"))))
295 ->* $
cy::Syntax::Throw($
V(cye
))));
297 context
.Replace(declare
);
298 rescue
->Replace(context
);
302 ->* $
cy::Syntax::Try(statements
, rescue
, NULL
);
306 CYIdentifier
*CYContext::Unique() {
307 return $
CYIdentifier($pool
.strcat("$cy", $pool
.itoa(unique_
++), NULL
));
310 CYStatement
*CYContinue::Replace(CYContext
&context
) {
314 CYStatement
*CYDebugger::Replace(CYContext
&context
) {
318 CYTarget
*CYBinding::Target(CYContext
&context
) {
319 return $
V(identifier_
);
322 CYAssignment
*CYBinding::Replace(CYContext
&context
, CYIdentifierKind kind
) {
323 identifier_
= identifier_
->Replace(context
, kind
);
325 if (initializer_
== NULL
)
328 CYAssignment
*value($
CYAssign(Target(context
), initializer_
));
333 CYExpression
*CYBindings::Replace(CYContext
&context
, CYIdentifierKind kind
) { $
T(NULL
)
334 CYAssignment
*assignment(binding_
->Replace(context
, kind
));
335 CYExpression
*compound(next_
->Replace(context
, kind
));
337 if (assignment
!= NULL
)
338 if (compound
== NULL
)
339 compound
= assignment
;
341 compound
= $
CYCompound(assignment
, compound
);
345 CYFunctionParameter
*CYBindings::Parameter(CYContext
&context
) { $
T(NULL
)
346 return $
CYFunctionParameter($
CYBinding(binding_
->identifier_
), next_
->Parameter(context
));
349 CYArgument
*CYBindings::Argument(CYContext
&context
) { $
T(NULL
)
350 return $
CYArgument(binding_
->initializer_
, next_
->Argument(context
));
353 CYTarget
*CYDirectMember::Replace(CYContext
&context
) {
354 context
.Replace(object_
);
355 context
.Replace(property_
);
359 CYStatement
*CYDoWhile::Replace(CYContext
&context
) {
360 context
.Replace(test_
);
361 context
.ReplaceAll(code_
);
365 void CYElementSpread::Replace(CYContext
&context
) {
366 context
.Replace(value_
);
369 void CYElementValue::Replace(CYContext
&context
) {
370 context
.Replace(value_
);
373 CYForInitializer
*CYEmpty::Replace(CYContext
&context
) {
377 CYTarget
*CYEncodedType::Replace(CYContext
&context
) {
378 return typed_
->Replace(context
);
381 CYTarget
*CYEval::Replace(CYContext
&context
) {
382 context
.scope_
->Damage();
383 if (arguments_
!= NULL
)
384 arguments_
->value_
= $
C1($
M($
V("Cycript"), $
S("compile")), arguments_
->value_
);
385 return $
C($
V("eval"), arguments_
);
388 CYStatement
*CYExpress::Return() {
389 return $
CYReturn(expression_
);
392 CYForInitializer
*CYExpress::Replace(CYContext
&context
) {
393 context
.Replace(expression_
);
397 CYTarget
*CYExpression::AddArgument(CYContext
&context
, CYExpression
*value
) {
398 return $
C1(this, value
);
401 CYFunctionParameter
*CYExpression::Parameter() const {
405 CYTarget
*CYExtend::Replace(CYContext
&context
) {
406 return object_
.Replace(context
, lhs_
);
409 CYStatement
*CYExternalDefinition::Replace(CYContext
&context
) {
410 return $
E($
CYAssign($
V(name_
), $
CYExternalExpression(abi_
, type_
, name_
)));
413 CYTarget
*CYExternalExpression::Replace(CYContext
&context
) {
414 CYExpression
*expression(name_
->Number(context
));
415 if (expression
== NULL
)
416 expression
= $
C2($
V("dlsym"), $
V("RTLD_DEFAULT"), name_
->PropertyName(context
));
417 return $
C1(type_
->Replace(context
), expression
);
420 CYNumber
*CYFalse::Number(CYContext
&context
) {
424 CYString
*CYFalse::String(CYContext
&context
) {
428 CYExpression
*CYFatArrow::Replace(CYContext
&context
) {
429 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
430 function
->this_
.SetNext(context
.this_
);
434 void CYFinally::Replace(CYContext
&context
) { $
T()
435 CYScope
scope(true, context
);
436 context
.ReplaceAll(code_
);
437 scope
.Close(context
);
440 CYStatement
*CYFor::Replace(CYContext
&context
) {
441 CYScope
outer(true, context
);
442 context
.Replace(initializer_
);
444 context
.Replace(test_
);
447 CYScope
inner(true, context
);
448 context
.ReplaceAll(code_
);
449 inner
.Close(context
);
452 context
.Replace(increment_
);
454 outer
.Close(context
);
458 CYStatement
*CYForLexical::Initialize(CYContext
&context
, CYExpression
*value
) {
460 if (binding_
->initializer_
== NULL
)
462 value
= binding_
->initializer_
;
465 return $
CYLexical(constant_
, $
B1($
CYBinding(binding_
->identifier_
, value
)));
468 CYTarget
*CYForLexical::Replace(CYContext
&context
) {
469 _assert(binding_
->Replace(context
, CYIdentifierLexical
) == NULL
);
470 return binding_
->Target(context
);
473 CYStatement
*CYForIn::Replace(CYContext
&context
) {
474 CYScope
scope(true, context
);
475 context
.Replace(initializer_
);
476 context
.Replace(iterable_
);
477 context
.ReplaceAll(code_
);
478 scope
.Close(context
);
482 CYStatement
*CYForInitialized::Replace(CYContext
&context
) {
483 CYAssignment
*assignment(binding_
->Replace(context
, CYIdentifierVariable
));
485 ->* (assignment
== NULL
? NULL
: $
CYExpress(assignment
))
486 ->* $
CYForIn(binding_
->Target(context
), iterable_
, code_
));
489 CYFunctionParameter
*CYForInComprehension::Parameter(CYContext
&context
) const {
490 return $
CYFunctionParameter(binding_
);
493 CYStatement
*CYForInComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
494 return $
CYForIn(binding_
->Target(context
), iterable_
, CYComprehension::Replace(context
, statement
));
497 CYStatement
*CYForOf::Replace(CYContext
&context
) {
498 CYIdentifier
*item(context
.Unique()), *list(context
.Unique());
501 ->* initializer_
->Initialize(context
, NULL
)
502 ->* $
CYLexical(false, $
B2($
B(list
, iterable_
), $
B(item
)))
503 ->* $
CYForIn($
V(item
), $
V(list
), $
CYBlock($$
504 ->* initializer_
->Initialize(context
, $
M($
V(list
), $
V(item
)))
509 CYFunctionParameter
*CYForOfComprehension::Parameter(CYContext
&context
) const {
510 return $
CYFunctionParameter(binding_
);
513 CYStatement
*CYForOfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
514 CYIdentifier
*cys(context
.Unique());
517 ->* $
CYLexical(false, $
B1($
B(cys
, iterable_
)))
518 ->* $
CYForIn(binding_
->Target(context
), $
V(cys
), $
CYBlock($$
519 ->* $
E($
CYAssign(binding_
->Target(context
), $
M($
V(cys
), binding_
->Target(context
))))
520 ->* CYComprehension::Replace(context
, statement
)
524 CYStatement
*CYForVariable::Initialize(CYContext
&context
, CYExpression
*value
) {
526 if (binding_
->initializer_
== NULL
)
528 value
= binding_
->initializer_
;
531 return $
CYVar($
B1($
CYBinding(binding_
->identifier_
, value
)));
534 CYTarget
*CYForVariable::Replace(CYContext
&context
) {
535 _assert(binding_
->Replace(context
, CYIdentifierVariable
) == NULL
);
536 return binding_
->Target(context
);
539 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
540 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
541 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
543 void CYFunction::Replace(CYContext
&context
) {
544 CYThisScope
*_this(context
.this_
);
545 context
.this_
= &this_
;
546 context
.this_
= CYGetLast(context
.this_
);
548 CYIdentifier
*super(context
.super_
);
549 context
.super_
= super_
;
551 CYNonLocal
*nonlocal(context
.nonlocal_
);
552 CYNonLocal
*nextlocal(context
.nextlocal_
);
555 if (nonlocal_
!= NULL
) {
557 context
.nonlocal_
= nonlocal_
;
560 nonlocal_
= $
CYNonLocal();
561 context
.nextlocal_
= nonlocal_
;
564 CYScope
scope(!localize
, context
);
566 $
I("arguments")->Replace(context
, CYIdentifierMagic
);
568 parameters_
->Replace(context
, code_
);
570 context
.ReplaceAll(code_
);
573 CYImplicitReturn(code_
);
575 if (CYIdentifier
*identifier
= this_
.identifier_
) {
576 context
.scope_
->Declare(context
, identifier
, CYIdentifierVariable
);
578 ->* $
E($
CYAssign($
V(identifier
), $
CYThis()))
583 context
.NonLocal(code_
);
585 context
.nextlocal_
= nextlocal
;
586 context
.nonlocal_
= nonlocal
;
588 context
.super_
= super
;
589 context
.this_
= _this
;
591 scope
.Close(context
, code_
);
594 CYTarget
*CYFunctionExpression::Replace(CYContext
&context
) {
595 CYScope
scope(false, context
);
597 name_
= name_
->Replace(context
, CYIdentifierOther
);
599 CYFunction::Replace(context
);
600 scope
.Close(context
);
604 void CYFunctionParameter::Replace(CYContext
&context
, CYStatement
*&statements
) { $
T()
605 CYAssignment
*assignment(binding_
->Replace(context
, CYIdentifierArgument
));
607 next_
->Replace(context
, statements
);
609 if (assignment
!= NULL
)
611 ->* $
CYIf($
CYIdentical($
CYTypeOf(binding_
->Target(context
)), $
S("undefined")), $$
616 CYStatement
*CYFunctionStatement::Replace(CYContext
&context
) {
617 name_
= name_
->Replace(context
, CYIdentifierOther
);
618 CYFunction::Replace(context
);
622 CYIdentifier
*CYIdentifier::Replace(CYContext
&context
, CYIdentifierKind kind
) {
626 return next_
->Replace(context
, kind
);
627 next_
= context
.scope_
->Declare(context
, this, kind
)->identifier_
;
631 CYStatement
*CYIf::Return() {
632 CYImplicitReturn(true_
);
633 CYImplicitReturn(false_
);
637 CYStatement
*CYIf::Replace(CYContext
&context
) {
638 context
.Replace(test_
);
639 context
.ReplaceAll(true_
);
640 context
.ReplaceAll(false_
);
644 CYFunctionParameter
*CYIfComprehension::Parameter(CYContext
&context
) const {
648 CYStatement
*CYIfComprehension::Replace(CYContext
&context
, CYStatement
*statement
) const {
649 return $
CYIf(test_
, CYComprehension::Replace(context
, statement
));
652 CYStatement
*CYImport::Replace(CYContext
&context
) {
653 return $
CYVar($
B1($
B($
I(module_
->part_
->Word()), $
C1($
V("require"), module_
->Replace(context
, "/")))));
656 CYStatement
*CYImportDeclaration::Replace(CYContext
&context
) {
657 CYIdentifier
*module(context
.Unique());
659 CYList
<CYStatement
> statements
;
660 CYForEach (specifier
, specifiers_
)
661 statements
->*specifier
->Replace(context
, module);
664 ->* $
CYLexical(false, $
B1($
B(module, $
C1($
V("require"), module_
))))
668 CYStatement
*CYImportSpecifier::Replace(CYContext
&context
, CYIdentifier
*module) {
669 binding_
= binding_
->Replace(context
, CYIdentifierLexical
);
671 CYExpression
*import($
V(module));
673 import = $
M(import, $
S(name_
));
674 return $
E($
CYAssign($
V(binding_
), import));
677 CYTarget
*CYIndirect::Replace(CYContext
&context
) {
678 return $
M(rhs_
, $
S("$cyi"));
681 CYTarget
*CYIndirectMember::Replace(CYContext
&context
) {
682 return $
M($
CYIndirect(object_
), property_
);
685 CYExpression
*CYInfix::Replace(CYContext
&context
) {
686 context
.Replace(lhs_
);
687 context
.Replace(rhs_
);
691 CYStatement
*CYLabel::Replace(CYContext
&context
) {
692 context
.Replace(statement_
);
696 CYTarget
*CYLambda::Replace(CYContext
&context
) {
697 return $
N2($
V("Functor"), $
CYFunctionExpression(NULL
, parameters_
->Parameters(context
), code_
), parameters_
->TypeSignature(context
, typed_
->Replace(context
)));
700 CYForInitializer
*CYLexical::Replace(CYContext
&context
) {
701 if (CYExpression
*expression
= bindings_
->Replace(context
, CYIdentifierLexical
))
702 return $
E(expression
);
706 CYFunctionExpression
*CYMethod::Constructor() {
710 void CYMethod::Replace(CYContext
&context
) {
711 CYFunction::Replace(context
);
714 CYString
*CYModule::Replace(CYContext
&context
, const char *separator
) const {
716 return $
CYString(part_
);
717 return $
CYString($pool
.strcat(next_
->Replace(context
, separator
)->Value(), separator
, part_
->Word(), NULL
));
720 CYExpression
*CYMultiply::Replace(CYContext
&context
) {
721 CYInfix::Replace(context
);
723 if (CYNumber
*lhn
= lhs_
->Number(context
))
724 if (CYNumber
*rhn
= rhs_
->Number(context
))
725 return $
D(lhn
->Value() * rhn
->Value());
733 CYTarget
*New::AddArgument(CYContext
&context
, CYExpression
*value
) {
734 CYSetLast(arguments_
) = $
CYArgument(value
);
738 CYTarget
*New::Replace(CYContext
&context
) {
739 context
.Replace(constructor_
);
740 arguments_
->Replace(context
);
746 CYNumber
*CYNull::Number(CYContext
&context
) {
750 CYString
*CYNull::String(CYContext
&context
) {
754 CYNumber
*CYNumber::Number(CYContext
&context
) {
758 CYString
*CYNumber::String(CYContext
&context
) {
759 // XXX: there is a precise algorithm for this
760 return $
S($pool
.sprintf(24, "%.17g", Value()));
763 CYExpression
*CYNumber::PropertyName(CYContext
&context
) {
764 return String(context
);
767 CYTarget
*CYObject::Replace(CYContext
&context
, CYTarget
*seed
) {
769 if (properties_
!= NULL
)
770 properties_
= properties_
->ReplaceAll(context
, builder
, $
CYThis(), seed
!= this);
773 return $
C1($
M($
CYFunctionExpression(NULL
, builder
.bindings_
->Parameter(context
),
775 ->* $
CYReturn($
CYThis())
776 ), $
S("call")), seed
, builder
.bindings_
->Argument(context
));
779 CYForEach (property
, properties_
)
780 property
->Replace(context
);
784 CYTarget
*CYObject::Replace(CYContext
&context
) {
785 return Replace(context
, this);
788 CYTarget
*CYParenthetical::Replace(CYContext
&context
) {
789 // XXX: return expression_;
790 context
.Replace(expression_
);
794 CYExpression
*CYPostfix::Replace(CYContext
&context
) {
795 context
.Replace(lhs_
);
799 CYExpression
*CYPrefix::Replace(CYContext
&context
) {
800 context
.Replace(rhs_
);
804 CYProperty
*CYProperty::ReplaceAll(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool update
) {
807 Replace(context
, builder
, self
, false);
809 next_
= next_
->ReplaceAll(context
, builder
, self
, update
);
810 return update
? next_
: this;
813 void CYProperty::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, bool protect
) {
814 CYExpression
*name(name_
->PropertyName(context
));
815 if (name_
->Computed()) {
816 CYIdentifier
*unique(context
.Unique());
818 ->* $
B1($
B(unique
, name
));
822 Replace(context
, builder
, self
, name
, protect
);
825 bool CYProperty::Update() const {
826 return name_
->Computed();
829 void CYPropertyGetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
830 CYIdentifier
*unique(context
.Unique());
832 ->* $
B1($
B(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
834 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("get"), $
V(unique
)));
837 CYFunctionExpression
*CYPropertyMethod::Constructor() {
838 return name_
->Constructor() ? $
CYFunctionExpression(NULL
, parameters_
, code_
) : NULL
;
841 void CYPropertyMethod::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
842 CYIdentifier
*unique(context
.Unique());
844 ->* $
B1($
B(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
846 ->* (!protect
? $
E($
CYAssign($
M(self
, name
), $
V(unique
))) :
847 CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("value"), $
V(unique
), $
CYPropertyValue($
S("writable"), $
CYTrue()))));
850 bool CYPropertyMethod::Update() const {
854 void CYPropertySetter::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
855 CYIdentifier
*unique(context
.Unique());
857 ->* $
B1($
B(unique
, CYSuperize(context
, $
CYFunctionExpression(NULL
, parameters_
, code_
))));
859 ->* CYDefineProperty(self
, name
, true, !protect
, $
CYPropertyValue($
S("set"), $
V(unique
)));
862 void CYPropertyValue::Replace(CYContext
&context
, CYBuilder
&builder
, CYExpression
*self
, CYExpression
*name
, bool protect
) {
864 CYIdentifier
*unique(context
.Unique());
866 ->* $
B1($
B(unique
, value_
));
868 ->* $
E($
CYAssign($
M(self
, name
), $
V(unique
)));
871 void CYPropertyValue::Replace(CYContext
&context
) {
872 context
.Replace(value_
);
875 void CYScript::Replace(CYContext
&context
) {
876 CYScope
scope(false, context
);
877 context
.scope_
->Damage();
879 context
.nextlocal_
= $
CYNonLocal();
880 context
.ReplaceAll(code_
);
881 context
.NonLocal(code_
);
883 scope
.Close(context
, code_
);
887 for (std::vector
<CYIdentifier
*>::const_iterator
i(context
.replace_
.begin()); i
!= context
.replace_
.end(); ++i
) {
889 if (context
.options_
.verbose_
)
890 name
= $pool
.strcat("$", $pool
.itoa(offset
++), NULL
);
896 unsigned position(7), local(offset
++ + 1);
899 unsigned index(local
% (sizeof(MappingSet
) - 1));
900 local
/= sizeof(MappingSet
) - 1;
901 id
[--position
] = MappingSet
[index
];
902 } while (local
!= 0);
904 if (scope
.Lookup(context
, id
+ position
) != NULL
)
906 // XXX: at some point, this could become a keyword
908 name
= $pool
.strmemdup(id
+ position
, 7 - position
);
911 CYIdentifier
*identifier(*i
);
912 _assert(identifier
->next_
== identifier
);
913 identifier
->next_
= $
I(name
);
917 CYTarget
*CYResolveMember::Replace(CYContext
&context
) {
918 return $
M($
M(object_
, $
S("$cyr")), property_
);
921 CYStatement
*CYReturn::Replace(CYContext
&context
) {
922 if (context
.nonlocal_
!= NULL
) {
923 CYProperty
*value(value_
== NULL
? NULL
: $
CYPropertyValue($
S("$cyv"), value_
));
924 return $
cy::Syntax::Throw($
CYObject(
925 $
CYPropertyValue($
S("$cyk"), $
V(context
.nonlocal_
->Target(context
)), value
)
929 context
.Replace(value_
);
933 CYTarget
*CYRubyBlock::Replace(CYContext
&context
) {
934 return lhs_
->AddArgument(context
, proc_
->Replace(context
));
937 CYTarget
*CYRubyBlock::AddArgument(CYContext
&context
, CYExpression
*value
) {
938 return Replace(context
)->AddArgument(context
, value
);
941 CYTarget
*CYRubyProc::Replace(CYContext
&context
) {
942 CYFunctionExpression
*function($
CYFunctionExpression(NULL
, parameters_
, code_
));
943 function
= CYNonLocalize(context
, function
);
944 function
->implicit_
= true;
948 CYScope::CYScope(bool transparent
, CYContext
&context
) :
949 transparent_(transparent
),
950 parent_(context
.scope_
),
955 _assert(!transparent_
|| parent_
!= NULL
);
956 context
.scope_
= this;
959 void CYScope::Damage() {
965 CYIdentifierFlags
*CYScope::Lookup(CYContext
&context
, const char *word
) {
966 CYForEach (i
, internal_
)
967 if (strcmp(i
->identifier_
->Word(), word
) == 0)
972 CYIdentifierFlags
*CYScope::Lookup(CYContext
&context
, CYIdentifier
*identifier
) {
973 return Lookup(context
, identifier
->Word());
976 CYIdentifierFlags
*CYScope::Declare(CYContext
&context
, CYIdentifier
*identifier
, CYIdentifierKind kind
) {
977 _assert(identifier
->next_
== NULL
|| identifier
->next_
== identifier
);
979 CYIdentifierFlags
*existing(Lookup(context
, identifier
));
980 if (existing
== NULL
)
981 internal_
= $
CYIdentifierFlags(identifier
, kind
, internal_
);
983 if (existing
== NULL
)
986 if (kind
== CYIdentifierGlobal
);
987 else if (existing
->kind_
== CYIdentifierGlobal
|| existing
->kind_
== CYIdentifierMagic
)
988 existing
->kind_
= kind
;
989 else if (existing
->kind_
== CYIdentifierLexical
|| kind
== CYIdentifierLexical
)
991 else if (transparent_
&& existing
->kind_
== CYIdentifierArgument
&& kind
== CYIdentifierVariable
)
993 // XXX: throw new SyntaxError() instead of these asserts
998 void CYScope::Merge(CYContext
&context
, const CYIdentifierFlags
*flags
) {
999 _assert(flags
->identifier_
->next_
== flags
->identifier_
);
1000 CYIdentifierFlags
*existing(Declare(context
, flags
->identifier_
, flags
->kind_
));
1001 flags
->identifier_
->next_
= existing
->identifier_
;
1003 existing
->count_
+= flags
->count_
;
1004 if (existing
->offset_
< flags
->offset_
)
1005 existing
->offset_
= flags
->offset_
;
1008 void CYScope::Close(CYContext
&context
, CYStatement
*&statements
) {
1011 CYList
<CYBindings
> bindings
;
1013 CYForEach (i
, internal_
)
1014 if (i
->kind_
== CYIdentifierVariable
)
1016 ->* $
CYBindings($
CYBinding(i
->identifier_
));
1019 CYVar
*var($
CYVar(bindings
));
1020 var
->SetNext(statements
);
1025 void CYScope::Close(CYContext
&context
) {
1026 context
.scope_
= parent_
;
1028 CYForEach (i
, internal_
) {
1029 _assert(i
->identifier_
->next_
== i
->identifier_
);
1031 case CYIdentifierLexical
: {
1033 CYIdentifier
*replace(context
.Unique());
1034 replace
->next_
= replace
;
1035 i
->identifier_
->next_
= replace
;
1036 i
->identifier_
= replace
;
1040 i
->kind_
= CYIdentifierVariable
;
1042 parent_
->Declare(context
, i
->identifier_
, CYIdentifierVariable
);
1045 case CYIdentifierVariable
: {
1047 parent_
->Declare(context
, i
->identifier_
, i
->kind_
);
1048 i
->kind_
= CYIdentifierGlobal
;
1056 typedef std::multimap
<unsigned, CYIdentifier
*> CYIdentifierOffsetMap
;
1057 CYIdentifierOffsetMap offsets
;
1059 CYForEach (i
, internal_
) {
1060 _assert(i
->identifier_
->next_
== i
->identifier_
);
1062 case CYIdentifierArgument
:
1063 case CYIdentifierVariable
:
1064 offsets
.insert(CYIdentifierOffsetMap::value_type(i
->offset_
, i
->identifier_
));
1070 for (CYIdentifierOffsetMap::const_iterator
i(offsets
.begin()); i
!= offsets
.end(); ++i
) {
1071 if (offset
< i
->first
)
1073 CYIdentifier
*identifier(i
->second
);
1075 if (offset
>= context
.replace_
.size())
1076 context
.replace_
.resize(offset
+ 1, NULL
);
1077 CYIdentifier
*&replace(context
.replace_
[offset
++]);
1079 if (replace
== NULL
)
1080 replace
= identifier
;
1082 _assert(replace
->next_
== replace
);
1083 identifier
->next_
= replace
;
1087 if (parent_
== NULL
)
1090 CYForEach (i
, internal_
) {
1092 case CYIdentifierGlobal
: {
1093 if (i
->offset_
< offset
)
1094 i
->offset_
= offset
;
1095 parent_
->Merge(context
, i
);
1100 CYTarget
*CYSubscriptMember::Replace(CYContext
&context
) {
1101 return $
C1($
M(object_
, $
S("$cyg")), property_
);
1104 CYElementValue
*CYSpan::Replace(CYContext
&context
) { $
T(NULL
)
1105 return $
CYElementValue(expression_
, $
CYElementValue(string_
, next_
->Replace(context
)));
1108 CYStatement
*CYStatement::Return() {
1112 CYString
*CYString::Concat(CYContext
&context
, CYString
*rhs
) const {
1113 size_t size(size_
+ rhs
->size_
);
1114 char *value($
char[size
+ 1]);
1115 memcpy(value
, value_
, size_
);
1116 memcpy(value
+ size_
, rhs
->value_
, rhs
->size_
);
1118 return $
S(value
, size
);
1121 CYIdentifier
*CYString::Identifier() const {
1122 if (const char *word
= Word())
1123 return $
CYIdentifier(word
);
1127 CYNumber
*CYString::Number(CYContext
&context
) {
1128 // XXX: there is a precise algorithm for this
1132 CYExpression
*CYString::PropertyName(CYContext
&context
) {
1136 CYString
*CYString::String(CYContext
&context
) {
1140 CYStatement
*CYStructDefinition::Replace(CYContext
&context
) {
1141 CYTarget
*target(tail_
->Replace(context
));
1143 target
= $
C1($
M(target
, $
S("withName")), $
S(name_
->Word()));
1144 return $
CYLexical(false, $
B1($
B($
I($pool
.strcat(name_
->Word(), "$cy", NULL
)), target
)));
1147 CYTarget
*CYStructTail::Replace(CYContext
&context
) {
1148 CYList
<CYElementValue
> types
;
1149 CYList
<CYElementValue
> names
;
1151 CYForEach (field
, fields_
) {
1152 types
->*$
CYElementValue(field
->type_
->Replace(context
));
1155 if (field
->name_
== NULL
)
1158 name
= field
->name_
->PropertyName(context
);
1159 names
->*$
CYElementValue(name
);
1162 return $
N2($
V("Type"), $
CYArray(types
), $
CYArray(names
));
1165 CYTarget
*CYSuperAccess::Replace(CYContext
&context
) {
1166 return $
C1($
M($
M($
M($
V(context
.super_
), $
S("prototype")), property_
), $
S("bind")), $
CYThis());
1169 CYTarget
*CYSuperCall::Replace(CYContext
&context
) {
1170 return $
C($
C1($
M($
V(context
.super_
), $
S("bind")), $
CYThis()), arguments_
);
1173 CYTarget
*CYSymbol::Replace(CYContext
&context
) {
1174 return $
C1($
M($
V("Symbol"), $
S("for")), $
S(name_
));
1177 CYStatement
*CYSwitch::Replace(CYContext
&context
) {
1178 context
.Replace(value_
);
1179 clauses_
->Replace(context
);
1183 CYStatement
*CYTarget::Initialize(CYContext
&context
, CYExpression
*value
) {
1186 return $
E($
CYAssign(this, value
));
1189 CYTarget
*CYTemplate::Replace(CYContext
&context
) {
1190 return $
C2($
M($
M($
M($
V("String"), $
S("prototype")), $
S("concat")), $
S("apply")), $
S(""), $
CYArray($
CYElementValue(string_
, spans_
->Replace(context
))));
1193 CYString
*CYTemplate::String(CYContext
&context
) {
1194 // XXX: implement this over local concat
1200 CYTarget
*CYThis::Replace(CYContext
&context
) {
1201 if (context
.this_
!= NULL
)
1202 return $
V(context
.this_
->Identifier(context
));
1209 CYStatement
*Throw::Replace(CYContext
&context
) {
1210 context
.Replace(value_
);
1216 CYTarget
*CYTrivial::Replace(CYContext
&context
) {
1220 CYNumber
*CYTrue::Number(CYContext
&context
) {
1224 CYString
*CYTrue::String(CYContext
&context
) {
1231 CYStatement
*Try::Replace(CYContext
&context
) {
1232 CYScope
scope(true, context
);
1233 context
.ReplaceAll(code_
);
1234 scope
.Close(context
);
1236 catch_
->Replace(context
);
1237 finally_
->Replace(context
);
1243 CYTarget
*CYTypeArrayOf::Replace_(CYContext
&context
, CYTarget
*type
) {
1244 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("arrayOf")), $
CYArgument(size_
)));
1247 CYTarget
*CYTypeBlockWith::Replace_(CYContext
&context
, CYTarget
*type
) {
1248 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("blockWith")), parameters_
->Argument(context
)));
1251 CYTarget
*CYTypeCharacter::Replace(CYContext
&context
) {
1253 case CYTypeNeutral
: return $
V("char");
1254 case CYTypeSigned
: return $
V("schar");
1255 case CYTypeUnsigned
: return $
V("uchar");
1256 default: _assert(false);
1260 CYTarget
*CYTypeConstant::Replace_(CYContext
&context
, CYTarget
*type
) {
1261 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("constant"))));
1264 CYStatement
*CYTypeDefinition::Replace(CYContext
&context
) {
1265 return $
CYLexical(false, $
B1($
B(name_
, $
CYTypeExpression(type_
))));
1268 CYTarget
*CYTypeEnum::Replace(CYContext
&context
) {
1269 CYList
<CYProperty
> properties
;
1270 CYForEach (constant
, constants_
)
1271 properties
->*$
CYPropertyValue($
S(constant
->name_
->Word()), constant
->value_
);
1272 CYObject
*constants($
CYObject(properties
));
1274 if (specifier_
== NULL
)
1275 return $
N1($
V("Type"), constants
);
1277 return $
C1($
M(specifier_
->Replace(context
), $
S("enumFor")), constants
);
1280 CYTarget
*CYTypeError::Replace(CYContext
&context
) {
1285 CYTarget
*CYTypeExpression::Replace(CYContext
&context
) {
1286 return typed_
->Replace(context
);
1289 CYTarget
*CYTypeFloating::Replace(CYContext
&context
) {
1291 case 0: return $
V("float");
1292 case 1: return $
V("double");
1293 case 2: return $
V("longdouble");
1294 default: _assert(false);
1298 CYTarget
*CYTypeInt128::Replace(CYContext
&context
) {
1299 return $
V(signing_
== CYTypeUnsigned
? "uint128" : "int128");
1302 CYTarget
*CYTypeIntegral::Replace(CYContext
&context
) {
1303 bool u(signing_
== CYTypeUnsigned
);
1305 case 0: return $
V(u
? "ushort" : "short");
1306 case 1: return $
V(u
? "uint" : "int");
1307 case 2: return $
V(u
? "ulong" : "long");
1308 case 3: return $
V(u
? "ulonglong" : "longlong");
1309 default: _assert(false);
1313 CYTarget
*CYTypeModifier::Replace(CYContext
&context
, CYTarget
*type
) { $
T(type
)
1314 return Replace_(context
, type
);
1317 CYTarget
*CYTypeFunctionWith::Replace_(CYContext
&context
, CYTarget
*type
) {
1318 CYList
<CYArgument
> arguments(parameters_
->Argument(context
));
1320 arguments
->*$
C_($
CYNull());
1321 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("functionWith")), arguments
));
1324 CYTarget
*CYTypePointerTo::Replace_(CYContext
&context
, CYTarget
*type
) {
1325 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("pointerTo"))));
1328 CYTarget
*CYTypeReference::Replace(CYContext
&context
) {
1331 case CYTypeReferenceStruct
: prefix
= "$cys"; break;
1332 case CYTypeReferenceEnum
: prefix
= "$cye"; break;
1333 default: _assert(false);
1336 return $
V($pool
.strcat(prefix
, name_
->Word(), NULL
));
1339 CYTarget
*CYTypeStruct::Replace(CYContext
&context
) {
1340 CYTarget
*target(tail_
->Replace(context
));
1342 target
= $
C1($
M(target
, $
S("withName")), $
S(name_
->Word()));
1346 CYTarget
*CYTypeVariable::Replace(CYContext
&context
) {
1350 CYTarget
*CYTypeVoid::Replace(CYContext
&context
) {
1351 return $
N1($
V("Type"), $
CYString("v"));
1354 CYTarget
*CYTypeVolatile::Replace_(CYContext
&context
, CYTarget
*type
) {
1355 return next_
->Replace(context
, $
CYCall($
CYDirectMember(type
, $
CYString("volatile"))));
1358 CYTarget
*CYType::Replace(CYContext
&context
) {
1359 return modifier_
->Replace(context
, specifier_
->Replace(context
));
1362 CYTypeFunctionWith
*CYType::Function() {
1363 CYTypeModifier
*&modifier(CYGetLast(modifier_
));
1364 if (modifier
== NULL
)
1367 CYTypeFunctionWith
*function(modifier
->Function());
1368 if (function
== NULL
)
1375 CYArgument
*CYTypedParameter::Argument(CYContext
&context
) { $
T(NULL
)
1376 return $
CYArgument(type_
->Replace(context
), next_
->Argument(context
));
1379 CYFunctionParameter
*CYTypedParameter::Parameters(CYContext
&context
) { $
T(NULL
)
1380 return $
CYFunctionParameter($
CYBinding(name_
?: context
.Unique()), next_
->Parameters(context
));
1383 CYExpression
*CYTypedParameter::TypeSignature(CYContext
&context
, CYExpression
*prefix
) { $
T(prefix
)
1384 return next_
->TypeSignature(context
, $
CYAdd(prefix
, type_
->Replace(context
)));
1387 CYForInitializer
*CYVar::Replace(CYContext
&context
) {
1388 if (CYExpression
*expression
= bindings_
->Replace(context
, CYIdentifierVariable
))
1389 return $
E(expression
);
1393 CYTarget
*CYVariable::Replace(CYContext
&context
) {
1394 name_
= name_
->Replace(context
, CYIdentifierGlobal
);
1398 CYFunctionParameter
*CYVariable::Parameter() const {
1399 return $
CYFunctionParameter($
CYBinding(name_
));
1402 CYStatement
*CYWhile::Replace(CYContext
&context
) {
1403 context
.Replace(test_
);
1404 context
.ReplaceAll(code_
);
1408 CYStatement
*CYWith::Replace(CYContext
&context
) {
1409 context
.Replace(scope_
);
1410 CYScope
scope(true, context
);
1412 context
.ReplaceAll(code_
);
1413 scope
.Close(context
);
1417 CYExpression
*CYWord::PropertyName(CYContext
&context
) {