Skip to content

Commit b36bbfa

Browse files
committed
Add symboltable scope for comprehensions. Add _ast module nodes for comprehensions.
1 parent ba9736b commit b36bbfa

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

compiler/src/compile.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,7 @@ impl<O: OutputStream> Compiler<O> {
17821782
line_number,
17831783
name.clone(),
17841784
));
1785+
self.enter_scope();
17851786

17861787
// Create empty object of proper type:
17871788
match kind {
@@ -1891,6 +1892,9 @@ impl<O: OutputStream> Compiler<O> {
18911892
// Fetch code for listcomp function:
18921893
let code = self.pop_code_object();
18931894

1895+
// Pop scope
1896+
self.leave_scope();
1897+
18941898
// List comprehension code:
18951899
self.emit(Instruction::LoadConst {
18961900
value: bytecode::Constant::Code {

compiler/src/symboltable.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,23 @@ impl SymbolTableBuilder {
588588
self.scan_expressions(elements, context)?;
589589
}
590590
Comprehension { kind, generators } => {
591+
// Comprehensions are compiled as functions, so create a scope for them:
592+
let scope_name = match **kind {
593+
ast::ComprehensionKind::GeneratorExpression { .. } => "genexpr",
594+
ast::ComprehensionKind::List { .. } => "listcomp",
595+
ast::ComprehensionKind::Set { .. } => "setcomp",
596+
ast::ComprehensionKind::Dict { .. } => "dictcomp",
597+
};
598+
599+
self.enter_scope(
600+
scope_name,
601+
SymbolTableType::Function,
602+
expression.location.row(),
603+
);
604+
605+
// Register the passed argument to the generator function as the name ".0"
606+
self.register_name(".0", SymbolUsage::Parameter)?;
607+
591608
match **kind {
592609
ast::ComprehensionKind::GeneratorExpression { ref element }
593610
| ast::ComprehensionKind::List { ref element }
@@ -600,13 +617,25 @@ impl SymbolTableBuilder {
600617
}
601618
}
602619

620+
let mut is_first_generator = true;
603621
for generator in generators {
604622
self.scan_expression(&generator.target, &ExpressionContext::Store)?;
605-
self.scan_expression(&generator.iter, &ExpressionContext::Load)?;
623+
if is_first_generator {
624+
is_first_generator = false;
625+
} else {
626+
self.scan_expression(&generator.iter, &ExpressionContext::Load)?;
627+
}
628+
606629
for if_expr in &generator.ifs {
607630
self.scan_expression(if_expr, &ExpressionContext::Load)?;
608631
}
609632
}
633+
634+
self.leave_scope();
635+
636+
// The first iterable is passed as an argument into the created function:
637+
assert!(!generators.is_empty());
638+
self.scan_expression(&generators[0].iter, &ExpressionContext::Load)?;
610639
}
611640
Call {
612641
function,

vm/src/stdlib/ast.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -456,18 +456,25 @@ fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyRes
456456
let py_generators = map_ast(comprehension_to_ast, vm, generators)?;
457457

458458
match kind.deref() {
459-
ast::ComprehensionKind::GeneratorExpression { .. } => {
460-
node!(vm, GeneratorExp, {generators => py_generators})
461-
}
462-
ast::ComprehensionKind::List { .. } => {
463-
node!(vm, ListComp, {generators => py_generators})
464-
}
465-
ast::ComprehensionKind::Set { .. } => {
466-
node!(vm, SetComp, {generators => py_generators})
467-
}
468-
ast::ComprehensionKind::Dict { .. } => {
469-
node!(vm, DictComp, {generators => py_generators})
459+
ast::ComprehensionKind::GeneratorExpression { element } => {
460+
node!(vm, GeneratorExp, {
461+
elt => expression_to_ast(vm, element)?,
462+
generators => py_generators
463+
})
470464
}
465+
ast::ComprehensionKind::List { element } => node!(vm, ListComp, {
466+
elt => expression_to_ast(vm, element)?,
467+
generators => py_generators
468+
}),
469+
ast::ComprehensionKind::Set { element } => node!(vm, SetComp, {
470+
elt => expression_to_ast(vm, element)?,
471+
generators => py_generators
472+
}),
473+
ast::ComprehensionKind::Dict { key, value } => node!(vm, DictComp, {
474+
key => expression_to_ast(vm, key)?,
475+
value => expression_to_ast(vm, value)?,
476+
generators => py_generators
477+
}),
471478
}
472479
}
473480
Await { value } => {

0 commit comments

Comments
 (0)