mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-10 06:35:17 +00:00
Merge pull request #1215 from RustPython/syntax-fixes
Add variable annotation syntax.
This commit is contained in:
commit
dd53fe8f89
2 changed files with 90 additions and 27 deletions
106
src/compile.rs
106
src/compile.rs
|
@ -368,33 +368,7 @@ impl<O: OutputStream> Compiler<O> {
|
|||
}
|
||||
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,
|
||||
|
@ -563,6 +537,11 @@ impl<O: OutputStream> Compiler<O> {
|
|||
self.compile_op(op, true);
|
||||
self.compile_store(target)?;
|
||||
}
|
||||
AnnAssign {
|
||||
target,
|
||||
annotation,
|
||||
value,
|
||||
} => self.compile_annotated_assign(target, annotation, value)?,
|
||||
Delete { targets } => {
|
||||
for target in targets {
|
||||
self.compile_delete(target)?;
|
||||
|
@ -1011,6 +990,40 @@ impl<O: OutputStream> Compiler<O> {
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -1129,6 +1142,39 @@ impl<O: OutputStream> Compiler<O> {
|
|||
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 } => {
|
||||
|
@ -1272,6 +1318,8 @@ impl<O: OutputStream> Compiler<O> {
|
|||
|
||||
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 {
|
||||
|
@ -1664,6 +1712,10 @@ impl<O: OutputStream> Compiler<O> {
|
|||
|
||||
let mut loop_labels = vec![];
|
||||
for generator in generators {
|
||||
if generator.is_async {
|
||||
unimplemented!("async for comprehensions");
|
||||
}
|
||||
|
||||
if loop_labels.is_empty() {
|
||||
// Load iterator onto stack (passed as first argument):
|
||||
self.emit(Instruction::LoadName {
|
||||
|
|
|
@ -335,6 +335,17 @@ impl SymbolTableBuilder {
|
|||
self.scan_expression(target)?;
|
||||
self.scan_expression(value)?;
|
||||
}
|
||||
AnnAssign {
|
||||
target,
|
||||
annotation,
|
||||
value,
|
||||
} => {
|
||||
self.scan_expression(target)?;
|
||||
self.scan_expression(annotation)?;
|
||||
if let Some(value) = value {
|
||||
self.scan_expression(value)?;
|
||||
}
|
||||
}
|
||||
With { items, body, .. } => {
|
||||
for item in items {
|
||||
self.scan_expression(&item.context_expr)?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue