fdopen / ppx_cstubs

preprocessor for easier stub generation with ocaml-ctypes
https://fdopen.github.io/ppx_cstubs/
Other
55 stars 5 forks source link

How to use ppx_cstubs.merlin? #3

Closed mnxn closed 4 years ago

mnxn commented 4 years ago

I set up my dune project similar to the example and got the stub generation working well. However, there is minimal editor support when editing the file.

It's not very clear to me how I should be using ppx_cstubs.merlin as neither the readme nor user guide provide an example.

It would be helpful to have some instructions on how to use ppx_cstubs.merlin

Thanks.

fdopen commented 4 years ago

I don't know a good solution. Dune autogenerated merlin files won't work, because they don't include dependencies, that are added in such a custom way. In emacs you can activate it manually later via M-x merlin-use ⏎ ppx_cstubs.merlin. But your editor might not provide such an option.

mnxn commented 4 years ago

Now I understand that PKG ppx_cstubs.merlin needs to be in the .merlin for it to work. I can add it manually, but the obvious problem is that it will be overwritten when dune regenerates the .merlin file.

I will ask around to see what can be done to generate the PKG directive.

rgrinberg commented 4 years ago

What does ppx_cstubs.merlin actually do? If there's a need for a library to provide some information to merlin perhaps we should try and think of a good way to do that. I don't mind adding support on the dune side.

mnxn commented 4 years ago

My understanding is that this library has two code generators with the following differences:

The dune example doesn't use the preprocess field for generation with ppx_cstubs: https://github.com/fdopen/ppx_cstubs/blob/master/examples/dune-project/src/lib/dune

I tried adding the ppx_cstubs.merlin ppx flags to the library with (flags -ppx "ppx_cstubs --as-ppx"), but then the problem is that the correct code from ppx_cstubs is overwritten by the incorrect code from ppx_cstubs.merlin and fails to build.

Dune somehow needs to make merlin aware of ppx_cstubs.merlin without using ppx_cstubs.merlin to actually generate code.

fdopen commented 4 years ago

ppx_cstubs is far slower than an ordinary ppx extension, it creates two output files, and you have to pass many differents flags to it (CFLAGS, dependencies,...). Therefore I've made it an executable that is used like cppo.

ppx_cstubs.merlin is never used for compiling, it's just there for merlin.

ppx_cstubs does among others:

1) extracts constants from a c files (constants, structs size and offsets, enums, etc.), that are used in 2) and 3). 2) creates a c file with stub code 3) creates an OCaml parse tree

ppx_cstubs.merlin only does step 3). 2) is skipped and constants from 1) are replaced by dummy values in order to create a syntax tree for merlin. Step 1) would often be too slow for realtime feedback within editors.

rgrinberg commented 4 years ago

If this step is required is for 3)

extracts constants from a c files (constants, structs size and offsets, enums, etc.), that are used in 2) and 3).

Then how can you omit it for 3) in ppx_cstubs.merlin?

ghost commented 4 years ago

Note that if you want your ppx rewriter to behave differently when called from merlin, you can match on the tool_name parameter. In ppxlib, it's exposed via Ppxlib.Expansion_context.XXX.omp_config (or simply Ppxlib.Expansion_context.XXX.tool_name` in the latest version of ppxlib).

fdopen commented 4 years ago

Then how can you omit it for 3) in ppx_cstubs.merlin?

Dummy values that are semantically wrong, but syntactically correct and produce a properly typed parse tree - enough for merlin.

Note that if you want your ppx rewriter to behave differently when called from merlin, you can match on the tool_name parameter.

Thanks for this hint, I didn't know that merlin sets this value. This way it seems feasible.

@mnxn You can try the next branch with an updated ppx_cstubs.merlin sub-package.

It can now be added as an additional preprocessing step. See: https://github.com/fdopen/ppx_cstubs/blob/92e66506c9e2222aa6dfa7a45d16124face6ff6f/examples/dune-project/src/lib/dune#L24 When it is called outside merlin, it will just check, if the real preprocessor has been called in an earlier step. When merlin calls it, it will do the dummy preprocessing.

I've tested it under Emacs and with VSCode (and https://marketplace.visualstudio.com/items?itemName=freebroccolo.reasonml ) It seems to work out of the box, once the '.merlin' file was generated by dune.

mnxn commented 4 years ago

Works wonderfully with https://github.com/ocamllabs/vscode-ocaml-platform, thank you.