You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
letrec fix~fx=T
(functx ->
let (T f') = f (fix ~f) x in
f' ctx)
Here's an example that doesn't just pass () to the recursive call, and searches for a let binding with the given name to a maximum depth:
(** search through nested [let .. in ..] bindings until [let name = .. in ..] is found *)letfind_depthnamed=letpurex= __ |> map1 ~f:(Fun.const x) inletfselfn=if n >0then
pexp_let drop
(value_binding ~pat:(ppat_var (string name) |> as__) ~expr:drop ^:: nil)
drop
|> map1 ~f:Option.some
||| pexp_let drop drop (self (n -1))
||| pure Noneelse pure Nonein
fix ~f d
With an implementation for bind : ('a, 'b -> 'c, 'd) t -> f:('b -> ('a, 'e, 'c) t) -> ('a, 'e, 'd) t, the recursive parser can depend on parsed values:
let( let* )pf= bind p ~f(** in a sequence of [let .. in ..] bindings, find a shadowed binding *)let find_shadow =letf (self: _ -> (_, pattern option -> _, _) t) trace=let let_var = value_binding ~pat:(ppat_var __ |> as__) ~expr:drop ^:: nil inlet ppat_let_var =let* pat, name = pexp_let drop let_var drop |> pack2 inmatchList.assoc_opt name trace with|Someshadow -> pure (Some shadow)
|None -> pexp_let drop drop (self ((name, pat) :: trace))
in
ppat_let_var ||| pexp_let drop drop (self trace) ||| pure Nonein
fix ~f[]
Here is such an implementation:
letbind (T f1) ~f=T
(functxlocxk ->
f1 ctx loc x (funx' ->
let (T f2) = f x' in
f2 ctx loc x k))
Finally, this combinator might be useful:
letrejectmsg=T (fun_ctxloc_x_k -> fail loc msg)
I think fix and bind would both be very useful for writing general patterns. The performance of fix should be acceptable, but with bind there comes the risk of an explosion of search paths if one is not careful, given the backtracking implementation of the parser.
Is there any desire to have these included in the library?
The text was updated successfully, but these errors were encountered:
Unfortunately, I have very few time to allocate to ppxlib, and most of it is already taken by the modifications to the parsetree.
At first sight, your proposition seems a good improvement, and I've seen other people facing the same problem; and having to come up with a similar solution (ping @EmileTrotignon).
So, we will try to review your proposition to include this in the library in a not too distant future, but don't expect too much reactivity, at least from me... Apologies in advance!
Lets say we wanted to implement a pattern that takes a module type of the form
and parses it to a list of the functor arguments, followed by the core module type, of the form:
Here's a simple implementation that's not quite right:
This would work, but the strict nature of OCaml means this does nothing but run in circles.
Instead, a
fix
combinator may be added toAst_pattern
:Then, the definition of
strip_functors
becomes:This terminates just fine!
Here's a possible implementation for
fix
:Here's an example that doesn't just pass
()
to the recursive call, and searches for alet
binding with the given name to a maximum depth:Inspired partly by QCheck.
With an implementation for
bind : ('a, 'b -> 'c, 'd) t -> f:('b -> ('a, 'e, 'c) t) -> ('a, 'e, 'd) t
, the recursive parser can depend on parsed values:Here is such an implementation:
Finally, this combinator might be useful:
I think
fix
andbind
would both be very useful for writing general patterns. The performance offix
should be acceptable, but withbind
there comes the risk of an explosion of search paths if one is not careful, given the backtracking implementation of the parser.Is there any desire to have these included in the library?
The text was updated successfully, but these errors were encountered: