Skip to content

Commit 5203984

Browse files
committed
Use closure for generated properties in struct sequences.
1 parent 8b657ab commit 5203984

File tree

1 file changed

+61
-73
lines changed

1 file changed

+61
-73
lines changed

derive/src/pyclass.rs

Lines changed: 61 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -346,83 +346,71 @@ pub fn impl_pyclass(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
346346
}
347347

348348
pub fn impl_pystruct_sequence(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diagnostic> {
349-
if let Item::Struct(struc) = item {
350-
let class_def = generate_class_def(&struc.ident, "pystruct_sequence", attr, &struc.attrs)?;
351-
let mut methods = Vec::new();
352-
let mut method_references = Vec::new();
353-
let mut field_names = Vec::new();
354-
for (i, field) in struc.fields.iter().enumerate() {
355-
let idx = Index::from(i);
356-
if let Some(ref field_name) = field.ident {
357-
let method_name = format!("get_{}", field_name);
358-
let method_ident = Ident::new(&method_name, field_name.span());
359-
360-
let method = quote! {
361-
fn #method_ident(
362-
zelf: &::rustpython_vm::obj::objtuple::PyTuple,
363-
_vm: &::rustpython_vm::vm::VirtualMachine)
364-
-> ::rustpython_vm::pyobject::PyObjectRef {
365-
zelf.fast_getitem(#idx)
366-
}
367-
};
368-
methods.push(method);
369-
let field_name_str = field_name.to_string();
370-
// TODO add doc to the generated property
371-
let method_reference = quote! {
372-
class.set_str_attr(
373-
#field_name_str,
374-
::rustpython_vm::obj::objproperty::PropertyBuilder::new(ctx)
375-
.add_getter(Self::#method_ident)
376-
.create(),
377-
);
378-
};
379-
method_references.push(method_reference);
380-
field_names.push(quote!(#field_name));
381-
} else {
382-
field_names.push(quote!(#idx));
383-
}
384-
}
385-
386-
let ty = &struc.ident;
387-
let ret = quote! {
388-
#struc
389-
#class_def
390-
impl #ty {
391-
fn into_struct_sequence(&self,
392-
vm: &::rustpython_vm::vm::VirtualMachine,
393-
cls: ::rustpython_vm::obj::objtype::PyClassRef,
394-
) -> ::rustpython_vm::pyobject::PyResult<::rustpython_vm::obj::objtuple::PyTupleRef> {
395-
let tuple: ::rustpython_vm::obj::objtuple::PyTuple =
396-
vec![#(::rustpython_vm::pyobject::IntoPyObject
397-
::into_pyobject(self.#field_names, vm)?
398-
),*].into();
399-
::rustpython_vm::pyobject::PyValue::into_ref_with_type(tuple, vm, cls)
400-
}
401-
402-
#(#methods)*
403-
}
404-
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
405-
fn impl_extend_class(
406-
ctx: &::rustpython_vm::pyobject::PyContext,
407-
class: &::rustpython_vm::obj::objtype::PyClassRef,
408-
) {
409-
#(#method_references)*
410-
}
411-
412-
fn make_class(
413-
ctx: &::rustpython_vm::pyobject::PyContext
414-
) -> ::rustpython_vm::obj::objtype::PyClassRef {
415-
let py_class = ctx.new_class(<Self as ::rustpython_vm::pyobject::PyClassDef>::NAME, ctx.tuple_type());
416-
Self::extend_class(ctx, &py_class);
417-
py_class
418-
}
419-
}
420-
};
421-
Ok(ret)
349+
let struc = if let Item::Struct(struc) = item {
350+
struc
422351
} else {
423352
bail_span!(
424353
item,
425354
"#[pystruct_sequence] can only be on a struct declaration"
426355
)
356+
};
357+
let class_def = generate_class_def(&struc.ident, "pystruct_sequence", attr, &struc.attrs)?;
358+
let mut properties = Vec::new();
359+
let mut field_names = Vec::new();
360+
for (i, field) in struc.fields.iter().enumerate() {
361+
let idx = Index::from(i);
362+
if let Some(ref field_name) = field.ident {
363+
let field_name_str = field_name.to_string();
364+
// TODO add doc to the generated property
365+
let property = quote! {
366+
class.set_str_attr(
367+
#field_name_str,
368+
::rustpython_vm::obj::objproperty::PropertyBuilder::new(ctx)
369+
.add_getter(|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
370+
_vm: &::rustpython_vm::vm::VirtualMachine|
371+
zelf.fast_getitem(#idx))
372+
.create(),
373+
);
374+
};
375+
properties.push(property);
376+
field_names.push(quote!(#field_name));
377+
} else {
378+
field_names.push(quote!(#idx));
379+
}
427380
}
381+
382+
let ty = &struc.ident;
383+
let ret = quote! {
384+
#struc
385+
#class_def
386+
impl #ty {
387+
fn into_struct_sequence(&self,
388+
vm: &::rustpython_vm::vm::VirtualMachine,
389+
cls: ::rustpython_vm::obj::objtype::PyClassRef,
390+
) -> ::rustpython_vm::pyobject::PyResult<::rustpython_vm::obj::objtuple::PyTupleRef> {
391+
let tuple: ::rustpython_vm::obj::objtuple::PyTuple =
392+
vec![#(::rustpython_vm::pyobject::IntoPyObject
393+
::into_pyobject(self.#field_names, vm)?
394+
),*].into();
395+
::rustpython_vm::pyobject::PyValue::into_ref_with_type(tuple, vm, cls)
396+
}
397+
}
398+
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
399+
fn impl_extend_class(
400+
ctx: &::rustpython_vm::pyobject::PyContext,
401+
class: &::rustpython_vm::obj::objtype::PyClassRef,
402+
) {
403+
#(#properties)*
404+
}
405+
406+
fn make_class(
407+
ctx: &::rustpython_vm::pyobject::PyContext
408+
) -> ::rustpython_vm::obj::objtype::PyClassRef {
409+
let py_class = ctx.new_class(<Self as ::rustpython_vm::pyobject::PyClassDef>::NAME, ctx.tuple_type());
410+
Self::extend_class(ctx, &py_class);
411+
py_class
412+
}
413+
}
414+
};
415+
Ok(ret)
428416
}

0 commit comments

Comments
 (0)