diff --git a/Cargo.lock b/Cargo.lock index 3ccef5e02..552f2d3a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2282,9 +2282,9 @@ dependencies = [ [[package]] name = "syn-ext" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e039b5850edc6e974a22c8ea37ba9dc4de7909c2572eff65b2f943bd5dc984" +checksum = "9210542fa1f4811e2024f7ef22668ef8e035a54f6c9d4826faae8ae2885bd455" dependencies = [ "syn", ] diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 0defb9176..9b5f48abd 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -12,7 +12,7 @@ proc-macro = true [dependencies] syn = { version = "1.0", features = ["full", "extra-traits"] } -syn-ext = { version = "0.2.1", features = ["full"] } +syn-ext = { version = "0.2.3", features = ["full"] } quote = "1.0" proc-macro2 = "1.0" rustpython-compiler = { path = "../compiler/porcelain", version = "0.1.1" } diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index d3c8f9b39..01fcb06bf 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -337,13 +337,51 @@ where let item_attr = args.attrs.remove(self.index()); let item_meta = MethodItemMeta::from_attr(ident.clone(), &item_attr)?; - let py_name = item_meta.method_name()?; + + let sig_doc = args.item.function_or_method_impl().ok().map(|item| { + let sig = item.sig(); + let args: Vec<_> = sig + .inputs + .iter() + .filter_map(|arg| { + use syn::FnArg::*; + let arg = match arg { + Receiver(_) => return Some("$self".to_owned()), + Typed(typed) => typed, + }; + let ty = arg.ty.as_ref(); + let ty = quote!(#ty).to_string(); + if ty == "FuncArgs" { + return Some("*args, **kwargs".to_owned()); + } + if ty == "& VirtualMachine" { + return None; + } + let ident = match arg.pat.as_ref() { + syn::Pat::Ident(p) => p.ident.to_string(), + // FIXME: other => unreachable!("function arg pattern must be ident but found `{}`", quote!(fn #ident(.. #other ..))), + other => quote!(#other).to_string(), + }; + if ident == "zelf" { + return Some("$self".to_owned()); + } + if ident == "vm" { + unreachable!("type &VirtualMachine(`{}`) must be filtered already", ty); + } + Some(ident) + }) + .collect(); + format!("{}({})", py_name, args.join(", ")) + }); + let tokens = { - let doc = args.attrs.doc().map_or_else( - TokenStream::new, - |doc| quote!(.with_doc(#doc.to_owned(), ctx)), - ); + let doc = args.attrs.doc().map_or_else(TokenStream::new, |mut doc| { + if let Some(sig_doc) = sig_doc { + doc = format!("{}\n--\n\n{}", sig_doc, doc); + } + quote!(.with_doc(#doc.to_owned(), ctx)) + }); let build_func = match self.method_type.as_str() { "method" => quote!(.build_method(ctx, class.clone())), "classmethod" => quote!(.build_classmethod(ctx, class.clone())), diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index 6f47968dd..32930f4c3 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -33,9 +33,6 @@ impl PyValue for PyBaseObject { #[pyimpl(flags(BASETYPE))] impl PyBaseObject { - /// __new__($type, *args, **kwargs) - /// -- - /// /// Create and return a new object. See help(type) for accurate signature. #[pyslot] fn tp_new(mut args: FuncArgs, vm: &VirtualMachine) -> PyResult { @@ -92,105 +89,81 @@ impl PyBaseObject { Ok(res) } - /// __eq__($self, value, /) - /// -- - /// /// Return self==value. #[pymethod(magic)] fn eq( zelf: PyObjectRef, - other: PyObjectRef, + value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Eq, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Eq, vm) } - /// __ne__($self, value, /) - /// -- - /// /// Return self!=value. #[pymethod(magic)] fn ne( zelf: PyObjectRef, - other: PyObjectRef, + value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Ne, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Ne, vm) } - /// __lt__($self, value, /) - /// -- - /// /// Return self PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Lt, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Lt, vm) } - /// __le__($self, value, /) - /// -- - /// /// Return self<=value. #[pymethod(magic)] fn le( zelf: PyObjectRef, - other: PyObjectRef, + value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Le, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Le, vm) } - /// __ge__($self, value, /) - /// -- - /// /// Return self>=value. #[pymethod(magic)] fn ge( zelf: PyObjectRef, - other: PyObjectRef, + value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Ge, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Ge, vm) } - /// __gt__($self, value, /) - /// -- - /// /// Return self>value. #[pymethod(magic)] fn gt( zelf: PyObjectRef, - other: PyObjectRef, + value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult { - Self::cmp(&zelf, &other, PyComparisonOp::Gt, vm) + Self::cmp(&zelf, &value, PyComparisonOp::Gt, vm) } - /// __setattr__($self, name, value /) - /// -- - /// /// Implement setattr(self, name, value). #[pymethod] fn __setattr__( obj: PyObjectRef, - attr_name: PyStrRef, + name: PyStrRef, value: PyObjectRef, vm: &VirtualMachine, ) -> PyResult<()> { - setattr(&obj, attr_name, Some(value), vm) + setattr(&obj, name, Some(value), vm) } - /// __delattr__($self, name, /) - /// -- - /// /// Implement delattr(self, name). #[pymethod] - fn __delattr__(obj: PyObjectRef, attr_name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> { - setattr(&obj, attr_name, None, vm) + fn __delattr__(obj: PyObjectRef, name: PyStrRef, vm: &VirtualMachine) -> PyResult<()> { + setattr(&obj, name, None, vm) } #[pyslot] @@ -203,18 +176,12 @@ impl PyBaseObject { setattr(obj, attr_name, value, vm) } - /// __str__($self, /) - /// -- - /// /// Return str(self). #[pymethod(magic)] fn str(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult { vm.to_repr(&zelf) } - /// __repr__($self, /) - /// -- - /// /// Return repr(self). #[pymethod(magic)] fn repr(zelf: PyObjectRef) -> String { @@ -288,9 +255,6 @@ impl PyBaseObject { } } - /// __getattribute__($self, name, /) - /// -- - /// /// Return getattr(self, name). #[pymethod(name = "__getattribute__")] #[pyslot] @@ -321,9 +285,6 @@ impl PyBaseObject { Ok(zelf.get_id() as _) } - /// __hash__($self, /) - /// -- - /// /// Return hash(self). #[pymethod(magic)] fn hash(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult {