Add symboltable scope for comprehensions. Add _ast module nodes for comprehensions.

This commit is contained in:
Windel Bouwman 2019-09-01 22:31:16 +02:00
parent efecef9d48
commit 024cf5db04
2 changed files with 34 additions and 1 deletions

View file

@ -588,6 +588,23 @@ impl SymbolTableBuilder {
self.scan_expressions(elements, context)?;
}
Comprehension { kind, generators } => {
// Comprehensions are compiled as functions, so create a scope for them:
let scope_name = match **kind {
ast::ComprehensionKind::GeneratorExpression { .. } => "genexpr",
ast::ComprehensionKind::List { .. } => "listcomp",
ast::ComprehensionKind::Set { .. } => "setcomp",
ast::ComprehensionKind::Dict { .. } => "dictcomp",
};
self.enter_scope(
scope_name,
SymbolTableType::Function,
expression.location.row(),
);
// Register the passed argument to the generator function as the name ".0"
self.register_name(".0", SymbolUsage::Parameter)?;
match **kind {
ast::ComprehensionKind::GeneratorExpression { ref element }
| ast::ComprehensionKind::List { ref element }
@ -600,13 +617,25 @@ impl SymbolTableBuilder {
}
}
let mut is_first_generator = true;
for generator in generators {
self.scan_expression(&generator.target, &ExpressionContext::Store)?;
self.scan_expression(&generator.iter, &ExpressionContext::Load)?;
if is_first_generator {
is_first_generator = false;
} else {
self.scan_expression(&generator.iter, &ExpressionContext::Load)?;
}
for if_expr in &generator.ifs {
self.scan_expression(if_expr, &ExpressionContext::Load)?;
}
}
self.leave_scope();
// The first iterable is passed as an argument into the created function:
assert!(!generators.is_empty());
self.scan_expression(&generators[0].iter, &ExpressionContext::Load)?;
}
Call {
function,