@@ -20,6 +20,7 @@ limitations under the License.
20
20
#include " desugarer.h"
21
21
#include " lexer.h"
22
22
#include " parser.h"
23
+ #include " pass.h"
23
24
#include " string_utils.h"
24
25
25
26
static const Fodder EF; // Empty fodder.
@@ -199,7 +200,11 @@ class Desugarer {
199
200
}
200
201
}
201
202
202
- void desugarFields (AST *ast, ObjectFields &fields, unsigned obj_level)
203
+ // For all occurrences, records the identifier that will replace super[e]
204
+ // If self occurs, also map the self identifier to nullptr.
205
+ typedef std::vector<std::pair<const Identifier *, AST *>> SuperVars;
206
+
207
+ SuperVars desugarFields (AST *ast, ObjectFields &fields, unsigned obj_level)
203
208
{
204
209
// Desugar children
205
210
for (auto &field : fields) {
@@ -283,15 +288,59 @@ class Desugarer {
283
288
}
284
289
}
285
290
291
+ class SubstituteSelfSuper : public CompilerPass {
292
+ Desugarer *desugarer;
293
+ SuperVars &superVars;
294
+ unsigned &counter;
295
+ const Identifier *newSelf;
296
+ public:
297
+ SubstituteSelfSuper (Desugarer *desugarer, SuperVars &super_vars, unsigned &counter)
298
+ : CompilerPass(*desugarer->alloc), desugarer(desugarer), superVars(super_vars),
299
+ counter (counter), newSelf(nullptr )
300
+ {
301
+ }
302
+ void visitExpr (AST *&expr)
303
+ {
304
+ if (dynamic_cast <Self*>(expr)) {
305
+ if (newSelf == nullptr ) {
306
+ newSelf = desugarer->id (U" $outer_self" );
307
+ superVars.emplace_back (newSelf, nullptr );
308
+ }
309
+ expr = alloc.make <Var>(expr->location , expr->openFodder , newSelf);
310
+ } else if (auto *super_index = dynamic_cast <SuperIndex*>(expr)) {
311
+ StringStream ss;
312
+ ss << " $outer_super" << (counter++);
313
+ const Identifier *super_var = desugarer->id (ss.str ());
314
+ AST *index = super_index->index ;
315
+ // Desugaring of expr should already have occurred.
316
+ assert (index != nullptr );
317
+ // Re-use super_index since we're replacing it here.
318
+ superVars.emplace_back (super_var, super_index);
319
+ expr = alloc.make <Var>(expr->location , expr->openFodder , super_var);
320
+ }
321
+ CompilerPass::visitExpr (expr);
322
+ }
323
+ };
324
+
325
+ SuperVars super_vars;
326
+ unsigned counter;
327
+
286
328
// Remove +:
287
329
for (auto &field : fields) {
288
330
if (!field.superSugar ) continue ;
289
- AST *super_f = make<SuperIndex>(field.expr1 ->location , EF, EF, field.expr1 , EF,
290
- nullptr );
291
- field.expr2 = make<Binary>(ast->location , EF, super_f, EF, BOP_PLUS,
292
- field.expr2 );
331
+ // We have to bind self/super from expr1 outside the class, as we copy the expression
332
+ // into the field body.
333
+ AST *index = field.expr1 ;
334
+ // Clone it so that we maintain the AST as a tree.
335
+ ClonePass (*alloc).expr (index );
336
+ // This will remove self/super.
337
+ SubstituteSelfSuper (this , super_vars, counter).expr (index );
338
+ AST *super_f = make<SuperIndex>(field.expr1 ->location , EF, EF, index , EF, nullptr );
339
+ field.expr2 = make<Binary>(ast->location , EF, super_f, EF, BOP_PLUS, field.expr2 );
293
340
field.superSugar = false ;
294
341
}
342
+
343
+ return super_vars;
295
344
}
296
345
297
346
void desugar (AST *&ast_, unsigned obj_level)
@@ -305,7 +354,7 @@ class Desugarer {
305
354
desugar (ast->left , obj_level);
306
355
desugar (ast->right , obj_level);
307
356
ast_ = make<Binary>(ast->location , ast->openFodder ,
308
- ast->left , EF, BOP_PLUS, ast->right );
357
+ ast->left , EF, BOP_PLUS, ast->right );
309
358
310
359
} else if (auto *ast = dynamic_cast <Array*>(ast_)) {
311
360
for (auto &el : ast->elements )
@@ -406,11 +455,11 @@ class Desugarer {
406
455
[[[...out...]]]
407
456
else
408
457
local [[[...var...]]] = $l[i_{i}];
409
- [[[...in...]]];`
410
- if std.type($l) ! = "array" then
411
- error "In comprehension, can only iterate over array.."
458
+ [[[...in...]]];
459
+ if std.type($l) = = "array" then
460
+ aux_{i}(0, $r) tailstrict
412
461
else
413
- aux_{i}(0, r) tailstrict ;
462
+ error "In comprehension, can only iterate over array.." ;
414
463
*/
415
464
in = make<Local>(
416
465
ast->location ,
@@ -635,7 +684,7 @@ class Desugarer {
635
684
ast->fields .push_back (ObjectField::Local (EF, EF, hidden_var, EF, body, EF));
636
685
}
637
686
638
- desugarFields (ast, ast->fields , obj_level);
687
+ SuperVars svs = desugarFields (ast, ast->fields , obj_level);
639
688
640
689
DesugaredObject::Fields new_fields;
641
690
ASTs new_asserts;
@@ -650,6 +699,19 @@ class Desugarer {
650
699
}
651
700
}
652
701
ast_ = make<DesugaredObject>(ast->location , new_asserts, new_fields);
702
+ if (svs.size () > 0 ) {
703
+ Local::Binds binds;
704
+ for (const auto &pair : svs) {
705
+ if (pair.second == nullptr ) {
706
+ // Self binding
707
+ binds.push_back (bind (pair.first , make<Self>(E, EF)));
708
+ } else {
709
+ // Super binding
710
+ binds.push_back (bind (pair.first , pair.second ));
711
+ }
712
+ }
713
+ ast_ = make<Local>(ast->location , EF, binds, ast_);
714
+ }
653
715
654
716
} else if (auto *ast = dynamic_cast <ObjectComprehension*>(ast_)) {
655
717
// Hidden variable to allow outer/top binding.
@@ -659,7 +721,7 @@ class Desugarer {
659
721
ast->fields .push_back (ObjectField::Local (EF, EF, hidden_var, EF, body, EF));
660
722
}
661
723
662
- desugarFields (ast, ast->fields , obj_level);
724
+ SuperVars svs = desugarFields (ast, ast->fields , obj_level);
663
725
664
726
for (ComprehensionSpec &spec : ast->specs )
665
727
desugar (spec.expr , obj_level);
0 commit comments