A .fln let takes more bindings on the lines indented under it, a top-level one more globals, and flan convert writes runs of short bindings that way

This commit is contained in:
Joseph Ferano 2026-09-26 06:26:36 +07:00
parent 04b29f283d
commit 12cd4feff0
8 changed files with 288 additions and 89 deletions

View File

@ -1362,8 +1362,53 @@ and let_lines n prs body =
| first :: more -> Source_text.tag t.loc.Loc.line first :: more
| [] -> []
in
(* A let whose body starts with another is one run of bindings: the reader
merges the two back whichever way they are written. *)
let rec absorb prs body =
match body with
| x :: rest when let_sugar x && !quasi = 0 ->
(match if rest = [] then Some x else flatten x rest with
| Some { v = Form.List (_ :: { v = Form.Vec bs; _ } :: inner); _ } ->
(match pairs bs with
| Some ps -> absorb (prs @ ps) inner
| None -> (prs, body))
| _ -> (prs, body))
| _ -> (prs, body)
in
let prs, body = absorb prs body in
let lines n b = let p, v = bind b in tagged b (value_lines n p v) in
List.concat_map (lines n) prs @ block n body
(* A binding that fits a line with a short value joins a group: the ones
after the first go on the lines under it, lined up with its name. *)
let short n b =
let p, v = bind b in
match value_lines n p v with
| [ l ] when String.length (at 0 v) <= 40 && not (!inside v) -> Some (tagged b [ l ])
| _ -> None
in
let under b =
let p, v = bind b in
let p = String.sub p 4 (String.length p - 4) in
match value_lines (n + 4) p v with
| [ l ] when String.length (at 0 v) <= 40 && not (!inside v) -> Some (tagged b [ l ])
| _ -> None
in
let rec emit = function
| [] -> []
| b :: rest ->
(match short n b with
| None -> lines n b @ emit rest
| Some first ->
let rec group acc = function
| b' :: rest' as all ->
(match under b' with
| Some l -> group (acc @ l) rest'
| None -> (acc, all))
| [] -> (acc, [])
in
let more, rest = group [] rest in
first @ more @ emit rest)
in
emit prs @ block n body
(** A whole file: top-level forms with a blank line between them. [macros]
is [Body_macros.table] of the file; without it, the prelude's and the

View File

@ -1474,10 +1474,27 @@ and value_line ?(block_ok = false) (s : st) ~after : Form.t =
| Form.List items -> mk p e.loc (Form.List (items @ body))
| _ -> mk p e.loc (Form.List (e :: body)))
| COMMA ->
failk "one-binding" (peek p).loc
let c = (peek p).loc in
(* On a let's line, the fix is the let's group: the rest of the line
under the first name. *)
let group =
let file, lines = !source in
if c.Loc.file <> file || c.Loc.line > Array.length lines then None
else
let line = lines.(c.Loc.line - 1) in
let head = String.trim (String.sub line 0 (c.Loc.col - 1)) in
let rest = String.trim (String.sub line c.Loc.col (String.length line - c.Loc.col)) in
if String.length head > 4 && String.sub head 0 4 = "let " && rest <> "" then
Some (Printf.sprintf ":\n\n %s\n %s" head rest)
else None
in
failk "one-binding" c
"%s is followed by a comma, and one line binds one name. Put each \
binding on its own line, one after the other"
binding on its own line%s"
(text_of e)
(match group with
| Some g -> ", the ones after the first under its name" ^ g
| None -> ", one after the other")
| _ -> lambda_block ~block_ok s e ~after:(text_of e)
(* Whether this line has a [then] at depth zero: a one-line if. *)
@ -1501,9 +1518,10 @@ and lambda_block ?(block_ok = false) (s : st) (e : Form.t) ~after =
else expect_eol p ~after;
e
and let_stmt (s : st) : Form.t list =
(* One binding of a let, [x = v], [x: T = v] or [{a .x} = p], through the
end of its line (and the block its value takes). *)
and binding (s : st) : Form.t * Form.t =
let p = s.p in
let t = advance p in
let target, _ = unary p in
(* [let x: T = v] is [(let [x (the T v)])]: a let binding has no type slot
of its own, and [the] is the form that says what a value is. *)
@ -1524,6 +1542,72 @@ and let_stmt (s : st) : Form.t list =
Form.make (Form.List [ sym tyf.loc "the"; tyf; v ]) (span p tyf.loc)
| None -> v
in
(target, v)
(* The lines indented under a let, each one more binding of it: [let a = 1]
and under it [b = a + 1], lined up with [a]. Anything else there is
refused; [first] is the let's first target, for the message. *)
and binding_lines : 'a. st -> first:Form.t -> one:(unit -> 'a) -> 'a list =
fun s ~first ~one ->
let p = s.p in
if (peek p).tok <> INDENT then []
else begin
ignore (advance p);
let rec go acc =
match (peek p).tok with
| DEDENT -> ignore (advance p); List.rev acc
| EOF -> List.rev acc
| _ when binding_line p -> go (one () :: acc)
| _ ->
failk "let-block" (where_ p)
"this line is indented under let %s, and the only lines that go \
there are more bindings of the let, lined up with its first name:\n\n\
\ let a = 1\n b = a + 1\n\n\
A let's names last to the end of the block the let is in, so any \
other line after it goes at the let's column"
(text_of first)
in
go []
end
(* Whether the line at point is a binding: a name, or a [[...]] or [{...}]
pattern, then [=] or [: T =]. [x += 1] and [f(x)] are not. *)
and binding_line p =
(* An [=] at the line's own depth, from token [k] on. *)
let rec eq k depth =
match (peek_at p k).tok with
| EOF | NEWLINE | INDENT | DEDENT -> false
| NAME "=" when depth = 0 -> true
| LP | LB | LC -> eq (k + 1) (depth + 1)
| RP | RB | RC -> eq (k + 1) (depth - 1)
| _ -> eq (k + 1) depth
in
match (peek p).tok with
| NAME s when s <> "" && s.[0] <> '.' && not (is_op_word s) ->
(match (peek_at p 1).tok with
| NAME "=" -> (peek_at p 1).sp
| COLON -> eq 2 0
| _ -> false)
(* [~g = a] in a template. *)
| UNQ -> eq 1 0
| LB | LC ->
let rec close k depth =
match (peek_at p k).tok with
| EOF | NEWLINE -> false
| LP | LB | LC -> close (k + 1) (depth + 1)
| RP | RB | RC when depth = 1 -> (peek_at p (k + 1)).tok = NAME "="
| RP | RB | RC -> close (k + 1) (depth - 1)
| _ -> close (k + 1) depth
in
close 0 0
| _ -> false
and let_stmt (s : st) : Form.t list =
let p = s.p in
let t = advance p in
let (target, v) = binding s in
let more = binding_lines s ~first:target ~one:(fun () -> binding s) in
let own = List.concat_map (fun (a, b) -> [ a; b ]) ((target, v) :: more) in
let make bindings body =
let f =
mk p t.loc
@ -1538,17 +1622,10 @@ and let_stmt (s : st) : Form.t list =
match body with
| [ ({ Form.v = Form.List (_ :: { v = Form.Vec bs; _ } :: body); _ } as inner) ]
when List.memq inner s.lets ->
make (target :: v :: bs) body
| _ -> make [ target; v ] body
make (own @ bs) body
| _ -> make own body
in
(* A let has no block: its name lasts to the end of the block it is in. *)
if (peek p).tok = INDENT then
failk "let-block" (peek_at p 1).loc
"this line is indented under let %s, which takes no block. A let's \
name lasts to the end of the block the let is in, so the lines after \
it go at the let's column"
(text_of target)
else [ merged (stmts s) ]
[ merged (stmts s) ]
and stmt (s : st) : Form.t =
let p = s.p in
@ -1697,57 +1774,7 @@ and header (s : st) w : Form.t =
in
named (if w = "fn" then "defn" else "defn-")
(name :: Form.make (Form.Vec ps) lp.loc :: ret :: (where_clause @ body))
| "def" | "once" | "const" ->
(* A top-level [let] is read here too, as [def]: [w] is then "def" and
[t] the let. *)
let shown = match t.tok with NAME "let" -> "let" | _ -> w in
let name = name_tok p ~what:"the name being defined" in
let tyf =
match (peek p).tok with
| COLON -> ignore (advance p); Some (ty p)
| _ -> None
in
let v =
match (peek p).tok with
| NAME "=" ->
ignore (advance p);
Some (value_line s ~after:(shown ^ " " ^ text_of name ^ " ="))
| _ ->
expect_eol p ~after:(match tyf with Some f -> text_of f | None -> text_of name);
None
in
let head =
match w with "def" -> "def" | "once" -> "defonce" | _ -> "defconst"
in
if shown = "def" then
failk "def-is-let" l0
"a global is written with let, at the file's top level:\n\n let %s%s%s"
(text_of name)
(match tyf, v with
| Some t, _ -> ": " ^ text_of t
| None, None -> ": i32"
| None, Some _ -> "")
(match v, tyf with
| Some v, _ -> " = " ^ text_of v
| None, None -> " = 0"
| None, Some _ -> "");
let items =
match w, tyf, v with
| "const", None, Some v -> [ name; v ]
| "const", Some t, Some v -> [ name; t; v ]
| "const", _, None ->
failk "const-value" l0
"a const needs its value: const %s = 3" (text_of name)
| _, None, Some v -> [ name; sym name.loc "dyn"; v ]
| _, Some t, None -> [ name; t ]
| _, Some t, Some v -> [ name; t; v ]
| _, None, None ->
failk "def-empty" l0
"%s %s names neither a type nor a value. Give it one or both: %s %s: \
i32 = 0"
shown (text_of name) shown (text_of name)
in
named head items
| "def" | "once" | "const" -> def_form s w t l0
| "struct" | "union" ->
let name = name_tok p ~what:"the type's name" in
(* [struct Pt(x: i32, y: i32)]: the fields on the header's line, as a
@ -2268,6 +2295,65 @@ and header (s : st) w : Form.t =
named "quasiquote" [ e ])
| _ -> assert false
(* [let x = v] at the top level, [once x = v] or [const x = v], from the
name on: [t] is the word, and [l0] where the form starts. A top-level let
leaves the lines indented under it to [read_all], which reads each as one
more global. *)
and def_form (s : st) w (t : token) l0 : Form.t =
let p = s.p in
let named head items = mk p l0 (Form.List (sym l0 head :: items)) in
(* A top-level [let] is read here too, as [def]: [w] is then "def" and
[t] the let. *)
let shown = match t.tok with NAME "let" -> "let" | _ -> w in
let name = name_tok p ~what:"the name being defined" in
let tyf =
match (peek p).tok with
| COLON -> ignore (advance p); Some (ty p)
| _ -> None
in
let v =
match (peek p).tok with
| NAME "=" ->
ignore (advance p);
Some (value_line ~block_ok:(shown = "let") s
~after:(shown ^ " " ^ text_of name ^ " ="))
| _ ->
expect_eol p ~after:(match tyf with Some f -> text_of f | None -> text_of name);
None
in
let head =
match w with "def" -> "def" | "once" -> "defonce" | _ -> "defconst"
in
if shown = "def" then
failk "def-is-let" l0
"a global is written with let, at the file's top level:\n\n let %s%s%s"
(text_of name)
(match tyf, v with
| Some t, _ -> ": " ^ text_of t
| None, None -> ": i32"
| None, Some _ -> "")
(match v, tyf with
| Some v, _ -> " = " ^ text_of v
| None, None -> " = 0"
| None, Some _ -> "");
let items =
match w, tyf, v with
| "const", None, Some v -> [ name; v ]
| "const", Some t, Some v -> [ name; t; v ]
| "const", _, None ->
failk "const-value" l0
"a const needs its value: const %s = 3" (text_of name)
| _, None, Some v -> [ name; sym name.loc "dyn"; v ]
| _, Some t, None -> [ name; t ]
| _, Some t, Some v -> [ name; t; v ]
| _, None, None ->
failk "def-empty" l0
"%s %s names neither a type nor a value. Give it one or both: %s %s: \
i32 = 0"
shown (text_of name) shown (text_of name)
in
named head items
(* handler-case, handler-bind and restart-case take nothing on their own line. *)
and clause_header_end p w =
match (peek p).tok with
@ -2340,8 +2426,25 @@ let read_all ?(line = 1) ?col ?indent ?(global_let = true) ~file src =
| EOF -> []
| DEDENT -> ignore (advance s.p); []
| NAME "let" when header_follow s.p "let" ->
let t = peek s.p in
let f = header s "def" in
f :: top ()
(* The lines indented under it are more globals, one each: a global
is one name, so a pattern there is refused. *)
let first = match f.v with Form.List (_ :: n :: _) -> n | _ -> f in
let more =
binding_lines s ~first ~one:(fun () ->
let l = peek s.p in
(match l.tok with
| LB | LC ->
failk "global-pattern" l.loc
"a global binds one name, and this line under let %s is a \
pattern. Bind the value to a name, and take it apart inside \
the function that uses it"
(text_of first)
| _ -> ());
def_form s "def" t l.loc)
in
f :: more @ top ()
| _ -> let f = stmt s in f :: top ()
in
let fs = if global_let then top () else stmts s in

View File

@ -187,9 +187,23 @@ Each item: the proposal, then the reason in one line.
- **`let x = v`** scopes to the end of its block and reads as
`(let [x v] rest…)`. Consecutive `let`s merge into one binding vector.
A `let` is always flat: a line indented deeper under `let x = v` is
refused. To end a `let`'s scope early, put it in a `do:` block.
The printer writes every `let` flat. A `let` with statements after it
A `let` takes more bindings on the lines indented under it, lined up with
its first name, each seeing the ones above:
```
let row = r + 1
col: i32 = c - 1
{x .x} = p
```
is `(let [row (+ r 1) col (the i32 (- c 1)) {x .x} p] rest…)`. Any other
line indented there is refused. At the top level each such line is one
more global, `(def col i32 …)`; a pattern there is refused, since a global
binds one name. A `let` is otherwise flat: its scope is the rest of its
block. To end it early, put it in a `do:` block.
The printer writes every `let` flat, and a run of bindings whose values
are short (one line, 40 characters or fewer) as one `let` with the rest
under the first name; top-level globals stay one `let` each. A `let` with statements after it
takes them into its body; when one of them means an outer name the `let`
rebinds, the `let`'s is renamed (`x` to `x-2`, a name the top-level form
does not use; a struct pattern is written as `{x-2 .x}` pairs). A macro's

View File

@ -25,8 +25,8 @@ fn flush(field: Ptr(Vec(u8)), row: Ptr(Vec(str))) -> ()
fn parse-line(line: [const u8]) -> Vec(str)
let row = vec-new(str)
let field = vec-new(u8)
let state = State.start
field = vec-new(u8)
state = State.start
for i in range(length(line))
let c = line[i]
match state

View File

@ -61,7 +61,7 @@ fn eval-form(e, env) -> dyn
last
_ ->
let f = eval(op, env)
let arg = eval(e[1], env)
arg = eval(e[1], env)
eval(get(f, :body), extend(get(f, :env), get(f, :param), arg))
fn run(program) -> ()

View File

@ -40,8 +40,8 @@ fn show(l: Light) -> str
; whoever handles it may reset the light to red.
fn run(ticks: i32, presses: [const i32], fault-at: i32) -> ()
let l = Light.Red{.left 1, .walk false}
let p = 0
let t = 0
p = 0
t = 0
until :clock t >= ticks
let pressed = p < length(presses)
and presses[p] == t

View File

@ -18,9 +18,9 @@ fn letter?(c: u8) -> bool
; The words of text, lowercased, in order.
fn words(text: [const u8]) -> Vec([const u8])
let out = vec-new([const u8])
let lower = to-lower(text)
let i = 0
let n = length(lower)
lower = to-lower(text)
i = 0
n = length(lower)
while :scan i < n
until i >= n or letter?(lower[i])
i += 1
@ -67,11 +67,11 @@ fn main() -> i32
let {.word .n} = counts[i]
println(str(word), n)
let top: [3 i32] = [counts[0].n counts[1].n counts[2].n]
let [most & others] = top
[most & others] = top
println("most frequent seen", most, "times, then", others)
let total = i32(length(ws))
let distinct = i32(length(counts))
let g = grade(distinct, total)
distinct = i32(length(counts))
g = grade(distinct, total)
println(distinct, "of", total, "distinct:", describe(g))
let longest = reduce(slice(ws), slice(ws[0], 0, 0), fn(a, b) =>
if length(b) > length(a) then b else a)

View File

@ -539,7 +539,7 @@ let () =
(* Statements. *)
reads "lets merge" "fn f() -> i32\n let a = 1\n let b = 2\n a + b"
"(defn f [] i32 (let [a 1 b 2] (+ a b)))";
refuses ~global:false "let with a block" "let a = 1\n a\nb" "indent/let-block" "go at the let's column";
refuses ~global:false "let with a block" "let a = 1\n a\nb" "indent/let-block" "goes at the let's column";
reads ~global:false "flat let" "let a = 1\na\nb" "(let [a 1] a b)";
reads "elif" "if a\n 1\nelif b\n 2\nelse\n 3" "(cond a 1 b 2 :else 3)";
reads "one-line if" "x = if a then 1 else 2" "(set x (if a 1 2))";
@ -643,6 +643,8 @@ let () =
refuses "two assignments" "if a then b = c = d" "indent/assign-in-test" "if a then b = c,";
refuses "a let-bound if with no block" "let r = if a > 1\nr" "indent/expected-block" "if a > 1 takes";
refuses "two bindings on a line" "let v: i32 = a, w = b" "indent/one-binding" "a is followed by a comma";
refuses "two bindings on a let's line" "fn f()\n let v = a, w = b\n v" "indent/one-binding"
"under its name:\n\n let v = a\n w = b";
reads ~global:false "a let-bound match" "let r = match a\n 1 -> 2\n _ -> 3\nr" "(let [r (match a 1 2 _ 3)] r)";
reads ~global:false "a let-bound if" "let q = if a\n 1\nelse\n 2\nq" "(let [q (if a 1 2)] q)";
reads ~global:false "a let-bound call with a block" "let v = foo(a):\n x\nv" "(let [v (foo a x)] v)";
@ -659,7 +661,7 @@ let () =
"(defmacro m [x] (quasiquote (+ (unquote x) 1)))";
reads ~global:false "typed let" "let x: i32 = 5\nx" "(let [x (the i32 5)] x)";
refuses "a let takes no block" "fn f() -> ()\n let x = 1\n g(x)\n h(x)"
"indent/let-block" "go at the let's column";
"indent/let-block" "goes at the let's column";
(* Mistakes carried over from other languages, answered in this one. *)
refuses "a block without the colon names the call" "with-allocator(a, b)\n g()"
"indent/stray-indent" "as in with-allocator(a, b):";
@ -693,6 +695,29 @@ let () =
"indent/lambda-block-left" "Indent it into the block";
refuses "a block lambda's brackets left open" "f(fn(a) =>\n a\n"
"indent/unclosed" "ends where this bracket closes";
(* A let's bindings on the lines under it. *)
reads ~global:false "a let's bindings on indented lines" "let a = 1\n b = a + 1\n c: i32 = b\ng(c)"
"(let [a 1 b (+ a 1) c (the i32 b)] (g c))";
reads ~global:false "patterns among them" "let p = q()\n {x .x} = p\n [h & t] = xs\ng(x, h)"
"(let [p (q) {x .x} p [h & t] xs] (g x h))";
reads ~global:false "a binding with a block value" "let a = 1\n b =\n f()\n a\n c = match b\n 1 -> 2\n _ -> 3\ng(c)"
"(let [a 1 b (do (f) a) c (match b 1 2 _ 3)] (g c))";
reads ~global:false "a let after a group merges into it" "let a = 1\n b = 2\nlet c = 3\ng(c)"
"(let [a 1 b 2 c 3] (g c))";
reads ~global:false "a group in a body" "fn f()\n let a = 1\n b = 2\n a + b"
"(defn f [] _ (let [a 1 b 2] (+ a b)))";
refuses ~global:false "a statement under a let" "let a = 1\n g(a)\nh()"
"indent/let-block" "b = a + 1";
refuses ~global:false "an assignment to a field under a let" "let a = p()\n a.x = 1\nh()"
"indent/let-block" "only lines that go there are more bindings";
refuses ~global:false "a compound assignment under a let" "let a = 1\n a += 1\nh()"
"indent/let-block" "let's column";
reads "a top-level group is several globals" "let a = 1\n b: i32 = 2\nfn f() = a"
"(def a dyn 1)\n(def b i32 2)\n(defn f [] _ a)";
refuses "a global group binds names" "let a = 1\n {x .x} = p"
"indent/global-pattern" "a global binds one name";
refuses "a statement under a global" "let a = 1\n f(a)"
"indent/let-block" "more bindings of the let";
(* Indices separate as a vector's elements do. *)
reads "indices separated by spaces" "x = grid[row col].color-idx"
"(set x (.color-idx (at grid row col)))";
@ -786,18 +811,18 @@ let () =
(* A let is always flat: it takes in the rest of its block. *)
prints "flat let" "(defn f [] () (let [j 1] (g j)) (h))" " let j = 1\n g(j)\n h()";
prints "a chain of lets, all flat" "(defn f [] () (let [a 1] (let [b 2] (g b)) (k a)) (h))"
" let a = 1\n let b = 2\n g(b)\n k(a)\n h()";
" let a = 1\n b = 2\n g(b)\n k(a)\n h()";
(* A later statement that means an outer name of the same spelling: the
let's own is renamed. *)
prints "a later outer name of the same spelling renames the let's"
"(defn f [x i32] () (let [x 1] (g x)) (h x))" " let x-2 = 1\n g(x-2)\n h(x)";
prints "the inner let of a chain renamed"
"(defn f [] () (let [a 1] (let [b 2] (g b)) (h b)))" " let a = 1\n let b-2 = 2\n g(b-2)\n h(b)";
"(defn f [] () (let [a 1] (let [b 2] (g b)) (h b)))" " let a = 1\n b-2 = 2\n g(b-2)\n h(b)";
prints "the binding's own value keeps the outer name"
"(defn f [x i32] () (let [x (+ x 1)] (g x)) (h x))" " let x-2 = x + 1\n g(x-2)\n h(x)";
prints "a later binding's value takes the new name"
"(defn f [x i32] () (let [x 1 y (+ x 1)] (g y)) (h x))"
" let x-2 = 1\n let y = x-2 + 1\n g(y)\n h(x)";
" let x-2 = 1\n y = x-2 + 1\n g(y)\n h(x)";
prints "the new name is one the function does not use"
"(defn f [x i32] () (let [x 1] (g x x-2)) (h x))" " let x-3 = 1\n g(x-3, x-2)\n h(x)";
prints "a later let of the same name is no mention"
@ -838,10 +863,10 @@ let () =
prints "comment is a body in order" "(comment (let [a 1] (g a)) (h))" "comment:\n let a = 1\n g(a)\n h()";
prints "a later lambda keeps the outer name"
"(defn f [] i32 (let [x 1] (let [x 5] (g x)) (app (fn [y] (+ x y)) 2)))"
" let x = 1\n let x-2 = 5\n g(x-2)\n app(fn(y) => x + y, 2)";
" let x = 1\n x-2 = 5\n g(x-2)\n app(fn(y) => x + y, 2)";
prints "a renamed name renamed again counts on"
"(defn f [] () (let [x 1] (let [x 2] (let [x 3] (g x)) (g x)) (g x)))"
" let x = 1\n let x-2 = 2\n let x-3 = 3\n g(x-3)\n g(x-2)\n g(x)";
" let x = 1\n x-2 = 2\n x-3 = 3\n g(x-3)\n g(x-2)\n g(x)";
prints "a macro that names the let's name keeps its scope"
"(defmacro show-it [] `(println it))\n(defn f [] () (let [it 1] (let [it 2] (show-it)) (show-it)))"
" let it = 1\n do:\n let it = 2\n show-it()\n show-it()";
@ -898,7 +923,19 @@ let () =
"(let [a 1 ; first\n b 2] ; second";
prints "each binding keeps its comment, indented"
"(defn f [] i32\n (let [a 1 ; first\n b 2] ; second\n (+ a b)))"
" let a = 1 ; first\n let b = 2 ; second";
" let a = 1 ; first\n b = 2 ; second";
prints "a comment line between grouped bindings"
"(defn f [] i32\n (let [a 1\n ;; why b\n b 2]\n (+ a b)))"
" let a = 1\n ;; why b\n b = 2\n";
prints "a long value starts a let of its own"
"(defn f [] i32 (let [a 1 b (some-function-with-a-long-name alpha beta gamma) c 2] (+ a b c)))"
" let a = 1\n let b = some-function-with-a-long-name(alpha, beta, gamma)\n let c = 2\n";
prints "a block value ends the group"
"(defn f [] i32 (let [a 1 b 2 c (do (g) a) d 4 e 5] (+ a b c d e)))"
" let a = 1\n b = 2\n let c =\n g()\n a\n let d = 4\n e = 5\n";
prints "typed and pattern bindings in a group"
"(defn f [p dyn] i32 (let [a (the i32 1) {x .x} p [h & t] xs] (+ a x h)))"
" let a: i32 = 1\n {x .x} = p\n [h & t] = xs\n";
back "comments to parens" "; head\n\nfn main() -> i32\n ; why\n g() ; note\n 0"
"; head\n\n(defn main [] i32\n ; why\n (g) ; note\n 0)";
(* Written the way the corpus writes them. *)