From f29438e004361b4a2ab61cbc854b1bf6f05aea0d Mon Sep 17 00:00:00 2001 From: Aaron Dufour Date: Fri, 7 Aug 2020 14:57:08 +0800 Subject: [PATCH 1/7] add both native and ppx let-syntax support, and corresponding tests --- angstrom.opam | 3 ++- dune-project | 2 +- lib/angstrom.ml | 27 ++++++++++++++++++++++ lib/angstrom.mli | 36 ++++++++++++++++++++++++++++++ lib/dune | 3 ++- lib_test/dune | 14 ++++++++++-- lib_test/test_let_syntax_native.ml | 11 +++++++++ lib_test/test_let_syntax_ppx.ml | 18 +++++++++++++++ 8 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 lib_test/test_let_syntax_native.ml create mode 100644 lib_test/test_let_syntax_ppx.ml diff --git a/angstrom.opam b/angstrom.opam index 2537e7e..94a1f67 100644 --- a/angstrom.opam +++ b/angstrom.opam @@ -12,10 +12,11 @@ build: [ ] depends: [ "ocaml" {>= "4.04.0"} - "dune" {>= "1.0"} + "dune" {>= "1.8"} "alcotest" {with-test & >= "0.8.1"} "bigstringaf" "result" + "ppx_let" {with-test & >= "0.14.0"} ] synopsis: "Parser combinators built for speed and memory-efficiency" description: """ diff --git a/dune-project b/dune-project index b28bf05..5bfddd0 100644 --- a/dune-project +++ b/dune-project @@ -1,2 +1,2 @@ -(lang dune 1.0) +(lang dune 1.8) (name angstrom) diff --git a/lib/angstrom.ml b/lib/angstrom.ml index 6d9d851..b025121 100644 --- a/lib/angstrom.ml +++ b/lib/angstrom.ml @@ -571,6 +571,33 @@ let consume_with p f = let consumed p = consume_with p Bigstringaf.substring let consumed_bigstring p = consume_with p Bigstringaf.copy +let both a b = lift2 (fun a b -> a, b) a b +let map t ~f = t >>| f +let bind t ~f = t >>= f +let map2 a b ~f = lift2 f a b +let map3 a b c ~f = lift3 f a b c +let map4 a b c d ~f = lift4 f a b c d + +module Let_syntax = struct + let return = return + let ( >>| ) = ( >>| ) + let ( >>= ) = ( >>= ) + + module Let_syntax = struct + let return = return + let map = map + let bind = bind + let both = both + let map2 = map2 + let map3 = map3 + let map4 = map4 + end +end + +let ( let+ ) = ( >>| ) +let ( let* ) = ( >>= ) +let ( and+ ) = both + module BE = struct (* XXX(seliopou): The pattern in both this module and [LE] are a compromise * between efficiency and code reuse. By inlining [ensure] you can recover diff --git a/lib/angstrom.mli b/lib/angstrom.mli index e947699..19bda5b 100644 --- a/lib/angstrom.mli +++ b/lib/angstrom.mli @@ -426,6 +426,42 @@ val lift4 : ('a -> 'b -> 'c -> 'd -> 'e) -> 'a t -> 'b t -> 'c t -> 'd t -> 'e t Even with the partial application, it will be more efficient than the applicative implementation. *) +val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t +val map3 : 'a t -> 'b t -> 'c t -> f:('a -> 'b -> 'c -> 'd) -> 'd t +val map4 : 'a t -> 'b t -> 'c t -> 'd t -> f:('a -> 'b -> 'c -> 'd -> 'e) -> 'e t +(** The [mapn] family of functions are just like [liftn], with a slightly + different interface. *) + +val bind : 'a t -> f:('a -> 'b t) -> 'b t +(** [bind] is a prefix version of [>>=] *) + +val map : 'a t -> f:('a -> 'b) -> 'b t +(** [map] is a prefix version of [>>|] *) + +val both : 'a t -> 'b t -> ('a * 'b) t +(** [both p q] runs [p] followed by [q] and returns both results in a tuple *) + +(** The [Let_syntax] module is intended to be used with the [ppx_let] + pre-processor, and just contains copies of functions described elsewhere. *) +module Let_syntax : sig + val return : 'a -> 'a t + val ( >>| ) : 'a t -> ('a -> 'b) -> 'b t + val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t + + module Let_syntax : sig + val return : 'a -> 'a t + val map : 'a t -> f:('a -> 'b) -> 'b t + val bind : 'a t -> f:('a -> 'b t) -> 'b t + val both : 'a t -> 'b t -> ('a * 'b) t + val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t + val map3 : 'a t -> 'b t -> 'c t -> f:('a -> 'b -> 'c -> 'd) -> 'd t + val map4 : 'a t -> 'b t -> 'c t -> 'd t -> f:('a -> 'b -> 'c -> 'd -> 'e) -> 'e t + end +end + +val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t +val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t +val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t (** Unsafe Operations on Angstrom's Internal Buffer diff --git a/lib/dune b/lib/dune index 0e6cc37..65b87bc 100644 --- a/lib/dune +++ b/lib/dune @@ -2,4 +2,5 @@ (name angstrom) (public_name angstrom) (libraries bigstringaf) - (flags :standard -safe-string)) + (flags :standard -safe-string) + (preprocess future_syntax)) diff --git a/lib_test/dune b/lib_test/dune index 2e30ab3..6e00fe3 100644 --- a/lib_test/dune +++ b/lib_test/dune @@ -1,5 +1,15 @@ +(library + (name angstrom_test) + (libraries angstrom) + (flags :standard -safe-string) + (modules test_let_syntax_native test_let_syntax_ppx) + (preprocess + (per_module + (future_syntax test_let_syntax_native) + ((pps ppx_let) test_let_syntax_ppx)))) + (executables - (libraries alcotest angstrom) + (libraries alcotest angstrom angstrom_test) (modules test_angstrom) (names test_angstrom)) @@ -14,4 +24,4 @@ (deps (:< test_angstrom.exe)) (action - (run %{<}))) + (run %{<}))) \ No newline at end of file diff --git a/lib_test/test_let_syntax_native.ml b/lib_test/test_let_syntax_native.ml new file mode 100644 index 0000000..46db480 --- /dev/null +++ b/lib_test/test_let_syntax_native.ml @@ -0,0 +1,11 @@ +open Angstrom + +let (_ : int t) = + let* () = end_of_input in + return 1 + +let (_ : int t) = + let+ (_ : char) = any_char + and+ (_ : string) = string "foo" + in + 2 diff --git a/lib_test/test_let_syntax_ppx.ml b/lib_test/test_let_syntax_ppx.ml new file mode 100644 index 0000000..a21173c --- /dev/null +++ b/lib_test/test_let_syntax_ppx.ml @@ -0,0 +1,18 @@ +open Angstrom +open Let_syntax + +let (_ : int t) = + let%bind () = end_of_input in + return 1 + +let (_ : int t) = + let%map (_ : char) = any_char + and (_ : string) = string "foo" + in + 2 + +let (_ : int t) = + let%mapn (_ : char) = any_char + and (_ : string) = string "foo" + in + 2 From 88c0e92cff36bb0b87af98bba7969c8a5960ba30 Mon Sep 17 00:00:00 2001 From: Aaron Dufour Date: Fri, 7 Aug 2020 18:46:42 +0800 Subject: [PATCH 2/7] fixup! add both native and ppx let-syntax support, and corresponding tests --- angstrom.opam | 1 + 1 file changed, 1 insertion(+) diff --git a/angstrom.opam b/angstrom.opam index 94a1f67..104c581 100644 --- a/angstrom.opam +++ b/angstrom.opam @@ -17,6 +17,7 @@ depends: [ "bigstringaf" "result" "ppx_let" {with-test & >= "0.14.0"} + "ocaml-syntax-shims" {with-test} ] synopsis: "Parser combinators built for speed and memory-efficiency" description: """ From 9bf4a8b4b2f7bb53f0f98168d23c1b0cb121382d Mon Sep 17 00:00:00 2001 From: Aaron Dufour Date: Fri, 7 Aug 2020 19:09:20 +0800 Subject: [PATCH 3/7] fixup! add both native and ppx let-syntax support, and corresponding tests --- angstrom.opam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angstrom.opam b/angstrom.opam index 104c581..98c1b4e 100644 --- a/angstrom.opam +++ b/angstrom.opam @@ -17,7 +17,7 @@ depends: [ "bigstringaf" "result" "ppx_let" {with-test & >= "0.14.0"} - "ocaml-syntax-shims" {with-test} + "ocaml-syntax-shims" ] synopsis: "Parser combinators built for speed and memory-efficiency" description: """ From 93f29c2343491ef773efc89d2fa4e695a5bd1202 Mon Sep 17 00:00:00 2001 From: Spiros Eliopoulos Date: Wed, 16 Sep 2020 18:04:45 -0400 Subject: [PATCH 4/7] pr204: reorg new functions in interface --- lib/angstrom.mli | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/angstrom.mli b/lib/angstrom.mli index 19bda5b..b9fd964 100644 --- a/lib/angstrom.mli +++ b/lib/angstrom.mli @@ -271,6 +271,10 @@ val option : 'a -> 'a t -> 'a t (** [option v p] runs [p], returning the result of [p] if it succeeds and [v] if it fails. *) + +val both : 'a t -> 'b t -> ('a * 'b) t +(** [both p q] runs [p] followed by [q] and returns both results in a tuple *) + val list : 'a t list -> 'a list t (** [list ps] runs each [p] in [ps] in sequence, returning a list of results of each [p]. *) @@ -387,6 +391,9 @@ val (>>=) : 'a t -> ('a -> 'b t) -> 'b t (** [p >>= f] creates a parser that will run [p], pass its result to [f], run the parser that [f] produces, and return its result. *) +val bind : 'a t -> f:('a -> 'b t) -> 'b t +(** [bind] is a prefix version of [>>=] *) + val (>>|) : 'a t -> ('a -> 'b) -> 'b t (** [p >>| f] creates a parser that will run [p], and if it succeeds with result [v], will return [f v] *) @@ -426,21 +433,13 @@ val lift4 : ('a -> 'b -> 'c -> 'd -> 'e) -> 'a t -> 'b t -> 'c t -> 'd t -> 'e t Even with the partial application, it will be more efficient than the applicative implementation. *) +val map : 'a t -> f:('a -> 'b) -> 'b t val map2 : 'a t -> 'b t -> f:('a -> 'b -> 'c) -> 'c t val map3 : 'a t -> 'b t -> 'c t -> f:('a -> 'b -> 'c -> 'd) -> 'd t val map4 : 'a t -> 'b t -> 'c t -> 'd t -> f:('a -> 'b -> 'c -> 'd -> 'e) -> 'e t (** The [mapn] family of functions are just like [liftn], with a slightly different interface. *) -val bind : 'a t -> f:('a -> 'b t) -> 'b t -(** [bind] is a prefix version of [>>=] *) - -val map : 'a t -> f:('a -> 'b) -> 'b t -(** [map] is a prefix version of [>>|] *) - -val both : 'a t -> 'b t -> ('a * 'b) t -(** [both p q] runs [p] followed by [q] and returns both results in a tuple *) - (** The [Let_syntax] module is intended to be used with the [ppx_let] pre-processor, and just contains copies of functions described elsewhere. *) module Let_syntax : sig From 6a3a18dfd10b4ebc9a79a91fce087b51ae4e075e Mon Sep 17 00:00:00 2001 From: Aaron Dufour Date: Thu, 17 Sep 2020 20:30:22 +0800 Subject: [PATCH 5/7] dont link against ocaml-syntax-shims --- angstrom.opam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/angstrom.opam b/angstrom.opam index 98c1b4e..721a437 100644 --- a/angstrom.opam +++ b/angstrom.opam @@ -17,7 +17,7 @@ depends: [ "bigstringaf" "result" "ppx_let" {with-test & >= "0.14.0"} - "ocaml-syntax-shims" + "ocaml-syntax-shims" {build} ] synopsis: "Parser combinators built for speed and memory-efficiency" description: """ From 3e9a4cc3aa11043f3db256ca35421e6e9a236c00 Mon Sep 17 00:00:00 2001 From: Spiros Eliopoulos Date: Tue, 29 Sep 2020 06:54:25 -0400 Subject: [PATCH 6/7] pr204: add ppx_let as an extra dependency --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cfb702e..359fa6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: - PINS="angstrom-async:. angstrom-lwt-unix:. angstrom:." - PACKAGE="angstrom" - TESTS=true + - EXTRA_DEPS="ppx_let" - POST_INSTALL_HOOK="opam install --with-test angstrom-async angstrom-lwt-unix && opam exec -- make examples" matrix: - OCAML_VERSION="4.08" From 81a21a1626d0c06b9ebd08db2847b306401fcc97 Mon Sep 17 00:00:00 2001 From: Spiros Eliopoulos Date: Tue, 29 Sep 2020 08:00:52 -0400 Subject: [PATCH 7/7] pr204: disable mapn test for ppx_let --- lib_test/test_let_syntax_ppx.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib_test/test_let_syntax_ppx.ml b/lib_test/test_let_syntax_ppx.ml index a21173c..8640452 100644 --- a/lib_test/test_let_syntax_ppx.ml +++ b/lib_test/test_let_syntax_ppx.ml @@ -11,8 +11,12 @@ let (_ : int t) = in 2 +(* [mapn] support was introduced in ppx_let.v0.14.0, which CI does not reliably + install. *) +(* let (_ : int t) = let%mapn (_ : char) = any_char and (_ : string) = string "foo" in 2 +*)