ocaml-interop icon indicating copy to clipboard operation
ocaml-interop copied to clipboard

Switching to a proc macro for `ocaml_export!`?

Open mt-caret opened this issue 1 year ago • 2 comments

One unfortunate issue with ocaml_export is that is is not rustfmt-friendly, so functions inside of it do not get formatted. An alternate syntax could look something like this (somewhat similar to ocaml-rs):

#[ocaml_interop_export]
fn rust_expr_float(cr: &mut &mut OCamlRuntime, value: OCamlRef<OCamlFloat>) -> OCaml<DynBox<Expr>> {
    let value: f64 = value.to_rust(cr);
    OCaml::box_value(cr, lit(value))
}

A proc macro based approach also provides the following benefits: it's much easier to analyze the syntax (and e.g. extracting out named identifiers) so something like https://github.com/tizoc/ocaml-interop/issues/49#issuecomment-1627760159 is quite straightforward to implement. The cons are of course the added complexity of proc macros...

I've gone and written a re-implementation of most of ocaml_export! in a proc macro (https://github.com/mt-caret/polars-ocaml/blob/bc76aecb6f30afb6d22a695a9bd62421c8e2587a/rust/polars-ocaml-macros/src/lib.rs), and was wondering if this would be something you would be happy/willing to integrate. My current implementation also implements panic unwinding logic described in https://github.com/tizoc/ocaml-interop/issues/13#issuecomment-748582119.

mt-caret avatar Sep 09 '23 11:09 mt-caret

@mt-caret +1 to a proc macro based approach. You can kind of consider the ocaml_export! macro to be deprecated, it is just that there is nothing else right now. Initially the idea was that from that macro one could also generate the OCaml code with the external declarations to call the Rust functions, but I don't think that is a good idea anymore (annotations like in your example + something similar to ocaml-gen which takes care of the OCaml code generation part would be better).

tizoc avatar Sep 09 '23 13:09 tizoc

I've been spending some time experimenting with various approaches in polars-ocaml (and another separate project). Hopefully I'll be able to come up with a concrete proposal in a few months (fingers crossed!).

One question is that ocaml_export! currently seems to boxroot every function argument and creates an OCamlRef out of it. I'm slightly confused by this, since there are situations where this is not required (Examples that come to mind are immediate OCaml values and the implementation of the recursive function described in the boxroot paper). Is it conceivable to instead directly create an OCamlRef (e.g. via the unexposed OCamlCell::create_ref function) without rooting and make it the responsibility of the implementor to root it if required?

mt-caret avatar Feb 04 '24 03:02 mt-caret