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:
parent
04b29f283d
commit
12cd4feff0
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) -> ()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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. *)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user