A prelude function shadowed live keeps the prelude's own calls on the prelude's body, as a rebuild does
This commit is contained in:
parent
c41d27ec45
commit
d07c7b4e2c
5
TODO.org
5
TODO.org
@ -1480,11 +1480,6 @@ Its signature changes in the session but its body is not recompiled, so every ca
|
|||||||
stops on StaleCall naming a type nobody wrote. Proposal: recompile such callers.
|
stops on StaleCall naming a type nobody wrote. Proposal: recompile such callers.
|
||||||
Postponed 2026-09-25 while .fln takes priority.
|
Postponed 2026-09-25 while .fln takes priority.
|
||||||
|
|
||||||
** TODO A prelude function shadowed live is reached by the prelude's own calls
|
|
||||||
A defn of a prelude function's name sent to a running =flan dev= installs into the
|
|
||||||
host's cell for that name, so the prelude's calls compiled into the host follow it;
|
|
||||||
a rebuild gives them the prelude's again, as =Check.shadow_prelude= intends.
|
|
||||||
|
|
||||||
** DONE The dev loop, step 1: the reload primitive
|
** DONE The dev loop, step 1: the reload primitive
|
||||||
A list of top-level forms is recompiled and installed into a running process, and
|
A list of top-level forms is recompiled and installed into a running process, and
|
||||||
call sites compiled before those forms existed follow them through an indirection
|
call sites compiled before those forms existed follow them through an indirection
|
||||||
|
|||||||
@ -1158,9 +1158,52 @@ let eval ?(origin = "<eval>") ?base ?forms ?pause ?(step = false) ?(running = tr
|
|||||||
| None -> None)
|
| None -> None)
|
||||||
program.Tast.fns
|
program.Tast.fns
|
||||||
in
|
in
|
||||||
|
(* A name that takes over a prelude function's moves the prelude's body to
|
||||||
|
[Check.prelude_alias] and the prelude's own calls with it (see
|
||||||
|
[Check.shadow_prelude]). The process was built with those calls going
|
||||||
|
through the name's cell, which the new body is about to be installed
|
||||||
|
into, so the prelude's body is installed under its new name and every
|
||||||
|
body whose calls moved is compiled again: the prelude keeps its own
|
||||||
|
function, as a rebuild would give it. *)
|
||||||
|
let prelude_moved =
|
||||||
|
if not (List.exists (fun (f : Tast.fn) -> Check.internal_name f.Tast.name)
|
||||||
|
program.Tast.fns)
|
||||||
|
then []
|
||||||
|
else
|
||||||
|
let calls_moved (f : Tast.fn) (b : built) =
|
||||||
|
let hit = ref false in
|
||||||
|
let see (e : Tast.expr) =
|
||||||
|
match e.Tast.e with
|
||||||
|
| Tast.Call (m, _)
|
||||||
|
| Tast.FnAddr (Tast.Fnval m) | Tast.Closure (Tast.Fnval m, _)
|
||||||
|
when Check.internal_name m
|
||||||
|
&& not (List.exists
|
||||||
|
(fun (s : site) -> String.equal s.callee m) b.sites) ->
|
||||||
|
hit := true
|
||||||
|
| _ -> ()
|
||||||
|
in
|
||||||
|
List.iter (Tast.walk see) f.Tast.body;
|
||||||
|
List.iter (Tast.walk see) f.Tast.fdefers;
|
||||||
|
!hit
|
||||||
|
in
|
||||||
|
List.filter_map
|
||||||
|
(fun (f : Tast.fn) ->
|
||||||
|
if Check.internal_name f.Tast.name then
|
||||||
|
(if known t f.Tast.name || SM.mem f.Tast.name t.built then None
|
||||||
|
else Some f.Tast.name)
|
||||||
|
else
|
||||||
|
match SM.find_opt f.Tast.name t.built with
|
||||||
|
| Some b when calls_moved f b ->
|
||||||
|
(* A lifted clause is compiled with the body it came from. *)
|
||||||
|
(match f.Tast.fparent with
|
||||||
|
| Some p when p <> "<thick>" -> Some p
|
||||||
|
| _ -> Some f.Tast.name)
|
||||||
|
| _ -> None)
|
||||||
|
program.Tast.fns
|
||||||
|
in
|
||||||
let fns =
|
let fns =
|
||||||
List.sort_uniq String.compare
|
List.sort_uniq String.compare
|
||||||
(declared_fns @ def_inits @ from_generics @ new_instances)
|
(declared_fns @ def_inits @ from_generics @ new_instances @ prelude_moved)
|
||||||
in
|
in
|
||||||
(* A constant that changed and can be published: known to the host, not
|
(* A constant that changed and can be published: known to the host, not
|
||||||
consumed by the checker. The module stores its new value at the frame
|
consumed by the checker. The module stores its new value at the frame
|
||||||
|
|||||||
@ -265,6 +265,27 @@ let () =
|
|||||||
if has c.Session.ir "flan_dev_cell" then
|
if has c.Session.ir "flan_dev_cell" then
|
||||||
fail "a name the host has went through the registry";
|
fail "a name the host has went through the registry";
|
||||||
|
|
||||||
|
(* A defn of a prelude function's name, sent live. The host's prelude calls
|
||||||
|
[rand-int] through the cell the new body goes into, so the prelude's body
|
||||||
|
moves to its own name and its callers are compiled again to call it, as
|
||||||
|
a rebuild would have them. Once: a second redefinition moves nothing. *)
|
||||||
|
(let t, _ = Session.create ~file:"programs/reload.flan" () in
|
||||||
|
let c =
|
||||||
|
Session.eval ~origin:"programs/reload.flan" t "(defn rand-int [] u64 4096)"
|
||||||
|
in
|
||||||
|
List.iter
|
||||||
|
(fun n ->
|
||||||
|
if not (List.mem n c.Session.fns) then
|
||||||
|
fail "shadowing rand-int live did not install %s: %s" n
|
||||||
|
(String.concat " " c.Session.fns))
|
||||||
|
[ "rand-int"; "prelude~/rand-int"; "rand"; "rand-int-range" ];
|
||||||
|
let c =
|
||||||
|
Session.eval ~origin:"programs/reload.flan" t "(defn rand-int [] u64 8)"
|
||||||
|
in
|
||||||
|
if c.Session.fns <> [ "rand-int" ] then
|
||||||
|
fail "redefining a shadowed rand-int again installed %s"
|
||||||
|
(String.concat " " c.Session.fns));
|
||||||
|
|
||||||
(* DWARF in a redefinition module, which is a property of the session and
|
(* DWARF in a redefinition module, which is a property of the session and
|
||||||
not of the call. [Emit.redefinition] has taken a ~debug argument all
|
not of the call. [Emit.redefinition] has taken a ~debug argument all
|
||||||
along and was tested with it; what was missing was anyone passing it, so
|
along and was tested with it; what was missing was anyone passing it, so
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user