From 53b344866f0bd699a03ca6087e898372ec6e77fa Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Fri, 12 Aug 2022 05:24:19 +0900 Subject: [PATCH] Implement new features for updated python asdl --- Cargo.lock | 1 + ast/Cargo.toml | 1 + ast/src/constant.rs | 30 +------- ast/src/fold_helpers.rs | 8 +- ast/src/unparse.rs | 19 ++--- bytecode/src/lib.rs | 23 +++++- compiler/src/compile.rs | 58 +++++++-------- compiler/src/error.rs | 4 + compiler/src/symboltable.rs | 30 +++++--- extra_tests/snippets/builtin_dict.py | 2 +- parser/python.lalrpop | 73 +++++++++++++++---- parser/src/fstring.rs | 8 +- ...s__fstring_parse_selfdocumenting_base.snap | 2 +- ...tring_parse_selfdocumenting_base_more.snap | 4 +- ..._fstring_parse_selfdocumenting_format.snap | 3 +- ...parser__fstring__tests__parse_fstring.snap | 4 +- ..._fstring__tests__parse_fstring_equals.snap | 3 +- ...ing__tests__parse_fstring_nested_spec.snap | 7 +- ...ring__tests__parse_fstring_not_equals.snap | 3 +- ..._tests__parse_fstring_not_nested_spec.snap | 3 +- ...sts__parse_fstring_selfdoc_prec_space.snap | 2 +- ..._parse_fstring_selfdoc_trailing_space.snap | 2 +- ...ring__tests__parse_fstring_yield_expr.snap | 3 +- ...rser__tests__parse_dict_comprehension.snap | 2 +- ...ests__parse_double_list_comprehension.snap | 5 +- ...rser__tests__parse_list_comprehension.snap | 2 +- vm/src/builtins/dict.rs | 24 +++--- vm/src/frame.rs | 8 +- vm/src/stdlib/ast.rs | 4 +- 29 files changed, 182 insertions(+), 156 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab5d65c7e..06b09c3c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,6 +1723,7 @@ name = "rustpython-ast" version = "0.1.0" dependencies = [ "num-bigint", + "rustpython-bytecode", "rustpython-common", ] diff --git a/ast/Cargo.toml b/ast/Cargo.toml index 8d1db18a8..996a01d89 100644 --- a/ast/Cargo.toml +++ b/ast/Cargo.toml @@ -13,3 +13,4 @@ unparse = ["rustpython-common"] [dependencies] num-bigint = "0.4.3" rustpython-common = { path = "../common", optional = true } +rustpython-bytecode = { path = "../bytecode"} diff --git a/ast/src/constant.rs b/ast/src/constant.rs index 0778f4f06..1d1655943 100644 --- a/ast/src/constant.rs +++ b/ast/src/constant.rs @@ -1,4 +1,5 @@ use num_bigint::BigInt; +pub use rustpython_bytecode::ConversionFlag; #[derive(Debug, PartialEq)] pub enum Constant { @@ -70,35 +71,6 @@ impl std::fmt::Display for Constant { } } -/// Transforms a value prior to formatting it. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[repr(usize)] -pub enum ConversionFlag { - /// Converts by calling `str()`. - Str = b's' as usize, - /// Converts by calling `ascii()`. - Ascii = b'a' as usize, - /// Converts by calling `repr()`. - Repr = b'r' as usize, -} - -impl ConversionFlag { - pub fn try_from_u32(b: usize) -> Option { - match b.try_into().ok()? { - b's' => Some(Self::Str), - b'a' => Some(Self::Ascii), - b'r' => Some(Self::Repr), - _ => None, - } - } -} - -impl From for ConversionFlag { - fn from(b: usize) -> Self { - Self::try_from_u32(b).unwrap() - } -} - #[cfg(feature = "constant-optimization")] #[non_exhaustive] #[derive(Default)] diff --git a/ast/src/fold_helpers.rs b/ast/src/fold_helpers.rs index 26a08b2fb..f15a9d5d0 100644 --- a/ast/src/fold_helpers.rs +++ b/ast/src/fold_helpers.rs @@ -63,10 +63,4 @@ macro_rules! simple_fold { }; } -simple_fold!( - usize, - String, - bool, - constant::Constant, - constant::ConversionFlag -); +simple_fold!(usize, String, bool, constant::Constant); diff --git a/ast/src/unparse.rs b/ast/src/unparse.rs index f0370b73f..70addae99 100644 --- a/ast/src/unparse.rs +++ b/ast/src/unparse.rs @@ -155,6 +155,7 @@ impl<'a> Unparser<'a> { write!(self, "{}: {}", *k, *v)?; } for d in unpacked { + self.p_delim(&mut first, ", ")?; write!(self, "**{}", *d)?; } self.p("}")?; @@ -281,7 +282,7 @@ impl<'a> Unparser<'a> { value, conversion, format_spec, - } => self.unparse_formatted(value, (*conversion).into(), format_spec.as_deref())?, + } => self.unparse_formatted(value, *conversion, format_spec.as_deref())?, ExprKind::JoinedStr { values } => self.unparse_joinedstr(values, false)?, ExprKind::Constant { value, kind } => { if let Some(kind) = kind { @@ -445,7 +446,7 @@ impl<'a> Unparser<'a> { fn unparse_formatted( &mut self, val: &Expr, - conversion: ConversionFlag, + conversion: usize, spec: Option<&Expr>, ) -> fmt::Result { let buffered = to_string_fmt(|f| Unparser::new(f).unparse_expr(val, precedence::TEST + 1)); @@ -459,12 +460,12 @@ impl<'a> Unparser<'a> { self.p(&buffered)?; drop(buffered); - let flag = match conversion { - ConversionFlag::Str => "!s", - ConversionFlag::Ascii => "!a", - ConversionFlag::Repr => "!r", - }; - self.p(flag)?; + if conversion != ConversionFlag::None as usize { + self.p("!")?; + let buf = &[conversion as u8]; + let c = std::str::from_utf8(buf).unwrap(); + self.p(c)?; + } if let Some(spec) = spec { self.p(":")?; @@ -490,7 +491,7 @@ impl<'a> Unparser<'a> { value, conversion, format_spec, - } => self.unparse_formatted(value, (*conversion).into(), format_spec.as_deref()), + } => self.unparse_formatted(value, *conversion, format_spec.as_deref()), _ => unreachable!(), } } diff --git a/bytecode/src/lib.rs b/bytecode/src/lib.rs index 832ad8473..ea490c59a 100644 --- a/bytecode/src/lib.rs +++ b/bytecode/src/lib.rs @@ -159,15 +159,30 @@ impl fmt::Display for Label { /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] pub enum ConversionFlag { /// No conversion - None, + None = 0, /// Converts by calling `str()`. - Str, + Str = b's', /// Converts by calling `ascii()`. - Ascii, + Ascii = b'a', /// Converts by calling `repr()`. - Repr, + Repr = b'r', +} + +impl TryFrom for ConversionFlag { + type Error = usize; + fn try_from(b: usize) -> Result { + let b = b.try_into().map_err(|_| b)?; + match b { + 0 => Ok(Self::None), + b's' => Ok(Self::Str), + b'a' => Ok(Self::Ascii), + b'r' => Ok(Self::Repr), + b => Err(b as usize), + } + } } /// The kind of Raise that occurred. diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index efb5e0873..6e5cbfc8a 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -680,6 +680,7 @@ impl Compiler { orelse, .. } => self.compile_for(target, iter, body, orelse, true)?, + Match { subject, cases } => self.compile_match(subject, cases)?, Raise { exc, cause } => { let kind = match exc { Some(value) => { @@ -881,17 +882,19 @@ impl Compiler { }); } - let mut num_kw_only_defaults = 0; - for (kw, default) in args.kwonlyargs.iter().zip(&args.kw_defaults) { - self.emit_constant(ConstantData::Str { - value: kw.node.arg.clone(), - }); - self.compile_expression(default)?; - num_kw_only_defaults += 1; - } - if num_kw_only_defaults > 0 { + if !args.kw_defaults.is_empty() { + 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 { + value: kw.node.arg.clone(), + }); + self.compile_expression(default)?; + } self.emit(Instruction::BuildMap { - size: num_kw_only_defaults, + size: args.kw_defaults.len() as u32, unpack: false, for_call: false, }); @@ -901,7 +904,7 @@ impl Compiler { if have_defaults { funcflags |= bytecode::MakeFunctionFlags::DEFAULTS; } - if num_kw_only_defaults > 0 { + if !args.kw_defaults.is_empty() { funcflags |= bytecode::MakeFunctionFlags::KW_ONLY_DEFAULTS; } @@ -1519,6 +1522,16 @@ impl Compiler { 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( &mut self, left: &ast::Expr, @@ -1928,11 +1941,7 @@ impl Compiler { Ok(()) } - fn compile_dict( - &mut self, - keys: &[ast::Expr], - values: &[ast::Expr], - ) -> CompileResult<()> { + fn compile_dict(&mut self, keys: &[ast::Expr], values: &[ast::Expr]) -> CompileResult<()> { let mut size = 0; let (packed_values, unpacked_values) = values.split_at(keys.len()); @@ -2099,7 +2108,7 @@ impl Compiler { }; self.compile_expression(value)?; self.emit(Instruction::FormatValue { - conversion: compile_conversion_flag(*conversion), + conversion: (*conversion).try_into().expect("invalid conversion flag"), }); } Name { id, .. } => self.load_name(id)?, @@ -2454,7 +2463,7 @@ impl Compiler { let mut loop_labels = vec![]; for generator in generators { - if generator.is_async { + if generator.is_async > 0 { unimplemented!("async for comprehensions"); } @@ -2543,7 +2552,7 @@ impl Compiler { return Err(self.error(CompileErrorType::InvalidFuturePlacement)); } for feature in features { - match &*feature.name { + match &*feature.node.name { // Python 3 features; we've already implemented them by default "nested_scopes" | "generators" | "division" | "absolute_import" | "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()) } -fn compile_conversion_flag( - conversion_flag: Option, -) -> 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 { match value { ast::Constant::None => ConstantData::None, diff --git a/compiler/src/error.rs b/compiler/src/error.rs index 1d2c1c2fc..2e125b01e 100644 --- a/compiler/src/error.rs +++ b/compiler/src/error.rs @@ -37,6 +37,7 @@ pub enum CompileErrorType { TooManyStarUnpack, EmptyWithItems, EmptyWithBody, + NotImplementedYet, // RustPython marker for unimplemented features } impl fmt::Display for CompileErrorType { @@ -78,6 +79,9 @@ impl fmt::Display for CompileErrorType { CompileErrorType::EmptyWithBody => { write!(f, "empty body on With") } + CompileErrorType::NotImplementedYet => { + write!(f, "RustPython does not implement this feature yet") + } } } } diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index 387656349..6dad4f23d 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -639,7 +639,7 @@ impl SymbolTableBuilder { if let ImportFrom { module, names, .. } = &statement.node { if module.as_deref() == Some("__future__") { for feature in names { - if feature.name == "annotations" { + if feature.node.name == "annotations" { self.future_annotations = true; } } @@ -739,13 +739,13 @@ impl SymbolTableBuilder { } Import { names } | ImportFrom { names, .. } => { for name in names { - if let Some(alias) = &name.asname { + if let Some(alias) = &name.node.asname { // `import mymodule as myalias` self.register_name(alias, SymbolUsage::Imported, location)?; } else { // `import module` self.register_name( - name.name.split('.').next().unwrap(), + name.node.name.split('.').next().unwrap(), SymbolUsage::Imported, location, )?; @@ -782,7 +782,7 @@ impl SymbolTableBuilder { } => { // https://github.com/python/cpython/blob/main/Python/symtable.c#L1233 match &target.node { - ast::ExprKind::Name { id, .. } if *simple => { + ast::ExprKind::Name { id, .. } if *simple > 0 => { self.register_name(id, SymbolUsage::AnnotationAssigned, location)?; } _ => { @@ -823,6 +823,15 @@ impl SymbolTableBuilder { self.scan_statements(orelse)?; 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 } => { if let Some(expression) = exc { self.scan_expression(expression, ExpressionContext::Load)?; @@ -875,12 +884,13 @@ impl SymbolTableBuilder { self.scan_expression(value, ExpressionContext::Load)?; } Dict { keys, values } => { - for (key, value) in keys.iter().zip(values) { - if let Some(key) = key { - self.scan_expression(key, context)?; - } else { - // dict unpacking marker - } + let (packed, unpacked) = values.split_at(keys.len()); + for (key, value) in keys.iter().zip(packed) { + self.scan_expression(key, context)?; + self.scan_expression(value, context)?; + } + for value in unpacked { + // dict unpacking marker self.scan_expression(value, context)?; } } diff --git a/extra_tests/snippets/builtin_dict.py b/extra_tests/snippets/builtin_dict.py index 19d9342f2..3ccea9723 100644 --- a/extra_tests/snippets/builtin_dict.py +++ b/extra_tests/snippets/builtin_dict.py @@ -285,7 +285,7 @@ y = {'b': 2, 'c': 2, 'd': 2} z = {'c': 3, 'd': 3, 'e': 3} w = {1: 1, **x, 2: 2, **y, 3: 3, **z, 4: 4} -assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4} +assert w == {1: 1, 'a': 1, 'b': 2, 'c': 3, 2: 2, 'd': 3, 3: 3, 'e': 3, 4: 4} # not in cpython test suite assert str({True: True, 1.0: 1.0}) == str({True: 1.0}) diff --git a/parser/python.lalrpop b/parser/python.lalrpop index 3d2dd189e..f68096168 100644 --- a/parser/python.lalrpop +++ b/parser/python.lalrpop @@ -268,19 +268,19 @@ ImportDots: usize = { }; ImportAsNames: Vec = { - >> => i, - "(" >> ","? ")" => i, - "*" => { + >> => i, + "(" >> ","? ")" => i, + "*" => { // Star import all - vec![ast::Alias(ast::AliasData { name: "*".to_string(), asname: None })] + vec![ast::Alias::new(location, ast::AliasData { name: "*".to_string(), asname: None })] }, }; #[inline] ImportAsAlias: ast::Alias = { - => ast::Alias { name, asname: a.map(|a| a.1) }, -}; + => ast::Alias::new(location, ast::AliasData { name, asname: a.map(|a| a.1) }), +} // A name like abc or abc.def.ghi DottedName: String = { @@ -590,20 +590,26 @@ TypedParameter: ast::Arg = { // Use inline here to make sure the "," is not creating an ambiguity. // TODO: figure out another grammar that makes this inline no longer required. #[inline] -ParameterListStarArgs: (Option>, Vec, Vec>>, Option>) = { +ParameterListStarArgs: (Option>, Vec, Vec, Option>) = { "*" )*> )?> => { // Extract keyword arguments: - let mut kwonlyargs = vec![]; - let mut kw_defaults = vec![]; + let mut kwonlyargs = Vec::new(); + let mut kw_defaults = Vec::new(); + let mut kwargs = Vec::new(); for (name, value) in kw.into_iter().map(|x| x.1) { - kwonlyargs.push(name); - kw_defaults.push(value.map(Box::new)); + if let Some(value) = value { + kwonlyargs.push(name); + kw_defaults.push(value); + } else { + kwargs.push(name); + } } + kwargs.extend(kwonlyargs.into_iter()); let kwarg = kwarg.map(|n| n.1).flatten(); let va = va.map(Box::new); - (va, kwonlyargs, kw_defaults, kwarg) + (va, kwargs, kw_defaults, kwarg) } }; @@ -1039,7 +1045,42 @@ Atom: ast::Expr = { }.into()) }, "{" "}" => { - let (keys, values) = e.unwrap_or_default(); + let pairs = e.unwrap_or_default(); + + let (keys, values) = match pairs.iter().position(|(k,_)| k.is_none()) { + Some(unpack_idx) => { + let mut pairs = pairs; + let (keys, mut values): (_, Vec<_>) = pairs.drain(..unpack_idx).map(|(k, v)| (*k.unwrap(), v)).unzip(); + + fn build_map(items: &mut Vec<(ast::Expr, ast::Expr)>) -> ast::Expr { + let location = items[0].0.location; + let (keys, values) = items.drain(..).unzip(); + ast::Expr { + location, + custom: (), + node: ast::ExprKind::Dict { keys, values } + } + } + + let mut items = Vec::new(); + for (key, value) in pairs.into_iter() { + if let Some(key) = key { + items.push((*key, value)); + continue; + } + if !items.is_empty() { + values.push(build_map(&mut items)); + } + values.push(value); + } + if !items.is_empty() { + values.push(build_map(&mut items)); + } + (keys, values) + }, + None => pairs.into_iter().map(|(k, v)| (*k.unwrap(), v)).unzip() + }; + ast::Expr { location, custom: (), @@ -1079,8 +1120,8 @@ ListLiteralValues: Vec = { > ","? => e, }; -DictLiteralValues: (Vec>>, Vec) = { - > ","? => elements.into_iter().unzip(), +DictLiteralValues: Vec<(Option>, ast::Expr)> = { + > ","? => elements, }; DictEntry: (ast::Expr, ast::Expr) = { @@ -1151,7 +1192,7 @@ SingleForComprehension: ast::Comprehension = { target: Box::new(target), iter: Box::new(iter), ifs, - is_async + is_async: if is_async { 1 } else { 0 }, } } }; diff --git a/parser/src/fstring.rs b/parser/src/fstring.rs index 9ffc116de..157325aa3 100644 --- a/parser/src/fstring.rs +++ b/parser/src/fstring.rs @@ -30,7 +30,7 @@ impl<'a> FStringParser<'a> { let mut expression = String::new(); let mut spec = None; let mut delims = Vec::new(); - let mut conversion = ConversionFlag::Str; + let mut conversion = ConversionFlag::None; let mut pred_expression_text = String::new(); let mut trailing_seq = String::new(); @@ -115,7 +115,7 @@ impl<'a> FStringParser<'a> { ) .parse()?, ), - conversion: b's' as usize, + conversion: ConversionFlag::None as _, format_spec: None, }), ); @@ -187,7 +187,7 @@ impl<'a> FStringParser<'a> { parse_fstring_expr(&expression) .map_err(|e| InvalidExpression(Box::new(e.error)))?, ), - conversion: conversion as usize, + conversion: conversion as _, format_spec: spec, })] } else { @@ -205,7 +205,7 @@ impl<'a> FStringParser<'a> { parse_fstring_expr(&expression) .map_err(|e| InvalidExpression(Box::new(e.error)))?, ), - conversion: conversion as usize, + conversion: conversion as _, format_spec: spec, }), ] diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base.snap index 33156007c..dceb49d35 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base.snap @@ -54,7 +54,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap index 6cc933de4..2725dbf1d 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap @@ -67,7 +67,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, @@ -128,7 +128,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_format.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_format.snap index 9ba81d0fb..4ab56f070 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_format.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__fstring_parse_selfdocumenting_format.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -55,7 +54,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: Some( Located { location: Location { diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring.snap index 457853a5b..26af1d8e9 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring.snap @@ -28,7 +28,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, @@ -50,7 +50,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_equals.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_equals.snap index 12176f12e..5a98ebdf0 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_equals.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_equals.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -58,7 +57,7 @@ Located { ], }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_nested_spec.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_nested_spec.snap index 6bcd55732..8ba0b5661 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_nested_spec.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_nested_spec.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -29,7 +28,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: Some( Located { location: Location { @@ -85,14 +84,14 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, ], }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_equals.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_equals.snap index 2cb6e1e2d..655bf1b32 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_equals.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_equals.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -58,7 +57,7 @@ Located { ], }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_nested_spec.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_nested_spec.snap index 682465de8..8950ebbea 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_nested_spec.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_not_nested_spec.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -29,7 +28,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: Some( Located { location: Location { diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap index 4b9b44582..73eaf6e0d 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap @@ -54,7 +54,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap index 09c0f32d2..e6ac5c13d 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap @@ -54,7 +54,7 @@ Located { ctx: Load, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_yield_expr.snap b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_yield_expr.snap index 8c16ec3b5..37e0d05a1 100644 --- a/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_yield_expr.snap +++ b/parser/src/snapshots/rustpython_parser__fstring__tests__parse_fstring_yield_expr.snap @@ -1,7 +1,6 @@ --- source: parser/src/fstring.rs expression: parse_ast - --- Located { location: Location { @@ -28,7 +27,7 @@ Located { value: None, }, }, - conversion: None, + conversion: 0, format_spec: None, }, }, diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap b/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap index 65369dc31..f7f9b52d2 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap +++ b/parser/src/snapshots/rustpython_parser__parser__tests__parse_dict_comprehension.snap @@ -56,7 +56,7 @@ Located { }, }, ifs: [], - is_async: false, + is_async: 0, }, ], }, diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap b/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap index 4095f6488..52d4b6cef 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap +++ b/parser/src/snapshots/rustpython_parser__parser__tests__parse_double_list_comprehension.snap @@ -1,7 +1,6 @@ --- source: parser/src/parser.rs expression: parse_ast - --- Located { location: Location { @@ -69,7 +68,7 @@ Located { }, }, ifs: [], - is_async: false, + is_async: 0, }, Comprehension { target: Located { @@ -172,7 +171,7 @@ Located { }, }, ], - is_async: false, + is_async: 0, }, ], }, diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap b/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap index d67e166da..8a6d8eb8d 100644 --- a/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap +++ b/parser/src/snapshots/rustpython_parser__parser__tests__parse_list_comprehension.snap @@ -45,7 +45,7 @@ Located { }, }, ifs: [], - is_async: false, + is_async: 0, }, ], }, diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index 9d7f2f282..ca7348184 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -71,15 +71,12 @@ impl PyDict { } // Used in update and ior. - fn merge_object( - dict: &DictContentType, - other: PyObjectRef, - vm: &VirtualMachine, - ) -> PyResult<()> { + pub(crate) fn merge_object(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> { let other = match other.downcast_exact(vm) { - Ok(dict_other) => return Self::merge_dict(dict, dict_other, vm), + Ok(dict_other) => return self.merge_dict(dict_other, vm), Err(other) => other, }; + let dict = &self.entries; if let Some(keys) = vm.get_method(other.clone(), vm.ctx.intern_str("keys")) { let keys = vm.invoke(&keys?, ())?.get_iter(vm)?; while let PyIterReturn::Return(key) = keys.next(vm)? { @@ -108,11 +105,8 @@ impl PyDict { Ok(()) } - fn merge_dict( - dict: &DictContentType, - dict_other: PyDictRef, - vm: &VirtualMachine, - ) -> PyResult<()> { + fn merge_dict(&self, dict_other: PyDictRef, vm: &VirtualMachine) -> PyResult<()> { + let dict = &self.entries; let dict_size = &dict_other.size(); for (key, value) in &dict_other { dict.insert(vm, &*key, value)?; @@ -363,7 +357,7 @@ impl PyDict { vm: &VirtualMachine, ) -> PyResult<()> { if let OptionalArg::Present(dict_obj) = dict_obj { - Self::merge_object(&self.entries, dict_obj, vm)?; + self.merge_object(dict_obj, vm)?; } for (key, value) in kwargs.into_iter() { self.entries.insert(vm, &key, value)?; @@ -373,7 +367,7 @@ impl PyDict { #[pymethod(magic)] fn ior(zelf: PyRef, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { - PyDict::merge_object(&zelf.entries, other, vm)?; + zelf.merge_object(other, vm)?; Ok(zelf) } @@ -382,7 +376,7 @@ impl PyDict { let dicted: Result = other.downcast(); if let Ok(other) = dicted { let other_cp = other.copy(); - PyDict::merge_dict(&other_cp.entries, zelf, vm)?; + other_cp.merge_dict(zelf, vm)?; return Ok(other_cp.into_pyobject(vm)); } Ok(vm.ctx.not_implemented()) @@ -393,7 +387,7 @@ impl PyDict { let dicted: Result = other.downcast(); if let Ok(other) = dicted { let self_cp = self.copy(); - PyDict::merge_dict(&self_cp.entries, other, vm)?; + self_cp.merge_dict(other, vm)?; return Ok(self_cp.into_pyobject(vm)); } Ok(vm.ctx.not_implemented()) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 4b60b296d..4dc391e15 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -679,9 +679,11 @@ impl ExecutingFrame<'_> { } => self.execute_build_map(vm, *size, *unpack, *for_call), bytecode::Instruction::DictUpdate => { let other = self.pop_value(); - let dict = self.pop_value(); - let updated = vm.call_method(&dict, "update", (other,))?; - self.push_value(updated); + let dict = self + .last_value_ref() + .downcast_ref::() + .expect("exact dict expected"); + dict.merge_object(other, vm)?; Ok(None) } bytecode::Instruction::BuildSlice { step } => self.execute_build_slice(vm, *step), diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 7d080c7fe..2c8c05baf 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -252,8 +252,8 @@ impl Node for ast::ConversionFlag { fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { i32::try_from_object(vm, object)? - .to_u8() - .and_then(ast::ConversionFlag::try_from_byte) + .to_usize() + .and_then(|f| f.try_into().ok()) .ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned())) } }