A dyn vec or map moved into typed storage takes a char where its code point fits, and a whole float in a trap's sentence reads as 2.0.

This commit is contained in:
Joseph Ferano 2026-09-26 12:54:08 +07:00
parent f35a2b240a
commit 5d41a2d424
3 changed files with 57 additions and 12 deletions

View File

@ -994,6 +994,9 @@ static void say_render(sayer *s, flan_dyn v, int depth) {
if (d != d) snprintf(buf, sizeof buf, "nan"); if (d != d) snprintf(buf, sizeof buf, "nan");
else snprintf(buf, sizeof buf, "%g", d); else snprintf(buf, sizeof buf, "%g", d);
say_puts(s, buf); say_puts(s, buf);
/* A trap's sentence says 2.0 for a float of 2, so it cannot be read as
the int 2; inf and an exponent already say float. */
if (strspn(buf, "-0123456789") == strlen(buf)) say_puts(s, ".0");
return; return;
} }
case FLAN_DYN_TAG_TEXT: { case FLAN_DYN_TAG_TEXT: {
@ -4536,6 +4539,23 @@ static void into_put(into_site *s, const uint8_t *d, flan_dyn x, uint8_t *p) {
int64_t lo, hi; int64_t lo, hi;
if (int_range(*d, &lo, &hi)) { if (int_range(*d, &lo, &hi)) {
int64_t n; int64_t n;
/* A char goes in as its code point where it fits, as it does into a
typed parameter ([flan_dyn_need_int]): into a byte only when ASCII,
since a byte past ASCII is not that char in UTF-8. */
if (flan_dyn_tag(x) == FLAN_DYN_TAG_CHAR) {
char cs[16];
n = (int64_t)dyn_payload(x);
if (n <= ((*d == 'b' || *d == 'B') ? 127 : hi)) goto store;
char_spell((uint32_t)n, cs);
desc_spell(d, ty, sizeof ty);
if (*d == 'b' || *d == 'B')
into_trap(s, "DynRange", "%s is the char %s, which is more than one "
"byte in UTF-8, so it is not %s %s. Take its code point as "
"an i32", into_who(s), cs, an(ty), ty);
into_trap(s, "DynRange", "%s is the char %s, code point %lld, and %s %s "
"holds %lld to %lld", into_who(s), cs, (long long)n, an(ty),
ty, (long long)lo, (long long)hi);
}
if (flan_dyn_tag(x) != FLAN_DYN_TAG_INT) { if (flan_dyn_tag(x) != FLAN_DYN_TAG_INT) {
into_wanted(why, sizeof why, d); into_wanted(why, sizeof why, d);
into_wrong(s, x, why); into_wrong(s, x, why);
@ -4550,6 +4570,7 @@ static void into_put(into_site *s, const uint8_t *d, flan_dyn x, uint8_t *p) {
into_who(s), (long long)n, an(ty), ty, (long long)lo, into_who(s), (long long)n, an(ty), ty, (long long)lo,
(long long)hi); (long long)hi);
} }
store:
switch (*d) { switch (*d) {
case 'b': case 'B': { uint8_t b = (uint8_t)n; memcpy(p, &b, 1); return; } case 'b': case 'B': { uint8_t b = (uint8_t)n; memcpy(p, &b, 1); return; }
case 'h': case 'H': { uint16_t h = (uint16_t)n; memcpy(p, &h, 2); return; } case 'h': case 'H': { uint16_t h = (uint16_t)n; memcpy(p, &h, 2); return; }

View File

@ -31,6 +31,8 @@
(println (i8 (d \a)) (u8 (d \a)) (i16 (d \a)) (u16 (d \a)) (println (i8 (d \a)) (u8 (d \a)) (i16 (d \a)) (u16 (d \a))
(i32 (d \a)) (u32 (d \a)) (i64 (d \a)) (u64 (d \a))) (i32 (d \a)) (u32 (d \a)) (i64 (d \a)) (u64 (d \a)))
(println (u32 (d -1)) (u32 (the i64 -1)) (u8 (d 256)) (u8 (the i64 256))) (println (u32 (d -1)) (u32 (the i64 -1)) (u8 (d 256)) (u8 (the i64 256)))
;; into a typed array and a struct, chars by the same rule
(println (sum (d [\a \b])) (pair-sum (d {:a \a :b \日})))
(when (> (length args) 1) (when (> (length args) 1)
(let [w (at args 1)] (let [w (at args 1)]
(cond (cond
@ -44,5 +46,21 @@
(= w "u64-neg") (println (to-u64 (d -1))) (= w "u64-neg") (println (to-u64 (d -1)))
(= w "u8-char") (println (to-u8 (d \é))) (= w "u8-char") (println (to-u8 (d \é)))
(= w "u16-char") (println (to-u16 (d \😀))) (= w "u16-char") (println (to-u16 (d \😀)))
(= w "float") (println (to-i64 (d 2.0)))
(= w "elem-char") (println (bytes-sum (d [\a \é])))
(= w "field-char") (println (pair-sum (d {:a \é :b 1})))
:else (println (to-i64 (d "x"))))))) :else (println (to-i64 (d "x")))))))
0) 0)
(defn sum [xs [const i32]] i64
(let [t (the i64 0)]
(dotimes [i (length xs)] (set t (+ t (i64 (at xs i)))))
t))
(defn bytes-sum [xs [const u8]] i64
(let [t (the i64 0)]
(dotimes [i (length xs)] (set t (+ t (i64 (at xs i)))))
t))
(defstruct Pair [a u8 b i32])
(defn pair-sum [p Pair] i64 (+ (i64 (.a p)) (i64 (.b p))))

View File

@ -5456,7 +5456,7 @@ level "1"
-2147483648 2147483647 128512\n0 4294967295 128512\n\ -2147483648 2147483647 128512\n0 4294967295 128512\n\
-9223372036854775807 9223372036854775807 128512\n\ -9223372036854775807 9223372036854775807 128512\n\
0 9223372036854775807 128512\n97 97 97 97 97 97 97 97\n\ 0 9223372036854775807 128512\n97 97 97 97 97 97 97 97\n\
4294967295 4294967295 0 0\n" 4294967295 4294967295 0 0\n195 26182\n"
in in
outputs "dyn: every integer width" "programs/dyn-int-widths.flan" widths_out; outputs "dyn: every integer width" "programs/dyn-int-widths.flan" widths_out;
outputs ~opt:"-O0" "dyn: every integer width, -O0" outputs ~opt:"-O0" "dyn: every integer width, -O0"
@ -5477,24 +5477,30 @@ level "1"
wanted: %S (exit 134)\n" wanted: %S (exit 134)\n"
arg (if x86 then ", --x86" else "") text code want arg (if x86 then ", --x86" else "") text code want
end) end)
[ ("u8-256", "37:42: dyn: a u8 is wanted here, and the int 256 is \ [ ("u8-256", "39:42: dyn: a u8 is wanted here, and the int 256 is \
outside a u8's range"); outside a u8's range");
("u8-neg", "38:42: dyn: a u8 is wanted here, and the int -1 is \ ("u8-neg", "40:42: dyn: a u8 is wanted here, and the int -1 is \
outside a u8's range"); outside a u8's range");
("i8-128", "39:42: dyn: an i8 is wanted here, and the int 128 is \ ("i8-128", "41:42: dyn: an i8 is wanted here, and the int 128 is \
outside an i8's range"); outside an i8's range");
("i16-big", "40:44: dyn: an i16 is wanted here, and the int 32768"); ("i16-big", "42:44: dyn: an i16 is wanted here, and the int 32768");
("u16-big", "41:44: dyn: a u16 is wanted here, and the int 65536"); ("u16-big", "43:44: dyn: a u16 is wanted here, and the int 65536");
("i32-big", "42:44: dyn: an i32 is wanted here, and the int \ ("i32-big", "44:44: dyn: an i32 is wanted here, and the int \
2147483648"); 2147483648");
("u32-neg", "43:44: dyn: a u32 is wanted here, and the int -1 is \ ("u32-neg", "45:44: dyn: a u32 is wanted here, and the int -1 is \
outside a u32's range"); outside a u32's range");
("u64-neg", "44:44: dyn: a u64 is wanted here, and the int -1"); ("u64-neg", "46:44: dyn: a u64 is wanted here, and the int -1");
("u8-char", "45:43: dyn: a u8 is wanted here, and the char \\é is \ ("u8-char", "47:43: dyn: a u8 is wanted here, and the char \\é is \
more than one byte in UTF-8"); more than one byte in UTF-8");
("u16-char", "46:45: dyn: a u16 is wanted here, and the char \ ("u16-char", "48:45: dyn: a u16 is wanted here, and the char \
\\😀, code point 128512, is outside a u16's range"); \\😀, code point 128512, is outside a u16's range");
("x", "47:34: dyn: an i64 is wanted here, and this is a text, \ ("float", "49:42: dyn: an i64 is wanted here, and this is a \
float, 2.0.");
("elem-char", "50:49: dyn into [const u8]: element 1 is the \
char \\é, which is more than one byte in UTF-8");
("field-char", "51:49: dyn into Pair: field :a is the char \\é, \
which is more than one byte in UTF-8");
("x", "52:34: dyn: an i64 is wanted here, and this is a text, \
\"x\". An i64 takes an int or a char's code point") ]) \"x\". An i64 takes an int or a char's code point") ])
[ false; true ]; [ false; true ];
(* Print, then read: each char dyn-char-spell.flan prints — every ASCII (* Print, then read: each char dyn-char-spell.flan prints — every ASCII