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
|
||||
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
|
||||
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.
|
||||
|
||||
@ -743,7 +743,7 @@ and postfix p =
|
||||
loop (mk p l0 (Form.List (f :: args)), 9)
|
||||
| LB ->
|
||||
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)
|
||||
| NAME s when String.length s > 1 && s.[0] = '.' ->
|
||||
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, for [Ptr(const u8)]: const is a reserved word in a type and never a
|
||||
value. *)
|
||||
(* [head] is the text of what is indexed, for [[ ]]'s message. *)
|
||||
and items ?head p closer open_loc ~what =
|
||||
and items p closer open_loc ~what =
|
||||
let opener = if closer = RB then '[' else '(' in
|
||||
let rec go acc =
|
||||
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
|
||||
failk "missing-comma" n.loc
|
||||
"%s follows %s with no comma between them. Separate %s with \
|
||||
commas: %s"
|
||||
commas: f(a, b)"
|
||||
(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))
|
||||
in
|
||||
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. *)
|
||||
and vec_items p open_loc =
|
||||
(* 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
|
||||
value may have an operator in it, `{.x a + 1, .y 2}`; the comma after it is
|
||||
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
|
||||
`(Vector2 {.x 1 .y 2})`. A bare `{.x 1}` is today's bare literal. `{:a 1}` is a
|
||||
dyn map. **Built.**
|
||||
|
||||
@ -693,8 +693,25 @@ 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";
|
||||
refuses "indices with no comma" "x = grid[row col].color-idx"
|
||||
"indent/missing-comma" "Separate indices with commas: grid[row, col]";
|
||||
(* 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)))";
|
||||
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)"
|
||||
"indent/missing-comma" "Separate arguments with commas: f(a, b)";
|
||||
refuses "a body glued to =>" "x = fn(a) =>a"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user