Skip to content
This repository has been archived by the owner on Oct 28, 2020. It is now read-only.

Procedural function attribute macro, Optional argument handling #18

Open
dnorman opened this issue Jun 19, 2019 · 4 comments
Open

Procedural function attribute macro, Optional argument handling #18

dnorman opened this issue Jun 19, 2019 · 4 comments

Comments

@dnorman
Copy link
Contributor

dnorman commented Jun 19, 2019

Objectives:

  1. Export functions to perl which contain optional arguments.
  2. Make argument handling more magical
  3. Move toward more idiomatic rust conventions for function binding

At present, the xs! macro is unable to handle Option arguments which may be omitted by the perl caller.

I propose that we do away with the xs! macro_rules in favor of a procedural function attribute macro, similar to wasm_bindgen or the pyo3 crate.

Proposed syntax:

//lib.rs:
mod bar;
mod blah;
perl_base_module!("Foo")

//bar.rs
#[perl]
fn alpha (maybe: Option<Something>){}

//blah.rs
#[perl]
fn beta (definitely: Something){}

By doing this as a procedural macro, this will also improve the ability to perform smarter argument handling / coercion, including derive structs, optional context argument, etc.

The goal here is to have a perfectly ordinary rust function be callable from within perl with little or no special accommodation for the perl guts, at least in some circumstances.

@vickenty
Copy link
Owner

How a procedural macro can improve argument coercions?

@dnorman
Copy link
Contributor Author

dnorman commented Jun 23, 2019

If nothing else, macro_rules style macros are too unwieldy to make sufficient improvement (at least they are for me) and I think they are also incapable of branching logic, as is required for Option<T> vs T or other such situations. I fully intend to implement this myself, and am not really asking for anyone else to do it per se. I was merely hoping to use this ticket as a way to socialize the idea and get feedback :)

I think it would be super cool to utilize a wasm_bindgen style attribute macro, such that the same rust function is able to accommodate rust callers and Perl callers.

It could more tightly integrate with the struct argument unpacking derive macro I wrote earlier as well.

@vickenty
Copy link
Owner

I wasn't really arguing against improving syntax; I agree that the current xs! macro is quite bulky.

But some of the improvements you want to make by switching to procedural macro don't make much sense to me.

Functions require all formal parameters to be specified quite deliberately, inspired by the behavior of xsubpp and perl's own subroutine signatures. If anything, I'd like to make it even more strict and die when too many parameters are supplied too (to make it even more like xsubpp and perl signatures). This is different story for another issue, but the point here is that this isn't really a limitation of the macro itself.

  • Handling Option vs other types is also not a job for a macro. AIUI procedural macros are expanded before name resolution, so it would be impossible to tell std Option from one defined in another crate. Trait system is the tool for this job, and some Option types are already supported (e.g. `Option).

Otherwise, sounds cool! :) I'm interested to see how this pans out.

@dnorman
Copy link
Contributor Author

dnorman commented Jun 26, 2019

One of the situations I'm trying to accommodate is this:

#[perlxs]
fn test ( a: String, b: Option<String> ){
...
}

Valid perl-side calling scenario 1:

test("Meow");

Valid perl-side calling scenario 2

test("Meow","Woof")

if fn test accepts Option<T> as a positional argument, then the binding code ( presently defined inside !xs should call the function with None instead of croaking with "not enough arguments ..."

Making this change also provides an opportunity to:

  • Make the perl context object an optional function argument – fn test(a: String) vs fn test(ctx: Context, a: String)
  • Handle argument types which impl FromPerlKV
  • Improve return type handling
  • More readable macro logic will encourage community improvement
  • Probably offers other benefits too :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants