Implement new module type syntax#87
Conversation
Yes, I think it is possible. The problem here is that you want, in one case, to extract something of some type The idea is to use a sum type to merge the two cases. Let me give an example (where the complex types are replaced with type input = Case1 of int | Case2 of char
let extractor1 = Ast_pattern.(eint __ |> map1 ~f:(fun i -> Case1 i))
let extractor2 = Ast_pattern.(echar __ |> map1 ~f:(fun c -> Case2 c))
(* Ast_pattern.map1 maps the first argument of the continuation before applying it.
So while [eint __] has type [(expression, int -> _, _) Ast_pattern.t],
[extractor1] has type [(expression, input -> _, _) Ast_pattern.t] *)
let extractor = Ast_pattern.(extractor1 ||| extractor2)
let handle_case_1 (i:int) = ...
let handle_case_2 (c:char) = ...
let handle input =
match input with
| Case1 i -> handle_case_1 i
| Case2 c -> handle_case_2 c |
<!-- ps-id: 597fd8ce-d920-40ad-b1e3-2bad11222b23 -->
<!-- ps-id: d0989bfd-2d2a-4182-89bb-40edf8006617 -->
<!-- ps-id: c4f408bb-cab8-4ea2-8486-702917493cfd -->
<!-- ps-id: d73095c3-be81-4a9c-8ad0-fddf33272dd4 -->
<!-- ps-id: 144ef8fa-2d04-4b5a-9077-11afcc4283c7 -->
7b55928 to
bb907f0
Compare
|
@panglesd amazing, that's exactly what I was looking for. Thanks so much for you help! 🙏🤗 |
8f895e3 to
2b3175a
Compare
2b3175a to
ab733da
Compare
|
Okay, so the only "downside" is that the errors are less verbose. See for example vs But I think that's okay. A bit more annoying is that some locations in the errors are different for OCaml versions |
I totally agree, I think that is clearly something that we should improve! I'll open an issue on the ppxlib repo.
It's not only that: some errors are actually syntax errors in |
Note: This contains extra commits from #80, #81 and #82 that should be merged first
This PR implements the new module type syntax, so instead of
module type S_rec = [%import: (module Stuff.S_rec)]we now write:
module type%import S_rec = Stuff.S_recor[%%import: module type S_rec = Stuff.S_rec]I didn't keep the old syntax, but it should be possible to have both coexist if desired.
As for the implementation, I first tried to declare an extender applied to
structure_itemwith the following patternpsig (psig_modtype __ ^:: nil) ||| pstr (pstr_modtype __ ^:: nil) )Unfortunately, this results in the following build error:
This is a bit more annoying, because we have to manually pattern-match to extract the cases we want to support, and return an error in all other cases.
I tried to combine both but
psig (psig_modtype __ ^:: nil) ||| pstr (pstr_modtype __ ^:: nil) )andpsig (psig_type __ __ ^:: nil) ||| pstr (pstr_type __ __ ^:: nil) )don't extract the same value. The only solution I found is to relax the pattern and extract the wholestructure_itemThat's a bit more annoying because we manually have to pattern match to extract the cases we want to support, and return an error in all the other cases.
I wonder if we could build a more "refined" pattern here. I've tried a few combinators to build patterns, but I haven't managed to build anything that works. I'm not sure I understood all of them though, so it could be that I'm missing something.
Maybe @pitag-ha or @panglesd could help? Or confirm that there is no other way than using the whole
structure_itemlike I did.Fixes #74