A frame whose slots are all the compiler's own is compared against the slot count its record carries, so a frame that prints keeps its globals and locals
This commit is contained in:
parent
285bb1047f
commit
c41d27ec45
3
TODO.org
3
TODO.org
@ -1657,9 +1657,6 @@ CLOSED: [2026-09-25]
|
|||||||
** TODO The inspector holds a value
|
** TODO The inspector holds a value
|
||||||
Reading needs no module now, so an address and a type are enough to keep a value on the daemon's side between requests, the way CIDER keeps a JVM object. Nothing holds one yet: the Emacs stack is still a stack of expressions.
|
Reading needs no module now, so an address and a type are enough to keep a value on the daemon's side between requests, the way CIDER keeps a JVM object. Nothing holds one yet: the Emacs stack is still a stack of expressions.
|
||||||
|
|
||||||
** TODO A frame that prints is skipped from the globals section
|
|
||||||
A frame whose body calls =print= comes back in =:skipped= as "running a body that has been redefined since" though nothing was redefined: its global-reference fingerprint differs between the build and the daemon. test/programs/dev-parity.flan stores each global to itself instead of printing it for this reason.
|
|
||||||
|
|
||||||
** DONE The watch table stays pushed
|
** DONE The watch table stays pushed
|
||||||
CLOSED: [2026-09-25]
|
CLOSED: [2026-09-25]
|
||||||
The watch table stays pushed, and shares the push channel program output moves to.
|
The watch table stays pushed, and shares the push channel program output moves to.
|
||||||
|
|||||||
10
lib/dev.ml
10
lib/dev.ml
@ -2588,11 +2588,11 @@ let stopped_frame t ~frame ~what : (string * Tast.fn, string) result =
|
|||||||
up" is a claim about the body this session holds, and a
|
up" is a claim about the body this session holds, and a
|
||||||
zero-slot frame whose body has since been replaced by one
|
zero-slot frame whose body has since been replaced by one
|
||||||
with slots is a frame that claim is false about. *)
|
with slots is a frame that claim is false about. *)
|
||||||
if nslots <> Array.length fn.Tast.slots then
|
if nslots <> Emit.recorded_slots fn then
|
||||||
Error
|
Error
|
||||||
(Printf.sprintf
|
(Printf.sprintf
|
||||||
"%s on the stack has %d slots and the %s this session holds has %d — the frame is running a body that has been redefined since"
|
"%s on the stack has %d slots and the %s this session holds has %d — the frame is running a body that has been redefined since"
|
||||||
name nslots name (Array.length fn.Tast.slots))
|
name nslots name (Emit.recorded_slots fn))
|
||||||
else if sig_ <> Emit.slot_fingerprint fn then
|
else if sig_ <> Emit.slot_fingerprint fn then
|
||||||
(* The count matching is not the same as the body matching.
|
(* The count matching is not the same as the body matching.
|
||||||
A redefinition that renames a local, or changes its type
|
A redefinition that renames a local, or changes its type
|
||||||
@ -2628,7 +2628,7 @@ let eval_expr ?frame ?at_stop t ~code ~origin ~pause =
|
|||||||
(* A frame with no slots has no locals to bind, and the program
|
(* A frame with no slots has no locals to bind, and the program
|
||||||
has no table to answer for it: the expression sees globals. *)
|
has no table to answer for it: the expression sees globals. *)
|
||||||
let bound =
|
let bound =
|
||||||
if Array.length fn.Tast.slots = 0 then Ok []
|
if Emit.recorded_slots fn = 0 then Ok []
|
||||||
else bound_slots t ~frame:index
|
else bound_slots t ~frame:index
|
||||||
in
|
in
|
||||||
(* [at_stop] is the stop the editor drew the frame at. It is not
|
(* [at_stop] is the stop the editor drew the frame at. It is not
|
||||||
@ -2677,7 +2677,7 @@ let locals t ~frame =
|
|||||||
match stopped_frame t ~frame ~what:"locals" with
|
match stopped_frame t ~frame ~what:"locals" with
|
||||||
| Error m -> error m
|
| Error m -> error m
|
||||||
| Ok (name, fn) ->
|
| Ok (name, fn) ->
|
||||||
if Array.length fn.Tast.slots = 0 then
|
if Emit.recorded_slots fn = 0 then
|
||||||
ok
|
ok
|
||||||
[ ":frame " ^ Wire.quote name; ":locals ()"; ":refused ()";
|
[ ":frame " ^ Wire.quote name; ":locals ()"; ":refused ()";
|
||||||
":note " ^ Wire.quote "this frame has no named locals" ]
|
":note " ^ Wire.quote "this frame has no named locals" ]
|
||||||
@ -3457,7 +3457,7 @@ let globals_op t =
|
|||||||
"not a function this session holds; a lifted handler clause \
|
"not a function this session holds; a lifted handler clause \
|
||||||
has no declaration of its own to read references from"
|
has no declaration of its own to read references from"
|
||||||
| Some fn ->
|
| Some fn ->
|
||||||
if nslots <> Array.length fn.Tast.slots then
|
if nslots <> Emit.recorded_slots fn then
|
||||||
skip
|
skip
|
||||||
"the frame is running a body that has been redefined \
|
"the frame is running a body that has been redefined \
|
||||||
since, so what this session holds is a different body's \
|
since, so what this session holds is a different body's \
|
||||||
|
|||||||
11
lib/emit.ml
11
lib/emit.ml
@ -2022,6 +2022,17 @@ let slot_fingerprint (fn : Tast.fn) =
|
|||||||
fn.Tast.slots;
|
fn.Tast.slots;
|
||||||
Hashtbl.hash (Buffer.contents b) land 0x3fffffff
|
Hashtbl.hash (Buffer.contents b) land 0x3fffffff
|
||||||
|
|
||||||
|
(* How many slots a frame's record says it has: all of them when any is named,
|
||||||
|
and none otherwise, since only a function with a named slot gets a slot
|
||||||
|
table (see the shadow stack's push in [emit_fn]). Both backends write it and
|
||||||
|
[Dev] compares a frame against it, so a body whose slots are all the
|
||||||
|
compiler's own — a [print]'s temporaries — reads as the same body at both
|
||||||
|
ends. *)
|
||||||
|
let recorded_slots (fn : Tast.fn) =
|
||||||
|
if Array.exists (fun n -> n <> None) fn.Tast.snames then
|
||||||
|
Array.length fn.Tast.slots
|
||||||
|
else 0
|
||||||
|
|
||||||
let fninfo m (fn : Tast.fn) ~nslots =
|
let fninfo m (fn : Tast.fn) ~nslots =
|
||||||
let nid, nlen = fi_bytes m fn.Tast.name in
|
let nid, nlen = fi_bytes m fn.Tast.name in
|
||||||
let lid, llen = fi_bytes m (Loc.to_string fn.Tast.floc) in
|
let lid, llen = fi_bytes m (Loc.to_string fn.Tast.floc) in
|
||||||
|
|||||||
@ -54,18 +54,17 @@
|
|||||||
(defonce pair (Pair i32))
|
(defonce pair (Pair i32))
|
||||||
|
|
||||||
;; The innermost frame names every global above, so the break loop's section
|
;; The innermost frame names every global above, so the break loop's section
|
||||||
;; holds all of them; then it stops. Each is stored back to itself rather than
|
;; holds all of them; then it stops. It prints them, and a frame whose only
|
||||||
;; printed: a frame that prints is refused attribution today (TODO.org, "A
|
;; slots are the printer's temporaries is still attributed its globals.
|
||||||
;; frame that prints is skipped from the globals section"), and this is about
|
|
||||||
;; the values.
|
|
||||||
(defn inner [] i64
|
(defn inner [] i64
|
||||||
(set small small) (set mid mid) (set large large) (set huge huge)
|
(print small) (print mid) (print large) (print huge)
|
||||||
(set neg neg) (set ratio ratio) (set far far) (set odd odd) (set yes yes)
|
(print neg) (print ratio) (print far) (print odd) (print yes)
|
||||||
(set byte byte) (set text text) (set colour colour) (set stray stray)
|
(print byte) (print text) (print colour) (print stray)
|
||||||
(set some some) (set none none) (set wide wide) (set deep deep)
|
(print some) (print none) (print wide) (print deep)
|
||||||
(set dot dot) (set empty empty) (set row row) (set words words)
|
(print dot) (print empty) (print row) (print words)
|
||||||
(set nums nums) (set live live) (set dead dead) (set nowhere nowhere)
|
(print nums) (print live) (print dead) (print nowhere)
|
||||||
(set un un) (set anything anything) (set pair pair)
|
(print un) (print anything) (print pair)
|
||||||
|
(println "")
|
||||||
(error (Boom {.why 3}))
|
(error (Boom {.why 3}))
|
||||||
0)
|
0)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user