From 4ccf1f25c1def58dd89035f0663e67f9ea5a712c Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 15:14:02 +0200 Subject: [PATCH] =?UTF-8?q?floats=20iter=202:=20JOURNAL=20=E2=80=94=20iter?= =?UTF-8?q?ation=20close=20(surface=20layer)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/JOURNAL.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index 08169dc..bdb8c92 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -13172,3 +13172,80 @@ milestone: - DESIGN.md §"Float semantics" subsection (A5 determinism contract) and line-2033 "supported primitive types" list update — iter 5. + +## 2026-05-10 — Iteration Floats.2: surface layer + +Lexer recognises Float literals in form +`.(e[+-]?)?` and `e[+-]?` +per spec A2; bare leading/trailing dots, missing fraction-after- +dot, and missing/sign-only exponents reject with +`LexError::InvalidFloat { literal, start }`. Hex floats are +naturally rejected by `f64::from_str` and by the digit-lead caller +arm. The new private `looks_like_float` helper enforces the spec +grammar before delegating the bit-pattern conversion to +`f64::from_str` + `f64::to_bits`. Leading-dot tokens like `.5` +fall through the digit-lead rule (first byte not a digit) and +classify as `Tok::Ident(".5")` — the lexer does not reject them; +downstream stages produce the diagnostic. The 11 new lex tests +pin both the positive grammar (`1.5`, `1.5e3`, `1e10`, `-1.5`, +signed zero, uppercase `E`) and the rejection set (trailing dot, +missing fraction-before-exp, empty exp, sign-only exp, double +dot, leading dot routes to ident). + +The new `Tok::Float(u64)` is wired through the parser at two +sites — `parse_term` (atom literal position) and `parse_pat_lit` +(inside `(pat-lit ...)`). The parser ACCEPTS Float in pattern +position even though pattern-matching on Float is semantically +dubious (per spec line 723-735). Typecheck-level rejection is +iter 3's job; the parser-side diagnostic stays a generic "literal +form" error widened to mention float. `tok_label` exhaustiveness +forced the wiring on the same iteration the variant landed — +that's the same enforcement-via-exhaustive-match pattern iter 1 +exercised on the AST `Literal` enum. + +The two `unimplemented!("Floats milestone iter 2: surface print")` +arms left by iter 1 in `print.rs` are gone. The new +`write_float_lit` helper formats via `f64::to_string` (Grisu3 +shortest round-trippable) and appends `.0` if the rendered form +contains neither `.` nor `e`/`E` — preserving the +`lex(print(L)) == L` round-trip property pinned by a new +regression test over six representative bit patterns (`1.5`, +`0.0`, `-0.0`, `10.0`, `-0.375`, `1e10`). Non-finite bits panic; +surface lex cannot produce them, so the only path that would feed +NaN/Inf to the printer is a Form-A direct construction — and the +printer is not a Form-A escape hatch. + +Process note from this iteration: the original plan's Step 11 +caveat ("`cargo test -p ailang-surface --lib` bypasses parse.rs") +was technically incorrect — `--lib` does compile the whole +library. The implementer caught this and routed Task 1's GREEN +verification through Task 2 instead, where `tok_label` +exhaustiveness gets restored and the lex tests can finally run. +The intent (commit Task 1 with parse.rs broken at exactly one +site, fix in Task 2) was unambiguous and was followed; the +imprecise note in the plan template is queued as a one-line +correction the next plan should not repeat. + +Per-task commits: + +- `d0c9133` floats iter 2.1: Tok::Float + LexError::InvalidFloat + spec-A2 grammar validator +- `f960e39` floats iter 2.1 fixup: drop task-tags + refresh stale prose + uppercase-E + leading-dot tests +- `f62bff0` floats iter 2.2: parser accepts Tok::Float in term and pat-lit positions +- `c619697` floats iter 2.3: surface print emits shortest round-trippable decimal with .0 fallback + +Known debt deliberately deferred to later iterations of this +milestone: + +- Typecheck rejection of `Pattern::Lit { lit: Literal::Float + { .. } }` per spec line 723-735 recommendation (a). The parser + accepts Float patterns; iter 3 surfaces the type error. +- Typecheck widening of `+`/`-`/`*`/`/`/`<`/`<=`/`>`/`>=` from + monomorphic Int to polymorphic-`{Int, Float}` — iter 3. +- Codegen Float lowering paths + (`fadd`/`fsub`/`fmul`/`fdiv`, `fcmp o*`/`une`, `sitofp`, + `@llvm.fptosi.sat.i64.f64`, `fcmp uno`, hex-float constants) — + iter 4. +- Prose round-trip for Float literals — iter 5. +- DESIGN.md §"Float semantics" subsection (A5 determinism + contract) and line-2033 "supported primitive types" list + update — iter 5.