Merge pull request #1787 from youknowone/posonly

PEP570 - positional only parameter support
This commit is contained in:
Noah
2020-03-13 17:19:21 -05:00
committed by GitHub
8 changed files with 1893 additions and 28 deletions

View File

@@ -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 '*'

View File

@@ -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);
}

View File

@@ -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),

View File

@@ -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>) = {