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");
else snprintf(buf, sizeof buf, "%g", d);
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;
}
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;
if (int_range(*d, &lo, &hi)) {
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) {
into_wanted(why, sizeof why, d);
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,
(long long)hi);
}
store:
switch (*d) {
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; }

View File

@ -31,6 +31,8 @@
(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)))
(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)
(let [w (at args 1)]
(cond
@ -44,5 +46,21 @@
(= w "u64-neg") (println (to-u64 (d -1)))
(= w "u8-char") (println (to-u8 (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")))))))
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\
-9223372036854775807 9223372036854775807 128512\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
outputs "dyn: every integer width" "programs/dyn-int-widths.flan" widths_out;
outputs ~opt:"-O0" "dyn: every integer width, -O0"
@ -5477,24 +5477,30 @@ level "1"
wanted: %S (exit 134)\n"
arg (if x86 then ", --x86" else "") text code want
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");
("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");
("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");
("i16-big", "40: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");
("i32-big", "42:44: dyn: an i32 is wanted here, and the int \
("i16-big", "42:44: dyn: an i16 is wanted here, and the int 32768");
("u16-big", "43:44: dyn: a u16 is wanted here, and the int 65536");
("i32-big", "44:44: dyn: an i32 is wanted here, and the int \
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");
("u64-neg", "44: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 \
("u64-neg", "46:44: dyn: a u64 is wanted here, and the int -1");
("u8-char", "47:43: dyn: a u8 is wanted here, and the char \\é is \
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");
("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") ])
[ false; true ];
(* Print, then read: each char dyn-char-spell.flan prints — every ASCII