]> git.saurik.com Git - cycript.git/blob - Replace.cpp
Support implicit return from block_lambda_revival.
[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 CYStatement *CYComment::Replace(CYContext &context) {
155 return this;
156 }
157
158 CYExpression *CYCompound::Replace(CYContext &context) {
159 context.Replace(expression_);
160 context.Replace(next_);
161
162 if (CYCompound *compound = dynamic_cast<CYCompound *>(expression_)) {
163 expression_ = compound->expression_;
164 compound->expression_ = compound->next_;
165 compound->next_ = next_;
166 next_ = compound;
167 }
168
169 return this;
170 }
171
172 CYFunctionParameter *CYCompound::Parameter() const {
173 CYFunctionParameter *next(next_->Parameter());
174 if (next == NULL)
175 return NULL;
176
177 CYFunctionParameter *parameter(expression_->Parameter());
178 if (parameter == NULL)
179 return NULL;
180
181 parameter->SetNext(next);
182 return parameter;
183 }
184
185 CYFunctionParameter *CYComprehension::Parameters(CYContext &context) const { $T(NULL)
186 CYFunctionParameter *next(next_->Parameters(context));
187 if (CYFunctionParameter *parameter = Parameter(context)) {
188 parameter->SetNext(next);
189 return parameter;
190 } else
191 return next;
192 }
193
194 CYStatement *CYComprehension::Replace(CYContext &context, CYStatement *statement) const {
195 return next_ == NULL ? statement : next_->Replace(context, statement);
196 }
197
198 CYExpression *CYCondition::Replace(CYContext &context) {
199 context.Replace(test_);
200 context.Replace(true_);
201 context.Replace(false_);
202 return this;
203 }
204
205 void CYContext::NonLocal(CYStatement *&statements) {
206 CYContext &context(*this);
207
208 if (nextlocal_ != NULL && nextlocal_->identifier_ != NULL) {
209 CYIdentifier *cye($I("$cye")->Replace(context));
210 CYIdentifier *unique(nextlocal_->identifier_->Replace(context));
211
212 CYStatement *declare(
213 $ CYVar($L1($ CYDeclaration(unique, $ CYObject()))));
214
215 cy::Syntax::Catch *rescue(
216 $ cy::Syntax::Catch(cye, $$->*
217 $ CYIf($ CYIdentical($M($V(cye), $S("$cyk")), $V(unique)), $$->*
218 $ CYReturn($M($V(cye), $S("$cyv"))))->*
219 $ cy::Syntax::Throw($V(cye))));
220
221 // XXX: I don't understand any of this
222 context.Replace(declare);
223 rescue->Replace(context);
224
225 statements = $$->*
226 declare->*
227 $ cy::Syntax::Try(statements, rescue, NULL);
228 }
229 }
230
231 CYIdentifier *CYContext::Unique() {
232 return $ CYIdentifier($pool.strcat("$cy", $pool.itoa(unique_++), NULL));
233 }
234
235 CYStatement *CYContinue::Replace(CYContext &context) {
236 return this;
237 }
238
239 CYStatement *CYDebugger::Replace(CYContext &context) {
240 return this;
241 }
242
243 CYAssignment *CYDeclaration::Assignment(CYContext &context) {
244 if (initialiser_ == NULL)
245 return NULL;
246
247 CYAssignment *value($ CYAssign(Variable(context), initialiser_));
248 initialiser_ = NULL;
249 return value;
250 }
251
252 CYVariable *CYDeclaration::Variable(CYContext &context) {
253 return $V(identifier_);
254 }
255
256 CYStatement *CYDeclaration::ForEachIn(CYContext &context, CYExpression *value) {
257 return $ CYVar($L1($ CYDeclaration(identifier_, value)));
258 }
259
260 CYExpression *CYDeclaration::Replace(CYContext &context) {
261 context.Replace(identifier_);
262 context.scope_->Declare(context, identifier_, CYIdentifierVariable);
263 return Variable(context);
264 }
265
266 void CYDeclarations::Replace(CYContext &context) { $T()
267 declaration_->Replace(context);
268 next_->Replace(context);
269 }
270
271 CYProperty *CYDeclarations::Property(CYContext &context) { $T(NULL)
272 return $ CYProperty(declaration_->identifier_, declaration_->initialiser_, next_->Property(context));
273 }
274
275 CYFunctionParameter *CYDeclarations::Parameter(CYContext &context) { $T(NULL)
276 return $ CYFunctionParameter($ CYDeclaration(declaration_->identifier_), next_->Parameter(context));
277 }
278
279 CYArgument *CYDeclarations::Argument(CYContext &context) { $T(NULL)
280 return $ CYArgument(declaration_->initialiser_, next_->Argument(context));
281 }
282
283 CYExpression *CYDeclarations::Expression(CYContext &context) { $T(NULL)
284 CYExpression *compound(next_->Expression(context));
285 if (CYAssignment *assignment = declaration_->Assignment(context))
286 if (compound == NULL)
287 compound = assignment;
288 else
289 compound = $ CYCompound(assignment, compound);
290 return compound;
291 }
292
293 CYExpression *CYDirectMember::Replace(CYContext &context) {
294 context.Replace(object_);
295 context.Replace(property_);
296 return this;
297 }
298
299 CYStatement *CYDoWhile::Replace(CYContext &context) {
300 context.Replace(test_);
301 context.ReplaceAll(code_);
302 return this;
303 }
304
305 void CYElement::Replace(CYContext &context) { $T()
306 context.Replace(value_);
307 next_->Replace(context);
308 }
309
310 CYStatement *CYEmpty::Replace(CYContext &context) {
311 return NULL;
312 }
313
314 CYExpression *CYEncodedType::Replace(CYContext &context) {
315 return typed_->Replace(context);
316 }
317
318 CYStatement *CYExpress::Return() {
319 return $ CYReturn(expression_);
320 }
321
322 CYStatement *CYExpress::Replace(CYContext &context) {
323 context.Replace(expression_);
324 return this;
325 }
326
327 CYExpression *CYExpression::AddArgument(CYContext &context, CYExpression *value) {
328 return $C1(this, value);
329 }
330
331 CYExpression *CYExpression::ClassName(CYContext &context, bool object) {
332 return this;
333 }
334
335 CYStatement *CYExpression::ForEachIn(CYContext &context, CYExpression *value) {
336 return $E($ CYAssign(this, value));
337 }
338
339 CYAssignment *CYExpression::Assignment(CYContext &context) {
340 return NULL;
341 }
342
343 CYFunctionParameter *CYExpression::Parameter() const {
344 return NULL;
345 }
346
347 CYStatement *CYExternal::Replace(CYContext &context) {
348 return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word())))));
349 }
350
351 CYNumber *CYFalse::Number(CYContext &context) {
352 return $D(0);
353 }
354
355 CYString *CYFalse::String(CYContext &context) {
356 return $S("false");
357 }
358
359 CYExpression *CYFatArrow::Replace(CYContext &context) {
360 CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
361 function->this_.SetNext(context.this_);
362 return function;
363 }
364
365 void CYFinally::Replace(CYContext &context) { $T()
366 context.ReplaceAll(code_);
367 }
368
369 CYStatement *CYFor::Replace(CYContext &context) {
370 context.Replace(initialiser_);
371 context.Replace(test_);
372 context.Replace(increment_);
373 context.ReplaceAll(code_);
374 return this;
375 }
376
377 CYExpression *CYForDeclarations::Replace(CYContext &context) {
378 declarations_->Replace(context);
379 return declarations_->Expression(context);
380 }
381
382 // XXX: this still feels highly suboptimal
383 CYStatement *CYForIn::Replace(CYContext &context) {
384 if (CYAssignment *assignment = initialiser_->Assignment(context))
385 return $ CYBlock($$->*
386 $E(assignment)->*
387 this
388 );
389
390 context.Replace(initialiser_);
391 context.Replace(set_);
392 context.ReplaceAll(code_);
393 return this;
394 }
395
396 CYFunctionParameter *CYForInComprehension::Parameter(CYContext &context) const {
397 return $ CYFunctionParameter($ CYDeclaration(name_));
398 }
399
400 CYStatement *CYForInComprehension::Replace(CYContext &context, CYStatement *statement) const {
401 return $ CYForIn($V(name_), set_, CYComprehension::Replace(context, statement));
402 }
403
404 CYStatement *CYForOf::Replace(CYContext &context) {
405 if (CYAssignment *assignment = initialiser_->Assignment(context))
406 return $ CYBlock($$->*
407 $E(assignment)->*
408 this
409 );
410
411 CYIdentifier *cys($I("$cys")), *cyt($I("$cyt"));
412
413 return $ CYLetStatement($L2($ CYDeclaration(cys, set_), $ CYDeclaration(cyt)), $$->*
414 $ CYForIn($V(cyt), $V(cys), $ CYBlock($$->*
415 initialiser_->ForEachIn(context, $M($V(cys), $V(cyt)))->*
416 code_
417 ))
418 );
419 }
420
421 CYFunctionParameter *CYForOfComprehension::Parameter(CYContext &context) const {
422 return $ CYFunctionParameter($ CYDeclaration(name_));
423 }
424
425 CYStatement *CYForOfComprehension::Replace(CYContext &context, CYStatement *statement) const {
426 CYIdentifier *cys($I("$cys"));
427
428 return $E($C0($F(NULL, $P1($L("$cys")), $$->*
429 $E($ CYAssign($V(cys), set_))->*
430 $ CYForIn($V(name_), $V(cys), $ CYBlock($$->*
431 $E($ CYAssign($V(name_), $M($V(cys), $V(name_))))->*
432 CYComprehension::Replace(context, statement)
433 ))
434 )));
435 }
436
437 void CYFunction::Inject(CYContext &context) {
438 context.Replace(name_);
439 context.scope_->Declare(context, name_, CYIdentifierOther);
440 }
441
442 void CYFunction::Replace_(CYContext &context, bool outer) {
443 if (outer)
444 Inject(context);
445
446 CYThisScope *_this(context.this_);
447 context.this_ = &this_;
448 context.this_ = CYGetLast(context.this_);
449
450 CYNonLocal *nonlocal(context.nonlocal_);
451 CYNonLocal *nextlocal(context.nextlocal_);
452
453 bool localize;
454 if (nonlocal_ != NULL) {
455 localize = false;
456 context.nonlocal_ = nonlocal_;
457 } else {
458 localize = true;
459 nonlocal_ = $ CYNonLocal();
460 context.nextlocal_ = nonlocal_;
461 }
462
463 CYScope scope(!localize, context);
464
465 if (!outer && name_ != NULL)
466 Inject(context);
467
468 parameters_->Replace(context, code_);
469 context.ReplaceAll(code_);
470
471 if (implicit_)
472 CYImplicitReturn(code_);
473
474 if (CYIdentifier *identifier = this_.identifier_)
475 code_ = $$->*
476 $ CYVar($L1($ CYDeclaration(identifier, $ CYThis())))->*
477 code_;
478
479 if (localize)
480 context.NonLocal(code_);
481
482 context.nextlocal_ = nextlocal;
483 context.nonlocal_ = nonlocal;
484
485 context.this_ = _this;
486
487 scope.Close(context, code_);
488 }
489
490 CYExpression *CYFunctionExpression::Replace(CYContext &context) {
491 Replace_(context, false);
492 return this;
493 }
494
495 void CYFunctionParameter::Replace(CYContext &context, CYStatement *&statements) { $T()
496 CYAssignment *assignment(initialiser_->Assignment(context));
497 context.Replace(initialiser_);
498
499 next_->Replace(context, statements);
500
501 if (assignment != NULL)
502 statements = $$->*
503 // XXX: this cast is quite incorrect
504 $ CYIf($ CYIdentical($ CYTypeOf(dynamic_cast<CYExpression *>(initialiser_)), $S("undefined")), $$->*
505 $E(assignment)
506 )->*
507 statements;
508 }
509
510 CYStatement *CYFunctionStatement::Replace(CYContext &context) {
511 Replace_(context, true);
512 return this;
513 }
514
515 CYIdentifier *CYIdentifier::Replace(CYContext &context) {
516 if (replace_ != NULL && replace_ != this)
517 return replace_->Replace(context);
518 replace_ = context.scope_->Lookup(context, this);
519 return replace_;
520 }
521
522 CYStatement *CYIf::Return() {
523 CYImplicitReturn(true_);
524 CYImplicitReturn(false_);
525 return this;
526 }
527
528 CYStatement *CYIf::Replace(CYContext &context) {
529 context.Replace(test_);
530 context.ReplaceAll(true_);
531 context.ReplaceAll(false_);
532 return this;
533 }
534
535 CYFunctionParameter *CYIfComprehension::Parameter(CYContext &context) const {
536 return NULL;
537 }
538
539 CYStatement *CYIfComprehension::Replace(CYContext &context, CYStatement *statement) const {
540 return $ CYIf(test_, CYComprehension::Replace(context, statement));
541 }
542
543 CYStatement *CYImport::Replace(CYContext &context) {
544 return $ CYVar($L1($L(module_->part_->Word(), $C1($V("require"), module_->Replace(context, "/")))));
545 }
546
547 CYExpression *CYIndirect::Replace(CYContext &context) {
548 return $M(rhs_, $S("$cyi"));
549 }
550
551 CYExpression *CYIndirectMember::Replace(CYContext &context) {
552 return $M($ CYIndirect(object_), property_);
553 }
554
555 CYExpression *CYInfix::Replace(CYContext &context) {
556 context.Replace(lhs_);
557 context.Replace(rhs_);
558 return this;
559 }
560
561 CYStatement *CYLabel::Replace(CYContext &context) {
562 context.Replace(statement_);
563 return this;
564 }
565
566 CYExpression *CYLambda::Replace(CYContext &context) {
567 return $N2($V("Functor"), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_), parameters_->TypeSignature(context, typed_->Replace(context)));
568 }
569
570 CYStatement *CYLetStatement::Replace(CYContext &context) {
571 return $E($ CYCall(CYNonLocalize(context, $ CYFunctionExpression(NULL, declarations_->Parameter(context), code_)), declarations_->Argument(context)));
572 }
573
574 CYString *CYModule::Replace(CYContext &context, const char *separator) const {
575 if (next_ == NULL)
576 return $ CYString(part_);
577 return $ CYString($pool.strcat(next_->Replace(context, separator)->Value(), separator, part_->Word(), NULL));
578 }
579
580 CYExpression *CYMultiply::Replace(CYContext &context) {
581 CYInfix::Replace(context);
582
583 if (CYNumber *lhn = lhs_->Number(context))
584 if (CYNumber *rhn = rhs_->Number(context))
585 return $D(lhn->Value() * rhn->Value());
586
587 return this;
588 }
589
590 namespace cy {
591 namespace Syntax {
592
593 CYExpression *New::AddArgument(CYContext &context, CYExpression *value) {
594 CYSetLast(arguments_) = $ CYArgument(value);
595 return this;
596 }
597
598 CYExpression *New::Replace(CYContext &context) {
599 context.Replace(constructor_);
600 arguments_->Replace(context);
601 return this;
602 }
603
604 } }
605
606 CYNumber *CYNull::Number(CYContext &context) {
607 return $D(0);
608 }
609
610 CYString *CYNull::String(CYContext &context) {
611 return $S("null");
612 }
613
614 CYNumber *CYNumber::Number(CYContext &context) {
615 return this;
616 }
617
618 CYString *CYNumber::String(CYContext &context) {
619 // XXX: there is a precise algorithm for this
620 return $S($pool.sprintf(24, "%.17g", Value()));
621 }
622
623 CYExpression *CYObject::Replace(CYContext &context) {
624 properties_->Replace(context);
625 return this;
626 }
627
628 CYExpression *CYParenthetical::Replace(CYContext &context) {
629 return expression_;
630 }
631
632 CYExpression *CYPostfix::Replace(CYContext &context) {
633 context.Replace(lhs_);
634 return this;
635 }
636
637 CYExpression *CYPrefix::Replace(CYContext &context) {
638 context.Replace(rhs_);
639 return this;
640 }
641
642 // XXX: this is evil evil black magic. don't ask, don't tell... don't believe!
643 #define MappingSet "0etnirsoalfucdphmgyvbxTwSNECAFjDLkMOIBPqzRH$_WXUVGYKQJZ"
644 //#define MappingSet "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_"
645
646 namespace {
647 struct IdentifierUsageLess :
648 std::binary_function<CYIdentifier *, CYIdentifier *, bool>
649 {
650 _finline bool operator ()(CYIdentifier *lhs, CYIdentifier *rhs) const {
651 if (lhs->usage_ != rhs->usage_)
652 return lhs->usage_ > rhs->usage_;
653 return lhs < rhs;
654 }
655 };
656
657 typedef std::set<CYIdentifier *, IdentifierUsageLess> IdentifierUsages;
658 }
659
660 void CYProgram::Replace(CYContext &context) {
661 CYScope scope(true, context);
662
663 context.nextlocal_ = $ CYNonLocal();
664 context.ReplaceAll(code_);
665 context.NonLocal(code_);
666
667 scope.Close(context, code_);
668
669 size_t offset(0);
670
671 CYCStringSet external;
672 for (CYIdentifierValueSet::const_iterator i(scope.identifiers_.begin()); i != scope.identifiers_.end(); ++i)
673 external.insert((*i)->Word());
674
675 IdentifierUsages usages;
676
677 if (offset < context.rename_.size())
678 CYForEach (i, context.rename_[offset].identifier_)
679 usages.insert(i);
680
681 // XXX: totalling the probable occurrences and sorting by them would improve the result
682 for (CYIdentifierUsageVector::const_iterator i(context.rename_.begin()); i != context.rename_.end(); ++i, ++offset) {
683 //std::cout << *i << ":" << (*i)->offset_ << std::endl;
684
685 const char *name;
686
687 if (context.options_.verbose_)
688 name = $pool.strcat("$", $pool.itoa(offset), NULL);
689 else {
690 char id[8];
691 id[7] = '\0';
692
693 id:
694 unsigned position(7), local(offset + 1);
695
696 do {
697 unsigned index(local % (sizeof(MappingSet) - 1));
698 local /= sizeof(MappingSet) - 1;
699 id[--position] = MappingSet[index];
700 } while (local != 0);
701
702 if (external.find(id + position) != external.end()) {
703 ++offset;
704 goto id;
705 }
706
707 name = $pool.strmemdup(id + position, 7 - position);
708 // XXX: at some point, this could become a keyword
709 }
710
711 CYForEach (identifier, i->identifier_)
712 identifier->Set(name);
713 }
714 }
715
716 void CYProperty::Replace(CYContext &context) { $T()
717 context.Replace(value_);
718 next_->Replace(context);
719 if (value_ == NULL)
720 value_ = $U;
721 }
722
723 CYStatement *CYReturn::Replace(CYContext &context) {
724 if (context.nonlocal_ != NULL) {
725 CYProperty *value(value_ == NULL ? NULL : $ CYProperty($S("$cyv"), value_));
726 return $ cy::Syntax::Throw($ CYObject(
727 $ CYProperty($S("$cyk"), $V(context.nonlocal_->Target(context)), value)
728 ));
729 }
730
731 context.Replace(value_);
732 return this;
733 }
734
735 CYExpression *CYRubyBlock::Replace(CYContext &context) {
736 return call_->AddArgument(context, proc_->Replace(context));
737 }
738
739 CYExpression *CYRubyProc::Replace(CYContext &context) {
740 CYFunctionExpression *function($ CYFunctionExpression(NULL, parameters_, code_));
741 function = CYNonLocalize(context, function);
742 function->implicit_ = true;
743 return function;
744 }
745
746 CYScope::CYScope(bool transparent, CYContext &context) :
747 transparent_(transparent),
748 parent_(context.scope_)
749 {
750 context.scope_ = this;
751 }
752
753 void CYScope::Declare(CYContext &context, CYIdentifier *identifier, CYIdentifierFlags flags) {
754 if (!transparent_ || flags == CYIdentifierArgument || flags == CYIdentifierCatch)
755 internal_.insert(CYIdentifierAddressFlagsMap::value_type(identifier, flags));
756 else if (parent_ != NULL)
757 parent_->Declare(context, identifier, flags);
758 }
759
760 CYIdentifier *CYScope::Lookup(CYContext &context, CYIdentifier *identifier) {
761 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
762 return *insert.first;
763 }
764
765 void CYScope::Merge(CYContext &context, CYIdentifier *identifier) {
766 std::pair<CYIdentifierValueSet::iterator, bool> insert(identifiers_.insert(identifier));
767 if (!insert.second) {
768 if ((*insert.first)->offset_ < identifier->offset_)
769 (*insert.first)->offset_ = identifier->offset_;
770 identifier->replace_ = *insert.first;
771 (*insert.first)->usage_ += identifier->usage_ + 1;
772 }
773 }
774
775 namespace {
776 struct IdentifierOffset {
777 size_t offset_;
778 CYIdentifierFlags flags_;
779 size_t usage_;
780 CYIdentifier *identifier_;
781
782 IdentifierOffset(CYIdentifier *identifier, CYIdentifierFlags flags) :
783 offset_(identifier->offset_),
784 flags_(flags),
785 usage_(identifier->usage_),
786 identifier_(identifier)
787 {
788 }
789 };
790
791 struct IdentifierOffsetLess :
792 std::binary_function<const IdentifierOffset &, const IdentifierOffset &, bool>
793 {
794 _finline bool operator ()(const IdentifierOffset &lhs, const IdentifierOffset &rhs) const {
795 if (lhs.offset_ != rhs.offset_)
796 return lhs.offset_ < rhs.offset_;
797 if (lhs.flags_ != rhs.flags_)
798 return lhs.flags_ < rhs.flags_;
799 /*if (lhs.usage_ != rhs.usage_)
800 return lhs.usage_ < rhs.usage_;*/
801 return lhs.identifier_ < rhs.identifier_;
802 }
803 };
804
805 typedef std::set<IdentifierOffset, IdentifierOffsetLess> IdentifierOffsets;
806 }
807
808 void CYScope::Close(CYContext &context, CYStatement *&statements) {
809 context.scope_ = parent_;
810
811 if (parent_ == NULL)
812 return;
813
814 CYDeclarations *last(NULL), *curr(NULL);
815
816 IdentifierOffsets offsets;
817
818 for (CYIdentifierAddressFlagsMap::const_iterator i(internal_.begin()); i != internal_.end(); ++i)
819 if (i->second != CYIdentifierMagic)
820 offsets.insert(IdentifierOffset(i->first, i->second));
821
822 size_t offset(0);
823
824 for (IdentifierOffsets::const_iterator i(offsets.begin()); i != offsets.end(); ++i) {
825 if (i->flags_ == CYIdentifierVariable) {
826 CYDeclarations *next($ CYDeclarations($ CYDeclaration(i->identifier_)));
827 if (last == NULL)
828 last = next;
829 if (curr != NULL)
830 curr->SetNext(next);
831 curr = next;
832 }
833
834 if (offset < i->offset_)
835 offset = i->offset_;
836 if (context.rename_.size() <= offset)
837 context.rename_.resize(offset + 1);
838
839 CYIdentifierUsage &rename(context.rename_[offset++]);
840 i->identifier_->SetNext(rename.identifier_);
841 rename.identifier_ = i->identifier_;
842 rename.usage_ += i->identifier_->usage_ + 1;
843 }
844
845 if (last != NULL) {
846 CYVar *var($ CYVar(last));
847 var->SetNext(statements);
848 statements = var;
849 }
850
851 for (CYIdentifierValueSet::const_iterator i(identifiers_.begin()); i != identifiers_.end(); ++i)
852 if (internal_.find(*i) == internal_.end()) {
853 //std::cout << *i << '=' << offset << std::endl;
854 if ((*i)->offset_ < offset)
855 (*i)->offset_ = offset;
856 parent_->Merge(context, *i);
857 }
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 *CYThis::Replace(CYContext &context) {
889 if (context.this_ != NULL)
890 return $V(context.this_->Identifier(context));
891 return this;
892 }
893
894 namespace cy {
895 namespace Syntax {
896
897 CYStatement *Throw::Replace(CYContext &context) {
898 context.Replace(value_);
899 return this;
900 }
901
902 } }
903
904 CYExpression *CYTrivial::Replace(CYContext &context) {
905 return this;
906 }
907
908 CYNumber *CYTrue::Number(CYContext &context) {
909 return $D(1);
910 }
911
912 CYString *CYTrue::String(CYContext &context) {
913 return $S("true");
914 }
915
916 namespace cy {
917 namespace Syntax {
918
919 CYStatement *Try::Replace(CYContext &context) {
920 context.ReplaceAll(code_);
921 catch_->Replace(context);
922 finally_->Replace(context);
923 return this;
924 }
925
926 } }
927
928 CYExpression *CYTypeArrayOf::Replace_(CYContext &context, CYExpression *type) {
929 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("arrayOf")), $ CYArgument(size_)));
930 }
931
932 CYExpression *CYTypeBlockWith::Replace_(CYContext &context, CYExpression *type) {
933 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("blockWith")), parameters_->Argument(context)));
934 }
935
936 CYExpression *CYTypeConstant::Replace_(CYContext &context, CYExpression *type) {
937 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant"))));
938 }
939
940 CYStatement *CYTypeDefinition::Replace(CYContext &context) {
941 return $E($ CYAssign($V(typed_->identifier_), typed_->Replace(context)));
942 }
943
944 CYExpression *CYTypeError::Replace(CYContext &context) {
945 _assert(false);
946 return NULL;
947 }
948
949 CYExpression *CYTypeModifier::Replace(CYContext &context, CYExpression *type) { $T(type)
950 return Replace_(context, type);
951 }
952
953 CYExpression *CYTypeFunctionWith::Replace_(CYContext &context, CYExpression *type) {
954 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context)));
955 }
956
957 CYExpression *CYTypeLong::Replace(CYContext &context) {
958 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("long")));
959 }
960
961 CYExpression *CYTypePointerTo::Replace_(CYContext &context, CYExpression *type) {
962 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo"))));
963 }
964
965 CYExpression *CYTypeShort::Replace(CYContext &context) {
966 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("short")));
967 }
968
969 CYExpression *CYTypeSigned::Replace(CYContext &context) {
970 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
971 }
972
973 CYExpression *CYTypeUnsigned::Replace(CYContext &context) {
974 return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
975 }
976
977 CYExpression *CYTypeVariable::Replace(CYContext &context) {
978 return $V(name_);
979 }
980
981 CYExpression *CYTypeVoid::Replace(CYContext &context) {
982 return $N1($V("Type"), $ CYString("v"));
983 }
984
985 CYExpression *CYTypeVolatile::Replace_(CYContext &context, CYExpression *type) {
986 return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("volatile"))));
987 }
988
989 CYExpression *CYTypedIdentifier::Replace(CYContext &context) {
990 return modifier_->Replace(context, specifier_->Replace(context));
991 }
992
993 CYTypeFunctionWith *CYTypedIdentifier::Function() {
994 CYTypeModifier **modifier(&modifier_);
995 if (*modifier == NULL)
996 return NULL;
997 while ((*modifier)->next_ != NULL)
998 modifier = &(*modifier)->next_;
999 CYTypeFunctionWith *function((*modifier)->Function());
1000 if (function == NULL)
1001 return NULL;
1002 *modifier = NULL;
1003 return function;
1004 }
1005
1006 CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL)
1007 return $ CYArgument(typed_->Replace(context), next_->Argument(context));
1008 }
1009
1010 CYFunctionParameter *CYTypedParameter::Parameters(CYContext &context) { $T(NULL)
1011 return $ CYFunctionParameter($ CYDeclaration(typed_->identifier_ ?: context.Unique()), next_->Parameters(context));
1012 }
1013
1014 CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *prefix) { $T(prefix)
1015 return next_->TypeSignature(context, $ CYAdd(prefix, typed_->Replace(context)));
1016 }
1017
1018 CYStatement *CYVar::Replace(CYContext &context) {
1019 declarations_->Replace(context);
1020 if (CYExpression *expression = declarations_->Expression(context))
1021 return $E(expression);
1022 return $ CYEmpty();
1023 }
1024
1025 CYExpression *CYVariable::Replace(CYContext &context) {
1026 context.Replace(name_);
1027 return this;
1028 }
1029
1030 CYFunctionParameter *CYVariable::Parameter() const {
1031 return $ CYFunctionParameter($ CYDeclaration(name_));
1032 }
1033
1034 CYStatement *CYWhile::Replace(CYContext &context) {
1035 context.Replace(test_);
1036 context.ReplaceAll(code_);
1037 return this;
1038 }
1039
1040 CYStatement *CYWith::Replace(CYContext &context) {
1041 context.Replace(scope_);
1042 context.ReplaceAll(code_);
1043 return this;
1044 }
1045
1046 CYExpression *CYWord::ClassName(CYContext &context, bool object) {
1047 CYString *name($S(this));
1048 if (object)
1049 return $C1($V("objc_getClass"), name);
1050 else
1051 return name;
1052 }