A struct's dyn view takes .field and [:k], read and assigned, and a get on it traps at its own site.

This commit is contained in:
Joseph Ferano 2026-09-26 09:32:49 +07:00
parent d519ca81dd
commit 7991e00e76
3 changed files with 28 additions and 2 deletions

View File

@ -3733,6 +3733,12 @@ flan_dyn flan_dyn_get(flan_dyn m, flan_dyn k, const uint8_t *loc,
int64_t loclen) {
class_entry *e;
if (!is_map(m)) trap2(loc, loclen, TYPE_TRAP, "get", "only a map answers it", m, k);
/* A struct's view: its field, or a trap at this site naming the fields. */
if (dyn_obj(m)->kind == OBJ_VIEW) {
const uint8_t *fty;
uint8_t *p = view_field(loc, loclen, "get", dyn_obj(m), k, &fty);
return view_read(loc, loclen, "get", dyn_obj(m), fty, p);
}
e = class_sync(dyn_obj(m));
if (e != NULL && class_slot(e, k) < 0)
trap_no_slot(loc, loclen, "get", dyn_obj(m), e, k);

View File

@ -160,6 +160,19 @@
(let [p (Point {.x 1.0 .y 2})
q (Point {.x 1.0 .y 2})]
(println (= (keep p) (keep q))))
;; .field and [:k] on a struct's view: a read is get, a set is put,
;; and the typed struct sees every write.
(let [p (Point {.x 1.0 .y 2})
m (Mix {.a 1 .b 2 .c 0.5 .d false .e [1 2 3] .f 4})
dp (keep p)
dm (keep m)]
(set (.y dp) 5)
(update (.y dp) + 10)
(set (at dp :x) 2.5)
(set (.d dm) true)
(set (at (.e dm) 1) 20)
(println (.y dp) (at dp :x) (.a dm) (.d dm) (at (.e dm) 1))
(println (.y p) (.x p) (.d m) (at (.e m) 1)))
0)
;; A value an element's width cannot hold.
(= n 1)
@ -215,4 +228,9 @@
(let [fs [(f32 0.5)]]
(set (at (keep fs) 0) 16777217)
0)
;; A field a struct does not have, through .field.
(= n 10)
(let [p (Point {.x 1.0 .y 2})]
(set (.z (keep p)) 3)
0)
:else (do (println "?") 1))))

View File

@ -5925,7 +5925,8 @@ level "1"
grid [[1 2 3] [4 5 60]]\n60\n\
points [#Point{:x 1 :y 1} #Point{:x 2 :y 20}]\n20\n\
vec [1 2 3]\n3\n6\n5\n4\n3\n\
temp #Point{:x 1.5 :y 2}\n4\n3\ntrue\n"
temp #Point{:x 1.5 :y 2}\n4\n3\ntrue\n\
15 2.5 1 true 20\n15 2.5 true 20\n"
in
let any_traps =
[ ("1", "300 does not fit a u8 element, which holds 0 to 255");
@ -5933,7 +5934,8 @@ level "1"
dyn int");
("3", "a Point has no field :z. Its fields are :x :y");
("8", "a str element is read-only through a dyn view");
("9", "16777217 has no exact f32") ]
("9", "16777217 has no exact f32");
("10", "dyn put: a Point has no field :z. Its fields are :x :y") ]
and any_stale =
[ ("4", "this view points into a local of leak-local, and that call \
has returned");