floats iter 3: JOURNAL — iteration close (typecheck + builtins)
This commit is contained in:
+101
@@ -13249,3 +13249,104 @@ milestone:
|
|||||||
- DESIGN.md §"Float semantics" subsection (A5 determinism
|
- DESIGN.md §"Float semantics" subsection (A5 determinism
|
||||||
contract) and line-2033 "supported primitive types" list
|
contract) and line-2033 "supported primitive types" list
|
||||||
update — iter 5.
|
update — iter 5.
|
||||||
|
|
||||||
|
## 2026-05-10 — Iteration Floats.3: typecheck + builtins
|
||||||
|
|
||||||
|
Widened the existing arithmetic and comparison builtins (`+`, `-`,
|
||||||
|
`*`, `/`, `!=`, `<`, `<=`, `>`, `>=`) from monomorphic
|
||||||
|
`(Int, Int) -> {Int,Bool}` to polymorphic `forall a. (a, a) -> a`
|
||||||
|
(resp. `... -> Bool`). Same shape `==` already had since iter 16e.
|
||||||
|
The `{Int, Float}` filter is enforced at codegen (iter 4); typecheck
|
||||||
|
accepts any matching pair, mirroring how `==` works today. `%` stays
|
||||||
|
monomorphic-Int (no fmod yet — `%` semantics for Float require an
|
||||||
|
explicit decision on sign-of-result and ±0/±Inf edge cases that has
|
||||||
|
not been made). The widening is type-side only; codegen lowering for
|
||||||
|
`+` etc. continues to use the monomorphic-Int `synth::builtin_binop`
|
||||||
|
table (iter 4 converts that to type-dispatched). The lockstep partner
|
||||||
|
table at `crates/ailang-codegen/src/synth.rs::builtin_ail_type` was
|
||||||
|
widened in the same commit so no codegen call site sees an
|
||||||
|
out-of-date polymorphic shape.
|
||||||
|
|
||||||
|
Stale comment caught and corrected during the iter-3.1 quality
|
||||||
|
review: the `==` install block carried "the other comparison ops
|
||||||
|
(`<`, `<=`, `>`, `>=`, `!=`) stay Int-only" since iter 16e.
|
||||||
|
Replaced with the actual current shape — and the same comment now
|
||||||
|
documents the codegen-dispatch table's Float arm that lands in
|
||||||
|
iter 4 (`Float → fcmp oeq double`), so the future-state pointer
|
||||||
|
sits next to the typecheck-side install rather than only in the
|
||||||
|
spec.
|
||||||
|
|
||||||
|
Five new Float builtins installed: `neg : forall a. (a) -> a`
|
||||||
|
(polymorphic; parallel to widened `+`), `int_to_float : (Int) ->
|
||||||
|
Float`, `float_to_int_truncate : (Float) -> Int`, `float_to_str :
|
||||||
|
(Float) -> Str`, `is_nan : (Float) -> Bool`. The polymorphic `neg`
|
||||||
|
rationale: spec section A3 calls out that the `(- 0.0 x)` desugar
|
||||||
|
is wrong for `-0.0` (returns `+0.0` per IEEE rounding), so Float
|
||||||
|
negation needs its own builtin name. Reusing the `forall a. (a) -> a`
|
||||||
|
shape lets Int negation share the symbol.
|
||||||
|
|
||||||
|
Three Float bit-pattern constants installed as bare values
|
||||||
|
(parallel to `__unreachable__` but with concrete `Type::float()`
|
||||||
|
rather than `forall a. a`): `nan`, `inf`, `neg_inf`. Reference site
|
||||||
|
is `(var nan)`, not `(app nan)`. Codegen emits `double 0x7FF8...` /
|
||||||
|
`double 0x7FF0...` / `double 0xFFF0...` at the use site in iter 4.
|
||||||
|
|
||||||
|
One new effect op installed: `io/print_float : (Float) -> Unit !IO`.
|
||||||
|
Mirrors `io/print_int|bool|str`. Codegen lowering through runtime C
|
||||||
|
glue `@ail_print_float` lands in iter 4.
|
||||||
|
|
||||||
|
Pattern-matching on Float literals is now typecheck-rejected via the
|
||||||
|
new `CheckError::FloatPatternNotAllowed` variant per spec line
|
||||||
|
723-735 recommendation (a). The surface lex / parser still ACCEPT
|
||||||
|
Float patterns (iter 2 left this open); the typecheck diagnostic
|
||||||
|
fires at the `Pattern::Lit { lit }` arm in
|
||||||
|
`crates/ailang-check/src/lib.rs`. The error message points the
|
||||||
|
LLM-author to the documented alternative — ordering operators and
|
||||||
|
`is_nan` for Float discrimination. The variant gets a parallel arm
|
||||||
|
in `CheckError::code()` returning `"float-pattern-not-allowed"` —
|
||||||
|
mechanical compile-completeness driven by the variant addition.
|
||||||
|
|
||||||
|
`ail builtins` reflects all twelve new entries (4 widened arithmetic
|
||||||
|
display strings + 5 Float fn builtins + 3 Float constants + 1
|
||||||
|
io/print_float effect op) via the refreshed `list()` table.
|
||||||
|
|
||||||
|
Per-task commits:
|
||||||
|
|
||||||
|
- `0981804` floats iter 3.1: widen +/-/*/// and !=/</<=/>/>= to polymorphic forall a
|
||||||
|
- `6890aa2` floats iter 3.1 fixup: correct stale ==-comparison comment + asymmetric Float test args + drop spec-section reference
|
||||||
|
- `60a4c68` floats iter 3.2: install neg/int_to_float/float_to_int_truncate/float_to_str/is_nan
|
||||||
|
- `fd3f74c` floats iter 3.3: install Float constants nan/inf/neg_inf + io/print_float effect op
|
||||||
|
- `d6da5c2` floats iter 3.4: typecheck rejects Pattern::Lit Float with FloatPatternNotAllowed
|
||||||
|
|
||||||
|
Process note: the Floats milestone keeps centralising the lockstep
|
||||||
|
between `crates/ailang-check/src/builtins.rs::install` and
|
||||||
|
`crates/ailang-codegen/src/synth.rs::{builtin_ail_type,
|
||||||
|
builtin_effect_op_ret}`. After iter 3 these two tables carry four
|
||||||
|
near-identical `Forall { vars: ["a"], …, body: Fn { params, ret, … } }`
|
||||||
|
constructions per crate. The two-table convention is established and
|
||||||
|
deliberate (different crates, no `ailang-core` dependency in `synth.rs`
|
||||||
|
on `ailang-check`-style helpers), but if the duplication crosses a
|
||||||
|
fifth pair of entries in iter 4 a small `ailang-core::ast::poly_a_a_to_a`
|
||||||
|
constructor starts to earn its keep. Queued as a roadmap item, not
|
||||||
|
fix-now.
|
||||||
|
|
||||||
|
Known debt deliberately deferred to later iterations of this
|
||||||
|
milestone:
|
||||||
|
|
||||||
|
- Codegen LOWERING for the widened `+`/`-`/`*`/`/` etc. — iter 4
|
||||||
|
converts the monomorphic-Int `synth::builtin_binop` table to
|
||||||
|
type-dispatched; emits `fadd double` / `fcmp olt double` / `fcmp
|
||||||
|
une double` (for `!=`!) / etc. for the Float arm.
|
||||||
|
- Codegen LOWERING for `neg` (Int → `sub i64 0, %x`, Float →
|
||||||
|
`fneg double %x`) — iter 4. The `fneg` instruction (LLVM 8+) is
|
||||||
|
needed for correct `-0.0` handling.
|
||||||
|
- Codegen LOWERING for `int_to_float` (`sitofp`),
|
||||||
|
`float_to_int_truncate` (`@llvm.fptosi.sat.i64.f64`),
|
||||||
|
`float_to_str` (runtime C glue), `is_nan` (`fcmp uno`) — iter 4.
|
||||||
|
- Codegen LOWERING for `nan`/`inf`/`neg_inf` constants (LLVM
|
||||||
|
hex-float literals at the use site) — iter 4.
|
||||||
|
- Codegen LOWERING for `io/print_float` (parallel to
|
||||||
|
`io/print_int`, runtime glue `@ail_print_float`) — iter 4.
|
||||||
|
- Prose round-trip for Float literals — iter 5.
|
||||||
|
- DESIGN.md §"Float semantics" subsection (A5 determinism contract)
|
||||||
|
and the line-2033 "supported primitive types" list update — iter 5.
|
||||||
|
|||||||
Reference in New Issue
Block a user