]> git.saurik.com Git - cycript.git/blame - Replace.cpp
Massive changes to lexer to get template literals.
[cycript.git] / Replace.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c1d3e52e 2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
4644480a
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
4644480a 6/*
f95d2598
JF
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.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
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/>.
b3378a02 19**/
4644480a
JF
20/* }}} */
21
3b52fd1a 22#include "Parser.hpp"
6a981250 23#include "Replace.hpp"
3b52fd1a 24
3b52fd1a
JF
25#include <iomanip>
26
61fe0c53
JF
27CYFunctionExpression *CYNonLocalize(CYContext &context, CYFunctionExpression *function) {
28 function->nonlocal_ = context.nextlocal_;
29 return function;
30}
31
12e37ba3
JF
32static void CYImplicitReturn(CYStatement *&code) {
33 if (CYStatement *&last = CYGetLast(code))
34 last = last->Return();
35}
36
4644480a
JF
37CYExpression *CYAdd::Replace(CYContext &context) {
38 CYInfix::Replace(context);
39
fd5cdf97
JF
40 CYString *lhs(dynamic_cast<CYString *>(lhs_));
41 CYString *rhs(dynamic_cast<CYString *>(rhs_));
4644480a
JF
42
43 if (lhs != NULL || rhs != NULL) {
44 if (lhs == NULL) {
fd5cdf97 45 lhs = lhs_->String(context);
4644480a 46 if (lhs == NULL)
029bc65b 47 return this;
4644480a 48 } else if (rhs == NULL) {
fd5cdf97 49 rhs = rhs_->String(context);
4644480a 50 if (rhs == NULL)
029bc65b 51 return this;
4644480a
JF
52 }
53
54 return lhs->Concat(context, rhs);
55 }
56
fd5cdf97
JF
57 if (CYNumber *lhn = lhs_->Number(context))
58 if (CYNumber *rhn = rhs_->Number(context))
4644480a
JF
59 return $D(lhn->Value() + rhn->Value());
60
029bc65b 61 return this;
4644480a
JF
62}
63
3b52fd1a 64CYExpression *CYAddressOf::Replace(CYContext &context) {
3b52fd1a
JF
65 return $C0($M(rhs_, $S("$cya")));
66}
67
5192746c 68CYArgument *CYArgument::Replace(CYContext &context) { $T(NULL)
3b52fd1a 69 context.Replace(value_);
5192746c
JF
70 next_ = next_->Replace(context);
71
72 if (value_ == NULL) {
73 if (next_ == NULL)
74 return NULL;
75 else
76 value_ = $U;
77 }
78
79 return this;
3b52fd1a
JF
80}
81
82CYExpression *CYArray::Replace(CYContext &context) {
83 elements_->Replace(context);
029bc65b 84 return this;
3b52fd1a
JF
85}
86
87CYExpression *CYArrayComprehension::Replace(CYContext &context) {
88 CYVariable *cyv($V("$cyv"));
89
c8a0500b 90 return $C0($F(NULL, $P1($L("$cyv"), comprehensions_->Parameters(context)), $$->*
3b52fd1a
JF
91 $E($ CYAssign(cyv, $ CYArray()))->*
92 comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
93 $ CYReturn(cyv)
94 ));
95}
96
97CYExpression *CYAssignment::Replace(CYContext &context) {
98 context.Replace(lhs_);
99 context.Replace(rhs_);
029bc65b 100 return this;
3b52fd1a
JF
101}
102
12e37ba3
JF
103CYStatement *CYBlock::Return() {
104 CYImplicitReturn(code_);
105 return this;
106}
107
3b52fd1a 108CYStatement *CYBlock::Replace(CYContext &context) {
b0385401
JF
109 context.ReplaceAll(code_);
110 if (code_ == NULL)
029bc65b
JF
111 return $ CYEmpty();
112 return this;
3b52fd1a
JF
113}
114
115CYStatement *CYBreak::Replace(CYContext &context) {
029bc65b 116 return this;
3b52fd1a
JF
117}
118
6c093cce
JF
119CYExpression *CYCall::AddArgument(CYContext &context, CYExpression *value) {
120 CYArgument **argument(&arguments_);
121 while (*argument != NULL)
122 argument = &(*argument)->next_;
123 *argument = $ CYArgument(value);
124 return this;
125}
126
3b52fd1a
JF
127CYExpression *CYCall::Replace(CYContext &context) {
128 context.Replace(function_);
129 arguments_->Replace(context);
029bc65b 130 return this;
3b52fd1a
JF
131}
132
37954781
JF
133namespace cy {
134namespace Syntax {
135
136void Catch::Replace(CYContext &context) { $T()
50a3d79f 137 CYScope scope(true, context);
daf22a65
JF
138
139 context.Replace(name_);
140 context.scope_->Declare(context, name_, CYIdentifierCatch);
141
b0385401
JF
142 context.ReplaceAll(code_);
143 scope.Close(context, code_);
3b52fd1a
JF
144}
145
37954781
JF
146} }
147
3b52fd1a
JF
148void CYClause::Replace(CYContext &context) { $T()
149 context.Replace(case_);
b0385401 150 context.ReplaceAll(code_);
3b52fd1a
JF
151 next_->Replace(context);
152}
153
154CYExpression *CYCompound::Replace(CYContext &context) {
fd5cdf97
JF
155 context.Replace(expression_);
156 context.Replace(next_);
157
158 if (CYCompound *compound = dynamic_cast<CYCompound *>(expression_)) {
159 expression_ = compound->expression_;
160 compound->expression_ = compound->next_;
161 compound->next_ = next_;
162 next_ = compound;
163 }
164
9efd8b03 165 return this;
3b52fd1a
JF
166}
167
b0385401
JF
168CYFunctionParameter *CYCompound::Parameter() const {
169 CYFunctionParameter *next(next_->Parameter());
170 if (next == NULL)
e06e5ee1 171 return NULL;
0afc9ba3
JF
172
173 CYFunctionParameter *parameter(expression_->Parameter());
174 if (parameter == NULL)
175 return NULL;
176
177 parameter->SetNext(next);
178 return parameter;
179}
180
3b52fd1a
JF
181CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
182 CYFunctionParameter *next(next_->Parameters(context));
183 if (CYFunctionParameter *parameter = Parameter(context)) {
184 parameter->SetNext(next);
185 return parameter;
186 } else
187 return next;
188}
189
190CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
191 return next_ == NULL ? statement : next_->Replace(context, statement);
192}
193
194CYExpression *CYCondition::Replace(CYContext &context) {
195 context.Replace(test_);
196 context.Replace(true_);
197 context.Replace(false_);
029bc65b 198 return this;
3b52fd1a
JF
199}
200
ab2aa221
JF
201void CYContext::NonLocal(CYStatement *&statements) {
202 CYContext &context(*this);
203
06293152 204 if (nextlocal_ != NULL && nextlocal_->identifier_ != NULL) {
daf22a65
JF
205 CYIdentifier *cye($I("$cye")->Replace(context));
206 CYIdentifier *unique(nextlocal_->identifier_->Replace(context));
207
208 CYStatement *declare(
c8a0500b 209 $ CYVar($L1($ CYDeclaration(unique, $ CYObject()))));
daf22a65
JF
210
211 cy::Syntax::Catch *rescue(
212 $ cy::Syntax::Catch(cye, $$->*
4e58e244
JF
213 $ CYIf($ CYIdentical($M($V(cye), $S("$cyk")), $V(unique)), $$->*
214 $ CYReturn($M($V(cye), $S("$cyv"))))->*
215 $ cy::Syntax::Throw($V(cye))));
daf22a65 216
b0385401 217 // XXX: I don't understand any of this
577bfbfa 218 context.Replace(declare);
daf22a65 219 rescue->Replace(context);
ab2aa221
JF
220
221 statements = $$->*
daf22a65
JF
222 declare->*
223 $ cy::Syntax::Try(statements, rescue, NULL);
ab2aa221
JF
224 }
225}
226
227CYIdentifier *CYContext::Unique() {
0cbeddf8 228 return $ CYIdentifier($pool.strcat("$cy", $pool.itoa(unique_++), NULL));
ab2aa221
JF
229}
230
3b52fd1a 231CYStatement *CYContinue::Replace(CYContext &context) {
029bc65b
JF
232 return this;
233}
234
c8a0500b
JF
235CYStatement *CYDebugger::Replace(CYContext &context) {
236 return this;
237}
238
029bc65b 239CYAssignment *CYDeclaration::Assignment(CYContext &context) {
15b88a33
JF
240 if (initialiser_ == NULL)
241 return NULL;
127c1a9c
JF
242
243 CYAssignment *value($ CYAssign(Variable(context), initialiser_));
244 initialiser_ = NULL;
245 return value;
15b88a33
JF
246}
247
248CYVariable *CYDeclaration::Variable(CYContext &context) {
249 return $V(identifier_);
3b52fd1a
JF
250}
251
ad3b38bb 252CYStatement *CYDeclaration::ForEachIn(CYContext &context, CYExpression *value) {
c8a0500b 253 return $ CYVar($L1($ CYDeclaration(identifier_, value)));
3b52fd1a
JF
254}
255
029bc65b 256CYExpression *CYDeclaration::Replace(CYContext &context) {
15b88a33
JF
257 context.Replace(identifier_);
258 context.scope_->Declare(context, identifier_, CYIdentifierVariable);
259 return Variable(context);
260}
261
262void CYDeclarations::Replace(CYContext &context) { $T()
263 declaration_->Replace(context);
264 next_->Replace(context);
3b52fd1a
JF
265}
266
550ee46a 267CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
5192746c 268 return $ CYProperty(declaration_->identifier_, declaration_->initialiser_, next_->Property(context));
550ee46a
JF
269}
270
15b88a33 271CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL)
c8a0500b 272 return $ CYFunctionParameter($ CYDeclaration(declaration_->identifier_), next_->Parameter(context));
15b88a33
JF
273}
274
275CYArgument *CYDeclarations::Argument(CYContext &context) { $T(NULL)
5192746c 276 return $ CYArgument(declaration_->initialiser_, next_->Argument(context));
15b88a33
JF
277}
278
b0385401
JF
279CYExpression *CYDeclarations::Expression(CYContext &context) { $T(NULL)
280 CYExpression *compound(next_->Expression(context));
029bc65b 281 if (CYAssignment *assignment = declaration_->Assignment(context))
b0385401
JF
282 if (compound == NULL)
283 compound = assignment;
284 else
285 compound = $ CYCompound(assignment, compound);
029bc65b 286 return compound;
3b52fd1a
JF
287}
288
289CYExpression *CYDirectMember::Replace(CYContext &context) {
ca0f097f
JF
290 context.Replace(object_);
291 context.Replace(property_);
029bc65b 292 return this;
3b52fd1a
JF
293}
294
295CYStatement *CYDoWhile::Replace(CYContext &context) {
296 context.Replace(test_);
b0385401 297 context.ReplaceAll(code_);
029bc65b 298 return this;
3b52fd1a
JF
299}
300
301void CYElement::Replace(CYContext &context) { $T()
302 context.Replace(value_);
303 next_->Replace(context);
304}
305
306CYStatement *CYEmpty::Replace(CYContext &context) {
9cd63688 307 return NULL;
029bc65b
JF
308}
309
9a39f705
JF
310CYExpression *CYEncodedType::Replace(CYContext &context) {
311 return typed_->Replace(context);
312}
313
12e37ba3
JF
314CYStatement *CYExpress::Return() {
315 return $ CYReturn(expression_);
316}
317
720a57a8 318CYStatement *CYExpress::Replace(CYContext &context) {
3b52fd1a 319 context.Replace(expression_);
029bc65b 320 return this;
3b52fd1a
JF
321}
322
6c093cce
JF
323CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value) {
324 return $C1(this, value);
325}
326
3b52fd1a
JF
327CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
328 return this;
329}
330
ad3b38bb
JF
331CYStatement *CYExpression::ForEachIn(CYContext &context, CYExpression *value) {
332 return $E($ CYAssign(this, value));
3b52fd1a
JF
333}
334
ae65d594
JF
335CYAssignment *CYExpression::Assignment(CYContext &context) {
336 return NULL;
337}
338
0afc9ba3
JF
339CYFunctionParameter *CYExpression::Parameter() const {
340 return NULL;
341}
342
c5587ed7
JF
343CYStatement *CYExternal::Replace(CYContext &context) {
344 return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word())))));
345}
346
4644480a
JF
347CYNumber *CYFalse::Number(CYContext &context) {
348 return $D(0);
349}
350
351CYString *CYFalse::String(CYContext &context) {
352 return $S("false");
353}
354
a0be43fc
JF
355CYExpression *CYFatArrow::Replace(CYContext &context) {
356 CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
357 function->this_.SetNext(context.this_);
358 return function;
359}
360
3b52fd1a 361void CYFinally::Replace(CYContext &context) { $T()
b0385401 362 context.ReplaceAll(code_);
3b52fd1a
JF
363}
364
365CYStatement *CYFor::Replace(CYContext &context) {
029bc65b 366 context.Replace(initialiser_);
3b52fd1a
JF
367 context.Replace(test_);
368 context.Replace(increment_);
b0385401 369 context.ReplaceAll(code_);
029bc65b 370 return this;
3b52fd1a
JF
371}
372
b0385401 373CYExpression *CYForDeclarations::Replace(CYContext &context) {
15b88a33 374 declarations_->Replace(context);
b0385401 375 return declarations_->Expression(context);
15b88a33
JF
376}
377
378// XXX: this still feels highly suboptimal
3b52fd1a 379CYStatement *CYForIn::Replace(CYContext &context) {
127c1a9c 380 if (CYAssignment *assignment = initialiser_->Assignment(context))
15b88a33
JF
381 return $ CYBlock($$->*
382 $E(assignment)->*
383 this
384 );
ae65d594 385
127c1a9c
JF
386 context.Replace(initialiser_);
387 context.Replace(set_);
b0385401 388 context.ReplaceAll(code_);
15b88a33 389 return this;
3b52fd1a
JF
390}
391
392CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
c8a0500b 393 return $ CYFunctionParameter($ CYDeclaration(name_));
3b52fd1a
JF
394}
395
396CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
4e58e244 397 return $ CYForIn($V(name_), set_, CYComprehension::Replace(context, statement));
3b52fd1a
JF
398}
399
d5618df7 400CYStatement *CYForOf::Replace(CYContext &context) {
04ea132d
JF
401 if (CYAssignment *assignment = initialiser_->Assignment(context))
402 return $ CYBlock($$->*
403 $E(assignment)->*
404 this
405 );
406
2eb8215d 407 CYIdentifier *cys($I("$cys")), *cyt($I("$cyt"));
3b52fd1a 408
c8a0500b 409 return $ CYLetStatement($L2($ CYDeclaration(cys, set_), $ CYDeclaration(cyt)), $$->*
2eb8215d 410 $ CYForIn($V(cyt), $V(cys), $ CYBlock($$->*
ad3b38bb 411 initialiser_->ForEachIn(context, $M($V(cys), $V(cyt)))->*
3b52fd1a
JF
412 code_
413 ))
550ee46a 414 );
3b52fd1a
JF
415}
416
d5618df7 417CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const {
c8a0500b 418 return $ CYFunctionParameter($ CYDeclaration(name_));
3b52fd1a
JF
419}
420
d5618df7 421CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const {
55c63f1d 422 CYIdentifier *cys($I("$cys"));
3b52fd1a 423
c8a0500b 424 return $E($C0($F(NULL, $P1($L("$cys")), $$->*
2eb8215d
JF
425 $E($ CYAssign($V(cys), set_))->*
426 $ CYForIn($V(name_), $V(cys), $ CYBlock($$->*
427 $E($ CYAssign($V(name_), $M($V(cys), $V(name_))))->*
3b52fd1a
JF
428 CYComprehension::Replace(context, statement)
429 ))
430 )));
431}
432
14ec9e00 433void CYFunction::Inject(CYContext &context) {
6a981250 434 context.Replace(name_);
a86e34d0 435 context.scope_->Declare(context, name_, CYIdentifierOther);
14ec9e00
JF
436}
437
438void CYFunction::Replace_(CYContext &context, bool outer) {
439 if (outer)
440 Inject(context);
441
a0be43fc 442 CYThisScope *_this(context.this_);
12e37ba3
JF
443 context.this_ = &this_;
444 context.this_ = CYGetLast(context.this_);
a0be43fc 445
06293152
JF
446 CYNonLocal *nonlocal(context.nonlocal_);
447 CYNonLocal *nextlocal(context.nextlocal_);
448
ab2aa221 449 bool localize;
06293152 450 if (nonlocal_ != NULL) {
ab2aa221 451 localize = false;
06293152
JF
452 context.nonlocal_ = nonlocal_;
453 } else {
ab2aa221
JF
454 localize = true;
455 nonlocal_ = $ CYNonLocal();
06293152 456 context.nextlocal_ = nonlocal_;
ab2aa221
JF
457 }
458
50a3d79f 459 CYScope scope(!localize, context);
61fe0c53 460
14ec9e00
JF
461 if (!outer && name_ != NULL)
462 Inject(context);
463
c8a0500b 464 parameters_->Replace(context, code_);
b0385401 465 context.ReplaceAll(code_);
029bc65b 466
12e37ba3
JF
467 if (implicit_)
468 CYImplicitReturn(code_);
469
a0be43fc 470 if (CYIdentifier *identifier = this_.identifier_)
b0385401 471 code_ = $$->*
a0be43fc 472 $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
b0385401 473 code_;
a0be43fc 474
ab2aa221 475 if (localize)
b0385401 476 context.NonLocal(code_);
06293152
JF
477
478 context.nextlocal_ = nextlocal;
ab2aa221
JF
479 context.nonlocal_ = nonlocal;
480
a0be43fc
JF
481 context.this_ = _this;
482
b0385401 483 scope.Close(context, code_);
3b52fd1a
JF
484}
485
486CYExpression *CYFunctionExpression::Replace(CYContext &context) {
14ec9e00 487 Replace_(context, false);
029bc65b
JF
488 return this;
489}
490
b0385401 491void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements) { $T()
c8a0500b
JF
492 CYAssignment *assignment(initialiser_->Assignment(context));
493 context.Replace(initialiser_);
494
b0385401 495 next_->Replace(context, statements);
c8a0500b
JF
496
497 if (assignment != NULL)
b0385401
JF
498 statements = $$->*
499 // XXX: this cast is quite incorrect
500 $ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
501 $E(assignment)
502 )->*
503 statements;
3b52fd1a
JF
504}
505
506CYStatement *CYFunctionStatement::Replace(CYContext &context) {
14ec9e00 507 Replace_(context, true);
029bc65b
JF
508 return this;
509}
510
511CYIdentifier *CYIdentifier::Replace(CYContext &context) {
a846a8cd 512 if (replace_ != NULL && replace_ != this)
de9fc71b 513 return replace_->Replace(context);
a846a8cd 514 replace_ = context.scope_->Lookup(context, this);
a86e34d0 515 return replace_;
3b52fd1a
JF
516}
517
12e37ba3
JF
518CYStatement *CYIf::Return() {
519 CYImplicitReturn(true_);
520 CYImplicitReturn(false_);
521 return this;
522}
523
3b52fd1a
JF
524CYStatement *CYIf::Replace(CYContext &context) {
525 context.Replace(test_);
b0385401
JF
526 context.ReplaceAll(true_);
527 context.ReplaceAll(false_);
029bc65b 528 return this;
3b52fd1a
JF
529}
530
531CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
532 return NULL;
533}
534
535CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
536 return $ CYIf(test_, CYComprehension::Replace(context, statement));
537}
538
7b750785
JF
539CYStatement *CYImport::Replace(CYContext &context) {
540 return $ CYVar($L1($L(module_->part_->Word(), $C1($V("require"), module_->Replace(context, "/")))));
541}
542
3b52fd1a 543CYExpression *CYIndirect::Replace(CYContext &context) {
3b52fd1a
JF
544 return $M(rhs_, $S("$cyi"));
545}
546
547CYExpression *CYIndirectMember::Replace(CYContext &context) {
3b52fd1a
JF
548 return $M($ CYIndirect(object_), property_);
549}
550
551CYExpression *CYInfix::Replace(CYContext &context) {
552 context.Replace(lhs_);
553 context.Replace(rhs_);
029bc65b 554 return this;
3b52fd1a
JF
555}
556
557CYStatement *CYLabel::Replace(CYContext &context) {
558 context.Replace(statement_);
029bc65b 559 return this;
3b52fd1a
JF
560}
561
690cf1a8 562CYExpression *CYLambda::Replace(CYContext &context) {
b0385401 563 return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context)));
690cf1a8
JF
564}
565
c8a0500b 566CYStatement *CYLetStatement::Replace(CYContext &context) {
61fe0c53 567 return $E($ CYCall(CYNonLocalize(context, $ CYFunctionExpression(NULL, declarations_->Parameter(context), code_)), declarations_->Argument(context)));
550ee46a
JF
568}
569
7b750785
JF
570CYString *CYModule::Replace(CYContext &context, const char *separator) const {
571 if (next_ == NULL)
572 return $ CYString(part_);
573 return $ CYString($pool.strcat(next_->Replace(context, separator)->Value(), separator, part_->Word(), NULL));
574}
575
62f398e4
JF
576CYExpression *CYMultiply::Replace(CYContext &context) {
577 CYInfix::Replace(context);
578
fd5cdf97
JF
579 if (CYNumber *lhn = lhs_->Number(context))
580 if (CYNumber *rhn = rhs_->Number(context))
62f398e4
JF
581 return $D(lhn->Value() * rhn->Value());
582
583 return this;
584}
585
2eb8215d
JF
586namespace cy {
587namespace Syntax {
588
589CYExpression *New::AddArgument(CYContext &context, CYExpression *value) {
bf45251b 590 CYSetLast(arguments_) = $ CYArgument(value);
6c093cce
JF
591 return this;
592}
593
2eb8215d 594CYExpression *New::Replace(CYContext &context) {
3b52fd1a
JF
595 context.Replace(constructor_);
596 arguments_->Replace(context);
029bc65b 597 return this;
3b52fd1a
JF
598}
599
2eb8215d
JF
600} }
601
4644480a
JF
602CYNumber *CYNull::Number(CYContext &context) {
603 return $D(0);
604}
605
606CYString *CYNull::String(CYContext &context) {
607 return $S("null");
608}
609
610CYNumber *CYNumber::Number(CYContext &context) {
611 return this;
612}
613
614CYString *CYNumber::String(CYContext &context) {
615 // XXX: there is a precise algorithm for this
0cbeddf8 616 return $S($pool.sprintf(24, "%.17g", Value()));
4644480a
JF
617}
618
3b52fd1a
JF
619CYExpression *CYObject::Replace(CYContext &context) {
620 properties_->Replace(context);
029bc65b 621 return this;
3b52fd1a
JF
622}
623
b0385401
JF
624CYExpression *CYParenthetical::Replace(CYContext &context) {
625 return expression_;
626}
627
3b52fd1a
JF
628CYExpression *CYPostfix::Replace(CYContext &context) {
629 context.Replace(lhs_);
029bc65b 630 return this;
3b52fd1a
JF
631}
632
633CYExpression *CYPrefix::Replace(CYContext &context) {
634 context.Replace(rhs_);
029bc65b 635 return this;
3b52fd1a
JF
636}
637
10711823 638// XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
45d0c928 639#define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
10711823 640//#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
45d0c928 641
e013809d
JF
642namespace {
643 struct IdentifierUsageLess :
644 std::binary_function<CYIdentifier *, CYIdentifier *, bool>
645 {
646 _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const {
647 if (lhs->usage_ != rhs->usage_)
648 return lhs->usage_ > rhs->usage_;
649 return lhs < rhs;
650 }
651 };
652
653 typedef std::set<CYIdentifier *, IdentifierUsageLess> IdentifierUsages;
654}
655
a7d8b413 656void CYScript::Replace(CYContext &context) {
50a3d79f 657 CYScope scope(true, context);
ab2aa221 658
06293152 659 context.nextlocal_ = $ CYNonLocal();
b0385401
JF
660 context.ReplaceAll(code_);
661 context.NonLocal(code_);
ab2aa221 662
b0385401 663 scope.Close(context, code_);
14ec9e00
JF
664
665 size_t offset(0);
666
6a981250 667 CYCStringSet external;
a846a8cd 668 for (CYIdentifierValueSet::const_iterator i(scope.identifiers_.begin()); i != scope.identifiers_.end(); ++i)
6a981250
JF
669 external.insert((*i)->Word());
670
e013809d
JF
671 IdentifierUsages usages;
672
a846a8cd 673 if (offset < context.rename_.size())
c2c9f509
JF
674 CYForEach (i, context.rename_[offset].identifier_)
675 usages.insert(i);
e013809d 676
14ec9e00 677 // XXX: totalling the probable occurrences and sorting by them would improve the result
a846a8cd 678 for (CYIdentifierUsageVector::const_iterator i(context.rename_.begin()); i != context.rename_.end(); ++i, ++offset) {
de9fc71b
JF
679 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
680
14ec9e00
JF
681 const char *name;
682
683 if (context.options_.verbose_)
0cbeddf8 684 name = $pool.strcat("$", $pool.itoa(offset), NULL);
14ec9e00
JF
685 else {
686 char id[8];
687 id[7] = '\0';
688
689 id:
690 unsigned position(7), local(offset + 1);
691
692 do {
45d0c928
JF
693 unsigned index(local % (sizeof(MappingSet) - 1));
694 local /= sizeof(MappingSet) - 1;
695 id[--position] = MappingSet[index];
14ec9e00
JF
696 } while (local != 0);
697
6a981250 698 if (external.find(id + position) != external.end()) {
14ec9e00
JF
699 ++offset;
700 goto id;
701 }
702
b799113b 703 name = $pool.strmemdup(id + position, 7 - position);
14ec9e00
JF
704 // XXX: at some point, this could become a keyword
705 }
706
c2c9f509 707 CYForEach (identifier, i->identifier_)
14ec9e00
JF
708 identifier->Set(name);
709 }
3b52fd1a
JF
710}
711
712void CYProperty::Replace(CYContext &context) { $T()
713 context.Replace(value_);
714 next_->Replace(context);
5192746c
JF
715 if (value_ == NULL)
716 value_ = $U;
3b52fd1a
JF
717}
718
719CYStatement *CYReturn::Replace(CYContext &context) {
ab2aa221
JF
720 if (context.nonlocal_ != NULL) {
721 CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_));
722 return $ cy::Syntax::Throw($ CYObject(
4e58e244 723 $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
ab2aa221
JF
724 ));
725 }
726
3b52fd1a 727 context.Replace(value_);
029bc65b
JF
728 return this;
729}
730
6c093cce 731CYExpression *CYRubyBlock::Replace(CYContext &context) {
6c093cce
JF
732 return call_->AddArgument(context, proc_->Replace(context));
733}
734
735CYExpression *CYRubyProc::Replace(CYContext &context) {
12e37ba3
JF
736 CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
737 function = CYNonLocalize(context, function);
738 function->implicit_ = true;
739 return function;
6c093cce
JF
740}
741
50a3d79f 742CYScope::CYScope(bool transparent, CYContext &context) :
61fe0c53 743 transparent_(transparent),
daf22a65
JF
744 parent_(context.scope_)
745{
50a3d79f 746 context.scope_ = this;
daf22a65
JF
747}
748
a86e34d0 749void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
61fe0c53 750 if (!transparent_ || flags == CYIdentifierArgument || flags == CYIdentifierCatch)
daf22a65 751 internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags));
61fe0c53
JF
752 else if (parent_ != NULL)
753 parent_->Declare(context, identifier, flags);
a86e34d0
JF
754}
755
756CYIdentifier *CYScope::Lookup(CYContext &context, CYIdentifier *identifier) {
757 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
758 return *insert.first;
759}
760
6a981250 761void CYScope::Merge(CYContext &context, CYIdentifier *identifier) {
10711823 762 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
6a981250
JF
763 if (!insert.second) {
764 if ((*insert.first)->offset_ < identifier->offset_)
765 (*insert.first)->offset_ = identifier->offset_;
766 identifier->replace_ = *insert.first;
e013809d 767 (*insert.first)->usage_ += identifier->usage_ + 1;
029bc65b
JF
768 }
769}
770
10711823
JF
771namespace {
772 struct IdentifierOffset {
773 size_t offset_;
774 CYIdentifierFlags flags_;
e013809d 775 size_t usage_;
10711823
JF
776 CYIdentifier *identifier_;
777
e013809d
JF
778 IdentifierOffset(CYIdentifier *identifier, CYIdentifierFlags flags) :
779 offset_(identifier->offset_),
10711823 780 flags_(flags),
e013809d 781 usage_(identifier->usage_),
10711823
JF
782 identifier_(identifier)
783 {
784 }
785 };
786
787 struct IdentifierOffsetLess :
788 std::binary_function<const IdentifierOffset &, const IdentifierOffset &, bool>
789 {
790 _finline bool operator ()(const IdentifierOffset &lhs, const IdentifierOffset &rhs) const {
791 if (lhs.offset_ != rhs.offset_)
792 return lhs.offset_ < rhs.offset_;
793 if (lhs.flags_ != rhs.flags_)
794 return lhs.flags_ < rhs.flags_;
e013809d 795 /*if (lhs.usage_ != rhs.usage_)
a846a8cd 796 return lhs.usage_ < rhs.usage_;*/
10711823
JF
797 return lhs.identifier_ < rhs.identifier_;
798 }
799 };
800
801 typedef std::set<IdentifierOffset, IdentifierOffsetLess> IdentifierOffsets;
802}
803
50a3d79f
JF
804void CYScope::Close(CYContext &context, CYStatement *&statements) {
805 context.scope_ = parent_;
806
2c81c6df
JF
807 if (parent_ == NULL)
808 return;
809
029bc65b 810 CYDeclarations *last(NULL), *curr(NULL);
14ec9e00 811
10711823 812 IdentifierOffsets offsets;
6a981250 813
10711823 814 for (CYIdentifierAddressFlagsMap::const_iterator i(internal_.begin()); i != internal_.end(); ++i)
a846a8cd 815 if (i->second != CYIdentifierMagic)
e013809d 816 offsets.insert(IdentifierOffset(i->first, i->second));
10711823
JF
817
818 size_t offset(0);
819
820 for (IdentifierOffsets::const_iterator i(offsets.begin()); i != offsets.end(); ++i) {
821 if (i->flags_ == CYIdentifierVariable) {
822 CYDeclarations *next($ CYDeclarations($ CYDeclaration(i->identifier_)));
029bc65b
JF
823 if (last == NULL)
824 last = next;
825 if (curr != NULL)
826 curr->SetNext(next);
827 curr = next;
828 }
029bc65b 829
10711823
JF
830 if (offset < i->offset_)
831 offset = i->offset_;
a846a8cd
JF
832 if (context.rename_.size() <= offset)
833 context.rename_.resize(offset + 1);
10711823 834
a846a8cd 835 CYIdentifierUsage &rename(context.rename_[offset++]);
e013809d
JF
836 i->identifier_->SetNext(rename.identifier_);
837 rename.identifier_ = i->identifier_;
838 rename.usage_ += i->identifier_->usage_ + 1;
6a981250
JF
839 }
840
029bc65b
JF
841 if (last != NULL) {
842 CYVar *var($ CYVar(last));
843 var->SetNext(statements);
844 statements = var;
845 }
846
6a981250
JF
847 for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
848 if (internal_.find(*i) == internal_.end()) {
de9fc71b 849 //std::cout << *i << '=' << offset << std::endl;
6a981250
JF
850 if ((*i)->offset_ < offset)
851 (*i)->offset_ = offset;
852 parent_->Merge(context, *i);
853 }
029bc65b
JF
854}
855
b900e1a4
JF
856CYElement *CYSpan::Replace(CYContext &context) { $T(NULL)
857 return $ CYElement(expression_, $ CYElement(string_, next_->Replace(context)));
858}
859
12e37ba3
JF
860CYStatement *CYStatement::Return() {
861 return this;
862}
863
4644480a
JF
864CYString *CYString::Concat(CYContext &context, CYString *rhs) const {
865 size_t size(size_ + rhs->size_);
2eb8215d 866 char *value($ char[size + 1]);
4644480a
JF
867 memcpy(value, value_, size_);
868 memcpy(value + size_, rhs->value_, rhs->size_);
869 value[size] = '\0';
a14eb702 870 return $S(value, size);
4644480a
JF
871}
872
873CYNumber *CYString::Number(CYContext &context) {
874 // XXX: there is a precise algorithm for this
875 return NULL;
876}
877
878CYString *CYString::String(CYContext &context) {
879 return this;
880}
881
3b52fd1a
JF
882CYStatement *CYSwitch::Replace(CYContext &context) {
883 context.Replace(value_);
884 clauses_->Replace(context);
029bc65b 885 return this;
3b52fd1a
JF
886}
887
b900e1a4
JF
888CYExpression *CYTemplate::Replace(CYContext &context) {
889 return $C2($M($M($M($V("String"), $S("prototype")), $S("concat")), $S("apply")), $S(""), $ CYArray($ CYElement(string_, spans_->Replace(context))));
890}
891
3b52fd1a 892CYExpression *CYThis::Replace(CYContext &context) {
a0be43fc
JF
893 if (context.this_ != NULL)
894 return $V(context.this_->Identifier(context));
029bc65b 895 return this;
3b52fd1a
JF
896}
897
37954781
JF
898namespace cy {
899namespace Syntax {
900
901CYStatement *Throw::Replace(CYContext &context) {
3b52fd1a 902 context.Replace(value_);
029bc65b 903 return this;
3b52fd1a
JF
904}
905
37954781
JF
906} }
907
3b52fd1a 908CYExpression *CYTrivial::Replace(CYContext &context) {
029bc65b 909 return this;
3b52fd1a
JF
910}
911
4644480a
JF
912CYNumber *CYTrue::Number(CYContext &context) {
913 return $D(1);
914}
915
916CYString *CYTrue::String(CYContext &context) {
917 return $S("true");
918}
919
37954781
JF
920namespace cy {
921namespace Syntax {
922
923CYStatement *Try::Replace(CYContext &context) {
b0385401 924 context.ReplaceAll(code_);
3b52fd1a
JF
925 catch_->Replace(context);
926 finally_->Replace(context);
029bc65b 927 return this;
3b52fd1a
JF
928}
929
37954781
JF
930} }
931
9a39f705
JF
932CYExpression *CYTypeArrayOf::Replace_(CYContext &context, CYExpression *type) {
933 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("arrayOf")), $ CYArgument(size_)));
690cf1a8
JF
934}
935
3fe16be7
JF
936CYExpression *CYTypeBlockWith::Replace_(CYContext &context, CYExpression *type) {
937 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("blockWith")), parameters_->Argument(context)));
938}
939
9a39f705
JF
940CYExpression *CYTypeConstant::Replace_(CYContext &context, CYExpression *type) {
941 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant"))));
690cf1a8
JF
942}
943
60097023 944CYStatement *CYTypeDefinition::Replace(CYContext &context) {
84759b5b 945 return $E($ CYAssign($V(typed_->identifier_), typed_->Replace(context)));
60097023
JF
946}
947
03db6a67
JF
948CYExpression *CYTypeError::Replace(CYContext &context) {
949 _assert(false);
950 return NULL;
951}
952
9a39f705
JF
953CYExpression *CYTypeModifier::Replace(CYContext &context, CYExpression *type) { $T(type)
954 return Replace_(context, type);
955}
956
957CYExpression *CYTypeFunctionWith::Replace_(CYContext &context, CYExpression *type) {
958 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context)));
959}
960
3fe283c5
JF
961CYExpression *CYTypeLong::Replace(CYContext &context) {
962 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("long")));
963}
964
9a39f705
JF
965CYExpression *CYTypePointerTo::Replace_(CYContext &context, CYExpression *type) {
966 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo"))));
663c538f
JF
967}
968
3fe283c5
JF
969CYExpression *CYTypeShort::Replace(CYContext &context) {
970 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("short")));
971}
972
973CYExpression *CYTypeSigned::Replace(CYContext &context) {
974 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
975}
976
977CYExpression *CYTypeUnsigned::Replace(CYContext &context) {
978 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
979}
980
981CYExpression *CYTypeVariable::Replace(CYContext &context) {
982 return $V(name_);
983}
984
985CYExpression *CYTypeVoid::Replace(CYContext &context) {
986 return $N1($V("Type"), $ CYString("v"));
987}
988
9a39f705
JF
989CYExpression *CYTypeVolatile::Replace_(CYContext &context, CYExpression *type) {
990 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("volatile"))));
690cf1a8
JF
991}
992
9a39f705 993CYExpression *CYTypedIdentifier::Replace(CYContext &context) {
3fe283c5 994 return modifier_->Replace(context, specifier_->Replace(context));
690cf1a8
JF
995}
996
00b4cb83
JF
997CYTypeFunctionWith *CYTypedIdentifier::Function() {
998 CYTypeModifier **modifier(&modifier_);
999 if (*modifier == NULL)
1000 return NULL;
1001 while ((*modifier)->next_ != NULL)
1002 modifier = &(*modifier)->next_;
1003 CYTypeFunctionWith *function((*modifier)->Function());
1004 if (function == NULL)
1005 return NULL;
1006 *modifier = NULL;
1007 return function;
1008}
1009
663c538f 1010CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL)
9a39f705 1011 return $ CYArgument(typed_->Replace(context), next_->Argument(context));
663c538f
JF
1012}
1013
690cf1a8
JF
1014CYFunctionParameter *CYTypedParameter::Parameters(CYContext &context) { $T(NULL)
1015 return $ CYFunctionParameter($ CYDeclaration(typed_->identifier_ ?: context.Unique()), next_->Parameters(context));
1016}
1017
1018CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *prefix) { $T(prefix)
a2f3ecab 1019 return next_->TypeSignature(context, $ CYAdd(prefix, typed_->Replace(context)));
690cf1a8
JF
1020}
1021
3b52fd1a 1022CYStatement *CYVar::Replace(CYContext &context) {
15b88a33 1023 declarations_->Replace(context);
b0385401
JF
1024 if (CYExpression *expression = declarations_->Expression(context))
1025 return $E(expression);
fd5cdf97 1026 return $ CYEmpty();
3b52fd1a
JF
1027}
1028
1029CYExpression *CYVariable::Replace(CYContext &context) {
577bfbfa 1030 context.Replace(name_);
029bc65b 1031 return this;
3b52fd1a
JF
1032}
1033
0afc9ba3
JF
1034CYFunctionParameter *CYVariable::Parameter() const {
1035 return $ CYFunctionParameter($ CYDeclaration(name_));
1036}
1037
3b52fd1a
JF
1038CYStatement *CYWhile::Replace(CYContext &context) {
1039 context.Replace(test_);
b0385401 1040 context.ReplaceAll(code_);
029bc65b 1041 return this;
3b52fd1a
JF
1042}
1043
1044CYStatement *CYWith::Replace(CYContext &context) {
1045 context.Replace(scope_);
b0385401 1046 context.ReplaceAll(code_);
029bc65b 1047 return this;
3b52fd1a
JF
1048}
1049
1050CYExpression *CYWord::ClassName(CYContext &context, bool object) {
1051 CYString *name($S(this));
1052 if (object)
1053 return $C1($V("objc_getClass"), name);
1054 else
1055 return name;
1056}