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
|
The prelude's own =unless= has not been converted and still answers a bare
|
||||||
undefined name.
|
undefined name.
|
||||||
|
|
||||||
** TODO gensym's counter restarts in a second module
|
** DONE gensym's counter restarts in a second module
|
||||||
The counter lives in the loaded module and a module is dlopened once per compiler
|
CLOSED: [2026-09-25]
|
||||||
process, so it is process-wide in practice — but the rounds already build more
|
The counter is C data in the runtime (=flan_gensym_n=), and =lib/macro.ml= writes
|
||||||
than one module for a program whose macros call macros. Seed it from the module's
|
the compiler's own count into the module before every macro call and reads it
|
||||||
index.
|
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
|
** TODO A quasiquote inside a quasiquote is refused
|
||||||
Nothing counts nesting levels — not the reader, deliberately, and not the
|
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=.
|
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.
|
Closing it needs a reader literal or a float-capable folding pass.
|
||||||
|
|
||||||
** TODO A u64 constant above 2^63 cannot be written in decimal
|
** DONE 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
|
CLOSED: [2026-09-25]
|
||||||
as a bit pattern and works. The same limit has a second face: a cast's argument is
|
A decimal between 2^63 and 2^64 is read as its bit pattern, as hex is. A cast's
|
||||||
checked against the default type, so =(u64 2935910691)= is refused for not fitting
|
integer literal that does not fit =i32= is checked at the cast's type; one that
|
||||||
in an =i32=.
|
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
|
** DONE {.row .col} binds same-named locals
|
||||||
CLOSED: [2026-09-20]
|
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
|
daemon's half-typed recompiles could feel it. A cheaper retry was tried and
|
||||||
shelved because it changes which literal gets the nicer message.
|
shelved because it changes which literal gets the nicer message.
|
||||||
|
|
||||||
** TODO and's last operand gets a misdirected caret
|
** DONE and's last operand gets a misdirected caret
|
||||||
=(println (and true true (vec-new i32)))= puts the caret on the second =true=. The
|
CLOSED: [2026-09-25]
|
||||||
last operand of an =and= is the then arm and the then arm is typed first, so the
|
Already fixed by 3672da2, which blames the arm that is not a compiler temp; the
|
||||||
mismatch is blamed on the else arm, which carries the previous operand's location.
|
caret is on the last operand and =test/test_flan.ml= asserts its column. Rules
|
||||||
The fix is preferring the arm that is not a compiler temp when deciding whom to
|
out relabelling the else arm, a bool sentinel, and inverting the condition.
|
||||||
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.
|
|
||||||
|
|
||||||
** TODO Signature pairing's cold-rebuild edge
|
** TODO Signature pairing's cold-rebuild edge
|
||||||
Whether a parameter vector reads as one annotated parameter or two dyn ones
|
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
|
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.
|
lines at the call site, where =K= is known.
|
||||||
|
|
||||||
** TODO (vec-new [u8]) is refused
|
** DONE (vec-new [u8]) is refused
|
||||||
The element type must be a bare symbol naming a type, so a =(Vec [u8])= can only
|
CLOSED: [2026-09-25]
|
||||||
be made where the context names it. The fix is letting it take a type expression —
|
The type positions of =vec-new= and =map-new= take a type expression: brackets, or
|
||||||
the same parser that already reads =[u8]= in a parameter list.
|
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]
|
** TODO An array literal cannot say it is [f32]
|
||||||
A float literal defaults to =f64=, an array literal has no context, and a =let=
|
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.
|
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
|
** TODO A let binding takes no type annotation
|
||||||
Everything under the surface is there — the binding carries a type slot and the
|
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:
|
redefinition, which the cell indirection already makes deliverable. Open:
|
||||||
whether stepping suspends the frame loop, and what it does to a game's clock.
|
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
|
** DONE 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
|
CLOSED: [2026-09-25]
|
||||||
=(i32 nan)= reports the =i32= bounds as if the value had overshot them. NaN and
|
Two more =ArithError= codes: 5 for a cast of NaN and 6 for a cast of an infinity,
|
||||||
the infinities convert to no integer at all and want saying so by name. Found
|
each with its own sentence. Both backends choose the code on the cold path, so the
|
||||||
by filling a struct holding an =f32= with =(filled 0xFF)=, where every bit set
|
guard is still two compares. =lhs= and =rhs= still carry the range. Rules out
|
||||||
is NaN.
|
carrying the float value in the condition.
|
||||||
|
|
||||||
** TODO The break buffer prints fields, not the sentence the runtime wrote
|
** 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
|
||||||
@ -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-.=,
|
frames, but no key opens the file at that line. Wants RET-on-a-frame, or =M-.=,
|
||||||
and =next-error= over the frame list.
|
and =next-error= over the frame list.
|
||||||
|
|
||||||
** TODO loop's bindings should be sequential, like let's
|
** DONE loop's bindings should be sequential, like let's
|
||||||
=check_loop= (=lib/check.ml:4741=) checks every initialiser before binding any,
|
CLOSED: [2026-09-25]
|
||||||
so =(loop [curr-r r next-r (inc curr-r)] ...)= cannot see =curr-r= and the
|
=check_loop= binds each name before checking the next initialiser; =recur= still
|
||||||
refusal reads as an unknown name. Every binding form is sequential — there is
|
rebinds all at once. No other form had the gap: =let= was already sequential,
|
||||||
no =let*= here and there is not going to be one. Check the other binding forms
|
=dotimes= binds one name, and =fn=, =defn=, =match= and the handler and restart
|
||||||
for the same gap while fixing it.
|
clauses bind parameters with no initialisers.
|
||||||
|
|
||||||
** TODO C-c C-c reports one error, not every error in the form
|
** 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
|
Whole-file paths use =Check.program_all= and report every bad declaration. The
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user