diff --git a/parser/src/ast.rs b/parser/src/ast.rs index b063841ee3..56fc51ed8b 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -14,6 +14,7 @@ pub struct Node { } */ +#[allow(clippy::large_enum_variant)] #[derive(Debug, PartialEq)] pub enum Top { Program(Program), @@ -41,7 +42,6 @@ pub struct Located { pub type Statement = Located; /// Abstract syntax tree nodes for python statements. -#[allow(clippy::large_enum_variant)] #[derive(Debug, PartialEq)] pub enum StatementType { Break, @@ -100,8 +100,8 @@ pub enum StatementType { }, For { is_async: bool, - target: Expression, - iter: Expression, + target: Box, + iter: Box, body: Vec, orelse: Option>, }, @@ -125,7 +125,7 @@ pub enum StatementType { FunctionDef { is_async: bool, name: String, - args: Parameters, + args: Box, body: Vec, decorator_list: Vec, returns: Option, @@ -217,7 +217,7 @@ pub enum ExpressionType { name: String, }, Lambda { - args: Parameters, + args: Box, body: Box, }, IfExpression { @@ -293,6 +293,7 @@ pub struct Parameters { #[derive(Debug, PartialEq, Default)] pub struct Parameter { + pub location: Location, pub arg: String, pub annotation: Option>, } @@ -308,6 +309,7 @@ pub enum ComprehensionKind { #[derive(Debug, PartialEq)] pub struct Comprehension { + pub location: Location, pub target: Expression, pub iter: Expression, pub ifs: Vec, @@ -321,6 +323,7 @@ pub struct Keyword { #[derive(Debug, PartialEq)] pub struct ExceptHandler { + pub location: Location, pub typ: Option, pub name: Option, pub body: Vec, diff --git a/parser/src/parser.rs b/parser/src/parser.rs index b0e3ec5ab5..11dd61803a 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -233,13 +233,15 @@ mod tests { Ok(vec![as_statement(ast::Expression { location: ast::Location::new(1, 1), node: ast::ExpressionType::Lambda { - args: ast::Parameters { + args: Box::new(ast::Parameters { args: vec![ ast::Parameter { + location: ast::Location::new(1, 8), arg: String::from("x"), annotation: None, }, ast::Parameter { + location: ast::Location::new(1, 11), arg: String::from("y"), annotation: None, } @@ -249,7 +251,7 @@ mod tests { kwarg: ast::Varargs::None, defaults: vec![], kw_defaults: vec![], - }, + }), body: Box::new(ast::Expression { location: ast::Location::new(1, 16), node: ast::ExpressionType::Binop { @@ -308,8 +310,9 @@ mod tests { node: ast::StatementType::FunctionDef { is_async: false, name: String::from("__init__"), - args: ast::Parameters { + args: Box::new(ast::Parameters { args: vec![ast::Parameter { + location: ast::Location::new(2, 15), arg: String::from("self"), annotation: None, }], @@ -318,7 +321,7 @@ mod tests { kwarg: ast::Varargs::None, defaults: vec![], kw_defaults: vec![], - }, + }), body: vec![ast::Statement { location: ast::Location::new(3, 3), node: ast::StatementType::Pass, @@ -332,13 +335,15 @@ mod tests { node: ast::StatementType::FunctionDef { is_async: false, name: String::from("method_with_default"), - args: ast::Parameters { + args: Box::new(ast::Parameters { args: vec![ ast::Parameter { + location: ast::Location::new(4, 26), arg: String::from("self"), annotation: None, }, ast::Parameter { + location: ast::Location::new(4, 32), arg: String::from("arg"), annotation: None, } @@ -348,7 +353,7 @@ mod tests { kwarg: ast::Varargs::None, defaults: vec![make_string("default", 4, 37)], kw_defaults: vec![], - }, + }), body: vec![ast::Statement { location: ast::Location::new(5, 3), node: ast::StatementType::Pass, @@ -377,6 +382,7 @@ mod tests { element: mk_ident("x", 1, 2), }), generators: vec![ast::Comprehension { + location: ast::Location::new(1, 4), target: mk_ident("y", 1, 8), iter: mk_ident("z", 1, 13), ifs: vec![], @@ -400,6 +406,7 @@ mod tests { }), generators: vec![ ast::Comprehension { + location: ast::Location::new(1, 4), target: ast::Expression { location: ast::Location::new(1, 8), node: ast::ExpressionType::Tuple { @@ -410,6 +417,7 @@ mod tests { ifs: vec![], }, ast::Comprehension { + location: ast::Location::new(1, 19), target: mk_ident("a", 1, 23), iter: mk_ident("b", 1, 28), ifs: vec![ diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 8eb44ff2f7..def4bef4ac 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -66,33 +66,33 @@ SmallStatement: ast::Statement = { }; PassStatement: ast::Statement = { - "pass" => { + "pass" => { ast::Statement { - location: loc, + location, node: ast::StatementType::Pass, } }, }; DelStatement: ast::Statement = { - "del" => { + "del" => { ast::Statement { - location: loc, - node: ast::StatementType::Delete { targets: e }, + location, + node: ast::StatementType::Delete { targets }, } }, }; ExpressionStatement: ast::Statement = { - => { + => { // Just an expression, no assignment: if suffix.is_empty() { ast::Statement { location, - node: ast::StatementType::Expression { expression: expr } + node: ast::StatementType::Expression { expression } } } else { - let mut targets = vec![expr]; + let mut targets = vec![expression]; let mut values = suffix; while values.len() > 1 { @@ -177,10 +177,10 @@ FlowStatement: ast::Statement = { node: ast::StatementType::Return { value }, } }, - => { + => { ast::Statement { location, - node: ast::StatementType::Expression { expression: y }, + node: ast::StatementType::Expression { expression }, } }, RaiseStatement, @@ -283,10 +283,10 @@ NonlocalStatement: ast::Statement = { AssertStatement: ast::Statement = { "assert" => { ast::Statement { - location, - node: ast::StatementType::Assert { - test, msg: msg.map(|e| e.1) - } + location, + node: ast::StatementType::Assert { + test, msg: msg.map(|e| e.1) + } } }, }; @@ -302,32 +302,36 @@ CompoundStatement: ast::Statement = { }; IfStatement: ast::Statement = { - "if" ":" => { + "if" ":" => { // Determine last else: let mut last = s3.map(|s| s.2); // handle elif: for i in s2.into_iter().rev() { - let x = ast::Statement { - location: i.0, - node: ast::StatementType::If { test: i.2, body: i.4, orelse: last }, - }; - last = Some(vec![x]); + let x = ast::Statement { + location: i.0, + node: ast::StatementType::If { test: i.2, body: i.4, orelse: last }, + }; + last = Some(vec![x]); } ast::Statement { location, - node: ast::StatementType::If { test, body: s1, orelse: last } + node: ast::StatementType::If { test, body, orelse: last } } }, }; WhileStatement: ast::Statement = { "while" ":" => { - let or_else = s2.map(|s| s.2); + let orelse = s2.map(|s| s.2); ast::Statement { location, - node: ast::StatementType::While { test, body, orelse: or_else }, + node: ast::StatementType::While { + test, + body, + orelse + }, } }, }; @@ -338,40 +342,48 @@ ForStatement: ast::Statement = { let orelse = s2.map(|s| s.2); ast::Statement { location, - node: ast::StatementType::For { is_async, target, iter, body, orelse }, + node: ast::StatementType::For { + is_async, + target: Box::new(target), + iter: Box::new(iter), + body, + orelse + }, } }, }; TryStatement: ast::Statement = { "try" ":" => { - let or_else = else_suite.map(|s| s.2); + let orelse = else_suite.map(|s| s.2); let finalbody = finally.map(|s| s.2); ast::Statement { location, node: ast::StatementType::Try { - body: body, - handlers: handlers, - orelse: or_else, - finalbody: finalbody, + body, + handlers, + orelse, + finalbody, }, } }, }; ExceptClause: ast::ExceptHandler = { - "except" ":" => { + "except" ":" => { ast::ExceptHandler { - typ: typ, + location, + typ, name: None, - body: body, + body, } }, - "except" ":" => { + "except" ":" => { ast::ExceptHandler { + location, typ: Some(x.0), name: Some(x.2), - body: body, + body, } }, }; @@ -387,23 +399,23 @@ WithStatement: ast::Statement = { }; WithItem: ast::WithItem = { - => { + => { let optional_vars = n.map(|val| val.1); - ast::WithItem { context_expr: t, optional_vars } + ast::WithItem { context_expr, optional_vars } }, }; FuncDef: ast::Statement = { - "def" " Test)?> ":" => { + "def" " Test)?> ":" => { let is_async = is_async.is_some(); ast::Statement { location, node: ast::StatementType::FunctionDef { is_async, name, - args: a, + args: Box::new(args), body, - decorator_list: d, + decorator_list, returns: r.map(|x| x.1), } } @@ -411,7 +423,7 @@ FuncDef: ast::Statement = { }; Parameters: ast::Parameters = { - "(" )?> ")" => a.unwrap_or_else(Default::default), + "(" )?> ")" => a.unwrap_or_default(), }; // Note that this is a macro which is used once for function defs, and @@ -425,7 +437,7 @@ ParameterList: ast::Parameters = { ast::Parameters { args: names, - kwonlyargs: kwonlyargs, + kwonlyargs, vararg: vararg.into(), kwarg: kwarg.into(), defaults: default_elements, @@ -443,7 +455,7 @@ ParameterList: ast::Parameters = { ast::Parameters { args: names, - kwonlyargs: kwonlyargs, + kwonlyargs, vararg: vararg.into(), kwarg: kwarg.into(), defaults: default_elements, @@ -454,7 +466,7 @@ ParameterList: ast::Parameters = { let (vararg, kwonlyargs, kw_defaults, kwarg) = params; ast::Parameters { args: vec![], - kwonlyargs: kwonlyargs, + kwonlyargs, vararg: vararg.into(), kwarg: kwarg.into(), defaults: vec![], @@ -476,11 +488,7 @@ ParameterList: ast::Parameters = { // Use inline here to make sure the "," is not creating an ambiguity. #[inline] ParameterDefs: (Vec, Vec) = { - > )*> => { - // Combine first parameters: - let mut args = vec![param1]; - args.extend(param2.into_iter().map(|x| x.1)); - + >> => { let mut names = vec![]; let mut default_elements = vec![]; @@ -491,16 +499,15 @@ ParameterDefs: (Vec, Vec) = { if default_elements.len() > 0 { // Once we have started with defaults, all remaining arguments must // have defaults - panic!( - "non-default argument follows default argument: {}", - &name.arg - ); + panic!("non-default argument follows default argument: {}", &name.arg); } } names.push(name); } - (names, default_elements) + //Ok( + (names, default_elements) + //) } }; @@ -510,13 +517,13 @@ ParameterDef: (ast::Parameter, Option) = { }; UntypedParameter: ast::Parameter = { - => ast::Parameter { arg: i, annotation: None }, + => ast::Parameter { location, arg, annotation: None }, }; TypedParameter: ast::Parameter = { - => { + => { let annotation = a.map(|x| Box::new(x.1)); - ast::Parameter { arg, annotation } + ast::Parameter { location, arg, annotation } }, }; @@ -546,7 +553,7 @@ KwargParameter: Option = { }; ClassDef: ast::Statement = { - "class" ":" => { + "class" ":" => { let (bases, keywords) = match a { Some((_, args, _)) => args, None => (vec![], vec![]), @@ -558,7 +565,7 @@ ClassDef: ast::Statement = { bases, keywords, body, - decorator_list: d, + decorator_list, }, } }, @@ -634,7 +641,7 @@ LambdaDef: ast::Expression = { ast::Expression { location, node: ast::ExpressionType::Lambda { - args: p.unwrap_or(Default::default()), + args: Box::new(p.unwrap_or_default()), body: Box::new(body) } } @@ -720,7 +727,7 @@ AndExpression: ast::Expression = { ShiftExpression: ast::Expression = { => ast::Expression { location, - node: ast::ExpressionType::Binop { a: Box::new(e1), op: op, b: Box::new(e2) } + node: ast::ExpressionType::Binop { a: Box::new(e1), op, b: Box::new(e2) } }, ArithmaticExpression, }; @@ -733,7 +740,7 @@ ShiftOp: ast::Operator = { ArithmaticExpression: ast::Expression = { => ast::Expression { location, - node: ast::ExpressionType::Binop { a: Box::new(a), op: op, b: Box::new(b) } + node: ast::ExpressionType::Binop { a: Box::new(a), op, b: Box::new(b) } }, Term, }; @@ -870,14 +877,14 @@ Atom: ast::Expression = { node: ast::ExpressionType::Identifier { name } }, "[" "]" => { - let elements = e.unwrap_or(Vec::new()); + let elements = e.unwrap_or_default(); ast::Expression { location, node: ast::ExpressionType::List { elements } } }, "[" "]" => e, - "(" ")" => { + "(" ")" => { elements.unwrap_or(ast::Expression { location, node: ast::ExpressionType::Tuple { elements: Vec::new() } @@ -894,7 +901,7 @@ Atom: ast::Expression = { }, "{" "}" => ast::Expression { location, - node: ast::ExpressionType::Dict { elements: e.unwrap_or(Vec::new()) } + node: ast::ExpressionType::Dict { elements: e.unwrap_or_default() } }, "{" "}" => e, "{" "}" => ast::Expression { @@ -1016,8 +1023,8 @@ StarExpr: ast::Expression = { CompFor: Vec = => c; SingleForComprehension: ast::Comprehension = { - "for" "in" => { - ast::Comprehension { target, iter, ifs: c2 } + "for" "in" => { + ast::Comprehension { location, target, iter, ifs } } }; @@ -1071,6 +1078,7 @@ FunctionArgument: (Option>, ast::Expression) = { "**" => (Some(None), e), }; +#[inline] Comma: Vec = { ",")*> => { let mut items = items; diff --git a/tests/snippets/tuple.py b/tests/snippets/tuple.py index f7d880e901..b57346378d 100644 --- a/tests/snippets/tuple.py +++ b/tests/snippets/tuple.py @@ -39,6 +39,9 @@ def __eq__(self, x): a += 1, assert a == (1, 2, 3, 1) +b = (55, *a) +assert b == (55, 1, 2, 3, 1) + assert () is () a = ()