Skip to content

Commit e92ba94

Browse files
committed
Modify ast regarding keyword arguments.
1 parent 2035f54 commit e92ba94

File tree

5 files changed

+99
-63
lines changed

5 files changed

+99
-63
lines changed

parser/src/ast.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,14 @@ pub enum Statement {
9595
ClassDef {
9696
name: String,
9797
body: Vec<LocatedStatement>,
98-
args: Vec<(String, Option<Expression>)>,
99-
// TODO: bases: Vec<Expression>,
100-
// TODO: keywords: Vec<Keyword>,
98+
bases: Vec<Expression>,
99+
keywords: Vec<Keyword>,
101100
decorator_list: Vec<Expression>,
102101
// TODO: docstring: String,
103102
},
104103
FunctionDef {
105104
name: String,
106-
args: Vec<(String, Option<Expression>)>,
105+
args: Parameters,
107106
// docstring: String,
108107
body: Vec<LocatedStatement>,
109108
decorator_list: Vec<Expression>,
@@ -182,7 +181,7 @@ pub enum Expression {
182181
name: String,
183182
},
184183
Lambda {
185-
args: Vec<(String, Option<Expression>)>,
184+
args: Parameters,
186185
body: Box<Expression>,
187186
},
188187
IfExpression {
@@ -195,6 +194,17 @@ pub enum Expression {
195194
None,
196195
}
197196

197+
/*
198+
* In cpython this is called arguments, but we choose parameters to
199+
* distuingish between function parameters and actual call arguments.
200+
*/
201+
#[derive(Debug, PartialEq)]
202+
pub struct Parameters {
203+
pub args: Vec<String>,
204+
pub vararg: Option<String>,
205+
pub defaults: Vec<Expression>,
206+
}
207+
198208
#[derive(Debug, PartialEq)]
199209
pub enum ComprehensionKind {
200210
List { element: Expression },

parser/src/parser.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,11 @@ mod tests {
226226
location: ast::Location::new(1, 1),
227227
node: ast::Statement::Expression {
228228
expression: ast::Expression::Lambda {
229-
args: vec![(String::from("x"), None), (String::from("y"), None)],
229+
args: ast::Parameters {
230+
args: vec![String::from("x"), String::from("y")],
231+
vararg: None,
232+
defaults: vec![],
233+
},
230234
body: Box::new(ast::Expression::Binop {
231235
a: Box::new(ast::Expression::Identifier {
232236
name: String::from("x"),
@@ -285,13 +289,25 @@ mod tests {
285289
location: ast::Location::new(1, 1),
286290
node: ast::Statement::ClassDef {
287291
name: String::from("Foo"),
288-
args: vec![(String::from("A"), None), (String::from("B"), None)],
292+
bases: vec![
293+
ast::Expression::Identifier {
294+
name: String::from("A")
295+
},
296+
ast::Expression::Identifier {
297+
name: String::from("B")
298+
}
299+
],
300+
keywords: vec![],
289301
body: vec![
290302
ast::LocatedStatement {
291303
location: ast::Location::new(2, 2),
292304
node: ast::Statement::FunctionDef {
293305
name: String::from("__init__"),
294-
args: vec![(String::from("self"), None)],
306+
args: ast::Parameters {
307+
args: vec![String::from("self")],
308+
vararg: None,
309+
defaults: vec![],
310+
},
295311
body: vec![ast::LocatedStatement {
296312
location: ast::Location::new(3, 3),
297313
node: ast::Statement::Pass,
@@ -303,15 +319,13 @@ mod tests {
303319
location: ast::Location::new(4, 2),
304320
node: ast::Statement::FunctionDef {
305321
name: String::from("method_with_default"),
306-
args: vec![
307-
(String::from("self"), None),
308-
(
309-
String::from("arg"),
310-
Some(ast::Expression::String {
311-
value: "default".to_string()
312-
})
313-
)
314-
],
322+
args: ast::Parameters {
323+
args: vec![String::from("self"), String::from("arg"),],
324+
vararg: None,
325+
defaults: vec![ast::Expression::String {
326+
value: "default".to_string()
327+
}]
328+
},
315329
body: vec![ast::LocatedStatement {
316330
location: ast::Location::new(5, 3),
317331
node: ast::Statement::Pass,

parser/src/python.lalrpop

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -406,33 +406,63 @@ FuncDef: ast::LocatedStatement = {
406406
},
407407
};
408408

409-
Parameters: Vec<(String, Option<ast::Expression>)> = {
409+
Parameters: ast::Parameters = {
410410
"(" <a: TypedArgsList> ")" => a,
411411
};
412412

413413
// parameters are (String, None), kwargs are (String, Some(Test)) where Test is
414414
// the default
415-
TypedArgsList: Vec<(String, Option<ast::Expression>)> = {
416-
<a: Comma<Parameter>> => a
415+
TypedArgsList: ast::Parameters = {
416+
<args: Comma<Parameter>> => {
417+
let mut names = vec![];
418+
let mut default_elements = vec![];
419+
420+
for (name, default) in args.into_iter() {
421+
names.push(name.clone());
422+
if let Some(default) = default {
423+
default_elements.push(default);
424+
} else {
425+
if default_elements.len() > 0 {
426+
// Once we have started with defaults, all remaining arguments must
427+
// have defaults
428+
panic!(
429+
"non-default argument follows default argument: {}",
430+
name
431+
);
432+
}
433+
}
434+
}
435+
436+
ast::Parameters {
437+
args: names,
438+
vararg: None,
439+
defaults: default_elements,
440+
}
441+
}
417442
};
418443

419444
Parameter: (String, Option<ast::Expression>) = {
420445
<i:Identifier> => (i.clone(), None),
421-
<i:Identifier> "=" <e:Expression> => (i.clone(), Some(e)),
446+
<i:Identifier> "=" <e:Test> => (i.clone(), Some(e)),
422447
};
423448

424449
ClassDef: ast::LocatedStatement = {
425-
<d:Decorator*> <loc:@L> "class" <n:Identifier> <a:Parameters?> ":" <s:Suite> => {
426-
ast::LocatedStatement {
427-
location: loc,
428-
node: ast::Statement::ClassDef {
429-
name: n,
430-
args: a.unwrap_or(vec![]),
431-
body: s,
432-
decorator_list: d,
433-
},
434-
}
435-
},
450+
<d:Decorator*> <loc:@L> "class" <n:Identifier> <a:("(" ArgumentList ")")?> ":" <s:Suite> => {
451+
let (bases, keywords) = match a {
452+
Some((_, args, _)) => args,
453+
None => (vec![], vec![]),
454+
};
455+
ast::LocatedStatement {
456+
location: loc,
457+
node: ast::Statement::ClassDef {
458+
name: n,
459+
bases: bases,
460+
keywords: keywords,
461+
body: s,
462+
decorator_list: d,
463+
},
464+
}
465+
},
436466
};
437467

438468
// Decorators:

vm/src/compile.rs

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -384,37 +384,18 @@ impl Compiler {
384384
decorator_list,
385385
} => {
386386
// Create bytecode for this function:
387-
let mut names = vec![];
388-
let mut default_elements = vec![];
389-
390-
for (name, default) in args {
391-
names.push(name.clone());
392-
if let Some(default) = default {
393-
default_elements.push(default.clone());
394-
} else {
395-
if default_elements.len() > 0 {
396-
// Once we have started with defaults, all remaining arguments must
397-
// have defaults
398-
return Err(format!(
399-
"non-default argument follows default argument: {}",
400-
name
401-
));
402-
}
403-
}
404-
}
405-
406-
let have_kwargs = default_elements.len() > 0;
387+
let have_kwargs = args.defaults.len() > 0;
407388
if have_kwargs {
408389
// Construct a tuple:
409-
let size = default_elements.len();
410-
for element in default_elements {
390+
let size = args.defaults.len();
391+
for element in &args.defaults {
411392
self.compile_expression(element)?;
412393
}
413394
self.emit(Instruction::BuildTuple { size });
414395
}
415396

416397
self.code_object_stack.push(CodeObject::new(
417-
names,
398+
args.args.clone(),
418399
self.source_path.clone(),
419400
name.clone(),
420401
));
@@ -453,7 +434,8 @@ impl Compiler {
453434
ast::Statement::ClassDef {
454435
name,
455436
body,
456-
args,
437+
bases,
438+
keywords: _,
457439
decorator_list,
458440
} => {
459441
self.prepare_decorators(decorator_list)?;
@@ -482,6 +464,7 @@ impl Compiler {
482464
value: name.clone(),
483465
},
484466
});
467+
485468
// Turn code object into function object:
486469
self.emit(Instruction::MakeFunction {
487470
flags: bytecode::FunctionOpArg::empty(),
@@ -493,13 +476,11 @@ impl Compiler {
493476
},
494477
});
495478

496-
for base in args {
497-
self.emit(Instruction::LoadName {
498-
name: base.0.clone(),
499-
});
479+
for base in bases {
480+
self.compile_expression(base)?;
500481
}
501482
self.emit(Instruction::CallFunction {
502-
count: 2 + args.len(),
483+
count: 2 + bases.len(),
503484
});
504485

505486
self.apply_decorators(decorator_list);
@@ -906,7 +887,7 @@ impl Compiler {
906887
}
907888
ast::Expression::Lambda { args, body } => {
908889
self.code_object_stack.push(CodeObject::new(
909-
args.iter().map(|(name, _default)| name.clone()).collect(),
890+
args.args.clone(),
910891
self.source_path.clone(),
911892
"<lambda>".to_string(),
912893
));

vm/src/stdlib/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ fn statement_to_ast(ctx: &PyContext, statement: &ast::LocatedStatement) -> PyObj
6464
ast::Statement::ClassDef {
6565
name,
6666
body,
67-
args: _,
67+
bases: _,
68+
keywords: _,
6869
decorator_list,
6970
} => {
7071
let node = create_node(ctx, "ClassDef");

0 commit comments

Comments
 (0)