4ec8f90b19
Third tranche, completing the honesty-rule sweep across the remaining
contracts. Same conservative bar: cut unbacked-verification claims,
change/deletion history, and forward-intent; keep present-state design
rationale.
- 0003: drop "sanitiser-verified" — no TSan/sanitiser test exists in
the tree, so the claim asserts a verification that does not happen.
The data-race-freedom property (argued from the non-atomic-but-never-
shared hot path + atomic-relaxed shared counter) stays.
- 0008: the `Type::Con.name` hash paragraph ("the tightening shifted
the hashes ... The new pins ... re-asserts the pre-tightening hashes")
-> present-state: which fixtures carry which hash shape and which test
pins each.
- 0013: drop "the former codegen-side fallback (at ..., and the
now-deleted `synth_with_extras`) is retracted" (deletion history; the
present fact is that codegen does not re-resolve, per the boundary);
"A future refactor that loosens any one of the four breaks ..." ->
present-tense statement that the four are load-bearing and each pinned.
- 0017: drop "a real cost surfaced by the `bench_closure_chain`
regression at the operator-routing-eq-ord milestone" (history) and
"the symmetric extensions are mechanical when the first such workload
appears" (forward-intent); keep the present-state allocation cost, the
pin, and the Int-only-asymmetry rationale.
All 18 contracts now reviewed against the code. Ledger pins green;
honesty sweep clean.
73 lines
3.9 KiB
Markdown
73 lines
3.9 KiB
Markdown
# Prelude (built-in) classes
|
|
|
|
## Prelude (built-in) classes
|
|
|
|
The prelude ships the `Ordering` ADT, the `Eq` and `Ord`
|
|
[classes](0013-typeclasses.md), primitive `Eq Int/Bool/Str/Unit` and
|
|
`Ord Int/Bool/Str` instances, and the five polymorphic free-fn
|
|
helpers `ne`/`lt`/`le`/`gt`/`ge`. The primitive `Eq` / `Ord`
|
|
instance bodies carry the `(intrinsic)` marker in `examples/prelude.ail`
|
|
(the marker is the lockstep partner to the `INTERCEPTS` registry);
|
|
the codegen intercept `try_emit_primitive_instance_body` supplies
|
|
their single-instruction bodies (`icmp eq i64` for `eq__Int`,
|
|
`icmp eq i1` for `eq__Bool`, `@ail_str_eq` for `eq__Str`,
|
|
`ret i1 1` for `eq__Unit`; a three-way `icmp` ladder constructing
|
|
`LT`/`EQ`/`GT` for `compare__T`) and attaches `alwaysinline` so
|
|
the call folds to the single instruction at every use site.
|
|
|
|
The five Ord-class free helpers (`ne`/`lt`/`le`/`gt`/`ge`) have
|
|
source-level bodies that route through `eq` / `compare` plus
|
|
`match` over `Ordering` — written that way so the surface form is
|
|
LLM-natural and so user-ADT instances of `Eq`/`Ord` automatically
|
|
pick up working helpers without any per-type opt-in. At Int the
|
|
codegen intercept short-circuits this indirection: `lt__Int`,
|
|
`le__Int`, `gt__Int`, `ge__Int`, and `ne__Int` are intercept-
|
|
overridden to emit `icmp slt i64` / `sle i64` / `sgt i64` /
|
|
`sge i64` / `ne i64` directly, bypassing the `compare__Int` →
|
|
`Ordering`-ctor → `match` path. Without this short-circuit the
|
|
`Ordering` ctor allocates per call inside hot loops; the
|
|
short-circuit is pinned by
|
|
`crates/ail/tests/ord_int_intercept_ir_pin.rs`. It
|
|
is *Int-only* by deliberate asymmetry: no current bench or
|
|
example fixture exercises Ord-`lt`/`le`/`gt`/`ge` at Bool or
|
|
Str at sufficient call frequency to justify the intercept-arm
|
|
maintenance.
|
|
|
|
Float has neither `Eq` nor `Ord` instance per [Float semantics](
|
|
0005-float-semantics.md); a polymorphic helper invoked at Float fires
|
|
`NoInstance` at typecheck with a Float-aware diagnostic that names
|
|
the explicit `float_eq` / `float_lt` alternatives and
|
|
cross-references this section. The lookup machinery that turns a
|
|
`show x` call site into the right monomorphic instance is
|
|
documented in [method dispatch](0016-method-dispatch.md).
|
|
|
|
Float comparison is a separate surface: the six monomorphic prelude
|
|
fns `float_eq` / `float_ne` / `float_lt` / `float_le` / `float_gt`
|
|
/ `float_ge` each carry the type `(Float, Float) -> Bool` without
|
|
a class constraint. They lower via the same intercept machinery as
|
|
the primitive `Eq` instances (single `fcmp` instruction with the
|
|
matching predicate `oeq` / `une` / `olt` / `ole` / `ogt` / `oge`,
|
|
plus `alwaysinline`). They replace what would otherwise be a
|
|
polymorphic `==` / `<` on Float — Float gets full comparability
|
|
via explicit named fns, not via an implicit class instance.
|
|
|
|
The prelude ships `class Show a where show : (a borrow) -> Str` and
|
|
primitive `Show Int`, `Show Bool`, `Show Str`, `Show Float`
|
|
instances. Float **is** included in Show (unlike Eq/Ord) — IEEE-754
|
|
makes structural equality and total ordering semantically dubious,
|
|
but textual representation of a Float is well-defined modulo the
|
|
NaN-spelling caveat in [Float semantics](0005-float-semantics.md). Each
|
|
`Show <T>` instance body is a single-application lambda invoking the
|
|
corresponding runtime primitive (`int_to_str`, `bool_to_str`,
|
|
`str_clone`, `float_to_str`; see [Str ABI](0011-str-abi.md) for the
|
|
heap-Str primitives); no codegen intercept is required. The
|
|
polymorphic helper `print : forall a. Show a => a -> () !IO` has body
|
|
`\x -> let s = show x in do io/print_str s` (explicit let-binder for
|
|
heap-Str RC discipline per the Str carve-out in
|
|
[Str ABI](0011-str-abi.md)). The let-binder is
|
|
structurally pinned by `crates/ail/tests/print_mono_body_shape.rs`.
|
|
Routing through `print` is the path for non-`Str` primitives;
|
|
`io/print_str` is the only built-in direct-output effect-op.
|
|
|
|
Ratified by: `crates/ail/tests/show_no_instance_e2e.rs`.
|