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

OcamlP4 is unsupported on newer versions of ocaml #224

Open
jpdoyle opened this issue Jan 1, 2021 · 6 comments
Open

OcamlP4 is unsupported on newer versions of ocaml #224

jpdoyle opened this issue Jan 1, 2021 · 6 comments

Comments

@jpdoyle
Copy link
Contributor

jpdoyle commented Jan 1, 2021

I updated my system, which installed ocaml v4.10.0, which no longer supports ocamlp4. It looks like the alternative recommendation is PPX, but automatic translation with https://github.com/janestreet/camlp4-to-ppx throws up some parsing errors. I'm not familiar enough with camp4 or ppx to confidently do the translation by hand.

@jpdoyle
Copy link
Contributor Author

jpdoyle commented Jan 1, 2021

I think the actual issue is an ocaml packaging problem on my OS, but leaving this issue open since camlp4 may fully lose support at any moment

@btj
Copy link
Member

btj commented Jan 1, 2021

VeriFast currently uses Camlp4 to translate the streams notation used in parser.ml.

Note that ppx is a very different approach to "preprocessing". In particular, ppx plugins transform the OCaml AST, so the input is first parsed by the regular OCaml parser. Therefore, ppx cannot be used to support the streams notation.

My understanding is that we will get in trouble only if we ever want to use post-OCaml 4.08 syntax. At that point, the obvious next thing to try would be to switch to Camlp5.

If we ever want to stop depending on OCaml's -pp support, I guess we'll have to update parser.ml to use a different notation. It's not immediately clear to me that there is a straightforward ppx-based alternative.

@btj
Copy link
Member

btj commented Jan 1, 2021

@btj
Copy link
Member

btj commented Jan 4, 2021

Consider the following code using stream parser syntax:

type tok = If | Then | Else | Let | In | Equal | Ident of int
let rec expr =
  parser
    [< 'If; x = expr; 'Then; y = expr; 'Else; z = expr >] -> "if"
  | [< 'Let; 'Ident x; 'Equal; x = expr; 'In; y = expr >] -> "let"

Camlp4 translates it into something like

let expect s f = try let x = f (Stream.peek s) in Stream.junk s; x with Match_failure _ -> raise (Stream.Error "Parse error")
type tok = If | Then | Else | Let | In | Equal | Ident of int
let rec expr =
  fun s ->
  match Stream.peek s with
    If -> Stream.junk s;
    let x = expr s in
    let () = expect s (fun Then -> ()) in
    let y = expr s in
    let () = expect s (fun Else -> ()) in
    let z = expr s in
    "if"
  | Let -> Stream.junk s;
    let x = expect (fun (Ident x) -> x) in
    let () = expect (fun Equal -> ()) in
    let x = expr s in
    let () = expect (fun In -> ()) in
    let y = expr s in
    "let"
  | _ -> raise Stream.Failure

The stream parser syntax can be approximated using OCaml's extension nodes syntax as follows:

let rec expr =
  function%parser
    [ If; [%let x = expr]; Then; [%let y = expr]; Else; [%let z = expr] ] -> "if"
  | [ Let; Ident x; Equal; [%let x = expr]; In; [%let y = expr] ] -> "let"

@btj
Copy link
Member

btj commented Jan 11, 2021

@jeremiedimino pointed out to me that the following also works:

let rec expr =
  function%parser
    [ If; expr as x; Then; expr as y; Else; expr as z ] -> "if"
  | [ Let; Ident x; Equal; expr as x; In; expr as y ] -> "let"

Very tolerable indeed!

Note: the E as x syntax does not work if E is not just a simple function name. In those cases, we still need to use the clunkier [%let x = E] syntax.

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

2 participants