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
|
||||
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
|
||||
sentence for that op is "this value does not fit the integer type it is cast
|
||||
to" (=runtime/flan_rt.c:986=). The good sentences exist and go to stderr on an
|
||||
unhandled stop; the buffer renders the struct generically instead. Either put
|
||||
the rendered sentence on the wire, or let a condition type carry a printer.
|
||||
=op= being a bare number is the same gap — it is an enum spelled as =i32=.
|
||||
sentence is "this value does not fit the integer type it is cast to"
|
||||
(=runtime/flan_rt.c:986=). Worse for a dyn trap: =DynType= has no struct at all,
|
||||
so the buffer says "no struct is named DynType" while =flan_dyn.c:799= has
|
||||
written the operation, both tags and both values to stderr. The sentences exist
|
||||
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
|
||||
=fninfo= (=lib/emit.ml:185=) holds one static =loc=, the =defn='s own, and
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user