mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
Merge pull request #1182 from RustPython/example1
Add support for star expression in tuple.
This commit is contained in:
@@ -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<T> {
|
||||
pub type Statement = Located<StatementType>;
|
||||
|
||||
/// 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<Expression>,
|
||||
iter: Box<Expression>,
|
||||
body: Vec<Statement>,
|
||||
orelse: Option<Vec<Statement>>,
|
||||
},
|
||||
@@ -125,7 +125,7 @@ pub enum StatementType {
|
||||
FunctionDef {
|
||||
is_async: bool,
|
||||
name: String,
|
||||
args: Parameters,
|
||||
args: Box<Parameters>,
|
||||
body: Vec<Statement>,
|
||||
decorator_list: Vec<Expression>,
|
||||
returns: Option<Expression>,
|
||||
@@ -217,7 +217,7 @@ pub enum ExpressionType {
|
||||
name: String,
|
||||
},
|
||||
Lambda {
|
||||
args: Parameters,
|
||||
args: Box<Parameters>,
|
||||
body: Box<Expression>,
|
||||
},
|
||||
IfExpression {
|
||||
@@ -293,6 +293,7 @@ pub struct Parameters {
|
||||
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Parameter {
|
||||
pub location: Location,
|
||||
pub arg: String,
|
||||
pub annotation: Option<Box<Expression>>,
|
||||
}
|
||||
@@ -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<Expression>,
|
||||
@@ -321,6 +323,7 @@ pub struct Keyword {
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ExceptHandler {
|
||||
pub location: Location,
|
||||
pub typ: Option<Expression>,
|
||||
pub name: Option<String>,
|
||||
pub body: Vec<Statement>,
|
||||
|
||||
@@ -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![
|
||||
|
||||
@@ -66,33 +66,33 @@ SmallStatement: ast::Statement = {
|
||||
};
|
||||
|
||||
PassStatement: ast::Statement = {
|
||||
<loc:@L> "pass" => {
|
||||
<location:@L> "pass" => {
|
||||
ast::Statement {
|
||||
location: loc,
|
||||
location,
|
||||
node: ast::StatementType::Pass,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
DelStatement: ast::Statement = {
|
||||
<loc:@L> "del" <e:ExpressionList2> => {
|
||||
<location:@L> "del" <targets:ExpressionList2> => {
|
||||
ast::Statement {
|
||||
location: loc,
|
||||
node: ast::StatementType::Delete { targets: e },
|
||||
location,
|
||||
node: ast::StatementType::Delete { targets },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
ExpressionStatement: ast::Statement = {
|
||||
<location:@L> <expr:TestOrStarExprList> <suffix:AssignSuffix*> => {
|
||||
<location:@L> <expression:TestOrStarExprList> <suffix:AssignSuffix*> => {
|
||||
// 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 },
|
||||
}
|
||||
},
|
||||
<location:@L> <y:YieldExpr> => {
|
||||
<location:@L> <expression:YieldExpr> => {
|
||||
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 = {
|
||||
<location:@L> "assert" <test:Test> <msg: ("," Test)?> => {
|
||||
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 = {
|
||||
<location:@L> "if" <test:Test> ":" <s1:Suite> <s2:(@L "elif" Test ":" Suite)*> <s3:("else" ":" Suite)?> => {
|
||||
<location:@L> "if" <test:Test> ":" <body:Suite> <s2:(@L "elif" Test ":" Suite)*> <s3:("else" ":" Suite)?> => {
|
||||
// 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 = {
|
||||
<location:@L> "while" <test:Test> ":" <body:Suite> <s2:("else" ":" Suite)?> => {
|
||||
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 = {
|
||||
<location:@L> "try" ":" <body:Suite> <handlers:ExceptClause*> <else_suite:("else" ":" Suite)?> <finally:("finally" ":" Suite)?> => {
|
||||
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" <typ:Test?> ":" <body:Suite> => {
|
||||
<location:@L> "except" <typ:Test?> ":" <body:Suite> => {
|
||||
ast::ExceptHandler {
|
||||
typ: typ,
|
||||
location,
|
||||
typ,
|
||||
name: None,
|
||||
body: body,
|
||||
body,
|
||||
}
|
||||
},
|
||||
"except" <x:(Test "as" Identifier)> ":" <body:Suite> => {
|
||||
<location:@L> "except" <x:(Test "as" Identifier)> ":" <body:Suite> => {
|
||||
ast::ExceptHandler {
|
||||
location,
|
||||
typ: Some(x.0),
|
||||
name: Some(x.2),
|
||||
body: body,
|
||||
body,
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -387,23 +399,23 @@ WithStatement: ast::Statement = {
|
||||
};
|
||||
|
||||
WithItem: ast::WithItem = {
|
||||
<t:Test> <n:("as" Expression)?> => {
|
||||
<context_expr:Test> <n:("as" Expression)?> => {
|
||||
let optional_vars = n.map(|val| val.1);
|
||||
ast::WithItem { context_expr: t, optional_vars }
|
||||
ast::WithItem { context_expr, optional_vars }
|
||||
},
|
||||
};
|
||||
|
||||
FuncDef: ast::Statement = {
|
||||
<d:Decorator*> <location:@L> <is_async:"async"?> "def" <name:Identifier> <a:Parameters> <r:("->" Test)?> ":" <body:Suite> => {
|
||||
<decorator_list:Decorator*> <location:@L> <is_async:"async"?> "def" <name:Identifier> <args:Parameters> <r:("->" Test)?> ":" <body:Suite> => {
|
||||
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: (ParameterList<TypedParameter>)?> ")" => a.unwrap_or_else(Default::default),
|
||||
"(" <a: (ParameterList<TypedParameter>)?> ")" => a.unwrap_or_default(),
|
||||
};
|
||||
|
||||
// Note that this is a macro which is used once for function defs, and
|
||||
@@ -425,7 +437,7 @@ ParameterList<ArgType>: ast::Parameters = {
|
||||
|
||||
ast::Parameters {
|
||||
args: names,
|
||||
kwonlyargs: kwonlyargs,
|
||||
kwonlyargs,
|
||||
vararg: vararg.into(),
|
||||
kwarg: kwarg.into(),
|
||||
defaults: default_elements,
|
||||
@@ -443,7 +455,7 @@ ParameterList<ArgType>: ast::Parameters = {
|
||||
|
||||
ast::Parameters {
|
||||
args: names,
|
||||
kwonlyargs: kwonlyargs,
|
||||
kwonlyargs,
|
||||
vararg: vararg.into(),
|
||||
kwarg: kwarg.into(),
|
||||
defaults: default_elements,
|
||||
@@ -454,7 +466,7 @@ ParameterList<ArgType>: 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<ArgType>: ast::Parameters = {
|
||||
// Use inline here to make sure the "," is not creating an ambiguity.
|
||||
#[inline]
|
||||
ParameterDefs<ArgType>: (Vec<ast::Parameter>, Vec<ast::Expression>) = {
|
||||
<param1:ParameterDef<ArgType>> <param2:("," ParameterDef<ArgType>)*> => {
|
||||
// Combine first parameters:
|
||||
let mut args = vec![param1];
|
||||
args.extend(param2.into_iter().map(|x| x.1));
|
||||
|
||||
<args:OneOrMore<ParameterDef<ArgType>>> => {
|
||||
let mut names = vec![];
|
||||
let mut default_elements = vec![];
|
||||
|
||||
@@ -491,16 +499,15 @@ ParameterDefs<ArgType>: (Vec<ast::Parameter>, Vec<ast::Expression>) = {
|
||||
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<ArgType>: (ast::Parameter, Option<ast::Expression>) = {
|
||||
};
|
||||
|
||||
UntypedParameter: ast::Parameter = {
|
||||
<i:Identifier> => ast::Parameter { arg: i, annotation: None },
|
||||
<location:@L> <arg:Identifier> => ast::Parameter { location, arg, annotation: None },
|
||||
};
|
||||
|
||||
TypedParameter: ast::Parameter = {
|
||||
<arg:Identifier> <a:(":" Test)?>=> {
|
||||
<location:@L> <arg:Identifier> <a:(":" Test)?>=> {
|
||||
let annotation = a.map(|x| Box::new(x.1));
|
||||
ast::Parameter { arg, annotation }
|
||||
ast::Parameter { location, arg, annotation }
|
||||
},
|
||||
};
|
||||
|
||||
@@ -546,7 +553,7 @@ KwargParameter<ArgType>: Option<ast::Parameter> = {
|
||||
};
|
||||
|
||||
ClassDef: ast::Statement = {
|
||||
<d:Decorator*> <location:@L> "class" <name:Identifier> <a:("(" ArgumentList ")")?> ":" <body:Suite> => {
|
||||
<decorator_list:Decorator*> <location:@L> "class" <name:Identifier> <a:("(" ArgumentList ")")?> ":" <body:Suite> => {
|
||||
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 = {
|
||||
<e1:ShiftExpression> <location:@L> <op:ShiftOp> <e2:ArithmaticExpression> => 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 = {
|
||||
<a:ArithmaticExpression> <location:@L> <op:AddOp> <b:Term> => 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 }
|
||||
},
|
||||
<location:@L> "[" <e:TestListComp?> "]" => {
|
||||
let elements = e.unwrap_or(Vec::new());
|
||||
let elements = e.unwrap_or_default();
|
||||
ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::List { elements }
|
||||
}
|
||||
},
|
||||
"[" <e:TestListComp2> "]" => e,
|
||||
<location:@L> "(" <elements:TestList?> ")" => {
|
||||
<location:@L> "(" <elements:TestOrStarExprList?> ")" => {
|
||||
elements.unwrap_or(ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::Tuple { elements: Vec::new() }
|
||||
@@ -894,7 +901,7 @@ Atom: ast::Expression = {
|
||||
},
|
||||
<location:@L> "{" <e:TestDict?> "}" => ast::Expression {
|
||||
location,
|
||||
node: ast::ExpressionType::Dict { elements: e.unwrap_or(Vec::new()) }
|
||||
node: ast::ExpressionType::Dict { elements: e.unwrap_or_default() }
|
||||
},
|
||||
"{" <e:TestDictComp> "}" => e,
|
||||
<location:@L> "{" <e:TestSet> "}" => ast::Expression {
|
||||
@@ -1016,8 +1023,8 @@ StarExpr: ast::Expression = {
|
||||
CompFor: Vec<ast::Comprehension> = <c:SingleForComprehension+> => c;
|
||||
|
||||
SingleForComprehension: ast::Comprehension = {
|
||||
"for" <target:ExpressionList> "in" <iter:OrTest> <c2:ComprehensionIf*> => {
|
||||
ast::Comprehension { target, iter, ifs: c2 }
|
||||
<location:@L> "for" <target:ExpressionList> "in" <iter:OrTest> <ifs:ComprehensionIf*> => {
|
||||
ast::Comprehension { location, target, iter, ifs }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1071,6 +1078,7 @@ FunctionArgument: (Option<Option<String>>, ast::Expression) = {
|
||||
"**" <e:Test> => (Some(None), e),
|
||||
};
|
||||
|
||||
#[inline]
|
||||
Comma<T>: Vec<T> = {
|
||||
<items: (<T> ",")*> <last: T?> => {
|
||||
let mut items = items;
|
||||
|
||||
@@ -39,6 +39,9 @@ a = (1, 2, 3)
|
||||
a += 1,
|
||||
assert a == (1, 2, 3, 1)
|
||||
|
||||
b = (55, *a)
|
||||
assert b == (55, 1, 2, 3, 1)
|
||||
|
||||
assert () is ()
|
||||
|
||||
a = ()
|
||||
|
||||
Reference in New Issue
Block a user