Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ast_patter.map0 actually call the continuation when it has only one argument #400

Open
panglesd opened this issue Mar 21, 2023 · 0 comments

Comments

@panglesd
Copy link
Collaborator

For instance,

open Ppxlib

let ext =
  Extension.declare "example" Extension.Context.module_expr
    Ast_pattern.(
      ptyp
        (map0 ~f:"foo" @@ ptyp_constr (lident (string "foo")) nil
        ||| map0 ~f:"bar" @@ ptyp_constr (lident (string "bar")) nil))
    (fun ~loc ~path:_ arg ->
      Stdlib.Printf.eprintf "expand: %s\n" arg;
      Ast_builder.Default.pmod_structure ~loc [])

let () = Ppxlib.Driver.register_transformation "example" ~extensions:[ ext ]

applied on

module _ = [%example: bar]

will write

expand: foo
expand: bar

instead of only

expand: bar

The reason is that map0 will actually call the continuation when this one has one argument, even though the "matching" is not finished:

let map0 (T func) ~f = T (fun ctx loc x k -> func ctx loc x (k f))

I think (but I'm not confident) that one way to fix this would be to abstract the continuation to make sure it is never executed too early:

type ('matched_value, 'k, 'k_result) t =
  | T of (context -> Location.t -> 'matched_value -> (unit -> 'k) -> 'k_result)

As a workaround before this is fixed, map_result can be used to protect the continuation to be executed:

open Ppxlib

let ext =
  Extension.declare "example" Extension.Context.module_expr
    Ast_pattern.(
      ptyp
        (map0 ~f:"foo"
         @@ map_result ~f:(fun k -> k ())
         @@ ptyp_constr (lident (string "foo")) nil
        ||| map0 ~f:"bar"
            @@ map_result ~f:(fun k -> k ())
            @@ ptyp_constr (lident (string "bar")) nil))
    (fun ~loc ~path:_ arg () ->
      Stdlib.Printf.eprintf "expand: %s\n" arg;
      Ast_builder.Default.pmod_structure ~loc [])

let () = Ppxlib.Driver.register_transformation "example" ~extensions:[ ext ]

Thanks @ceastlund for finding the bug and the minimal example!

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

No branches or pull requests

1 participant