Keep the printed struct a colon; it is a wire format Emacs reads back
render.ml's output is parsed by emacs/flan-inspect.el, which hard-codes the colon when it reads a field out of a rendered struct. Moving the printer on its own would break inspection in the dev loop without breaking a test that says so, so the printer waits and moves with its reader, in the Emacs lane. The sweep could not tell a rendered *expectation* from a Flan *source* snippet -- both are strings in a test -- so it converted both. The suite named every one it got wrong, and those are back. emacs/test-flan-dev.el:415 is the one edit inside emacs/: Flan source sent to the daemon for eval, which the parser now refuses in the old spelling. One label, in a fixture.
This commit is contained in:
parent
8e47356592
commit
cb757868b4
@ -412,7 +412,7 @@ is written instead — the real `message' call the real command makes."
|
||||
;; that errors stops it on its own game thread, in a frame of its own — not
|
||||
;; inside anything this client asked for. Nothing tells Emacs.
|
||||
(flan-dev--eval
|
||||
"(defn step [] i64 (restart-case (do (error (Missing {:id 7})) 0) (use-placeholder [] -1)))"
|
||||
"(defn step [] i64 (restart-case (do (error (Missing {.id 7})) 0) (use-placeholder [] -1)))"
|
||||
"form")
|
||||
(let ((deadline (+ (float-time) 20)))
|
||||
(while (and (not flan-dev--stopped) (< (float-time) deadline))
|
||||
|
||||
@ -147,7 +147,11 @@ let rec render c depth (e : Tast.expr) : Tast.expr list =
|
||||
(fun i (f : Tast.field) ->
|
||||
let v = { Tast.e = Tast.Field (e, i); ty = f.Tast.fty; loc } in
|
||||
(if i = 0 then [] else [ lit " " ])
|
||||
@ [ lit ("." ^ f.Tast.fname ^ " ") ]
|
||||
(* Still a colon, deliberately. This printed form is a wire
|
||||
format: emacs/flan-inspect.el parses it back, and it
|
||||
hard-codes the colon. Moving the printer to the dot has
|
||||
to land with that reader, in the Emacs lane. *)
|
||||
@ [ lit (":" ^ f.Tast.fname ^ " ") ]
|
||||
@ render c (depth + 1) v)
|
||||
shown)
|
||||
in
|
||||
|
||||
@ -150,15 +150,15 @@ let () =
|
||||
let println_out =
|
||||
"plain string\nplain bytes\n42\n-7\n5\n18446744073709551615\n3.5\n\
|
||||
-0.25\ntrue\nfalse\n()\n:green\n:red\n<ptr>\n(some 0)\nnone\n\
|
||||
(Blob {.id 7 .name \"sandy \\\"quoted\\\"\" .pos (V {.x 1.5 .y -2}) .tags [ 0 42 0]})\n\
|
||||
(Blob {:id 7 :name \"sandy \\\"quoted\\\"\" :pos (V {:x 1.5 :y -2}) :tags [ 0 42 0]})\n\
|
||||
[ 0 0 9 0]\n[ 0 0 0 0 0 0 0 0 ...]\n[ 0 9 0]\n\
|
||||
(D1 {.d (D2 {.d (D3 {.d (D4 {.d (D5 {.n ...})})})})})\n[ 0 0]\n\
|
||||
(D1 {:d (D2 {:d (D3 {:d (D4 {:d (D5 {:n ...})})})})})\n[ 0 0]\n\
|
||||
[ 0 0]\n[ 9 0]\n"
|
||||
(* The escape buffer is 1024 and the input is 1100 x's, so this is the
|
||||
truncation: the ellipsis goes *inside* the quotes, and the count is
|
||||
spelled out rather than pasted so that a change to the buffer or to
|
||||
the reserve shows up here as a number and not as a wall of x. *)
|
||||
^ "(Long {.s \"" ^ String.make 1014 'x' ^ "...\"})\n"
|
||||
^ "(Long {:s \"" ^ String.make 1014 'x' ^ "...\"})\n"
|
||||
^ "abc\n"
|
||||
in
|
||||
outputs "println, every arm" "programs/println.flan" println_out;
|
||||
|
||||
@ -775,7 +775,7 @@ let () =
|
||||
let want =
|
||||
[ ("n", "i64", "3");
|
||||
("label", "string", "\"hello\"");
|
||||
("p", "Point", "(Point {.x 1.5 .y 2.5})");
|
||||
("p", "Point", "(Point {:x 1.5 :y 2.5})");
|
||||
("xs", "[3 i32]", "[ 10 20 30]");
|
||||
("flag", "bool", "true") ]
|
||||
in
|
||||
|
||||
@ -618,6 +618,12 @@ let () =
|
||||
rejects_check "field given twice"
|
||||
(cursor ^ "(defn f [s [u8]] Cursor (Cursor {.pos 0 .pos 1}))")
|
||||
~needle:"given twice";
|
||||
(* The old spelling is refused rather than quietly accepted, and the refusal
|
||||
names the new one. Two accepted spellings is how two spellings become
|
||||
permanent, and the colon is wanted for keys. *)
|
||||
rejects_check "a field label written with a colon"
|
||||
(cursor ^ "(defn f [s [u8]] Cursor (Cursor {:src s}))")
|
||||
~needle:"a field label is written .src, not :src";
|
||||
accepts "field through a pointer auto-derefs"
|
||||
(cursor ^ "(defn f [c (Ptr Cursor)] i32 (.pos c))");
|
||||
accepts "set through a pointer"
|
||||
@ -957,6 +963,14 @@ let () =
|
||||
rejects_check "a pattern with no field name after it"
|
||||
(pt ^ "(defn f [p Point] i32 (let [{a b} p] 0))")
|
||||
~needle:"expected .field after a";
|
||||
(* The same refusal on the destructuring side: a field is a field wherever it
|
||||
is named, so the rule is not half-applied. :keys is the one that keeps its
|
||||
colon, and the test below it says so. *)
|
||||
rejects_check "a destructured field written with a colon"
|
||||
(pt ^ "(defn f [p Point] i32 (let [{a :x} p] a))")
|
||||
~needle:"a field label is written .x, not :x";
|
||||
accepts ":keys keeps its colon, naming no field"
|
||||
(pt ^ "(defn f [p Point] i32 (let [{:keys [x y]} p] (+ x y)))");
|
||||
|
||||
(* Clojure's other map-destructuring keys. Each is refused by its own name:
|
||||
"unexpected form" would leave the author guessing which of the four they
|
||||
|
||||
@ -96,9 +96,9 @@ let () =
|
||||
this would otherwise come back as -1. *)
|
||||
value "u64 at its maximum" "big" "18446744073709551615";
|
||||
(* A struct, nested, with a fixed array inside it. *)
|
||||
value "a struct" "(.pos b)" "(V {.x 1.5 .y 0})";
|
||||
value "a struct" "(.pos b)" "(V {:x 1.5 :y 0})";
|
||||
value "a nested struct" "b"
|
||||
"(Blob {.id 7 .name \"sandy \\\"quoted\\\"\" .pos (V {.x 1.5 .y 0}) .tags [ 0 42 0]})";
|
||||
"(Blob {:id 7 :name \"sandy \\\"quoted\\\"\" :pos (V {:x 1.5 :y 0}) :tags [ 0 42 0]})";
|
||||
value "a fixed array" "arr" "[ 0 0 9 0]";
|
||||
(* A slice's length is not known until it runs, so this one renders
|
||||
through a loop rather than by unrolling. *)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user