From 581f6e176cf47102cfd4febe77105485a7a37c8f Mon Sep 17 00:00:00 2001 From: harupy Date: Sun, 15 Jan 2023 13:01:59 +0900 Subject: [PATCH] Fix dict spreading in dict literal --- ast/src/ast_gen.rs | 2 +- parser/python.lalrpop | 72 ++++++++--------- parser/src/parser.rs | 6 ++ ...parser__tests__dict_containing_spread.snap | 81 +++++++++++++++++++ 4 files changed, 124 insertions(+), 37 deletions(-) create mode 100644 parser/src/snapshots/rustpython_parser__parser__tests__dict_containing_spread.snap diff --git a/ast/src/ast_gen.rs b/ast/src/ast_gen.rs index 241ebe1..32dd89c 100644 --- a/ast/src/ast_gen.rs +++ b/ast/src/ast_gen.rs @@ -195,7 +195,7 @@ pub enum ExprKind { orelse: Box>, }, Dict { - keys: Vec>, + keys: Vec>>, values: Vec>, }, Set { diff --git a/parser/python.lalrpop b/parser/python.lalrpop index 90f4ce2..7007905 100644 --- a/parser/python.lalrpop +++ b/parser/python.lalrpop @@ -1138,42 +1138,42 @@ Atom: ast::Expr = { "{" "}" => { 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 end_location = items[0].0.end_location; - let (keys, values) = items.drain(..).unzip(); - ast::Expr { - location, - end_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() - }; - + // 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 end_location = items[0].0.end_location; + // let (keys, values) = items.drain(..).unzip(); + // ast::Expr { + // location, + // end_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, v)).unzip() + // }; + let (keys, values) = pairs.into_iter().map(|(k, v)| (k.map(|x| *x), v)).unzip(); ast::Expr { location, end_location: Some(end_location), diff --git a/parser/src/parser.rs b/parser/src/parser.rs index fb18155..ced5d9b 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -309,4 +309,10 @@ with (0 as a, 1 as b,): pass assert!(parse_program(source, "").is_err()); } } + + #[test] + fn test_dict_containing_spread() { + let parse_ast = parse_expression(r#"{"k": "v", **d}"#, "").unwrap(); + insta::assert_debug_snapshot!(parse_ast); + } } diff --git a/parser/src/snapshots/rustpython_parser__parser__tests__dict_containing_spread.snap b/parser/src/snapshots/rustpython_parser__parser__tests__dict_containing_spread.snap new file mode 100644 index 0000000..29eb084 --- /dev/null +++ b/parser/src/snapshots/rustpython_parser__parser__tests__dict_containing_spread.snap @@ -0,0 +1,81 @@ +--- +source: compiler/parser/src/parser.rs +expression: parse_ast +--- +Located { + location: Location { + row: 1, + column: 0, + }, + end_location: Some( + Location { + row: 1, + column: 15, + }, + ), + custom: (), + node: Dict { + keys: [ + Some( + Located { + location: Location { + row: 1, + column: 1, + }, + end_location: Some( + Location { + row: 1, + column: 4, + }, + ), + custom: (), + node: Constant { + value: Str( + "k", + ), + kind: None, + }, + }, + ), + None, + ], + values: [ + Located { + location: Location { + row: 1, + column: 6, + }, + end_location: Some( + Location { + row: 1, + column: 9, + }, + ), + custom: (), + node: Constant { + value: Str( + "v", + ), + kind: None, + }, + }, + Located { + location: Location { + row: 1, + column: 13, + }, + end_location: Some( + Location { + row: 1, + column: 14, + }, + ), + custom: (), + node: Name { + id: "d", + ctx: Load, + }, + }, + ], + }, +}