forked from Rust-related/RustPython
Merge pull request #1787 from youknowone/posonly
PEP570 - positional only parameter support
This commit is contained in:
@@ -374,6 +374,7 @@ impl Expression {
|
||||
/// distinguish between function parameters and actual call arguments.
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Parameters {
|
||||
pub posonlyargs_count: usize,
|
||||
pub args: Vec<Parameter>,
|
||||
pub kwonlyargs: Vec<Parameter>,
|
||||
pub vararg: Varargs, // Optionally we handle optionally named '*args' or '*'
|
||||
|
||||
@@ -7,11 +7,13 @@ type ParameterDefs = (Vec<ast::Parameter>, Vec<ast::Expression>);
|
||||
type ParameterDef = (ast::Parameter, Option<ast::Expression>);
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
pub fn parse_params(params: Vec<ParameterDef>) -> Result<ParameterDefs, LexicalError> {
|
||||
pub fn parse_params(
|
||||
params: (Vec<ParameterDef>, Vec<ParameterDef>),
|
||||
) -> Result<ParameterDefs, LexicalError> {
|
||||
let mut names = vec![];
|
||||
let mut defaults = vec![];
|
||||
|
||||
for (name, default) in params {
|
||||
let mut try_default = |name: &ast::Parameter, default| {
|
||||
if let Some(default) = default {
|
||||
defaults.push(default);
|
||||
} else {
|
||||
@@ -20,10 +22,20 @@ pub fn parse_params(params: Vec<ParameterDef>) -> Result<ParameterDefs, LexicalE
|
||||
// have defaults
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::DefaultArgumentError,
|
||||
location: name.location,
|
||||
location: name.location.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
for (name, default) in params.0 {
|
||||
try_default(&name, default)?;
|
||||
names.push(name);
|
||||
}
|
||||
|
||||
for (name, default) in params.1 {
|
||||
try_default(&name, default)?;
|
||||
names.push(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ mod tests {
|
||||
location: ast::Location::new(1, 1),
|
||||
node: ast::ExpressionType::Lambda {
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(1, 8),
|
||||
@@ -335,6 +336,7 @@ mod tests {
|
||||
is_async: false,
|
||||
name: String::from("__init__"),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![ast::Parameter {
|
||||
location: ast::Location::new(2, 15),
|
||||
arg: String::from("self"),
|
||||
@@ -360,6 +362,7 @@ mod tests {
|
||||
is_async: false,
|
||||
name: String::from("method_with_default"),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(4, 26),
|
||||
|
||||
@@ -456,22 +456,25 @@ Parameters: ast::Parameters = {
|
||||
// once for lambda defs.
|
||||
ParameterList<ArgType>: ast::Parameters = {
|
||||
<param1:ParameterDefs<ArgType>> <args2:("," ParameterListStarArgs<ArgType>)?> ","? =>? {
|
||||
let (names, default_elements) = parse_params(param1)?;
|
||||
let posonlyargs_count = param1.0.len();
|
||||
let (names, defaults) = parse_params(param1)?;
|
||||
|
||||
// Now gather rest of parameters:
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = args2.map_or((None, vec![], vec![], None), |x| x.1);
|
||||
|
||||
Ok(ast::Parameters {
|
||||
posonlyargs_count,
|
||||
args: names,
|
||||
kwonlyargs,
|
||||
vararg: vararg.into(),
|
||||
kwarg: kwarg.into(),
|
||||
defaults: default_elements,
|
||||
kw_defaults: kw_defaults,
|
||||
defaults,
|
||||
kw_defaults,
|
||||
})
|
||||
},
|
||||
<param1:ParameterDefs<ArgType>> <kw:("," KwargParameter<ArgType>)> ","? =>? {
|
||||
let (names, default_elements) = parse_params(param1)?;
|
||||
let posonlyargs_count = param1.0.len();
|
||||
let (names, defaults) = parse_params(param1)?;
|
||||
|
||||
// Now gather rest of parameters:
|
||||
let vararg = None;
|
||||
@@ -480,27 +483,30 @@ ParameterList<ArgType>: ast::Parameters = {
|
||||
let kwarg = Some(kw.1);
|
||||
|
||||
Ok(ast::Parameters {
|
||||
posonlyargs_count,
|
||||
args: names,
|
||||
kwonlyargs,
|
||||
vararg: vararg.into(),
|
||||
kwarg: kwarg.into(),
|
||||
defaults: default_elements,
|
||||
kw_defaults: kw_defaults,
|
||||
defaults,
|
||||
kw_defaults,
|
||||
})
|
||||
},
|
||||
<params:ParameterListStarArgs<ArgType>> ","? => {
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = params;
|
||||
ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![],
|
||||
kwonlyargs,
|
||||
vararg: vararg.into(),
|
||||
kwarg: kwarg.into(),
|
||||
defaults: vec![],
|
||||
kw_defaults: kw_defaults,
|
||||
kw_defaults,
|
||||
}
|
||||
},
|
||||
<kw:KwargParameter<ArgType>> ","? => {
|
||||
ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![],
|
||||
kwonlyargs: vec![],
|
||||
vararg: ast::Varargs::None,
|
||||
@@ -513,10 +519,13 @@ ParameterList<ArgType>: ast::Parameters = {
|
||||
|
||||
// Use inline here to make sure the "," is not creating an ambiguity.
|
||||
#[inline]
|
||||
ParameterDefs<ArgType>: Vec<(ast::Parameter, Option<ast::Expression>)> = {
|
||||
ParameterDefs<ArgType>: (Vec<(ast::Parameter, Option<ast::Expression>)>, Vec<(ast::Parameter, Option<ast::Expression>)>) = {
|
||||
<args:OneOrMore<ParameterDef<ArgType>>> => {
|
||||
args
|
||||
}
|
||||
(vec![], args)
|
||||
},
|
||||
<pos_args:OneOrMore<ParameterDef<ArgType>>> "," "/" <args:("," ParameterDef<ArgType>)*> => {
|
||||
(pos_args, args.into_iter().map(|e| e.1).collect())
|
||||
},
|
||||
};
|
||||
|
||||
ParameterDef<ArgType>: (ast::Parameter, Option<ast::Expression>) = {
|
||||
|
||||
Reference in New Issue
Block a user