mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Add parsing for star arg parameters.
This commit is contained in:
@@ -198,11 +198,14 @@ pub enum Expression {
|
||||
* In cpython this is called arguments, but we choose parameters to
|
||||
* distuingish between function parameters and actual call arguments.
|
||||
*/
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Parameters {
|
||||
pub args: Vec<String>,
|
||||
pub kwonlyargs: Vec<String>,
|
||||
pub vararg: Option<String>,
|
||||
pub kwarg: Option<String>,
|
||||
pub defaults: Vec<Expression>,
|
||||
pub kw_defaults: Vec<Option<Expression>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
||||
@@ -228,8 +228,11 @@ mod tests {
|
||||
expression: ast::Expression::Lambda {
|
||||
args: ast::Parameters {
|
||||
args: vec![String::from("x"), String::from("y")],
|
||||
kwonlyargs: vec![],
|
||||
vararg: None,
|
||||
kwarg: None,
|
||||
defaults: vec![],
|
||||
kw_defaults: vec![],
|
||||
},
|
||||
body: Box::new(ast::Expression::Binop {
|
||||
a: Box::new(ast::Expression::Identifier {
|
||||
@@ -305,8 +308,11 @@ mod tests {
|
||||
name: String::from("__init__"),
|
||||
args: ast::Parameters {
|
||||
args: vec![String::from("self")],
|
||||
kwonlyargs: vec![],
|
||||
vararg: None,
|
||||
kwarg: None,
|
||||
defaults: vec![],
|
||||
kw_defaults: vec![],
|
||||
},
|
||||
body: vec![ast::LocatedStatement {
|
||||
location: ast::Location::new(3, 3),
|
||||
@@ -321,10 +327,13 @@ mod tests {
|
||||
name: String::from("method_with_default"),
|
||||
args: ast::Parameters {
|
||||
args: vec![String::from("self"), String::from("arg"),],
|
||||
kwonlyargs: vec![],
|
||||
vararg: None,
|
||||
kwarg: None,
|
||||
defaults: vec![ast::Expression::String {
|
||||
value: "default".to_string()
|
||||
}]
|
||||
}],
|
||||
kw_defaults: vec![],
|
||||
},
|
||||
body: vec![ast::LocatedStatement {
|
||||
location: ast::Location::new(5, 3),
|
||||
|
||||
@@ -407,13 +407,22 @@ FuncDef: ast::LocatedStatement = {
|
||||
};
|
||||
|
||||
Parameters: ast::Parameters = {
|
||||
"(" <a: TypedArgsList> ")" => a,
|
||||
"(" <a: (TypedArgsList)?> ")" => {
|
||||
match a {
|
||||
Some(a) => a,
|
||||
None => Default::default(),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// parameters are (String, None), kwargs are (String, Some(Test)) where Test is
|
||||
// the default
|
||||
TypedArgsList: ast::Parameters = {
|
||||
<args: Comma<Parameter>> => {
|
||||
<param1:TypedParameterDef> <param2:("," TypedParameterDef)*> <args2:("," ParameterListStarArgs)?> => {
|
||||
// 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![];
|
||||
|
||||
@@ -433,17 +442,71 @@ TypedArgsList: ast::Parameters = {
|
||||
}
|
||||
}
|
||||
|
||||
// Now gather rest of parameters:
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = match args2 {
|
||||
Some((_, x)) => x,
|
||||
None => (None, vec![], vec![], None),
|
||||
};
|
||||
|
||||
ast::Parameters {
|
||||
args: names,
|
||||
vararg: None,
|
||||
kwonlyargs: kwonlyargs,
|
||||
vararg: vararg,
|
||||
kwarg: kwarg,
|
||||
defaults: default_elements,
|
||||
kw_defaults: kw_defaults,
|
||||
}
|
||||
}
|
||||
},
|
||||
<params:ParameterListStarArgs> => {
|
||||
let (vararg, kwonlyargs, kw_defaults, kwarg) = params;
|
||||
ast::Parameters {
|
||||
args: vec![],
|
||||
kwonlyargs: kwonlyargs,
|
||||
vararg: vararg,
|
||||
kwarg: kwarg,
|
||||
defaults: vec![],
|
||||
kw_defaults: kw_defaults,
|
||||
}
|
||||
},
|
||||
"**" <kw:Identifier> => {
|
||||
ast::Parameters {
|
||||
args: vec![],
|
||||
kwonlyargs: vec![],
|
||||
vararg: None,
|
||||
kwarg: Some(kw),
|
||||
defaults: vec![],
|
||||
kw_defaults: vec![],
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Parameter: (String, Option<ast::Expression>) = {
|
||||
<i:Identifier> => (i.clone(), None),
|
||||
<i:Identifier> "=" <e:Test> => (i.clone(), Some(e)),
|
||||
TypedParameterDef: (String, Option<ast::Expression>) = {
|
||||
<i:TypedParameter> => (i, None),
|
||||
<i:TypedParameter> "=" <e:Test> => (i, Some(e)),
|
||||
};
|
||||
|
||||
// TODO: add type annotations here:
|
||||
TypedParameter: String = {
|
||||
Identifier,
|
||||
};
|
||||
|
||||
ParameterListStarArgs: (Option<String>, Vec<String>, Vec<Option<ast::Expression>>, Option<String>) = {
|
||||
"*" <va:Identifier> <kw:("," TypedParameterDef)*> <kwarg:("," "**" Identifier)?> => {
|
||||
// Extract keyword arguments:
|
||||
let mut kwonlyargs = vec![];
|
||||
let mut kw_defaults = vec![];
|
||||
for (name, value) in kw.into_iter().map(|x| x.1) {
|
||||
kwonlyargs.push(name);
|
||||
kw_defaults.push(value);
|
||||
}
|
||||
|
||||
let kwarg = match kwarg {
|
||||
Some((_, _, name)) => Some(name),
|
||||
None => None,
|
||||
};
|
||||
|
||||
(Some(va), kwonlyargs, kw_defaults, kwarg)
|
||||
}
|
||||
};
|
||||
|
||||
ClassDef: ast::LocatedStatement = {
|
||||
@@ -505,9 +568,9 @@ Test: ast::Expression = {
|
||||
};
|
||||
|
||||
LambdaDef: ast::Expression = {
|
||||
"lambda" <p:TypedArgsList> ":" <b:Expression> =>
|
||||
"lambda" <p:TypedArgsList?> ":" <b:Expression> =>
|
||||
ast::Expression::Lambda {
|
||||
args:p,
|
||||
args: p.unwrap_or(Default::default()),
|
||||
body:Box::new(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,11 @@
|
||||
a = 1
|
||||
del a
|
||||
|
||||
class MyObject: pass
|
||||
foo = MyObject()
|
||||
foo.bar = 2
|
||||
assert hasattr(foo, 'bar')
|
||||
del foo.bar
|
||||
|
||||
assert not hasattr(foo, 'bar')
|
||||
|
||||
|
||||
@@ -49,6 +49,28 @@ fn object_ne(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
objbool::not(vm, &eq)
|
||||
}
|
||||
|
||||
// TODO: is object the right place for delattr?
|
||||
fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(zelf, Some(vm.ctx.object())),
|
||||
(attr, Some(vm.ctx.str_type()))
|
||||
]
|
||||
);
|
||||
|
||||
// Get dict:
|
||||
let dict = match zelf.borrow().kind {
|
||||
PyObjectKind::Class { ref dict, .. } => dict.clone(),
|
||||
PyObjectKind::Instance { ref dict, .. } => dict.clone(),
|
||||
_ => return Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
};
|
||||
|
||||
// Delete attr from dict:
|
||||
vm.call_method(&dict, "__delitem__", vec![attr.clone()])
|
||||
}
|
||||
|
||||
fn object_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.object()))]);
|
||||
vm.call_method(zelf, "__repr__", vec![])
|
||||
@@ -67,6 +89,7 @@ pub fn init(context: &PyContext) {
|
||||
object.set_attr("__init__", context.new_rustfunc(object_init));
|
||||
object.set_attr("__eq__", context.new_rustfunc(object_eq));
|
||||
object.set_attr("__ne__", context.new_rustfunc(object_ne));
|
||||
object.set_attr("__delattr__", context.new_rustfunc(object_delattr));
|
||||
object.set_attr("__dict__", context.new_member_descriptor(object_dict));
|
||||
object.set_attr("__str__", context.new_rustfunc(object_str));
|
||||
object.set_attr("__repr__", context.new_rustfunc(object_repr));
|
||||
|
||||
Reference in New Issue
Block a user