]> git.saurik.com Git - cycript.git/blame - Replace.cpp
Port Objective-C/Replace to C++.
[cycript.git] / Replace.cpp
CommitLineData
e91fbe93 1/* Cycript - Inlining/Optimizing JavaScript Compiler
4644480a
JF
2 * Copyright (C) 2009 Jay Freeman (saurik)
3*/
4
5/* Modified BSD License {{{ */
6/*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
18 * distribution.
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*/
38/* }}} */
39
3b52fd1a 40#include "Parser.hpp"
6a981250 41#include "Replace.hpp"
3b52fd1a 42
3b52fd1a
JF
43#include <iomanip>
44
4644480a
JF
45CYExpression *CYAdd::Replace(CYContext &context) {
46 CYInfix::Replace(context);
47
48 CYExpression *lhp(lhs_->Primitive(context));
49 CYExpression *rhp(rhs_->Primitive(context));
50
51 CYString *lhs(dynamic_cast<CYString *>(lhp));
52 CYString *rhs(dynamic_cast<CYString *>(rhp));
53
54 if (lhs != NULL || rhs != NULL) {
55 if (lhs == NULL) {
56 lhs = lhp->String(context);
57 if (lhs == NULL)
029bc65b 58 return this;
4644480a
JF
59 } else if (rhs == NULL) {
60 rhs = rhp->String(context);
61 if (rhs == NULL)
029bc65b 62 return this;
4644480a
JF
63 }
64
65 return lhs->Concat(context, rhs);
66 }
67
68 if (CYNumber *lhn = lhp->Number(context))
69 if (CYNumber *rhn = rhp->Number(context))
70 return $D(lhn->Value() + rhn->Value());
71
029bc65b 72 return this;
4644480a
JF
73}
74
3b52fd1a
JF
75CYExpression *CYAddressOf::Replace(CYContext &context) {
76 CYPrefix::Replace(context);
77 return $C0($M(rhs_, $S("$cya")));
78}
79
80void CYArgument::Replace(CYContext &context) { $T()
81 context.Replace(value_);
82 next_->Replace(context);
83}
84
85CYExpression *CYArray::Replace(CYContext &context) {
86 elements_->Replace(context);
029bc65b 87 return this;
3b52fd1a
JF
88}
89
90CYExpression *CYArrayComprehension::Replace(CYContext &context) {
91 CYVariable *cyv($V("$cyv"));
92
93 return $C0($F(NULL, $P1("$cyv", comprehensions_->Parameters(context)), $$->*
94 $E($ CYAssign(cyv, $ CYArray()))->*
95 comprehensions_->Replace(context, $E($C1($M(cyv, $S("push")), expression_)))->*
96 $ CYReturn(cyv)
97 ));
98}
99
100CYExpression *CYAssignment::Replace(CYContext &context) {
101 context.Replace(lhs_);
102 context.Replace(rhs_);
029bc65b 103 return this;
3b52fd1a
JF
104}
105
106CYStatement *CYBlock::Replace(CYContext &context) {
107 statements_ = statements_->ReplaceAll(context);
029bc65b
JF
108 if (statements_ == NULL)
109 return $ CYEmpty();
110 return this;
3b52fd1a
JF
111}
112
113CYStatement *CYBreak::Replace(CYContext &context) {
029bc65b 114 return this;
3b52fd1a
JF
115}
116
6c093cce
JF
117CYExpression *CYCall::AddArgument(CYContext &context, CYExpression *value) {
118 CYArgument **argument(&arguments_);
119 while (*argument != NULL)
120 argument = &(*argument)->next_;
121 *argument = $ CYArgument(value);
122 return this;
123}
124
3b52fd1a
JF
125CYExpression *CYCall::Replace(CYContext &context) {
126 context.Replace(function_);
127 arguments_->Replace(context);
029bc65b 128 return this;
3b52fd1a
JF
129}
130
37954781
JF
131namespace cy {
132namespace Syntax {
133
134void Catch::Replace(CYContext &context) { $T()
daf22a65
JF
135 CYScope scope(CYScopeCatch, context, code_.statements_);
136
137 context.Replace(name_);
138 context.scope_->Declare(context, name_, CYIdentifierCatch);
139
3b52fd1a 140 code_.Replace(context);
daf22a65 141 scope.Close();
3b52fd1a
JF
142}
143
37954781
JF
144} }
145
3b52fd1a
JF
146void CYClause::Replace(CYContext &context) { $T()
147 context.Replace(case_);
148 statements_ = statements_->ReplaceAll(context);
149 next_->Replace(context);
150}
151
320ce753 152CYStatement *CYComment::Replace(CYContext &context) {
029bc65b 153 return this;
320ce753
JF
154}
155
3b52fd1a
JF
156CYExpression *CYCompound::Replace(CYContext &context) {
157 expressions_ = expressions_->ReplaceAll(context);
029bc65b 158 return expressions_ == NULL ? NULL : this;
3b52fd1a
JF
159}
160
161CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
162 CYFunctionParameter *next(next_->Parameters(context));
163 if (CYFunctionParameter *parameter = Parameter(context)) {
164 parameter->SetNext(next);
165 return parameter;
166 } else
167 return next;
168}
169
170CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
171 return next_ == NULL ? statement : next_->Replace(context, statement);
172}
173
174CYExpression *CYCondition::Replace(CYContext &context) {
175 context.Replace(test_);
176 context.Replace(true_);
177 context.Replace(false_);
029bc65b 178 return this;
3b52fd1a
JF
179}
180
ab2aa221
JF
181void CYContext::NonLocal(CYStatement *&statements) {
182 CYContext &context(*this);
183
06293152 184 if (nextlocal_ != NULL && nextlocal_->identifier_ != NULL) {
daf22a65
JF
185 CYIdentifier *cye($I("$cye")->Replace(context));
186 CYIdentifier *unique(nextlocal_->identifier_->Replace(context));
187
188 CYStatement *declare(
189 $ CYVar($L1($L(unique, $ CYObject()))));
190
191 cy::Syntax::Catch *rescue(
192 $ cy::Syntax::Catch(cye, $$->*
4e58e244
JF
193 $ CYIf($ CYIdentical($M($V(cye), $S("$cyk")), $V(unique)), $$->*
194 $ CYReturn($M($V(cye), $S("$cyv"))))->*
195 $ cy::Syntax::Throw($V(cye))));
daf22a65 196
577bfbfa 197 context.Replace(declare);
daf22a65 198 rescue->Replace(context);
ab2aa221
JF
199
200 statements = $$->*
daf22a65
JF
201 declare->*
202 $ cy::Syntax::Try(statements, rescue, NULL);
ab2aa221
JF
203 }
204}
205
206CYIdentifier *CYContext::Unique() {
2eb8215d 207 return $ CYIdentifier(apr_psprintf($pool, "$cy%u", unique_++));
ab2aa221
JF
208}
209
3b52fd1a 210CYStatement *CYContinue::Replace(CYContext &context) {
029bc65b
JF
211 return this;
212}
213
214CYAssignment *CYDeclaration::Assignment(CYContext &context) {
215 CYExpression *variable(Replace(context));
216 return initialiser_ == NULL ? NULL : $ CYAssign(variable, initialiser_);
3b52fd1a
JF
217}
218
219CYExpression *CYDeclaration::ForEachIn(CYContext &context) {
4e58e244 220 return $V(identifier_);
3b52fd1a
JF
221}
222
029bc65b 223CYExpression *CYDeclaration::Replace(CYContext &context) {
a86e34d0
JF
224 context.Replace(identifier_);
225 context.scope_->Declare(context, identifier_, CYIdentifierVariable);
4e58e244 226 return $V(identifier_);
3b52fd1a
JF
227}
228
550ee46a
JF
229CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
230 return $ CYProperty(declaration_->identifier_, declaration_->initialiser_ ?: $U, next_->Property(context));
231}
232
029bc65b
JF
233CYCompound *CYDeclarations::Replace(CYContext &context) {
234 CYCompound *compound;
235 if (next_ == NULL) compound:
236 compound = $ CYCompound();
237 else {
238 compound = next_->Replace(context);
239 if (compound == NULL)
240 goto compound;
241 }
242
243 if (CYAssignment *assignment = declaration_->Assignment(context))
244 compound->AddPrev(assignment);
245 return compound;
3b52fd1a
JF
246}
247
248CYExpression *CYDirectMember::Replace(CYContext &context) {
249 Replace_(context);
029bc65b 250 return this;
3b52fd1a
JF
251}
252
253CYStatement *CYDoWhile::Replace(CYContext &context) {
254 context.Replace(test_);
255 context.Replace(code_);
029bc65b 256 return this;
3b52fd1a
JF
257}
258
259void CYElement::Replace(CYContext &context) { $T()
260 context.Replace(value_);
261 next_->Replace(context);
262}
263
029bc65b
JF
264CYStatement *CYEmpty::Collapse(CYContext &context) {
265 return next_;
266}
267
3b52fd1a 268CYStatement *CYEmpty::Replace(CYContext &context) {
029bc65b
JF
269 return this;
270}
271
272CYStatement *CYExpress::Collapse(CYContext &context) {
273 if (CYExpress *express = dynamic_cast<CYExpress *>(next_)) {
274 CYCompound *next(dynamic_cast<CYCompound *>(express->expression_));
275 if (next == NULL)
276 next = $ CYCompound(express->expression_);
277 next->AddPrev(expression_);
278 expression_ = next;
279 SetNext(express->next_);
280 }
281
282 return this;
3b52fd1a
JF
283}
284
285CYStatement *CYExpress::Replace(CYContext &context) {
286 context.Replace(expression_);
029bc65b
JF
287 if (expression_ == NULL)
288 return $ CYEmpty();
289 return this;
3b52fd1a
JF
290}
291
6c093cce
JF
292CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value) {
293 return $C1(this, value);
294}
295
3b52fd1a
JF
296CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
297 return this;
298}
299
300CYExpression *CYExpression::ForEachIn(CYContext &context) {
301 return this;
302}
303
304CYExpression *CYExpression::ReplaceAll(CYContext &context) { $T(NULL)
305 CYExpression *replace(this);
306 context.Replace(replace);
307
308 if (CYExpression *next = next_->ReplaceAll(context))
309 replace->SetNext(next);
310 else
311 replace->SetNext(next_);
312
313 return replace;
314}
315
4644480a
JF
316CYNumber *CYFalse::Number(CYContext &context) {
317 return $D(0);
318}
319
320CYString *CYFalse::String(CYContext &context) {
321 return $S("false");
322}
323
3b52fd1a
JF
324void CYFinally::Replace(CYContext &context) { $T()
325 code_.Replace(context);
326}
327
328CYStatement *CYFor::Replace(CYContext &context) {
029bc65b 329 context.Replace(initialiser_);
3b52fd1a
JF
330 context.Replace(test_);
331 context.Replace(increment_);
332 context.Replace(code_);
029bc65b 333 return this;
3b52fd1a
JF
334}
335
336CYStatement *CYForIn::Replace(CYContext &context) {
029bc65b
JF
337 // XXX: this actually might need a prefix statement
338 context.Replace(initialiser_);
3b52fd1a
JF
339 context.Replace(set_);
340 context.Replace(code_);
029bc65b 341 return this;
3b52fd1a
JF
342}
343
344CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
345 return $ CYFunctionParameter(name_);
346}
347
348CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
4e58e244 349 return $ CYForIn($V(name_), set_, CYComprehension::Replace(context, statement));
3b52fd1a
JF
350}
351
352CYStatement *CYForEachIn::Replace(CYContext &context) {
2eb8215d 353 CYIdentifier *cys($I("$cys")), *cyt($I("$cyt"));
3b52fd1a 354
2eb8215d
JF
355 return $ CYLet($L2($L(cys, set_), $L(cyt)), $$->*
356 $ CYForIn($V(cyt), $V(cys), $ CYBlock($$->*
357 $E($ CYAssign(initialiser_->ForEachIn(context), $M($V(cys), $V(cyt))))->*
3b52fd1a
JF
358 code_
359 ))
550ee46a 360 );
3b52fd1a
JF
361}
362
363CYFunctionParameter *CYForEachInComprehension::Parameter(CYContext &context) const {
364 return $ CYFunctionParameter(name_);
365}
366
367CYStatement *CYForEachInComprehension::Replace(CYContext &context, CYStatement *statement) const {
2eb8215d 368 CYIdentifier *cys($I("cys"));
3b52fd1a
JF
369
370 return $E($C0($F(NULL, $P1("$cys"), $$->*
2eb8215d
JF
371 $E($ CYAssign($V(cys), set_))->*
372 $ CYForIn($V(name_), $V(cys), $ CYBlock($$->*
373 $E($ CYAssign($V(name_), $M($V(cys), $V(name_))))->*
3b52fd1a
JF
374 CYComprehension::Replace(context, statement)
375 ))
376 )));
377}
378
14ec9e00 379void CYFunction::Inject(CYContext &context) {
6a981250 380 context.Replace(name_);
a86e34d0 381 context.scope_->Declare(context, name_, CYIdentifierOther);
14ec9e00
JF
382}
383
384void CYFunction::Replace_(CYContext &context, bool outer) {
385 if (outer)
386 Inject(context);
387
daf22a65 388 CYScope scope(CYScopeFunction, context, code_.statements_);
029bc65b 389
06293152
JF
390 CYNonLocal *nonlocal(context.nonlocal_);
391 CYNonLocal *nextlocal(context.nextlocal_);
392
ab2aa221 393 bool localize;
06293152 394 if (nonlocal_ != NULL) {
ab2aa221 395 localize = false;
06293152
JF
396 context.nonlocal_ = nonlocal_;
397 } else {
ab2aa221
JF
398 localize = true;
399 nonlocal_ = $ CYNonLocal();
06293152 400 context.nextlocal_ = nonlocal_;
ab2aa221
JF
401 }
402
14ec9e00
JF
403 if (!outer && name_ != NULL)
404 Inject(context);
405
6c093cce
JF
406 if (parameters_ != NULL)
407 parameters_ = parameters_->Replace(context, code_);
daf22a65 408
3b52fd1a 409 code_.Replace(context);
029bc65b 410
ab2aa221
JF
411 if (localize)
412 context.NonLocal(code_.statements_);
06293152
JF
413
414 context.nextlocal_ = nextlocal;
ab2aa221
JF
415 context.nonlocal_ = nonlocal;
416
daf22a65 417 scope.Close();
3b52fd1a
JF
418}
419
420CYExpression *CYFunctionExpression::Replace(CYContext &context) {
14ec9e00 421 Replace_(context, false);
029bc65b
JF
422 return this;
423}
424
4e11a430 425CYFunctionParameter *CYFunctionParameter::Replace(CYContext &context, CYBlock &code) {
577bfbfa 426 context.Replace(name_);
a86e34d0 427 context.scope_->Declare(context, name_, CYIdentifierArgument);
4e11a430
JF
428 if (next_ != NULL)
429 next_ = next_->Replace(context, code);
430 return this;
3b52fd1a
JF
431}
432
433CYStatement *CYFunctionStatement::Replace(CYContext &context) {
14ec9e00 434 Replace_(context, true);
029bc65b
JF
435 return this;
436}
437
438CYIdentifier *CYIdentifier::Replace(CYContext &context) {
a846a8cd 439 if (replace_ != NULL && replace_ != this)
de9fc71b 440 return replace_->Replace(context);
a846a8cd 441 replace_ = context.scope_->Lookup(context, this);
a86e34d0 442 return replace_;
3b52fd1a
JF
443}
444
445CYStatement *CYIf::Replace(CYContext &context) {
446 context.Replace(test_);
447 context.Replace(true_);
448 context.Replace(false_);
029bc65b 449 return this;
3b52fd1a
JF
450}
451
452CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
453 return NULL;
454}
455
456CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
457 return $ CYIf(test_, CYComprehension::Replace(context, statement));
458}
459
460CYExpression *CYIndirect::Replace(CYContext &context) {
461 CYPrefix::Replace(context);
462 return $M(rhs_, $S("$cyi"));
463}
464
465CYExpression *CYIndirectMember::Replace(CYContext &context) {
466 Replace_(context);
467 return $M($ CYIndirect(object_), property_);
468}
469
470CYExpression *CYInfix::Replace(CYContext &context) {
471 context.Replace(lhs_);
472 context.Replace(rhs_);
029bc65b 473 return this;
3b52fd1a
JF
474}
475
476CYStatement *CYLabel::Replace(CYContext &context) {
477 context.Replace(statement_);
029bc65b 478 return this;
3b52fd1a
JF
479}
480
550ee46a
JF
481CYStatement *CYLet::Replace(CYContext &context) {
482 return $ CYWith($ CYObject(declarations_->Property(context)), &code_);
483}
484
3b52fd1a
JF
485void CYMember::Replace_(CYContext &context) {
486 context.Replace(object_);
487 context.Replace(property_);
488}
489
2eb8215d
JF
490namespace cy {
491namespace Syntax {
492
493CYExpression *New::AddArgument(CYContext &context, CYExpression *value) {
6c093cce
JF
494 CYArgument **argument(&arguments_);
495 while (*argument != NULL)
496 argument = &(*argument)->next_;
497 *argument = $ CYArgument(value);
498 return this;
499}
500
2eb8215d 501CYExpression *New::Replace(CYContext &context) {
3b52fd1a
JF
502 context.Replace(constructor_);
503 arguments_->Replace(context);
029bc65b 504 return this;
3b52fd1a
JF
505}
506
2eb8215d
JF
507} }
508
4644480a
JF
509CYNumber *CYNull::Number(CYContext &context) {
510 return $D(0);
511}
512
513CYString *CYNull::String(CYContext &context) {
514 return $S("null");
515}
516
517CYNumber *CYNumber::Number(CYContext &context) {
518 return this;
519}
520
521CYString *CYNumber::String(CYContext &context) {
522 // XXX: there is a precise algorithm for this
2eb8215d 523 return $S(apr_psprintf($pool, "%.17g", Value()));
4644480a
JF
524}
525
3b52fd1a
JF
526CYExpression *CYObject::Replace(CYContext &context) {
527 properties_->Replace(context);
029bc65b 528 return this;
3b52fd1a
JF
529}
530
4e11a430
JF
531CYFunctionParameter *CYOptionalFunctionParameter::Replace(CYContext &context, CYBlock &code) {
532 CYFunctionParameter *parameter($ CYFunctionParameter(name_, next_));
533 parameter = parameter->Replace(context, code);
577bfbfa 534 context.Replace(initializer_);
4e11a430 535
4e58e244 536 CYVariable *name($V(name_));
4e11a430
JF
537 code.AddPrev($ CYIf($ CYIdentical($ CYTypeOf(name), $S("undefined")), $$->*
538 $E($ CYAssign(name, initializer_))
539 ));
540
541 return parameter;
542}
543
3b52fd1a
JF
544CYExpression *CYPostfix::Replace(CYContext &context) {
545 context.Replace(lhs_);
029bc65b 546 return this;
3b52fd1a
JF
547}
548
549CYExpression *CYPrefix::Replace(CYContext &context) {
550 context.Replace(rhs_);
029bc65b 551 return this;
3b52fd1a
JF
552}
553
10711823 554// XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
45d0c928 555#define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
10711823 556//#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
45d0c928 557
e013809d
JF
558namespace {
559 struct IdentifierUsageLess :
560 std::binary_function<CYIdentifier *, CYIdentifier *, bool>
561 {
562 _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const {
563 if (lhs->usage_ != rhs->usage_)
564 return lhs->usage_ > rhs->usage_;
565 return lhs < rhs;
566 }
567 };
568
569 typedef std::set<CYIdentifier *, IdentifierUsageLess> IdentifierUsages;
570}
571
3b52fd1a 572void CYProgram::Replace(CYContext &context) {
daf22a65 573 CYScope scope(CYScopeProgram, context, statements_);
ab2aa221 574
06293152 575 context.nextlocal_ = $ CYNonLocal();
3b52fd1a 576 statements_ = statements_->ReplaceAll(context);
ab2aa221
JF
577 context.NonLocal(statements_);
578
daf22a65 579 scope.Close();
14ec9e00
JF
580
581 size_t offset(0);
582
6a981250 583 CYCStringSet external;
a846a8cd 584 for (CYIdentifierValueSet::const_iterator i(scope.identifiers_.begin()); i != scope.identifiers_.end(); ++i)
6a981250
JF
585 external.insert((*i)->Word());
586
e013809d
JF
587 IdentifierUsages usages;
588
a846a8cd
JF
589 if (offset < context.rename_.size())
590 for (CYIdentifier *i(context.rename_[offset].identifier_); i != NULL; i = i->next_)
591 usages.insert(i);
e013809d 592
14ec9e00 593 // XXX: totalling the probable occurrences and sorting by them would improve the result
a846a8cd 594 for (CYIdentifierUsageVector::const_iterator i(context.rename_.begin()); i != context.rename_.end(); ++i, ++offset) {
de9fc71b
JF
595 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
596
14ec9e00
JF
597 const char *name;
598
599 if (context.options_.verbose_)
2eb8215d 600 name = apr_psprintf($pool, "$%"APR_SIZE_T_FMT"", offset);
14ec9e00
JF
601 else {
602 char id[8];
603 id[7] = '\0';
604
605 id:
606 unsigned position(7), local(offset + 1);
607
608 do {
45d0c928
JF
609 unsigned index(local % (sizeof(MappingSet) - 1));
610 local /= sizeof(MappingSet) - 1;
611 id[--position] = MappingSet[index];
14ec9e00
JF
612 } while (local != 0);
613
6a981250 614 if (external.find(id + position) != external.end()) {
14ec9e00
JF
615 ++offset;
616 goto id;
617 }
618
2eb8215d 619 name = apr_pstrmemdup($pool, id + position, 7 - position);
14ec9e00
JF
620 // XXX: at some point, this could become a keyword
621 }
622
e013809d 623 for (CYIdentifier *identifier(i->identifier_); identifier != NULL; identifier = identifier->next_)
14ec9e00
JF
624 identifier->Set(name);
625 }
3b52fd1a
JF
626}
627
628void CYProperty::Replace(CYContext &context) { $T()
629 context.Replace(value_);
630 next_->Replace(context);
631}
632
633CYStatement *CYReturn::Replace(CYContext &context) {
ab2aa221
JF
634 if (context.nonlocal_ != NULL) {
635 CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_));
636 return $ cy::Syntax::Throw($ CYObject(
4e58e244 637 $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
ab2aa221
JF
638 ));
639 }
640
3b52fd1a 641 context.Replace(value_);
029bc65b
JF
642 return this;
643}
644
6c093cce
JF
645CYExpression *CYRubyBlock::Replace(CYContext &context) {
646 // XXX: this needs to do something much more epic to handle return
647 return call_->AddArgument(context, proc_->Replace(context));
648}
649
650CYExpression *CYRubyProc::Replace(CYContext &context) {
ab2aa221 651 CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
06293152 652 function->nonlocal_ = context.nextlocal_;
ab2aa221 653 return function;
6c093cce
JF
654}
655
daf22a65
JF
656CYScope::CYScope(CYScopeType type, CYContext &context, CYStatement *&statements) :
657 type_(type),
658 context_(context),
659 statements_(statements),
660 parent_(context.scope_)
661{
662 context_.scope_ = this;
663}
664
665void CYScope::Close() {
666 context_.scope_ = parent_;
667 Scope(context_, statements_);
668}
669
a86e34d0 670void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
daf22a65
JF
671 if (type_ == CYScopeCatch && flags != CYIdentifierCatch)
672 parent_->Declare(context, identifier, flags);
673 else
674 internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags));
a86e34d0
JF
675}
676
677CYIdentifier *CYScope::Lookup(CYContext &context, CYIdentifier *identifier) {
678 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
679 return *insert.first;
680}
681
6a981250 682void CYScope::Merge(CYContext &context, CYIdentifier *identifier) {
10711823 683 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
6a981250
JF
684 if (!insert.second) {
685 if ((*insert.first)->offset_ < identifier->offset_)
686 (*insert.first)->offset_ = identifier->offset_;
687 identifier->replace_ = *insert.first;
e013809d 688 (*insert.first)->usage_ += identifier->usage_ + 1;
029bc65b
JF
689 }
690}
691
10711823
JF
692namespace {
693 struct IdentifierOffset {
694 size_t offset_;
695 CYIdentifierFlags flags_;
e013809d 696 size_t usage_;
10711823
JF
697 CYIdentifier *identifier_;
698
e013809d
JF
699 IdentifierOffset(CYIdentifier *identifier, CYIdentifierFlags flags) :
700 offset_(identifier->offset_),
10711823 701 flags_(flags),
e013809d 702 usage_(identifier->usage_),
10711823
JF
703 identifier_(identifier)
704 {
705 }
706 };
707
708 struct IdentifierOffsetLess :
709 std::binary_function<const IdentifierOffset &, const IdentifierOffset &, bool>
710 {
711 _finline bool operator ()(const IdentifierOffset &lhs, const IdentifierOffset &rhs) const {
712 if (lhs.offset_ != rhs.offset_)
713 return lhs.offset_ < rhs.offset_;
714 if (lhs.flags_ != rhs.flags_)
715 return lhs.flags_ < rhs.flags_;
e013809d 716 /*if (lhs.usage_ != rhs.usage_)
a846a8cd 717 return lhs.usage_ < rhs.usage_;*/
10711823
JF
718 return lhs.identifier_ < rhs.identifier_;
719 }
720 };
721
722 typedef std::set<IdentifierOffset, IdentifierOffsetLess> IdentifierOffsets;
723}
724
029bc65b 725void CYScope::Scope(CYContext &context, CYStatement *&statements) {
2c81c6df
JF
726 if (parent_ == NULL)
727 return;
728
029bc65b 729 CYDeclarations *last(NULL), *curr(NULL);
14ec9e00 730
10711823 731 IdentifierOffsets offsets;
6a981250 732
10711823 733 for (CYIdentifierAddressFlagsMap::const_iterator i(internal_.begin()); i != internal_.end(); ++i)
a846a8cd 734 if (i->second != CYIdentifierMagic)
e013809d 735 offsets.insert(IdentifierOffset(i->first, i->second));
10711823
JF
736
737 size_t offset(0);
738
739 for (IdentifierOffsets::const_iterator i(offsets.begin()); i != offsets.end(); ++i) {
740 if (i->flags_ == CYIdentifierVariable) {
741 CYDeclarations *next($ CYDeclarations($ CYDeclaration(i->identifier_)));
029bc65b
JF
742 if (last == NULL)
743 last = next;
744 if (curr != NULL)
745 curr->SetNext(next);
746 curr = next;
747 }
029bc65b 748
10711823
JF
749 if (offset < i->offset_)
750 offset = i->offset_;
a846a8cd
JF
751 if (context.rename_.size() <= offset)
752 context.rename_.resize(offset + 1);
10711823 753
a846a8cd 754 CYIdentifierUsage &rename(context.rename_[offset++]);
e013809d
JF
755 i->identifier_->SetNext(rename.identifier_);
756 rename.identifier_ = i->identifier_;
757 rename.usage_ += i->identifier_->usage_ + 1;
6a981250
JF
758 }
759
029bc65b
JF
760 if (last != NULL) {
761 CYVar *var($ CYVar(last));
762 var->SetNext(statements);
763 statements = var;
764 }
765
6a981250
JF
766 for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
767 if (internal_.find(*i) == internal_.end()) {
de9fc71b 768 //std::cout << *i << '=' << offset << std::endl;
6a981250
JF
769 if ((*i)->offset_ < offset)
770 (*i)->offset_ = offset;
771 parent_->Merge(context, *i);
772 }
029bc65b
JF
773}
774
775CYStatement *CYStatement::Collapse(CYContext &context) {
776 return this;
3b52fd1a
JF
777}
778
3b52fd1a
JF
779CYStatement *CYStatement::ReplaceAll(CYContext &context) { $T(NULL)
780 CYStatement *replace(this);
781 context.Replace(replace);
029bc65b
JF
782 replace->SetNext(next_->ReplaceAll(context));
783 return replace->Collapse(context);
3b52fd1a
JF
784}
785
4644480a
JF
786CYString *CYString::Concat(CYContext &context, CYString *rhs) const {
787 size_t size(size_ + rhs->size_);
2eb8215d 788 char *value($ char[size + 1]);
4644480a
JF
789 memcpy(value, value_, size_);
790 memcpy(value + size_, rhs->value_, rhs->size_);
791 value[size] = '\0';
a14eb702 792 return $S(value, size);
4644480a
JF
793}
794
795CYNumber *CYString::Number(CYContext &context) {
796 // XXX: there is a precise algorithm for this
797 return NULL;
798}
799
800CYString *CYString::String(CYContext &context) {
801 return this;
802}
803
3b52fd1a
JF
804CYStatement *CYSwitch::Replace(CYContext &context) {
805 context.Replace(value_);
806 clauses_->Replace(context);
029bc65b 807 return this;
3b52fd1a
JF
808}
809
810CYExpression *CYThis::Replace(CYContext &context) {
029bc65b 811 return this;
3b52fd1a
JF
812}
813
37954781
JF
814namespace cy {
815namespace Syntax {
816
817CYStatement *Throw::Replace(CYContext &context) {
3b52fd1a 818 context.Replace(value_);
029bc65b 819 return this;
3b52fd1a
JF
820}
821
37954781
JF
822} }
823
3b52fd1a 824CYExpression *CYTrivial::Replace(CYContext &context) {
029bc65b 825 return this;
3b52fd1a
JF
826}
827
4644480a
JF
828CYNumber *CYTrue::Number(CYContext &context) {
829 return $D(1);
830}
831
832CYString *CYTrue::String(CYContext &context) {
833 return $S("true");
834}
835
37954781
JF
836namespace cy {
837namespace Syntax {
838
839CYStatement *Try::Replace(CYContext &context) {
3b52fd1a
JF
840 code_.Replace(context);
841 catch_->Replace(context);
842 finally_->Replace(context);
029bc65b 843 return this;
3b52fd1a
JF
844}
845
37954781
JF
846} }
847
3b52fd1a 848CYStatement *CYVar::Replace(CYContext &context) {
029bc65b 849 return $E(declarations_->Replace(context));
3b52fd1a
JF
850}
851
852CYExpression *CYVariable::Replace(CYContext &context) {
577bfbfa 853 context.Replace(name_);
029bc65b 854 return this;
3b52fd1a
JF
855}
856
857CYStatement *CYWhile::Replace(CYContext &context) {
858 context.Replace(test_);
859 context.Replace(code_);
029bc65b 860 return this;
3b52fd1a
JF
861}
862
863CYStatement *CYWith::Replace(CYContext &context) {
864 context.Replace(scope_);
865 context.Replace(code_);
029bc65b 866 return this;
3b52fd1a
JF
867}
868
869CYExpression *CYWord::ClassName(CYContext &context, bool object) {
870 CYString *name($S(this));
871 if (object)
872 return $C1($V("objc_getClass"), name);
873 else
874 return name;
875}