mirror of
https://github.com/RustPython/Parser.git
synced 2025-08-31 23:57:57 +00:00
Properly fill the __annotations__ dictionary.
This commit is contained in:
parent
b22698a6f1
commit
b6dd92daf6
1 changed files with 71 additions and 37 deletions
108
src/compile.rs
108
src/compile.rs
|
@ -358,33 +358,7 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
self.set_label(end_label);
|
self.set_label(end_label);
|
||||||
}
|
}
|
||||||
While { test, body, orelse } => {
|
While { test, body, orelse } => self.compile_while(test, body, orelse)?,
|
||||||
let start_label = self.new_label();
|
|
||||||
let else_label = self.new_label();
|
|
||||||
let end_label = self.new_label();
|
|
||||||
self.emit(Instruction::SetupLoop {
|
|
||||||
start: start_label,
|
|
||||||
end: end_label,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.set_label(start_label);
|
|
||||||
|
|
||||||
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
|
|
||||||
|
|
||||||
let was_in_loop = self.in_loop;
|
|
||||||
self.in_loop = true;
|
|
||||||
self.compile_statements(body)?;
|
|
||||||
self.in_loop = was_in_loop;
|
|
||||||
self.emit(Instruction::Jump {
|
|
||||||
target: start_label,
|
|
||||||
});
|
|
||||||
self.set_label(else_label);
|
|
||||||
self.emit(Instruction::PopBlock);
|
|
||||||
if let Some(orelse) = orelse {
|
|
||||||
self.compile_statements(orelse)?;
|
|
||||||
}
|
|
||||||
self.set_label(end_label);
|
|
||||||
}
|
|
||||||
With {
|
With {
|
||||||
is_async,
|
is_async,
|
||||||
items,
|
items,
|
||||||
|
@ -557,16 +531,7 @@ impl Compiler {
|
||||||
target,
|
target,
|
||||||
annotation,
|
annotation,
|
||||||
value,
|
value,
|
||||||
} => {
|
} => self.compile_annotated_assign(target, annotation, value)?,
|
||||||
// Throw away annotation:
|
|
||||||
self.compile_expression(annotation)?;
|
|
||||||
self.emit(Instruction::Pop);
|
|
||||||
|
|
||||||
if let Some(value) = value {
|
|
||||||
self.compile_expression(value)?;
|
|
||||||
self.compile_store(target)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Delete { targets } => {
|
Delete { targets } => {
|
||||||
for target in targets {
|
for target in targets {
|
||||||
self.compile_delete(target)?;
|
self.compile_delete(target)?;
|
||||||
|
@ -1015,6 +980,40 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_while(
|
||||||
|
&mut self,
|
||||||
|
test: &ast::Expression,
|
||||||
|
body: &[ast::Statement],
|
||||||
|
orelse: &Option<Vec<ast::Statement>>,
|
||||||
|
) -> Result<(), CompileError> {
|
||||||
|
let start_label = self.new_label();
|
||||||
|
let else_label = self.new_label();
|
||||||
|
let end_label = self.new_label();
|
||||||
|
self.emit(Instruction::SetupLoop {
|
||||||
|
start: start_label,
|
||||||
|
end: end_label,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.set_label(start_label);
|
||||||
|
|
||||||
|
self.compile_test(test, None, Some(else_label), EvalContext::Statement)?;
|
||||||
|
|
||||||
|
let was_in_loop = self.in_loop;
|
||||||
|
self.in_loop = true;
|
||||||
|
self.compile_statements(body)?;
|
||||||
|
self.in_loop = was_in_loop;
|
||||||
|
self.emit(Instruction::Jump {
|
||||||
|
target: start_label,
|
||||||
|
});
|
||||||
|
self.set_label(else_label);
|
||||||
|
self.emit(Instruction::PopBlock);
|
||||||
|
if let Some(orelse) = orelse {
|
||||||
|
self.compile_statements(orelse)?;
|
||||||
|
}
|
||||||
|
self.set_label(end_label);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_for(
|
fn compile_for(
|
||||||
&mut self,
|
&mut self,
|
||||||
target: &ast::Expression,
|
target: &ast::Expression,
|
||||||
|
@ -1133,6 +1132,39 @@ impl Compiler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compile_annotated_assign(
|
||||||
|
&mut self,
|
||||||
|
target: &ast::Expression,
|
||||||
|
annotation: &ast::Expression,
|
||||||
|
value: &Option<ast::Expression>,
|
||||||
|
) -> Result<(), CompileError> {
|
||||||
|
if let Some(value) = value {
|
||||||
|
self.compile_expression(value)?;
|
||||||
|
self.compile_store(target)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile annotation:
|
||||||
|
self.compile_expression(annotation)?;
|
||||||
|
|
||||||
|
if let ast::ExpressionType::Identifier { name } = &target.node {
|
||||||
|
// Store as dict entry in __annotations__ dict:
|
||||||
|
self.emit(Instruction::LoadName {
|
||||||
|
name: String::from("__annotations__"),
|
||||||
|
scope: bytecode::NameScope::Local,
|
||||||
|
});
|
||||||
|
self.emit(Instruction::LoadConst {
|
||||||
|
value: bytecode::Constant::String {
|
||||||
|
value: name.to_string(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
self.emit(Instruction::StoreSubscript);
|
||||||
|
} else {
|
||||||
|
// Drop annotation if not assigned to simple identifier.
|
||||||
|
self.emit(Instruction::Pop);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn compile_store(&mut self, target: &ast::Expression) -> Result<(), CompileError> {
|
fn compile_store(&mut self, target: &ast::Expression) -> Result<(), CompileError> {
|
||||||
match &target.node {
|
match &target.node {
|
||||||
ast::ExpressionType::Identifier { name } => {
|
ast::ExpressionType::Identifier { name } => {
|
||||||
|
@ -1276,6 +1308,8 @@ impl Compiler {
|
||||||
|
|
||||||
fn compile_expression(&mut self, expression: &ast::Expression) -> Result<(), CompileError> {
|
fn compile_expression(&mut self, expression: &ast::Expression) -> Result<(), CompileError> {
|
||||||
trace!("Compiling {:?}", expression);
|
trace!("Compiling {:?}", expression);
|
||||||
|
self.set_source_location(&expression.location);
|
||||||
|
|
||||||
use ast::ExpressionType::*;
|
use ast::ExpressionType::*;
|
||||||
match &expression.node {
|
match &expression.node {
|
||||||
Call {
|
Call {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue