Simplify import AST in line with CPython.

This commit is contained in:
Windel Bouwman 2019-07-15 21:00:28 +02:00
parent 5e468baa16
commit 69c4d0b240
2 changed files with 58 additions and 66 deletions

View file

@ -267,61 +267,63 @@ impl Compiler {
self.set_source_location(&statement.location); self.set_source_location(&statement.location);
match &statement.node { match &statement.node {
ast::Statement::Import { import_parts } => { ast::Statement::Import { names } => {
for ast::SingleImport { // import a, b, c as d
module, for name in names {
symbols, self.emit(Instruction::Import {
alias, name: name.symbol.clone(),
level, symbols: vec![],
} in import_parts level: 0,
{ });
let level = *level;
if let Some(alias) = alias { if let Some(alias) = &name.alias {
// import module as alias self.store_name(alias);
self.emit(Instruction::Import {
name: module.clone(),
symbols: vec![],
level,
});
self.store_name(&alias);
} else if symbols.is_empty() {
// import module
self.emit(Instruction::Import {
name: module.clone(),
symbols: vec![],
level,
});
self.store_name(&module.clone());
} else { } else {
let import_star = symbols self.store_name(&name.symbol);
.iter() }
.any(|import_symbol| import_symbol.symbol == "*"); }
if import_star { }
// from module import * ast::Statement::ImportFrom {
self.emit(Instruction::ImportStar { level,
name: module.clone(), module,
level, names,
}); } => {
let import_star = names.iter().any(|n| n.symbol == "*");
if import_star {
// from .... import *
self.emit(Instruction::ImportStar {
name: module.clone().unwrap(),
level: *level,
});
} else {
// from mod import a, b as c
// First, determine the fromlist (for import lib):
let from_list = names.iter().map(|n| n.symbol.clone()).collect();
// Load module once:
self.emit(Instruction::Import {
name: module.clone().unwrap(),
symbols: from_list,
level: *level,
});
for name in names {
// import symbol from module:
self.emit(Instruction::ImportFrom {
name: name.symbol.to_string(),
});
// Store module under proper name:
if let Some(alias) = &name.alias {
self.store_name(alias);
} else { } else {
// from module import symbol self.store_name(&name.symbol);
// from module import symbol as alias
let (names, symbols_strings): (Vec<String>, Vec<String>) = symbols
.iter()
.map(|ast::ImportSymbol { symbol, alias }| {
(
alias.clone().unwrap_or_else(|| symbol.to_string()),
symbol.to_string(),
)
})
.unzip();
self.emit(Instruction::Import {
name: module.clone(),
symbols: symbols_strings,
level,
});
names.iter().rev().for_each(|name| self.store_name(&name));
} }
} }
// Pop module from stack:
self.emit(Instruction::Pop);
} }
} }
ast::Statement::Expression { expression } => { ast::Statement::Expression { expression } => {

View file

@ -296,24 +296,14 @@ impl SymbolTableBuilder {
ast::Statement::Break | ast::Statement::Continue | ast::Statement::Pass => { ast::Statement::Break | ast::Statement::Continue | ast::Statement::Pass => {
// No symbols here. // No symbols here.
} }
ast::Statement::Import { import_parts } => { ast::Statement::Import { names } | ast::Statement::ImportFrom { names, .. } => {
for part in import_parts { for name in names {
if let Some(alias) = &part.alias { if let Some(alias) = &name.alias {
// `import mymodule as myalias` // `import mymodule as myalias`
self.register_name(alias, SymbolRole::Assigned)?; self.register_name(alias, SymbolRole::Assigned)?;
} else if part.symbols.is_empty() {
// `import module`
self.register_name(&part.module, SymbolRole::Assigned)?;
} else { } else {
// `from mymodule import myimport` // `import module`
for symbol in &part.symbols { self.register_name(&name.symbol, SymbolRole::Assigned)?;
if let Some(alias) = &symbol.alias {
// `from mymodule import myimportname as myalias`
self.register_name(alias, SymbolRole::Assigned)?;
} else {
self.register_name(&symbol.symbol, SymbolRole::Assigned)?;
}
}
} }
} }
} }