Properly fill the __annotations__ dictionary.

This commit is contained in:
Windel Bouwman 2019-08-07 16:13:12 +02:00
parent b22698a6f1
commit b6dd92daf6

View file

@ -358,33 +358,7 @@ impl Compiler {
}
self.set_label(end_label);
}
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);
}
While { test, body, orelse } => self.compile_while(test, body, orelse)?,
With {
is_async,
items,
@ -557,16 +531,7 @@ impl Compiler {
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)?;
}
}
} => self.compile_annotated_assign(target, annotation, value)?,
Delete { targets } => {
for target in targets {
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(
&mut self,
target: &ast::Expression,
@ -1133,6 +1132,39 @@ impl Compiler {
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> {
match &target.node {
ast::ExpressionType::Identifier { name } => {
@ -1276,6 +1308,8 @@ impl Compiler {
fn compile_expression(&mut self, expression: &ast::Expression) -> Result<(), CompileError> {
trace!("Compiling {:?}", expression);
self.set_source_location(&expression.location);
use ast::ExpressionType::*;
match &expression.node {
Call {