The direction a container-fixed binding admits, pinned
A narrower scalar at a $t a slice already fixed widens into the fixed type — the same cast a monomorphic parameter applies — where the old rule refused both directions. One accepts pin, one runtime line in int-generic.flan, and the web page's predicate table catches up: five predicates, integer? at the head, and the entailment chain grown one link.
This commit is contained in:
parent
f71cc40bb5
commit
cdda829835
@ -101,4 +101,12 @@
|
|||||||
;; A literal beside a wider variable joins too: 4 arrives as an i32 and the
|
;; A literal beside a wider variable joins too: 4 arrives as an i32 and the
|
||||||
;; copy is i64's.
|
;; copy is i64's.
|
||||||
(let [w (i64 38)]
|
(let [w (i64 38)]
|
||||||
(println (tri w 3 1))))
|
(println (tri w 3 1)))
|
||||||
|
;; And the one direction a container-bound variable does admit: the slice
|
||||||
|
;; fixed $t at i32 exactly, and a narrower scalar widens *into* that — the
|
||||||
|
;; same conversion a monomorphic i32 parameter would apply. (The reverse,
|
||||||
|
;; an i64 scalar against this slice, stays refused; the checker pins it.)
|
||||||
|
(let [ns [5 3 9 1]]
|
||||||
|
(match (index-of (slice ns 0 4) (i16 9))
|
||||||
|
(Some i) (println i)
|
||||||
|
_ (println -1))))
|
||||||
|
|||||||
@ -2652,12 +2652,14 @@ let () =
|
|||||||
spells. Then the integer?-only operations at several widths, and last
|
spells. Then the integer?-only operations at several widths, and last
|
||||||
the join family: [true true], [6 6] and [42] are mixed widths at one
|
the join family: [true true], [6 6] and [42] are mixed widths at one
|
||||||
$t answering identically in both argument orders, from one copy at
|
$t answering identically in both argument orders, from one copy at
|
||||||
the wider type (FIX.org 2026-09-20). *)
|
the wider type (FIX.org 2026-09-20). The closing [2] is an i16 scalar
|
||||||
|
widening into the i32 a slice fixed index-of's $t at — the one
|
||||||
|
direction a container-bound variable admits. *)
|
||||||
let int_generic_out =
|
let int_generic_out =
|
||||||
"7\n7\n7\n7\n7\n7\n-2147483648\n-9223372036854775808\n\
|
"7\n7\n7\n7\n7\n7\n-2147483648\n-9223372036854775808\n\
|
||||||
0\n0\n1.5\n2.5\n\
|
0\n0\n1.5\n2.5\n\
|
||||||
7\n15\n31\ntrue\nfalse\ntrue\n240\n9\n5\n-2\n301\n301\n\
|
7\n15\n31\ntrue\nfalse\ntrue\n240\n9\n5\n-2\n301\n301\n\
|
||||||
true\ntrue\n6\n6\n42\n"
|
true\ntrue\n6\n6\n42\n2\n"
|
||||||
in
|
in
|
||||||
outputs "integer? and the collapsed abs" "programs/int-generic.flan"
|
outputs "integer? and the collapsed abs" "programs/int-generic.flan"
|
||||||
int_generic_out;
|
int_generic_out;
|
||||||
|
|||||||
@ -5030,6 +5030,14 @@ let () =
|
|||||||
"(defn main [] () (let [ns [5 3 9 1]] \
|
"(defn main [] () (let [ns [5 3 9 1]] \
|
||||||
(match (index-of (slice ns 0 4) (i64 9)) \
|
(match (index-of (slice ns 0 4) (i64 9)) \
|
||||||
(Some i) (println i) _ (println -1))))";
|
(Some i) (println i) _ (println -1))))";
|
||||||
|
(* The one direction a container-fixed binding does admit, and it is new
|
||||||
|
with the join: a *narrower* scalar widens into the type the container
|
||||||
|
fixed, through the same cast a monomorphic i32 parameter applies. This
|
||||||
|
used to refuse with the same both-ways sentence as everything else. *)
|
||||||
|
accepts "a narrower scalar widens into a container-fixed binding"
|
||||||
|
"(defn main [] () (let [ns [5 3 9 1]] \
|
||||||
|
(match (index-of (slice ns 0 4) (i16 9)) \
|
||||||
|
(Some i) (println i) _ (println -1))))";
|
||||||
(* The written conversion is what the message asks for, and it is accepted:
|
(* The written conversion is what the message asks for, and it is accepted:
|
||||||
the refusal is about the *implicit* step, not about reaching i64. *)
|
the refusal is about the *implicit* step, not about reaching i64. *)
|
||||||
accepts "the written conversion is accepted"
|
accepts "the written conversion is accepted"
|
||||||
|
|||||||
@ -927,11 +927,12 @@ $t)} at the head of the body, or take the operation as a parameter — a
|
|||||||
<p>What makes that liveable is a <code>where</code> clause, written as a Clojure-style
|
<p>What makes that liveable is a <code>where</code> clause, written as a Clojure-style
|
||||||
map at the head of the body — <code>{:where (ordered? $t)}</code>, or a vector when
|
map at the head of the body — <code>{:where (ordered? $t)}</code>, or a vector when
|
||||||
there is more than one: <code>{:where [(ordered? $t) (hashable? $u)]}</code>. There
|
there is more than one: <code>{:where [(ordered? $t) (hashable? $u)]}</code>. There
|
||||||
are four predicates, and each gates builtins the compiler already has:</p>
|
are five predicates, and each gates builtins the compiler already has:</p>
|
||||||
|
|
||||||
<div class="scroll">
|
<div class="scroll">
|
||||||
<table>
|
<table>
|
||||||
<tr><th>Predicate</th><th>What it admits</th></tr>
|
<tr><th>Predicate</th><th>What it admits</th></tr>
|
||||||
|
<tr><td><code>integer?</code></td><td><code>bit-and</code> <code>bit-or</code> <code>bit-xor</code> <code><<</code> <code>>></code> — every integer type, no float</td></tr>
|
||||||
<tr><td><code>numeric?</code></td><td><code>+</code> <code>-</code> <code>*</code> <code>/</code> <code>%</code>, and a cast <code>(t x)</code></td></tr>
|
<tr><td><code>numeric?</code></td><td><code>+</code> <code>-</code> <code>*</code> <code>/</code> <code>%</code>, and a cast <code>(t x)</code></td></tr>
|
||||||
<tr><td><code>ordered?</code></td><td><code><</code> <code><=</code> <code>></code> <code>>=</code> <code>min</code> <code>max</code></td></tr>
|
<tr><td><code>ordered?</code></td><td><code><</code> <code><=</code> <code>></code> <code>>=</code> <code>min</code> <code>max</code></td></tr>
|
||||||
<tr><td><code>equal?</code></td><td><code>=</code> and <code>!=</code></td></tr>
|
<tr><td><code>equal?</code></td><td><code>=</code> and <code>!=</code></td></tr>
|
||||||
@ -940,9 +941,12 @@ are four predicates, and each gates builtins the compiler already has:</p>
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>They entail each other in one direction, so one clause usually does:
|
<p>They entail each other in one direction, so one clause usually does:
|
||||||
<code>numeric?</code> gives <code>ordered?</code>, and <code>ordered?</code> gives
|
<code>integer?</code> gives <code>numeric?</code>, <code>numeric?</code> gives
|
||||||
<code>equal?</code>. A <code>sort</code> that compares its elements declares
|
<code>ordered?</code>, and <code>ordered?</code> gives <code>equal?</code>. A
|
||||||
<code>ordered?</code> and nothing else.</p>
|
<code>sort</code> that compares its elements declares <code>ordered?</code> and
|
||||||
|
nothing else, and the prelude's <code>abs</code> declares <code>integer?</code>
|
||||||
|
alone — the bound is what keeps its integer body away from the floats, whose
|
||||||
|
<code>abs-f32</code>/<code>abs-f64</code> are libm's sign-bit clear.</p>
|
||||||
|
|
||||||
<p><strong>Every value copies.</strong> There used to be a fifth predicate,
|
<p><strong>Every value copies.</strong> There used to be a fifth predicate,
|
||||||
<code>copyable?</code>, gating a second read of a move-only variable; the move
|
<code>copyable?</code>, gating a second read of a move-only variable; the move
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user