Implement new features for updated python asdl

This commit is contained in:
Jeong YunWon 2022-08-12 05:24:19 +09:00
parent 308c82a935
commit 266b1f1aea
3 changed files with 52 additions and 40 deletions

View file

@ -680,6 +680,7 @@ impl Compiler {
orelse, orelse,
.. ..
} => self.compile_for(target, iter, body, orelse, true)?, } => self.compile_for(target, iter, body, orelse, true)?,
Match { subject, cases } => self.compile_match(subject, cases)?,
Raise { exc, cause } => { Raise { exc, cause } => {
let kind = match exc { let kind = match exc {
Some(value) => { Some(value) => {
@ -881,17 +882,19 @@ impl Compiler {
}); });
} }
let mut num_kw_only_defaults = 0; if !args.kw_defaults.is_empty() {
for (kw, default) in args.kwonlyargs.iter().zip(&args.kw_defaults) { let required_kw_count = args.kwonlyargs.len().saturating_sub(args.kw_defaults.len());
for (kw, default) in args.kwonlyargs[required_kw_count..]
.iter()
.zip(&args.kw_defaults)
{
self.emit_constant(ConstantData::Str { self.emit_constant(ConstantData::Str {
value: kw.node.arg.clone(), value: kw.node.arg.clone(),
}); });
self.compile_expression(default)?; self.compile_expression(default)?;
num_kw_only_defaults += 1;
} }
if num_kw_only_defaults > 0 {
self.emit(Instruction::BuildMap { self.emit(Instruction::BuildMap {
size: num_kw_only_defaults, size: args.kw_defaults.len() as u32,
unpack: false, unpack: false,
for_call: false, for_call: false,
}); });
@ -901,7 +904,7 @@ impl Compiler {
if have_defaults { if have_defaults {
funcflags |= bytecode::MakeFunctionFlags::DEFAULTS; funcflags |= bytecode::MakeFunctionFlags::DEFAULTS;
} }
if num_kw_only_defaults > 0 { if !args.kw_defaults.is_empty() {
funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS; funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS;
} }
@ -1519,6 +1522,16 @@ impl Compiler {
Ok(()) Ok(())
} }
fn compile_match(
&mut self,
subject: &ast::Expr,
cases: &[ast::MatchCase],
) -> CompileResult<()> {
eprintln!("match subject: {subject:?}");
eprintln!("match cases: {cases:?}");
Err(self.error(CompileErrorType::NotImplementedYet))
}
fn compile_chained_comparison( fn compile_chained_comparison(
&mut self, &mut self,
left: &ast::Expr, left: &ast::Expr,
@ -1928,11 +1941,7 @@ impl Compiler {
Ok(()) Ok(())
} }
fn compile_dict( fn compile_dict(&mut self, keys: &[ast::Expr], values: &[ast::Expr]) -> CompileResult<()> {
&mut self,
keys: &[ast::Expr],
values: &[ast::Expr],
) -> CompileResult<()> {
let mut size = 0; let mut size = 0;
let (packed_values, unpacked_values) = values.split_at(keys.len()); let (packed_values, unpacked_values) = values.split_at(keys.len());
@ -2099,7 +2108,7 @@ impl Compiler {
}; };
self.compile_expression(value)?; self.compile_expression(value)?;
self.emit(Instruction::FormatValue { self.emit(Instruction::FormatValue {
conversion: compile_conversion_flag(*conversion), conversion: (*conversion).try_into().expect("invalid conversion flag"),
}); });
} }
Name { id, .. } => self.load_name(id)?, Name { id, .. } => self.load_name(id)?,
@ -2454,7 +2463,7 @@ impl Compiler {
let mut loop_labels = vec![]; let mut loop_labels = vec![];
for generator in generators { for generator in generators {
if generator.is_async { if generator.is_async > 0 {
unimplemented!("async for comprehensions"); unimplemented!("async for comprehensions");
} }
@ -2543,7 +2552,7 @@ impl Compiler {
return Err(self.error(CompileErrorType::InvalidFuturePlacement)); return Err(self.error(CompileErrorType::InvalidFuturePlacement));
} }
for feature in features { for feature in features {
match &*feature.name { match &*feature.node.name {
// Python 3 features; we've already implemented them by default // Python 3 features; we've already implemented them by default
"nested_scopes" | "generators" | "division" | "absolute_import" "nested_scopes" | "generators" | "division" | "absolute_import"
| "with_statement" | "print_function" | "unicode_literals" => {} | "with_statement" | "print_function" | "unicode_literals" => {}
@ -2667,17 +2676,6 @@ fn compile_location(location: &ast::Location) -> bytecode::Location {
bytecode::Location::new(location.row(), location.column()) bytecode::Location::new(location.row(), location.column())
} }
fn compile_conversion_flag(
conversion_flag: Option<ast::ConversionFlag>,
) -> bytecode::ConversionFlag {
match conversion_flag {
None => bytecode::ConversionFlag::None,
Some(ast::ConversionFlag::Ascii) => bytecode::ConversionFlag::Ascii,
Some(ast::ConversionFlag::Repr) => bytecode::ConversionFlag::Repr,
Some(ast::ConversionFlag::Str) => bytecode::ConversionFlag::Str,
}
}
fn compile_constant(value: &ast::Constant) -> ConstantData { fn compile_constant(value: &ast::Constant) -> ConstantData {
match value { match value {
ast::Constant::None => ConstantData::None, ast::Constant::None => ConstantData::None,

View file

@ -37,6 +37,7 @@ pub enum CompileErrorType {
TooManyStarUnpack, TooManyStarUnpack,
EmptyWithItems, EmptyWithItems,
EmptyWithBody, EmptyWithBody,
NotImplementedYet, // RustPython marker for unimplemented features
} }
impl fmt::Display for CompileErrorType { impl fmt::Display for CompileErrorType {
@ -78,6 +79,9 @@ impl fmt::Display for CompileErrorType {
CompileErrorType::EmptyWithBody => { CompileErrorType::EmptyWithBody => {
write!(f, "empty body on With") write!(f, "empty body on With")
} }
CompileErrorType::NotImplementedYet => {
write!(f, "RustPython does not implement this feature yet")
}
} }
} }
} }

View file

@ -639,7 +639,7 @@ impl SymbolTableBuilder {
if let ImportFrom { module, names, .. } = &statement.node { if let ImportFrom { module, names, .. } = &statement.node {
if module.as_deref() == Some("__future__") { if module.as_deref() == Some("__future__") {
for feature in names { for feature in names {
if feature.name == "annotations" { if feature.node.name == "annotations" {
self.future_annotations = true; self.future_annotations = true;
} }
} }
@ -739,13 +739,13 @@ impl SymbolTableBuilder {
} }
Import { names } | ImportFrom { names, .. } => { Import { names } | ImportFrom { names, .. } => {
for name in names { for name in names {
if let Some(alias) = &name.asname { if let Some(alias) = &name.node.asname {
// `import mymodule as myalias` // `import mymodule as myalias`
self.register_name(alias, SymbolUsage::Imported, location)?; self.register_name(alias, SymbolUsage::Imported, location)?;
} else { } else {
// `import module` // `import module`
self.register_name( self.register_name(
name.name.split('.').next().unwrap(), name.node.name.split('.').next().unwrap(),
SymbolUsage::Imported, SymbolUsage::Imported,
location, location,
)?; )?;
@ -782,7 +782,7 @@ impl SymbolTableBuilder {
} => { } => {
// https://github.com/python/cpython/blob/main/Python/symtable.c#L1233 // https://github.com/python/cpython/blob/main/Python/symtable.c#L1233
match &target.node { match &target.node {
ast::ExprKind::Name { id, .. } if *simple => { ast::ExprKind::Name { id, .. } if *simple > 0 => {
self.register_name(id, SymbolUsage::AnnotationAssigned, location)?; self.register_name(id, SymbolUsage::AnnotationAssigned, location)?;
} }
_ => { _ => {
@ -823,6 +823,15 @@ impl SymbolTableBuilder {
self.scan_statements(orelse)?; self.scan_statements(orelse)?;
self.scan_statements(finalbody)?; self.scan_statements(finalbody)?;
} }
Match {
subject: _,
cases: _,
} => {
return Err(SymbolTableError {
error: "match expression is not implemented yet".to_owned(),
location: Location::default(),
});
}
Raise { exc, cause } => { Raise { exc, cause } => {
if let Some(expression) = exc { if let Some(expression) = exc {
self.scan_expression(expression, ExpressionContext::Load)?; self.scan_expression(expression, ExpressionContext::Load)?;
@ -875,12 +884,13 @@ impl SymbolTableBuilder {
self.scan_expression(value, ExpressionContext::Load)?; self.scan_expression(value, ExpressionContext::Load)?;
} }
Dict { keys, values } => { Dict { keys, values } => {
for (key, value) in keys.iter().zip(values) { let (packed, unpacked) = values.split_at(keys.len());
if let Some(key) = key { for (key, value) in keys.iter().zip(packed) {
self.scan_expression(key, context)?; self.scan_expression(key, context)?;
} else { self.scan_expression(value, context)?;
// dict unpacking marker
} }
for value in unpacked {
// dict unpacking marker
self.scan_expression(value, context)?; self.scan_expression(value, context)?;
} }
} }