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

generate better asts for function bindings #2651

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

v-gb
Copy link
Contributor

@v-gb v-gb commented Feb 11, 2025

Currently:

let foo1 : _ = function () -> ()
let foo2 x : _ = function () -> ()

are parsed into these value_bindings:

  (* foo1 *)
  { pvb_args = []
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }
  (* foo2 *)
  { pvb_args = ["x"]
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }

I expect instead:

  (* foo1 *)
  { pvb_args = []
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_body (Pexp_function ([], None, Pfunction_cases ...))
  }
  (* foo2 (no changes here) *)
  { pvb_args = ["x"]
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }

I think the ast for foo1:

  • is confusing
  • creates a needless distinction between let f : _ = function () -> () vs let f : _ = (function () -> ()), unlike, say, 1 + function () -> () vs 1 + (function () -> ()).
  • is essentially an invariant violation. The type of value_bindings in ocamlformat should be understood to be the union of a non-function let-binding + an inline pexp_function node. But the node for foo1 corresponds to the syntax of neither a non-function let-binding (because of body = Pfunction_cases _), nor an inline pexp_function (because pexp_function can't have a type_constraint with an empty list of params).

Currently:

```ocaml
let foo1 : _ = function () -> ()
let foo2 x : _ = function () -> ()
```

are parsed into these value_bindings:

```ocaml
  (* foo1 *)
  { pvb_args = []
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }
  (* foo2 *)
  { pvb_args = ["x"]
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }
```

I expect instead:

```ocaml
  (* foo1 *)
  { pvb_args = []
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_body (Pexp_function ([], None, Pfunction_cases ...))
  }
  (* foo2 (no changes here) *)
  { pvb_args = ["x"]
  ; pvb_constraint = Some "_"
  ; pvb_body = Pfunction_cases ...
  }
```

I think the ast for foo1:

- is confusing
- creates a needless distinction between
  `let f : _ = function () -> ()` vs `let f : _ = (function () -> ())`,
  unlike, say, `1 + function () -> ()` vs `1 + (function () -> ())`.
- is essentially an invariant violation. The type of value_bindings
  in ocamlformat should be understood to be the union of a non-function
  let-binding + an inline pexp_function node.
  But the node for foo1 corresponds to the syntax of neither a non-function
  let-binding (because of body = Pfunction_cases _), nor an inline
  pexp_function (because pexp_function can't have a type_constraint with
  an empty list of params).
@v-gb v-gb force-pushed the push-uullkpsupwvx branch from f1c296f to 75ff311 Compare February 11, 2025 13:37
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

Successfully merging this pull request may close these issues.

1 participant