Skip to content

Commit 0e4bec3

Browse files
committed
extract empty_arguments_object helper
1 parent 5b3b1d4 commit 0e4bec3

File tree

3 files changed

+36
-31
lines changed

3 files changed

+36
-31
lines changed

crates/vm/src/stdlib/ast.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,22 @@ fn node_add_location(
265265
.unwrap();
266266
}
267267

268+
/// Create an empty `arguments` AST node (no parameters).
269+
fn empty_arguments_object(vm: &VirtualMachine) -> PyObjectRef {
270+
let node = NodeAst
271+
.into_ref_with_type(vm, pyast::NodeArguments::static_type().to_owned())
272+
.unwrap();
273+
let dict = node.as_object().dict().unwrap();
274+
for list_field in ["posonlyargs", "args", "kwonlyargs", "kw_defaults", "defaults"] {
275+
dict.set_item(list_field, vm.ctx.new_list(vec![]).into(), vm)
276+
.unwrap();
277+
}
278+
for none_field in ["vararg", "kwarg"] {
279+
dict.set_item(none_field, vm.ctx.none(), vm).unwrap();
280+
}
281+
node.into()
282+
}
283+
268284
#[cfg(feature = "parser")]
269285
pub(crate) fn parse(
270286
vm: &VirtualMachine,

crates/vm/src/stdlib/ast/expression.rs

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -330,31 +330,7 @@ impl Node for ast::ExprLambda {
330330
// Lambda with no parameters should have an empty arguments object, not None
331331
let args = match parameters {
332332
Some(params) => params.ast_to_object(vm, source_file),
333-
None => {
334-
// Create an empty arguments object
335-
let args_node = NodeAst
336-
.into_ref_with_type(vm, pyast::NodeArguments::static_type().to_owned())
337-
.unwrap();
338-
let args_dict = args_node.as_object().dict().unwrap();
339-
args_dict
340-
.set_item("posonlyargs", vm.ctx.new_list(vec![]).into(), vm)
341-
.unwrap();
342-
args_dict
343-
.set_item("args", vm.ctx.new_list(vec![]).into(), vm)
344-
.unwrap();
345-
args_dict.set_item("vararg", vm.ctx.none(), vm).unwrap();
346-
args_dict
347-
.set_item("kwonlyargs", vm.ctx.new_list(vec![]).into(), vm)
348-
.unwrap();
349-
args_dict
350-
.set_item("kw_defaults", vm.ctx.new_list(vec![]).into(), vm)
351-
.unwrap();
352-
args_dict.set_item("kwarg", vm.ctx.none(), vm).unwrap();
353-
args_dict
354-
.set_item("defaults", vm.ctx.new_list(vec![]).into(), vm)
355-
.unwrap();
356-
args_node.into()
357-
}
333+
None => empty_arguments_object(vm),
358334
};
359335
dict.set_item("args", args, vm).unwrap();
360336
dict.set_item("body", body.ast_to_object(vm, source_file), vm)

crates/vm/src/stdlib/ast/python.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,11 @@ pub(crate) mod _ast {
9595
.is_some();
9696
if has_field_types {
9797
// ASDL list fields (type*) default to empty list,
98-
// optional fields (type?) default to None.
98+
// optional/required fields default to None.
99+
// Fields that are always list-typed regardless of node class.
99100
const LIST_FIELDS: &[&str] = &[
100-
"args",
101101
"argtypes",
102102
"bases",
103-
"body",
104103
"cases",
105104
"comparators",
106105
"decorator_list",
@@ -125,19 +124,33 @@ pub(crate) mod _ast {
125124
"values",
126125
];
127126

127+
let class_name = zelf.class().name().to_string();
128+
128129
for field in &fields {
129130
if !set_fields.contains(field.as_str()) {
130-
let default: PyObjectRef = if LIST_FIELDS.contains(&field.as_str()) {
131+
let field_name = field.as_str();
132+
// "args" and "body" have different ASDL types depending on the node:
133+
// args: expr* in Call, arg* in arguments, but single `arguments` in
134+
// Lambda/FunctionDef/AsyncFunctionDef
135+
// body: stmt* in most nodes, but single `expr` in Lambda/Expression
136+
let is_list_field = if field_name == "args" {
137+
class_name == "Call" || class_name == "arguments"
138+
} else if field_name == "body" {
139+
class_name != "Lambda" && class_name != "Expression"
140+
} else {
141+
LIST_FIELDS.contains(&field_name)
142+
};
143+
144+
let default: PyObjectRef = if is_list_field {
131145
vm.ctx.new_list(vec![]).into()
132146
} else {
133147
vm.ctx.none()
134148
};
135-
zelf.set_attr(vm.ctx.intern_str(field.as_str()), default, vm)?;
149+
zelf.set_attr(vm.ctx.intern_str(field_name), default, vm)?;
136150
}
137151
}
138152

139153
// Special defaults that are not None or empty list
140-
let class_name = &*zelf.class().name();
141154
if class_name == "ImportFrom" && !set_fields.contains("level") {
142155
zelf.set_attr("level", vm.ctx.new_int(0), vm)?;
143156
}

0 commit comments

Comments
 (0)