Phase 7i: byte indexing p[i] / p[i] = v (retire peek8/poke8)

Raw byte access is now indexing, not C-style peek/poke:

  peek8(src, i)          -> src[i]        (reads a byte, widened to int)
  poke8(out, j, r)       -> out[j] = r    (narrows the int to a byte)

E_INDEX on a non-slice pointer/string lowers to a `getelementptr i8` + load/zext
(read) or trunc/store (write) — byte-identical to the old peek8/poke8, so the
migration reproduces the compiler exactly. A "byte" element type (llty i8) drives
the widen/narrow. The compiler's own byte work now reads naturally, e.g.
`is_slice_ty` is `t[0] == 91 and t[1] == 93`.

Subtlety fixed on the way: g_addr_ty (the out-param carrying the indexed element
type) must be set AFTER evaluating the index expression, since a member/index in
the index would otherwise clobber it — doing it early made a byte read load a
full pointer from a byte address and crash the self-compile.

Two reseeds: add byte-index support keeping peek8/poke8, then migrate 148 call
sites and delete the intrinsics (+ the now-dead emit_gep_i8). Vocabulary drops
peek8/poke8. Reseeded (22604 lines); C-free fixpoint holds; goldens identical;
18/18; vocab clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-08-28 02:01:59 +03:00
parent 3aaf983cf5
commit feb3a71e56
25 changed files with 3309 additions and 3388 deletions

View file

@ -40,7 +40,7 @@ fn rt_init() -> void {
rt_map = mem_alloc(96 * 64)
mem_set(rt_map, 32, 96 * 64)
rt_statusbuf = mem_alloc(96)
poke8(rt_statusbuf, 0, 0)
rt_statusbuf[0] = 0
rt_image_init()
rt_tt_init()
rt_ui_init()
@ -117,7 +117,7 @@ fn rt_glyph(x: int, y: int, ch: int, colour: int, sc: int) -> void {
let base = (c - 32) * 7
let font = rt_font()
for row in 0 .. 7 {
let bits = peek8(font, base + row) - 48
let bits = font[base + row] - 48
var b = bits
for cc in 0 .. 5 {
let on = b / 16
@ -132,12 +132,12 @@ fn rt_glyph(x: int, y: int, ch: int, colour: int, sc: int) -> void {
fn rt_text(x: int, y: int, s: str, colour: int, sc: int) -> void {
var i = 0
var cx = x
var ch = peek8(s, 0)
var ch = s[0]
while ch != 0 {
rt_glyph(cx, y, ch, colour, sc)
cx = cx + 6 * sc
i = i + 1
ch = peek8(s, i)
ch = s[i]
}
}
@ -240,19 +240,19 @@ fn rt_running() -> bool {
fn rt_put_str(buf: ptr, at: int, s: str) -> int {
var i = 0
var n = at
var ch = peek8(s, 0)
var ch = s[0]
while ch != 0 {
poke8(buf, n, ch)
buf[n] = ch
n = n + 1
i = i + 1
ch = peek8(s, i)
ch = s[i]
}
return n
}
fn rt_put_int(buf: ptr, at: int, v: int) -> int {
if v == 0 {
poke8(buf, at, 48)
buf[at] = 48
return at + 1
}
var digits = 0
@ -268,7 +268,7 @@ fn rt_put_int(buf: ptr, at: int, v: int) -> int {
for k in 1 .. p {
div = div * 10
}
poke8(buf, n, 48 + (v / div) % 10)
buf[n] = 48 + (v / div) % 10
n = n + 1
p = p - 1
}
@ -291,9 +291,9 @@ fn rt_dump_ppm(path: str) -> void {
let buf = mem_alloc(px * 3)
for i in 0 .. px {
let c = peek32(rt_fb, i)
poke8(buf, i * 3, (c / 65536) % 256)
poke8(buf, i * 3 + 1, (c / 256) % 256)
poke8(buf, i * 3 + 2, c % 256)
buf[i * 3] = (c / 65536) % 256
buf[i * 3 + 1] = (c / 256) % 256
buf[i * 3 + 2] = c % 256
}
file_write(f, buf, px * 3)
file_close(f)
@ -324,12 +324,12 @@ fn rt_map_row(y: int, s: str) -> void {
if y < 0 { return }
if y >= 64 { return }
var x = 0
var ch = peek8(s, 0)
var ch = s[0]
while ch != 0 {
if x >= 96 { return }
poke8(rt_map, y * 96 + x, ch)
rt_map[y * 96 + x] = ch
x = x + 1
ch = peek8(s, x)
ch = s[x]
}
}
@ -338,7 +338,7 @@ fn rt_tile(x: int, y: int) -> int {
if y < 0 { return 35 }
if x >= rt_mapw { return 35 }
if y >= rt_maph { return 35 }
return peek8(rt_map, y * 96 + x)
return rt_map[y * 96 + x]
}
# ---- status line ----------------------------------------------------------
@ -348,16 +348,16 @@ var rt_statusbuf: ptr = null
fn rt_status(s: str) -> void {
var i = 0
var ch = peek8(s, 0)
var ch = s[0]
while ch != 0 {
if i >= 95 { ch = 0 }
if ch != 0 {
poke8(rt_statusbuf, i, ch)
rt_statusbuf[i] = ch
i = i + 1
ch = peek8(s, i)
ch = s[i]
}
}
poke8(rt_statusbuf, i, 0)
rt_statusbuf[i] = 0
}
fn rt_status_text() -> ptr {

View file

@ -31,14 +31,14 @@ fn rt_image_init() -> void {
# ---- decoding -------------------------------------------------------------
fn png_be32(b: ptr, at: int) -> int {
return (peek8(b, at) << 24) | (peek8(b, at + 1) << 16) | (peek8(b, at + 2) << 8) | peek8(b, at + 3)
return (b[at] << 24) | (b[at + 1] << 16) | (b[at + 2] << 8) | b[at + 3]
}
fn png_tag(b: ptr, at: int, a: int, c: int, d: int, e: int) -> bool {
if peek8(b, at) != a { return false }
if peek8(b, at + 1) != c { return false }
if peek8(b, at + 2) != d { return false }
if peek8(b, at + 3) != e { return false }
if b[at] != a { return false }
if b[at + 1] != c { return false }
if b[at + 2] != d { return false }
if b[at + 3] != e { return false }
return true
}
@ -70,8 +70,8 @@ fn rt_decode_png(path: str) -> bool {
if (d == null) { return false }
let size = rt_file_len
if size < 8 { mem_free(d); return false }
if peek8(d, 0) != 137 { mem_free(d); return false }
if peek8(d, 1) != 80 { mem_free(d); return false }
if d[0] != 137 { mem_free(d); return false }
if d[1] != 80 { mem_free(d); return false }
var w = 0
var h = 0
@ -97,19 +97,19 @@ fn rt_decode_png(path: str) -> bool {
if png_tag(d, typ, 73, 72, 68, 82) { # IHDR
w = png_be32(d, body)
h = png_be32(d, body + 4)
bd = peek8(d, body + 8)
ct = peek8(d, body + 9)
bd = d[body + 8]
ct = d[body + 9]
}
if png_tag(d, typ, 80, 76, 84, 69) { # PLTE
let m = min(ln, 768)
for k in 0 .. m { poke8(plte, k, peek8(d, body + k)) }
for k in 0 .. m { plte[k] = d[body + k] }
}
if png_tag(d, typ, 116, 82, 78, 83) { # tRNS
ntrns = min(ln, 256)
for k in 0 .. ntrns { poke8(trns, k, peek8(d, body + k)) }
for k in 0 .. ntrns { trns[k] = d[body + k] }
}
if png_tag(d, typ, 73, 68, 65, 84) { # IDAT
for k in 0 .. ln { poke8(idat, idlen + k, peek8(d, body + k)) }
for k in 0 .. ln { idat[idlen + k] = d[body + k] }
idlen = idlen + ln
}
if png_tag(d, typ, 73, 69, 78, 68) { done = 1 } # IEND
@ -139,17 +139,17 @@ fn rt_decode_png(path: str) -> bool {
# reverse the per-scanline filters, in place
for y in 0 .. h {
let line = y * (stride + 1)
let ft = peek8(raw, line)
let ft = raw[line]
let cur = line + 1
let prev = cur - (stride + 1)
for x in 0 .. stride {
var a = 0
var b = 0
var c = 0
if x >= fbpp { a = peek8(raw, cur + x - fbpp) }
if y > 0 { b = peek8(raw, prev + x) }
if x >= fbpp { if y > 0 { c = peek8(raw, prev + x - fbpp) } }
var v = peek8(raw, cur + x)
if x >= fbpp { a = raw[cur + x - fbpp] }
if y > 0 { b = raw[prev + x] }
if x >= fbpp { if y > 0 { c = raw[prev + x - fbpp] } }
var v = raw[cur + x]
if ft == 1 { v = v + a }
if ft == 2 { v = v + b }
if ft == 3 { v = v + (a + b) / 2 }
@ -163,7 +163,7 @@ fn rt_decode_png(path: str) -> bool {
if pa <= pb { if pa <= pc { pick = a } }
v = v + pick
}
poke8(raw, cur + x, (v & 255))
raw[cur + x] = (v & 255)
}
}
@ -178,33 +178,33 @@ fn rt_decode_png(path: str) -> bool {
var B = 0
var A = 255
if ct == 6 {
R = peek8(raw, row + x * 4)
G = peek8(raw, row + x * 4 + 1)
B = peek8(raw, row + x * 4 + 2)
A = peek8(raw, row + x * 4 + 3)
R = raw[row + x * 4]
G = raw[row + x * 4 + 1]
B = raw[row + x * 4 + 2]
A = raw[row + x * 4 + 3]
}
if ct == 2 {
R = peek8(raw, row + x * 3)
G = peek8(raw, row + x * 3 + 1)
B = peek8(raw, row + x * 3 + 2)
R = raw[row + x * 3]
G = raw[row + x * 3 + 1]
B = raw[row + x * 3 + 2]
}
if ct == 4 {
R = peek8(raw, row + x * 2)
R = raw[row + x * 2]
G = R
B = R
A = peek8(raw, row + x * 2 + 1)
A = raw[row + x * 2 + 1]
}
if ct == 3 {
let bp = x * bd
let idx = ((peek8(raw, row + bp / 8) >> (8 - bd - bp % 8)) & maxv)
R = peek8(plte, idx * 3)
G = peek8(plte, idx * 3 + 1)
B = peek8(plte, idx * 3 + 2)
if idx < ntrns { A = peek8(trns, idx) }
let idx = ((raw[row + bp / 8] >> (8 - bd - bp % 8)) & maxv)
R = plte[idx * 3]
G = plte[idx * 3 + 1]
B = plte[idx * 3 + 2]
if idx < ntrns { A = trns[idx] }
}
if ct == 0 {
let bp = x * bd
let s = ((peek8(raw, row + bp / 8) >> (8 - bd - bp % 8)) & maxv)
let s = ((raw[row + bp / 8] >> (8 - bd - bp % 8)) & maxv)
var g = s
if bd != 8 { g = s * 255 / maxv }
R = g
@ -389,15 +389,15 @@ fn rt_sprites_load(path: str) -> void {
var len = 0
var j = start
while j < size {
let ch = peek8(d, j)
let ch = d[j]
if ch == 10 { j = size } else { len = len + 1; j = j + 1 }
}
let c0 = peek8(d, start)
let c0 = d[start]
if c0 == 112 { # 'p' — "pal <char> <rrggbb>"
let ch = peek8(d, start + 4)
let ch = d[start + 4]
var v = 0
for k in 0 .. 6 {
let hv = rt_hexval(peek8(d, start + 6 + k))
let hv = rt_hexval(d[start + 6 + k])
if hv >= 0 { v = v * 16 + hv }
}
if ch < 128 { poke32(pal, ch, ((255 << 24) | v)) }
@ -419,7 +419,7 @@ fn rt_sprites_load(path: str) -> void {
for x in 0 .. SPR_SZ {
if x < len {
poke32(spr_px, cur * SPR_SZ * SPR_SZ + row * SPR_SZ + x,
peek32(pal, (peek8(d, start + x) & 127)))
peek32(pal, (d[start + x] & 127)))
}
}
row = row + 1

View file

@ -36,7 +36,7 @@ fn z_bits(need: int) -> int {
z_err = 1
return 0
}
val = (val | (peek8(z_src, z_pos) << z_bitcnt))
val = (val | (z_src[z_pos] << z_bitcnt))
z_pos = z_pos + 1
z_bitcnt = z_bitcnt + 8
}
@ -129,13 +129,13 @@ fn z_stored(out: ptr, at: int, cap: int) -> int {
z_bitbuf = 0
z_bitcnt = 0 # stored blocks are byte-aligned
if z_pos + 4 > z_len { return -1 }
let n = peek8(z_src, z_pos) + (peek8(z_src, z_pos + 1) << 8)
let n = z_src[z_pos] + (z_src[z_pos + 1] << 8)
z_pos = z_pos + 4 # LEN then its one's complement
var w = at
for i in 0 .. n {
if z_pos >= z_len { return -1 }
if w >= cap { return -1 }
poke8(out, w, peek8(z_src, z_pos))
out[w] = z_src[z_pos]
w = w + 1
z_pos = z_pos + 1
}
@ -150,7 +150,7 @@ fn z_codes(out: ptr, at: int, cap: int, lit: ptr, dist: ptr) -> int {
if sym < 0 { return -1 }
if sym < 256 {
if w >= cap { return -1 }
poke8(out, w, sym)
out[w] = sym
w = w + 1
}
if sym > 256 {
@ -163,7 +163,7 @@ fn z_codes(out: ptr, at: int, cap: int, lit: ptr, dist: ptr) -> int {
if distance > w { return -1 }
for k in 0 .. length {
if w >= cap { return -1 }
poke8(out, w, peek8(out, w - distance))
out[w] = out[w - distance]
w = w + 1
}
}
@ -197,7 +197,7 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
# 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 — biased by '0' so it is one literal
let order = "@AB08796:5;4<3=2>1?"
for i in 0 .. ncode {
poke32(lengths, peek8(order, i) - 48, z_bits(3))
poke32(lengths, order[i] - 48, z_bits(3))
}
let clen = z_table_new(19)
z_table_build(clen, lengths, 19)
@ -270,7 +270,7 @@ fn z_inflate(src: ptr, len: int, out: ptr, cap: int) -> int {
# zlib wrapper (RFC 1950): two header bytes, then DEFLATE, then Adler-32.
fn z_uncompress(src: ptr, len: int, out: ptr, cap: int) -> int {
if len < 2 { return -1 }
let cmf = peek8(src, 0)
let cmf = src[0]
if (cmf & 15) != 8 { return -1 }
return z_inflate(ptr_add(src, 2), len - 2, out, cap)
}

View file

@ -106,7 +106,7 @@ fn rt_tt_init() -> void {
# ---- big-endian readers ---------------------------------------------------
fn tt_u16(d: ptr, at: int) -> int {
return ((peek8(d, at) << 8) | peek8(d, at + 1))
return ((d[at] << 8) | d[at + 1])
}
fn tt_i16(d: ptr, at: int) -> int {
let v = tt_u16(d, at)
@ -114,10 +114,10 @@ fn tt_i16(d: ptr, at: int) -> int {
return v
}
fn tt_u32(d: ptr, at: int) -> int {
return (peek8(d, at) << 24) | (peek8(d, at + 1) << 16) | (peek8(d, at + 2) << 8) | peek8(d, at + 3)
return (d[at] << 24) | (d[at + 1] << 16) | (d[at + 2] << 8) | d[at + 3]
}
fn tt_i8(d: ptr, at: int) -> int {
let v = peek8(d, at)
let v = d[at]
if v >= 128 { return v - 256 }
return v
}
@ -126,10 +126,10 @@ fn tt_find_table(d: ptr, base: int, a: int, b: int, c: int, e: int) -> int {
let n = tt_u16(d, base + 4)
for i in 0 .. n {
let rec = base + 12 + i * 16
if peek8(d, rec) == a {
if peek8(d, rec + 1) == b {
if peek8(d, rec + 2) == c {
if peek8(d, rec + 3) == e { return tt_u32(d, rec + 8) }
if d[rec] == a {
if d[rec + 1] == b {
if d[rec + 2] == c {
if d[rec + 3] == e { return tt_u32(d, rec + 8) }
}
}
}
@ -174,7 +174,7 @@ fn rt_font_load(path: str) -> int {
var base = 0
# a .ttc collection points at its first font
if size >= 16 {
if peek8(d, 0) == 116 { if peek8(d, 1) == 116 { if peek8(d, 2) == 99 { if peek8(d, 3) == 102 {
if d[0] == 116 { if d[1] == 116 { if d[2] == 99 { if d[3] == 102 {
base = tt_u32(d, 12)
} } } }
}
@ -256,7 +256,7 @@ fn tt_glyph_index(id: int, cp: int) -> int {
return 0
}
if fmt == 0 {
if cp < 256 { return peek8(d, s + 6 + cp) }
if cp < 256 { return d[s + 6 + cp] }
}
return 0
}
@ -313,15 +313,15 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
let flags = mem_alloc(npts + 8)
var i = 0
while i < npts {
let fl = peek8(d, p)
let fl = d[p]
p = p + 1
poke8(flags, i, fl)
flags[i] = fl
i = i + 1
if (fl & 8) != 0 { # REPEAT
var r = peek8(d, p)
var r = d[p]
p = p + 1
while r > 0 {
if i < npts { poke8(flags, i, fl); i = i + 1 }
if i < npts { flags[i] = fl; i = i + 1 }
r = r - 1
}
}
@ -331,9 +331,9 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
let ys = mem_alloc((npts + 1) * 4)
var xv = 0
for k in 0 .. npts {
let fl = peek8(flags, k)
let fl = flags[k]
if (fl & 2) != 0 {
let dxv = peek8(d, p)
let dxv = d[p]
p = p + 1
if (fl & 16) != 0 { xv = xv + dxv } else { xv = xv - dxv }
} else {
@ -343,9 +343,9 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
}
var yv = 0
for k in 0 .. npts {
let fl = peek8(flags, k)
let fl = flags[k]
if (fl & 4) != 0 {
let dyv = peek8(d, p)
let dyv = d[p]
p = p + 1
if (fl & 32) != 0 { yv = yv + dyv } else { yv = yv - dyv }
} else {
@ -360,7 +360,7 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
for k in start .. last + 1 {
let X = fx(peek32(xs, k))
let Y = fx(peek32(ys, k))
ol_pt(a * X + c * Y + dx, b * X + e * Y + dy, (peek8(flags, k) & 1))
ol_pt(a * X + c * Y + dx, b * X + e * Y + dy, (flags[k] & 1))
}
if ol_ne < 256 {
poke32(ol_ends, ol_ne, ol_n)

View file

@ -215,9 +215,9 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
if cvr > 0.0 {
let oxp = sx / TT_SS
if oxp >= 0 { if oxp < W { if oy >= 0 { if oy < H {
var v = peek8(cover, oy * W + oxp) + flr(cvr * unit)
var v = cover[oy * W + oxp] + flr(cvr * unit)
if v > 255 { v = 255 }
poke8(cover, oy * W + oxp, v)
cover[oy * W + oxp] = v
} } } }
}
}
@ -270,7 +270,7 @@ fn tt_glyph_get(font: int, cp: int, px: int) -> int {
var u8_next: int = 0 # byte index just past the codepoint last decoded
fn tt_utf8(s: str, at: int) -> int {
let c = peek8(s, at)
let c = s[at]
var extra = 0 - 1
if c < 128 { extra = 0 }
if (c >> 5) == 6 { extra = 1 }
@ -286,7 +286,7 @@ fn tt_utf8(s: str, at: int) -> int {
}
var cp = (c & (63 >> extra))
for i in 0 .. extra {
let b = peek8(s, at + 1 + i)
let b = s[at + 1 + i]
if (b & 192) != 128 {
u8_next = at + 1 + i
return 65533
@ -308,7 +308,7 @@ fn tt_blit(bmp: ptr, w: int, h: int, dx: int, dy: int, colour: int) -> void {
if py >= 0 {
if py < rt_fbh {
for x in 0 .. w {
let a = peek8(bmp, y * w + x)
let a = bmp[y * w + x]
if a != 0 {
let pxx = dx + x
if pxx >= 0 {
@ -337,7 +337,7 @@ fn rt_text_ttf(font: int, x: int, y: int, s: str, colour: int, px: int) -> void
let lineh = flr(fx(peek32(tt_asc, font) - peek32(tt_desc, font) + peek32(tt_gap, font)) * scale + 0.5)
var penx = x
var i = 0
while peek8(s, i) != 0 {
while s[i] != 0 {
let cp = tt_utf8(s, i)
i = u8_next
if cp == 10 {
@ -358,7 +358,7 @@ fn rt_text_w(font: int, s: str, px: int) -> int {
var w = 0
var best = 0
var i = 0
while peek8(s, i) != 0 {
while s[i] != 0 {
let cp = tt_utf8(s, i)
i = u8_next
if cp == 10 {

View file

@ -197,7 +197,7 @@ fn ui_tw(font: int, s: ptr, size: int) -> int {
if font < tt_n { return rt_text_w(font, s, size) }
}
var n = 0
while peek8(s, n) != 0 { n = n + 1 }
while s[n] != 0 { n = n + 1 }
return n * 6 * max(size / 8, 1)
}

View file

@ -219,16 +219,16 @@ fn rt_ui_set_text(id: int, s: str) -> void {
if id >= ui_n { return }
let base = id * 96
var i = 0
var ch = peek8(s, 0)
var ch = s[0]
while ch != 0 {
if i >= 95 { ch = 0 }
if ch != 0 {
poke8(ui_dyn, base + i, ch)
ui_dyn[base + i] = ch
i = i + 1
ch = peek8(s, i)
ch = s[i]
}
}
poke8(ui_dyn, base + i, 0)
ui_dyn[base + i] = 0
poke32(ui_hasdyn, id, 1)
}
@ -239,12 +239,12 @@ fn rt_ui_set_int(id: int, n: int) -> void {
var at = 0
var v = n
if v < 0 {
poke8(ui_dyn, base, 45)
ui_dyn[base] = 45
at = 1
v = 0 - v
}
if v == 0 {
poke8(ui_dyn, base + at, 48)
ui_dyn[base + at] = 48
at = at + 1
} else {
var digits = 0
@ -257,12 +257,12 @@ fn rt_ui_set_int(id: int, n: int) -> void {
while p > 0 {
var div = 1
for k in 1 .. p { div = div * 10 }
poke8(ui_dyn, base + at, 48 + (v / div) % 10)
ui_dyn[base + at] = 48 + (v / div) % 10
at = at + 1
p = p - 1
}
}
poke8(ui_dyn, base + at, 0)
ui_dyn[base + at] = 0
poke32(ui_hasdyn, id, 1)
}