TODO.org records what this lane settled and the one decision it left
This commit is contained in:
parent
f142cfaadf
commit
7b843f6753
76
TODO.org
76
TODO.org
@ -73,11 +73,13 @@ is wrong where it was written rather than aborting the compile with no location.
|
||||
The prelude's own =unless= has not been converted and still answers a bare
|
||||
undefined name.
|
||||
|
||||
** TODO gensym's counter restarts in a second module
|
||||
The counter lives in the loaded module and a module is dlopened once per compiler
|
||||
process, so it is process-wide in practice — but the rounds already build more
|
||||
than one module for a program whose macros call macros. Seed it from the module's
|
||||
index.
|
||||
** DONE gensym's counter restarts in a second module
|
||||
CLOSED: [2026-09-25]
|
||||
The counter is C data in the runtime (=flan_gensym_n=), and =lib/macro.ml= writes
|
||||
the compiler's own count into the module before every macro call and reads it
|
||||
back after. It counts across every module a compiler process loads — each round,
|
||||
the program's module, and every expansion in a session. Rules out a counter per
|
||||
module, seeded or not.
|
||||
|
||||
** TODO A quasiquote inside a quasiquote is refused
|
||||
Nothing counts nesting levels — not the reader, deliberately, and not the
|
||||
@ -141,11 +143,14 @@ as words the reader will not read back. =(/ 1.0 0.0)= is the only route to an
|
||||
infinity, and the constant folder is integers only, so it cannot be a =defconst=.
|
||||
Closing it needs a reader literal or a float-capable folding pass.
|
||||
|
||||
** TODO A u64 constant above 2^63 cannot be written in decimal
|
||||
The reader reads a decimal integer literal as a signed 64-bit number; hex is read
|
||||
as a bit pattern and works. The same limit has a second face: a cast's argument is
|
||||
checked against the default type, so =(u64 2935910691)= is refused for not fitting
|
||||
in an =i32=.
|
||||
** DONE A u64 constant above 2^63 cannot be written in decimal
|
||||
CLOSED: [2026-09-25]
|
||||
A decimal between 2^63 and 2^64 is read as its bit pattern, as hex is. A cast's
|
||||
integer literal that does not fit =i32= is checked at the cast's type; one that
|
||||
fits keeps the =i32= default, so =(u32 -1)= still means what it did. It inherits
|
||||
hex's hole: a decimal above 2^63 at =i64= is accepted as a negative, and a refusal
|
||||
at a narrower type prints the negative number. Rules out a separate unsigned
|
||||
literal in =Form=, whose layout the prelude's =Form= mirrors.
|
||||
|
||||
** DONE {.row .col} binds same-named locals
|
||||
CLOSED: [2026-09-20]
|
||||
@ -790,14 +795,11 @@ program that does not type-check. Moot for anything that compiles; only the
|
||||
daemon's half-typed recompiles could feel it. A cheaper retry was tried and
|
||||
shelved because it changes which literal gets the nicer message.
|
||||
|
||||
** TODO and's last operand gets a misdirected caret
|
||||
=(println (and true true (vec-new i32)))= puts the caret on the second =true=. The
|
||||
last operand of an =and= is the then arm and the then arm is typed first, so the
|
||||
mismatch is blamed on the else arm, which carries the previous operand's location.
|
||||
The fix is preferring the arm that is not a compiler temp when deciding whom to
|
||||
blame. Three others were considered and rejected: relabelling the else arm reads
|
||||
backwards, a bool sentinel reverts the =or= fix, and inverting the condition costs
|
||||
a =not= per operand.
|
||||
** DONE and's last operand gets a misdirected caret
|
||||
CLOSED: [2026-09-25]
|
||||
Already fixed by 3672da2, which blames the arm that is not a compiler temp; the
|
||||
caret is on the last operand and =test/test_flan.ml= asserts its column. Rules
|
||||
out relabelling the else arm, a bool sentinel, and inverting the condition.
|
||||
|
||||
** TODO Signature pairing's cold-rebuild edge
|
||||
Whether a parameter vector reads as one annotated parameter or two dyn ones
|
||||
@ -841,14 +843,20 @@ Iteration is built; the remaining refusal is generics. A =defn= has to name its
|
||||
types and =(defn map-keys [m (Map K V)] (Vec K))= has no =K=. The loop is three
|
||||
lines at the call site, where =K= is known.
|
||||
|
||||
** TODO (vec-new [u8]) is refused
|
||||
The element type must be a bare symbol naming a type, so a =(Vec [u8])= can only
|
||||
be made where the context names it. The fix is letting it take a type expression —
|
||||
the same parser that already reads =[u8]= in a parameter list.
|
||||
** DONE (vec-new [u8]) is refused
|
||||
CLOSED: [2026-09-25]
|
||||
The type positions of =vec-new= and =map-new= take a type expression: brackets, or
|
||||
a parenthesised =Ptr=, =Option=, =Vec=, =Map=, =Fn= or =CFn=. Parse reads it with
|
||||
=texpr= into =Ast.TypeArg=; a bare name is still left for the checker to tell a
|
||||
type from an allocator. Rules out a type expression anywhere else in expression
|
||||
position.
|
||||
|
||||
** TODO An array literal cannot say it is [f32]
|
||||
A float literal defaults to =f64=, an array literal has no context, and a =let=
|
||||
has no annotation. Same shape as =(vec-new [u8])= and probably the same fix.
|
||||
Not the same fix: a bracket literal has no argument to put a type in. Decision:
|
||||
how a literal names its element type — a spelling of its own, or a =let=
|
||||
annotation.
|
||||
|
||||
** TODO A let binding takes no type annotation
|
||||
Everything under the surface is there — the binding carries a type slot and the
|
||||
@ -1808,12 +1816,12 @@ 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.
|
||||
** DONE A NaN cast says "does not fit", which reads as too big
|
||||
CLOSED: [2026-09-25]
|
||||
Two more =ArithError= codes: 5 for a cast of NaN and 6 for a cast of an infinity,
|
||||
each with its own sentence. Both backends choose the code on the cold path, so the
|
||||
guard is still two compares. =lhs= and =rhs= still carry the range. Rules out
|
||||
carrying the float value in the condition.
|
||||
|
||||
** TODO The break buffer prints fields, not the sentence the runtime wrote
|
||||
=ArithError — op 4, lhs -2147483648, rhs 2147483647= where the runtime's own
|
||||
@ -1837,12 +1845,12 @@ It prints the source line and carets for the stop (=flan-cnr.el:197=) and lists
|
||||
frames, but no key opens the file at that line. Wants RET-on-a-frame, or =M-.=,
|
||||
and =next-error= over the frame list.
|
||||
|
||||
** TODO loop's bindings should be sequential, like let's
|
||||
=check_loop= (=lib/check.ml:4741=) checks every initialiser before binding any,
|
||||
so =(loop [curr-r r next-r (inc curr-r)] ...)= cannot see =curr-r= and the
|
||||
refusal reads as an unknown name. Every binding form is sequential — there is
|
||||
no =let*= here and there is not going to be one. Check the other binding forms
|
||||
for the same gap while fixing it.
|
||||
** DONE loop's bindings should be sequential, like let's
|
||||
CLOSED: [2026-09-25]
|
||||
=check_loop= binds each name before checking the next initialiser; =recur= still
|
||||
rebinds all at once. No other form had the gap: =let= was already sequential,
|
||||
=dotimes= binds one name, and =fn=, =defn=, =match= and the handler and restart
|
||||
clauses bind parameters with no initialisers.
|
||||
|
||||
** TODO C-c C-c reports one error, not every error in the form
|
||||
Whole-file paths use =Check.program_all= and report every bad declaration. The
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user