What the dogfooding session turned up
This commit is contained in:
parent
9d7da2ba7a
commit
5557594f31
98
TODO.org
98
TODO.org
@ -1731,13 +1731,99 @@ specification's own branch — the flag is the command and the printed shape is
|
|||||||
error pattern, so anyone who wants one has the four lines, and the manual carries
|
error pattern, so anyone who wants one has the four lines, and the manual carries
|
||||||
them.
|
them.
|
||||||
|
|
||||||
** TODO The break buffer prints a condition's fields, not its message
|
** TODO defclass slots take types, checked on write
|
||||||
|
=(defclass State [pause bool step bool])= reads as four untyped slots and
|
||||||
|
reports a duplicate =bool=. Wanted: the slot list is name/type pairs, as CLOS
|
||||||
|
does it. The type is a declaration about the values and not a layout — an
|
||||||
|
instance stays a map, so redefinition and lazy migration are unchanged. SBCL
|
||||||
|
checks it on write (=src/pcl/slots.lisp:160=, the typecheck before the store),
|
||||||
|
which is where the bad value is, so =put= is the site here.
|
||||||
|
|
||||||
|
Open: what migration does with a stored value that no longer fits a changed
|
||||||
|
slot type, and whether an untyped slot stays legal (it should — =dyn= is a type
|
||||||
|
and writing nothing should mean it).
|
||||||
|
|
||||||
|
** TODO println takes up to a second to appear
|
||||||
|
Output is drained by =flan--poll= at =flan-poll-interval=, 1.0s
|
||||||
|
(=emacs/flan.el:541=). A reply carries whatever was buffered when it was
|
||||||
|
composed, so anything the program prints after that waits for the next tick.
|
||||||
|
Polling faster costs a request a second for nothing most of the time; the
|
||||||
|
daemon pushing on its own connection is the other shape. Decide which.
|
||||||
|
|
||||||
|
** TODO set writes a class slot; put is for maps
|
||||||
|
=put= exists because an absent map key has no location to store into, which is
|
||||||
|
why =(get m k)= is refused as a place (=lib/parse.ml:1159=). A class instance is
|
||||||
|
not in that situation: its slots are fixed by the =defclass=, so a declared slot
|
||||||
|
always exists and =(set (get state :pause) true)= is a field store like
|
||||||
|
=(set (.velocity g) 0.0)=. Make =set= take it, and leave =put= to maps, where
|
||||||
|
insertion is real. Writing an undeclared slot through =set= is then a refusal
|
||||||
|
naming the class.
|
||||||
|
|
||||||
|
** TODO update: change a place by applying a function to it
|
||||||
|
=(set (.velocity g) (inc (.velocity g)))= names the place twice. Clojure's
|
||||||
|
=update= would be a macro over the same two steps, for a struct field and a
|
||||||
|
class slot alike.
|
||||||
|
|
||||||
|
Blocked on the double-evaluation question, which =++=, =--= and any
|
||||||
|
compound assignment share: =(update (at grid (next-index) c) inc)= evaluates
|
||||||
|
=(next-index)= twice, and a place with a side effect is then wrong rather than
|
||||||
|
slow. Either places get a general single-evaluation rule — bind every
|
||||||
|
subexpression of a place to a temp once, which is what C's compound assignment
|
||||||
|
does — or the language says a place must be side-effect free and refuses
|
||||||
|
otherwise. The first is the real fix and it is a change to how every place
|
||||||
|
lowers, not to one macro.
|
||||||
|
|
||||||
|
** TODO A session eval reported (CFn [] ()) does not cross into dyn yet
|
||||||
|
At =sand.flan:46:20=, the =:pause= in =(when (get state :pause) (return))=,
|
||||||
|
where =state= is a =defclass= instance with a =pause= slot. =(CFn [] ())= is
|
||||||
|
the prelude's =pause='s own type, so a keyword looks to have resolved to the
|
||||||
|
function of that name. Not reproduced: the file type checks, =flan reload= of
|
||||||
|
the same form builds, and a minimal =defclass= + =get= + =return= program
|
||||||
|
compiles. So it is the session path against an installed program, and what is
|
||||||
|
missing is what that daemon had installed at the time.
|
||||||
|
|
||||||
|
** TODO A digit does not take the restart RET takes
|
||||||
|
Pressing =0= left the program stopped; RET on the same line resumed it. Both
|
||||||
|
end in =flan-cnr-take=, but the digit path (=flan-cnr-take-number=,
|
||||||
|
=flan-cnr.el:559=) scans from =point-min= for the line whose =flan-cnr-index=
|
||||||
|
matches and calls =take= inside a =save-excursion=. Not reproduced yet — needs
|
||||||
|
a non-raylib program stopped under a test daemon.
|
||||||
|
|
||||||
|
** TODO Eval in the frame, from the break loop
|
||||||
|
An expression is evaluated at a frame boundary, so it sees globals and not the
|
||||||
|
stopped frame's locals — which are the values anyone stopped there wants. Wants
|
||||||
|
SLIME's eval-in-frame: pick a frame, and the expression is checked and run with
|
||||||
|
its slots in scope. The slots are already on the frame and already readable
|
||||||
|
(=flan_dev_frame_slot=); what is missing is checking an expression against that
|
||||||
|
frame's names and types.
|
||||||
|
|
||||||
|
** TODO The stack lists prelude frames
|
||||||
|
=0: pause <prelude>:151:7= is the breakpoint the author wrote, not a step in
|
||||||
|
their program. Prelude frames want hiding by default, with a key to show them.
|
||||||
|
|
||||||
|
** TODO There is no stepper
|
||||||
|
=(pause)= stops and offers restarts, frames, locals and the inspector, but
|
||||||
|
nothing advances a form at a time. CIDER instruments a form and steps the
|
||||||
|
instrumented copy; the equivalent here is a dev-build-only instrumented
|
||||||
|
redefinition, which the cell indirection already makes deliverable. Open:
|
||||||
|
whether stepping suspends the frame loop, and what it does to a game's clock.
|
||||||
|
|
||||||
|
** TODO A NaN cast says "does not fit", which reads as too big
|
||||||
|
=runtime/flan_rt.c:1008= covers every out-of-range float with one sentence, so
|
||||||
|
=(i32 nan)= reports the =i32= bounds as if the value had overshot them. NaN and
|
||||||
|
the infinities convert to no integer at all and want saying so by name. Found
|
||||||
|
by filling a struct holding an =f32= with =(filled 0xFF)=, where every bit set
|
||||||
|
is NaN.
|
||||||
|
|
||||||
|
** TODO The break buffer prints fields, not the sentence the runtime wrote
|
||||||
=ArithError — op 4, lhs -2147483648, rhs 2147483647= where the runtime's own
|
=ArithError — op 4, lhs -2147483648, rhs 2147483647= where the runtime's own
|
||||||
sentence for that op is "this value does not fit the integer type it is cast
|
sentence is "this value does not fit the integer type it is cast to"
|
||||||
to" (=runtime/flan_rt.c:986=). The good sentences exist and go to stderr on an
|
(=runtime/flan_rt.c:986=). Worse for a dyn trap: =DynType= has no struct at all,
|
||||||
unhandled stop; the buffer renders the struct generically instead. Either put
|
so the buffer says "no struct is named DynType" while =flan_dyn.c:799= has
|
||||||
the rendered sentence on the wire, or let a condition type carry a printer.
|
written the operation, both tags and both values to stderr. The sentences exist
|
||||||
=op= being a bare number is the same gap — it is an enum spelled as =i32=.
|
and go to the daemon buffer; the break buffer wants them on the wire.
|
||||||
|
=ArithError='s =op= being a bare number is the same gap — it is an enum spelled
|
||||||
|
as =i32=.
|
||||||
|
|
||||||
** TODO A backtrace frame names the function, not the call
|
** TODO A backtrace frame names the function, not the call
|
||||||
=fninfo= (=lib/emit.ml:185=) holds one static =loc=, the =defn='s own, and
|
=fninfo= (=lib/emit.ml:185=) holds one static =loc=, the =defn='s own, and
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user