Indices in .fln separate like a vector's elements, by spaces between single values or by commas
This commit is contained in:
parent
6e006fce27
commit
f91ed8ad27
5
TODO.org
5
TODO.org
@ -648,11 +648,6 @@ CLOSED: [2026-09-26]
|
|||||||
A block lambda inside brackets is the last thing in them, its block ending where they close: a comma
|
A block lambda inside brackets is the last thing in them, its block ending where they close: a comma
|
||||||
after it (so a second block lambda, or one not last) is refused, and the fix names it with ~let~.
|
after it (so a second block lambda, or one not last) is refused, and the fix names it with ~let~.
|
||||||
|
|
||||||
** NEXT Indices separate like vector elements
|
|
||||||
Decided 2026-09-26: ~grid[r c]~ and ~grid[(r + 1) (c - 1)]~ read like a vector's
|
|
||||||
space-separated single values; commas always work; an index with a bare operator
|
|
||||||
needs them, ~grid[r + 1, c]~.
|
|
||||||
|
|
||||||
** WAIT Calls without parentheses
|
** WAIT Calls without parentheses
|
||||||
Held 2026-09-26 by the author: F#-style ~f x y~ or Nim-style one-argument calls
|
Held 2026-09-26 by the author: F#-style ~f x y~ or Nim-style one-argument calls
|
||||||
without parentheses. Collides with space-separated vector and index elements.
|
without parentheses. Collides with space-separated vector and index elements.
|
||||||
|
|||||||
@ -743,7 +743,7 @@ and postfix p =
|
|||||||
loop (mk p l0 (Form.List (f :: args)), 9)
|
loop (mk p l0 (Form.List (f :: args)), 9)
|
||||||
| LB ->
|
| LB ->
|
||||||
ignore (advance p);
|
ignore (advance p);
|
||||||
let idx = items p RB t.loc ~what:"indices" ~head:(text_of f) in
|
let idx = index_items p t.loc ~head:(text_of f) in
|
||||||
loop (mk p l0 (Form.List (sym t.loc "at" :: f :: idx)), 9)
|
loop (mk p l0 (Form.List (sym t.loc "at" :: f :: idx)), 9)
|
||||||
| NAME s when String.length s > 1 && s.[0] = '.' ->
|
| NAME s when String.length s > 1 && s.[0] = '.' ->
|
||||||
ignore (advance p);
|
ignore (advance p);
|
||||||
@ -1005,8 +1005,7 @@ and lambda_params args =
|
|||||||
(* Comma-separated values up to [closer]. [const T] is two elements without a
|
(* Comma-separated values up to [closer]. [const T] is two elements without a
|
||||||
comma, for [Ptr(const u8)]: const is a reserved word in a type and never a
|
comma, for [Ptr(const u8)]: const is a reserved word in a type and never a
|
||||||
value. *)
|
value. *)
|
||||||
(* [head] is the text of what is indexed, for [[ ]]'s message. *)
|
and items p closer open_loc ~what =
|
||||||
and items ?head p closer open_loc ~what =
|
|
||||||
let opener = if closer = RB then '[' else '(' in
|
let opener = if closer = RB then '[' else '(' in
|
||||||
let rec go acc =
|
let rec go acc =
|
||||||
let t = peek p in
|
let t = peek p in
|
||||||
@ -1037,15 +1036,77 @@ and items ?head p closer open_loc ~what =
|
|||||||
else if starts_value n.tok && n.sp && not (negative_literal n.tok) then
|
else if starts_value n.tok && n.sp && not (negative_literal n.tok) then
|
||||||
failk "missing-comma" n.loc
|
failk "missing-comma" n.loc
|
||||||
"%s follows %s with no comma between them. Separate %s with \
|
"%s follows %s with no comma between them. Separate %s with \
|
||||||
commas: %s"
|
commas: f(a, b)"
|
||||||
(show n.tok) (text_of e) what
|
(show n.tok) (text_of e) what
|
||||||
(match head with
|
|
||||||
| Some h -> Printf.sprintf "%s[%s, %s]" h (text_of e) (show n.tok)
|
|
||||||
| None -> "f(a, b)")
|
|
||||||
else stray p ~after:(text_of e))
|
else stray p ~after:(text_of e))
|
||||||
in
|
in
|
||||||
go []
|
go []
|
||||||
|
|
||||||
|
(* An index's values, [grid[r c]] or [grid[r + 1, c]]: separated as a
|
||||||
|
vector's elements are, by commas or, between single values only, by
|
||||||
|
spaces. The whole list is read before a mistake is named, so the fix can
|
||||||
|
be the index as written, commas put in. [head] is the text of what is
|
||||||
|
indexed. *)
|
||||||
|
and index_items p open_loc ~head =
|
||||||
|
let rec go acc =
|
||||||
|
let t = peek p in
|
||||||
|
match t.tok with
|
||||||
|
| RB -> ignore (advance p); List.rev acc
|
||||||
|
| EOF -> unclosed p '[' open_loc
|
||||||
|
| _ ->
|
||||||
|
let e, lvl = expr p in
|
||||||
|
(* The element as written, parentheses and all. *)
|
||||||
|
let src = text_of (Form.make (Form.Sym "") (span p t.loc)) in
|
||||||
|
let n = peek p in
|
||||||
|
match n.tok with
|
||||||
|
| COMMA -> ignore (advance p); go ((e, src, lvl, t.loc, Some n.loc) :: acc)
|
||||||
|
| RB -> ignore (advance p); List.rev ((e, src, lvl, t.loc, None) :: acc)
|
||||||
|
| EOF -> unclosed p '[' open_loc
|
||||||
|
(* [grid[i -1]]: most likely [i - 1] with its minus glued. *)
|
||||||
|
| (ATOM _ | NEG) when n.sp && (negative_literal n.tok || n.tok = NEG) ->
|
||||||
|
let x, _ = unary p in
|
||||||
|
let digits =
|
||||||
|
let s = text_of x in String.sub s 1 (String.length s - 1)
|
||||||
|
in
|
||||||
|
failk "glued-minus" n.loc
|
||||||
|
"%s is read as the value %s, right after %s with nothing between \
|
||||||
|
the minus and it. To subtract, space the minus: %s[%s - %s]. For \
|
||||||
|
two indices, separate them with a comma: %s[%s, %s]"
|
||||||
|
(text_of x) (text_of x) src head src digits head src (text_of x)
|
||||||
|
| tk when starts_value tk && n.sp -> go ((e, src, lvl, t.loc, None) :: acc)
|
||||||
|
| _ -> stray p ~after:(text_of e)
|
||||||
|
in
|
||||||
|
let xs = go [] in
|
||||||
|
let commas = List.exists (fun (_, _, _, _, c) -> c <> None) xs in
|
||||||
|
let spaces =
|
||||||
|
List.exists (fun (_, _, _, _, c) -> c = None) (match List.rev xs with _ :: r -> r | [] -> [])
|
||||||
|
in
|
||||||
|
let with_commas () =
|
||||||
|
Printf.sprintf "%s[%s]" head
|
||||||
|
(String.concat ", " (List.map (fun (_, s, _, _, _) -> s) xs))
|
||||||
|
in
|
||||||
|
if commas && spaces then begin
|
||||||
|
let at = match List.find_opt (fun (_, _, _, _, c) -> c <> None) xs with
|
||||||
|
| Some (_, _, _, _, Some l) -> l | _ -> open_loc
|
||||||
|
in
|
||||||
|
failk "mixed-separators" at
|
||||||
|
"these indices are separated some with commas and some with only \
|
||||||
|
spaces. Use one: %s%s"
|
||||||
|
(with_commas ())
|
||||||
|
(if List.for_all (fun (_, _, l, _, _) -> l >= 8) xs then
|
||||||
|
Printf.sprintf " or %s[%s]" head
|
||||||
|
(String.concat " " (List.map (fun (_, s, _, _, _) -> s) xs))
|
||||||
|
else "")
|
||||||
|
end;
|
||||||
|
(match List.find_opt (fun (_, _, l, _, _) -> l < 8) xs with
|
||||||
|
| Some (_, src, _, at, _) when spaces ->
|
||||||
|
failk "separate-elements" at
|
||||||
|
"%s has an operator in it and sits among indices separated by spaces, \
|
||||||
|
where only single values are. Separate the indices with commas: %s"
|
||||||
|
src (with_commas ())
|
||||||
|
| _ -> ());
|
||||||
|
List.map (fun (e, _, _, _, _) -> e) xs
|
||||||
|
|
||||||
(* [[a b c]] or [[a, b + 1]]: whitespace separates only single terms. *)
|
(* [[a b c]] or [[a, b + 1]]: whitespace separates only single terms. *)
|
||||||
and vec_items p open_loc =
|
and vec_items p open_loc =
|
||||||
(* One separator per bracket: [1 2, 3] mixes them, and which elements the
|
(* One separator per bracket: [1 2, 3] mixes them, and which elements the
|
||||||
|
|||||||
@ -145,6 +145,10 @@ Each item: the proposal, then the reason in one line.
|
|||||||
the Lisp look for data and is refusable by shape. **Built** (in braces a
|
the Lisp look for data and is refusable by shape. **Built** (in braces a
|
||||||
value may have an operator in it, `{.x a + 1, .y 2}`; the comma after it is
|
value may have an operator in it, `{.x a + 1, .y 2}`; the comma after it is
|
||||||
what is required).
|
what is required).
|
||||||
|
- **Indices separate the same way.** `grid[r c]` and `grid[(r + 1) (c - 1)]`
|
||||||
|
are two indices each; `grid[r + 1, c]` needs its comma, and `grid[r + 1 c]`
|
||||||
|
is refused with the commas put in as the fix. `grid[i -1]` is refused as a
|
||||||
|
glued minus. **Built**; the printer writes indices with commas.
|
||||||
- **Struct literal:** `Vector2{.x 1, .y 2}` (brace glued to the name) reads
|
- **Struct literal:** `Vector2{.x 1, .y 2}` (brace glued to the name) reads
|
||||||
`(Vector2 {.x 1 .y 2})`. A bare `{.x 1}` is today's bare literal. `{:a 1}` is a
|
`(Vector2 {.x 1 .y 2})`. A bare `{.x 1}` is today's bare literal. `{:a 1}` is a
|
||||||
dyn map. **Built.**
|
dyn map. **Built.**
|
||||||
|
|||||||
@ -693,8 +693,25 @@ let () =
|
|||||||
"indent/lambda-block-left" "Indent it into the block";
|
"indent/lambda-block-left" "Indent it into the block";
|
||||||
refuses "a block lambda's brackets left open" "f(fn(a) =>\n a\n"
|
refuses "a block lambda's brackets left open" "f(fn(a) =>\n a\n"
|
||||||
"indent/unclosed" "ends where this bracket closes";
|
"indent/unclosed" "ends where this bracket closes";
|
||||||
refuses "indices with no comma" "x = grid[row col].color-idx"
|
(* Indices separate as a vector's elements do. *)
|
||||||
"indent/missing-comma" "Separate indices with commas: grid[row, col]";
|
reads "indices separated by spaces" "x = grid[row col].color-idx"
|
||||||
|
"(set x (.color-idx (at grid row col)))";
|
||||||
|
reads "grouped indices separated by spaces" "x = grid[(r + 1) (c - 1)]"
|
||||||
|
"(set x (at grid (+ r 1) (- c 1)))";
|
||||||
|
reads "indices separated by commas" "x = grid[r + 1, c]" "(set x (at grid (+ r 1) c))";
|
||||||
|
reads "calls and fields as spaced indices" "x = grid[f(r) p.y]" "(set x (at grid (f r) (.y p)))";
|
||||||
|
reads "a negative literal first" "x = grid[-1 c]" "(set x (at grid -1 c))";
|
||||||
|
reads "a spaced index assigned" "grid[r c] = 1" "(set (at grid r c) 1)";
|
||||||
|
refuses "an operator among spaced indices" "x = grid[r + 1 c]"
|
||||||
|
"indent/separate-elements" "Separate the indices with commas: grid[r + 1, c]";
|
||||||
|
refuses "an operator last among spaced indices" "x = grid[r c - 1]"
|
||||||
|
"indent/separate-elements" "grid[r, c - 1]";
|
||||||
|
refuses "mixed index separators" "x = grid[r c, d]"
|
||||||
|
"indent/mixed-separators" "Use one: grid[r, c, d] or grid[r c d]";
|
||||||
|
refuses "a glued minus among indices" "x = grid[i -1]"
|
||||||
|
"indent/glued-minus" "grid[i - 1]";
|
||||||
|
refuses "a glued negation among indices" "x = grid[i -j]"
|
||||||
|
"indent/glued-minus" "grid[i, -j]";
|
||||||
refuses "arguments with no comma" "x = f(a b)"
|
refuses "arguments with no comma" "x = f(a b)"
|
||||||
"indent/missing-comma" "Separate arguments with commas: f(a, b)";
|
"indent/missing-comma" "Separate arguments with commas: f(a, b)";
|
||||||
refuses "a body glued to =>" "x = fn(a) =>a"
|
refuses "a body glued to =>" "x = fn(a) =>a"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user