flan/test/programs/dev-class.flan
Joseph Ferano 52a1ea183a A method added to a running program, proved end to end
The claim classes were built for, made against a real daemon rather than
at the session's report: dev-class.flan is compiled with one method for
one class, a second method is delivered into the live process, and the
call through the generic's cell answers with the new method's body while
the original one goes on answering. That is what a generic being exactly
one top-level name buys, and it is now pinned rather than argued.

Two things came out of writing it, neither of them about classes.

The x86 backend's redefinition module never emitted the per-type dyn
descriptors. Emit.redefinition has always emitted them, by going through
finish; the x86 twin ended at the rodata section and stopped. Nothing
had reached it, because a redefined body had to construct a struct
holding a dyn to need one, and until NoMethod there was no such struct a
compiler-written body could build. What it looks like is not a bad read
at run time but a link failure — desc_of mints a local label, the body
references it, and ld refuses the module with an undefined symbol. One
line, beside the same call in the executable path.

And the thing the test had to be written around: a dyn value answered by
eval-expr does not come back in the reply's :value at all. It renders to
the program's own stdout, which reaches a *later* reply's :output — the
dyn-global rows already read one that way and say so. So every answer
here is compared inside the expression, and what crosses the wire is a
typed 1 or 0. Left as it is; where a dyn expression's value should
surface is a question about the editor protocol, not about this lane.

The session-level test stays: it pins which names an added method
reports for installation, which is the half a daemon test cannot see.
2026-09-20 15:36:13 +07:00

27 lines
1009 B
Plaintext

;;;; A class and a generic function, for the dev loop rather than for output.
;;;;
;;;; What a session does with this is the question the feature is judged on:
;;;; adding a method to a running program has to reach the call sites that
;;;; were compiled before the method existed. It does, and the reason is that
;;;; a generic is one function — the methods are branches of its body, not
;;;; functions of their own — so a new method is the ordinary redefinition of
;;;; one name, through the cell the call already goes through.
;;;;
;;;; It keeps running rather than returning, for dev-repl.flan's reason: an
;;;; expression typed at the editor is a thunk the agent runs at a frame
;;;; boundary, and a parked program has none.
(import agent "vendor:agent")
(defclass point [x y])
(defclass circle [r])
(defgeneric area [self] dyn)
(defmethod area point [p] (* (get p :x) (get p :y)))
(defn main [] i32
(agent/start "/tmp/flan-dev-class-fallback.sock")
(dotimes [i 4000]
(agent/wait 5))
0)