mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-19 11:05:45 +00:00
Make from __future__
imports a syntactic construct in the compiler
This commit is contained in:
parent
330fdce246
commit
a499fb775a
2 changed files with 52 additions and 0 deletions
|
@ -29,6 +29,7 @@ struct Compiler<O: OutputStream = BasicOutputStream> {
|
||||||
source_path: Option<String>,
|
source_path: Option<String>,
|
||||||
current_source_location: ast::Location,
|
current_source_location: ast::Location,
|
||||||
current_qualified_path: Option<String>,
|
current_qualified_path: Option<String>,
|
||||||
|
done_with_future_stmts: bool,
|
||||||
ctx: CompileContext,
|
ctx: CompileContext,
|
||||||
opts: CompileOpts,
|
opts: CompileOpts,
|
||||||
}
|
}
|
||||||
|
@ -166,6 +167,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
source_path: None,
|
source_path: None,
|
||||||
current_source_location: ast::Location::default(),
|
current_source_location: ast::Location::default(),
|
||||||
current_qualified_path: None,
|
current_qualified_path: None,
|
||||||
|
done_with_future_stmts: false,
|
||||||
ctx: CompileContext {
|
ctx: CompileContext {
|
||||||
in_loop: false,
|
in_loop: false,
|
||||||
func: FunctionContext::NoFunction,
|
func: FunctionContext::NoFunction,
|
||||||
|
@ -334,6 +336,16 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
self.set_source_location(statement.location);
|
self.set_source_location(statement.location);
|
||||||
use ast::StatementType::*;
|
use ast::StatementType::*;
|
||||||
|
|
||||||
|
match &statement.node {
|
||||||
|
// we do this here because `from __future__` still executes that `from` statement at runtime,
|
||||||
|
// we still need to compile the ImportFrom down below
|
||||||
|
ImportFrom { module, names, .. } if module.as_deref() == Some("__future__") => {
|
||||||
|
self.compile_future_features(&names)?
|
||||||
|
}
|
||||||
|
// if we find any other statement, stop accepting future statements
|
||||||
|
_ => self.done_with_future_stmts = true,
|
||||||
|
}
|
||||||
|
|
||||||
match &statement.node {
|
match &statement.node {
|
||||||
Import { names } => {
|
Import { names } => {
|
||||||
// import a, b, c as d
|
// import a, b, c as d
|
||||||
|
@ -2132,6 +2144,38 @@ impl<O: OutputStream> Compiler<O> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_future_features(
|
||||||
|
&mut self,
|
||||||
|
features: &[ast::ImportSymbol],
|
||||||
|
) -> Result<(), CompileError> {
|
||||||
|
if self.done_with_future_stmts {
|
||||||
|
return Err(CompileError {
|
||||||
|
error: CompileErrorType::InvalidFuturePlacement,
|
||||||
|
location: self.current_source_location.clone(),
|
||||||
|
source_path: self.source_path.clone(),
|
||||||
|
statement: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for feature in features {
|
||||||
|
match &*feature.symbol {
|
||||||
|
// Python 3 features; we've already implemented them by default
|
||||||
|
"nested_scopes" | "generators" | "division" | "absolute_import"
|
||||||
|
| "with_statement" | "print_function" | "unicode_literals" => {}
|
||||||
|
// "generator_stop" => {}
|
||||||
|
// "annotations" => {}
|
||||||
|
other => {
|
||||||
|
return Err(CompileError {
|
||||||
|
error: CompileErrorType::InvalidFutureFeature(other.to_owned()),
|
||||||
|
location: self.current_source_location.clone(),
|
||||||
|
source_path: self.source_path.clone(),
|
||||||
|
statement: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Scope helpers:
|
// Scope helpers:
|
||||||
fn enter_scope(&mut self) {
|
fn enter_scope(&mut self) {
|
||||||
// println!("Enter scope {:?}", self.symbol_table_stack);
|
// println!("Enter scope {:?}", self.symbol_table_stack);
|
||||||
|
|
|
@ -58,6 +58,8 @@ pub enum CompileErrorType {
|
||||||
InvalidAwait,
|
InvalidAwait,
|
||||||
AsyncYieldFrom,
|
AsyncYieldFrom,
|
||||||
AsyncReturnValue,
|
AsyncReturnValue,
|
||||||
|
InvalidFuturePlacement,
|
||||||
|
InvalidFutureFeature(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileError {
|
impl CompileError {
|
||||||
|
@ -106,6 +108,12 @@ impl fmt::Display for CompileError {
|
||||||
CompileErrorType::AsyncReturnValue => {
|
CompileErrorType::AsyncReturnValue => {
|
||||||
"'return' with value inside async generator".to_owned()
|
"'return' with value inside async generator".to_owned()
|
||||||
}
|
}
|
||||||
|
CompileErrorType::InvalidFuturePlacement => {
|
||||||
|
"from __future__ imports must occur at the beginning of the file".to_owned()
|
||||||
|
}
|
||||||
|
CompileErrorType::InvalidFutureFeature(feat) => {
|
||||||
|
format!("future feature {} is not defined", feat)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(statement) = &self.statement {
|
if let Some(statement) = &self.statement {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue