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