Merge Phase 7k: bytes/words allocators

This commit is contained in:
Orkun ÇAKILKAYA 2026-08-28 02:26:15 +03:00
commit ae65acde33
22 changed files with 3118 additions and 3069 deletions

View file

@ -148,6 +148,9 @@ See `examples/menu.ludic` for a complete title screen.
| `byte` | pointer to bytes — `p[i]` reads/writes one byte | `ptr` |
| `words` | pointer to 32-bit words — `w[i]` reads/writes an `int` | `ptr` |
Allocate raw buffers with `bytes(n)` (n bytes) or `words(n)` (n 32-bit words);
both return a pointer you index with `buf[i]`.
Numeric literals: `42` and `0x1affff` are `int`; a literal with a decimal
point (`1.5`) is `fixed`. Arithmetic on two `fixed` values lowers to
`fxmul`/`fxdiv`; mixing `int` and `fixed` promotes the `int`. Convert with

View file

@ -34,12 +34,12 @@ fn rt_font() -> str {
}
fn rt_init() -> void {
rt_fb = mem_alloc(320 * 240 * 4)
rt_regs = mem_alloc(64 * 4)
rt_fb = words(320 * 240)
rt_regs = words(64)
mem_set(rt_regs, 0, 64 * 4)
rt_map = mem_alloc(96 * 64)
rt_map = bytes(96 * 64)
mem_set(rt_map, 32, 96 * 64)
rt_statusbuf = mem_alloc(96)
rt_statusbuf = bytes(96)
rt_statusbuf[0] = 0
rt_image_init()
rt_tt_init()
@ -279,7 +279,7 @@ fn rt_dump_ppm(path: str) -> void {
let f = file_open(path, "wb")
if (f == null) { return }
let hdr = mem_alloc(64)
let hdr = bytes(64)
var n = rt_put_str(hdr, 0, "P6\n")
n = rt_put_int(hdr, n, rt_fbw)
n = rt_put_str(hdr, n, " ")
@ -288,7 +288,7 @@ fn rt_dump_ppm(path: str) -> void {
file_write(f, hdr, n)
let px = rt_fbw * rt_fbh
let buf = mem_alloc(px * 3)
let buf = bytes(px * 3)
for i in 0 .. px {
let c = rt_fb[i]
buf[i * 3] = (c / 65536) % 256
@ -369,7 +369,7 @@ fn rt_status_text() -> ptr {
# only it knows their shape. Everything below belongs to the runtime, so the
# runtime writes it — same order both ways.
fn rt_save_state(f: ptr) -> void {
let w: words = mem_alloc(16)
let w: words = bytes(16)
w[0] = rt_rng
w[1] = rt_mapw
w[2] = rt_maph
@ -382,7 +382,7 @@ fn rt_save_state(f: ptr) -> void {
}
fn rt_load_state(f: ptr) -> void {
let w: words = mem_alloc(16)
let w: words = bytes(16)
file_read(f, w, 16)
rt_rng = w[0]
rt_mapw = w[1]

View file

@ -22,10 +22,10 @@ var spr_px: words = null # SPR_MAX * 16 * 16 RGBA pixels, one block
var spr_n: int = 0
fn rt_image_init() -> void {
img_px = mem_alloc(IMG_MAX * 8)
img_w = mem_alloc(IMG_MAX * 4)
img_h = mem_alloc(IMG_MAX * 4)
spr_px = mem_alloc(SPR_MAX * SPR_SZ * SPR_SZ * 4)
img_px = bytes(IMG_MAX * 8)
img_w = words(IMG_MAX)
img_h = words(IMG_MAX)
spr_px = words(SPR_MAX * SPR_SZ * SPR_SZ)
mem_set(spr_px, 0, SPR_MAX * SPR_SZ * SPR_SZ * 4)
}
@ -49,7 +49,7 @@ fn rt_read_file(path: str) -> ptr {
let n = file_tell(f)
file_seek(f, 0, 0)
if n <= 0 { file_close(f); return null }
let buf = mem_alloc(n + 8)
let buf = bytes(n + 8)
file_read(f, buf, n)
file_close(f)
rt_file_len = n
@ -77,10 +77,10 @@ fn rt_decode_png(path: str) -> bool {
var h = 0
var bd = 0
var ct = 0
let plte = mem_alloc(768)
let trns = mem_alloc(256)
let plte = bytes(768)
let trns = bytes(256)
var ntrns = 0
let idat = mem_alloc(size)
let idat = bytes(size)
var idlen = 0
var i = 8
var done = 0
@ -130,7 +130,7 @@ fn rt_decode_png(path: str) -> bool {
if fbpp < 1 { fbpp = 1 }
let stride = (w * bppbits + 7) / 8
let rawlen = h * (stride + 1)
let raw = mem_alloc(rawlen + 8)
let raw = bytes(rawlen + 8)
if z_uncompress(idat, idlen, raw, rawlen) < 0 {
mem_free(d); mem_free(raw); mem_free(idat)
return false
@ -168,7 +168,7 @@ fn rt_decode_png(path: str) -> bool {
}
# expand to 0xAARRGGBB
let out: words = mem_alloc(w * h * 4)
let out: words = words(w * h)
let maxv = (1 << bd) - 1
for y in 0 .. h {
let row = y * (stride + 1) + 1
@ -379,7 +379,7 @@ fn rt_sprites_load(path: str) -> void {
let d = rt_read_file(path)
if (d == null) { spr_n = 0; return }
let size = rt_file_len
let pal: words = mem_alloc(128 * 4)
let pal: words = words(128)
mem_set(pal, 0, 128 * 4)
var cur = 0 - 1
var row = 0

View file

@ -49,7 +49,7 @@ fn z_bits(need: int) -> int {
# A table is a single buffer: 16 length-counts followed by the symbols in
# canonical order. One allocation, no structs.
fn z_table_new(nsym: int) -> ptr {
return mem_alloc((16 + nsym) * 4)
return words((16 + nsym))
}
# lengths[i] = code length of symbol i (0 = symbol unused)
@ -63,7 +63,7 @@ fn z_table_build(table: words, lengths: words, n: int) -> void {
}
table[0] = 0 # length 0 means "not present"
# offset of each length's first symbol
let offs: words = mem_alloc(16 * 4)
let offs: words = words(16)
offs[1] = 0
for l in 1 .. 15 {
offs[l + 1] = offs[l] + table[l]
@ -173,7 +173,7 @@ fn z_codes(out: ptr, at: int, cap: int, lit: ptr, dist: ptr) -> int {
}
fn z_fixed_tables(lit: ptr, dist: ptr) -> void {
let lengths: words = mem_alloc(288 * 4)
let lengths: words = words(288)
for i in 0 .. 144 { lengths[i] = 8 }
for i in 144 .. 256 { lengths[i] = 9 }
for i in 256 .. 280 { lengths[i] = 7 }
@ -191,7 +191,7 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
if nlen > 286 { return 0 }
if ndist > 30 { return 0 }
let lengths: words = mem_alloc(320 * 4)
let lengths: words = words(320)
for i in 0 .. 19 { lengths[i] = 0 }
# the code-length alphabet is transmitted in this fixed permutation
# 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
@ -230,7 +230,7 @@ fn z_dynamic_tables(lit: ptr, dist: ptr) -> int {
}
z_table_build(lit, lengths, nlen)
# the distance lengths follow the literal ones in the same buffer
let dl: words = mem_alloc(32 * 4)
let dl: words = words(32)
for i in 0 .. ndist { dl[i] = lengths[nlen + i] }
z_table_build(dist, dl, ndist)
mem_free(dl)

View file

@ -64,43 +64,43 @@ var gc_adv: words = null
var gc_bmp: ptr = null
fn rt_tt_init() -> void {
tt_data = mem_alloc(TT_MAX * 8)
tt_size = mem_alloc(TT_MAX * 4)
tt_upem = mem_alloc(TT_MAX * 4)
tt_nglyf = mem_alloc(TT_MAX * 4)
tt_locfm = mem_alloc(TT_MAX * 4)
tt_nhm = mem_alloc(TT_MAX * 4)
tt_asc = mem_alloc(TT_MAX * 4)
tt_desc = mem_alloc(TT_MAX * 4)
tt_gap = mem_alloc(TT_MAX * 4)
tt_glyf = mem_alloc(TT_MAX * 4)
tt_loca = mem_alloc(TT_MAX * 4)
tt_hmtx = mem_alloc(TT_MAX * 4)
tt_cmap = mem_alloc(TT_MAX * 4)
tt_cfmt = mem_alloc(TT_MAX * 4)
tt_data = bytes(TT_MAX * 8)
tt_size = words(TT_MAX)
tt_upem = words(TT_MAX)
tt_nglyf = words(TT_MAX)
tt_locfm = words(TT_MAX)
tt_nhm = words(TT_MAX)
tt_asc = words(TT_MAX)
tt_desc = words(TT_MAX)
tt_gap = words(TT_MAX)
tt_glyf = words(TT_MAX)
tt_loca = words(TT_MAX)
tt_hmtx = words(TT_MAX)
tt_cmap = words(TT_MAX)
tt_cfmt = words(TT_MAX)
ol_x = mem_alloc(TT_PTS * 4)
ol_y = mem_alloc(TT_PTS * 4)
ol_on = mem_alloc(TT_PTS * 4)
ol_ends = mem_alloc(256 * 4)
ol_x = words(TT_PTS)
ol_y = words(TT_PTS)
ol_on = words(TT_PTS)
ol_ends = words(256)
ed_x0 = mem_alloc(TT_EDGES * 4)
ed_y0 = mem_alloc(TT_EDGES * 4)
ed_x1 = mem_alloc(TT_EDGES * 4)
ed_y1 = mem_alloc(TT_EDGES * 4)
sc_x = mem_alloc(TT_EDGES * 4)
sc_d = mem_alloc(TT_EDGES * 4)
ed_x0 = words(TT_EDGES)
ed_y0 = words(TT_EDGES)
ed_x1 = words(TT_EDGES)
ed_y1 = words(TT_EDGES)
sc_x = words(TT_EDGES)
sc_d = words(TT_EDGES)
gc_used = mem_alloc(TT_GC * 4)
gc_font = mem_alloc(TT_GC * 4)
gc_cp = mem_alloc(TT_GC * 4)
gc_px = mem_alloc(TT_GC * 4)
gc_w = mem_alloc(TT_GC * 4)
gc_h = mem_alloc(TT_GC * 4)
gc_ox = mem_alloc(TT_GC * 4)
gc_oy = mem_alloc(TT_GC * 4)
gc_adv = mem_alloc(TT_GC * 4)
gc_bmp = mem_alloc(TT_GC * 8)
gc_used = words(TT_GC)
gc_font = words(TT_GC)
gc_cp = words(TT_GC)
gc_px = words(TT_GC)
gc_w = words(TT_GC)
gc_h = words(TT_GC)
gc_ox = words(TT_GC)
gc_oy = words(TT_GC)
gc_adv = words(TT_GC)
gc_bmp = bytes(TT_GC * 8)
mem_set(gc_used, 0, TT_GC * 4)
}
@ -310,7 +310,7 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
var p = endpts + nc * 2
p = p + 2 + tt_u16(d, p) # skip instructions
let flags = mem_alloc(npts + 8)
let flags = bytes(npts + 8)
var i = 0
while i < npts {
let fl = d[p]
@ -327,8 +327,8 @@ fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx
}
}
let xs: words = mem_alloc((npts + 1) * 4)
let ys: words = mem_alloc((npts + 1) * 4)
let xs: words = words((npts + 1))
let ys: words = words((npts + 1))
var xv = 0
for k in 0 .. npts {
let fl = flags[k]

View file

@ -151,7 +151,7 @@ fn tt_raster(id: int, gid: int, px: int) -> ptr {
let SW = W * TT_SS
let SH = H * TT_SS
let cover = mem_alloc(W * H)
let cover = bytes(W * H)
mem_set(cover, 0, W * H)
let unit = 255 / (TT_SS * TT_SS)

View file

@ -80,35 +80,35 @@ var ui_active: int = -1
var ui_focus: int = -1
fn rt_ui_init() -> void {
ui_type = mem_alloc(UI_MAX * 4)
ui_parent = mem_alloc(UI_MAX * 4)
ui_w = mem_alloc(UI_MAX * 4)
ui_h = mem_alloc(UI_MAX * 4)
ui_x = mem_alloc(UI_MAX * 4)
ui_y = mem_alloc(UI_MAX * 4)
ui_haspos = mem_alloc(UI_MAX * 4)
ui_pad = mem_alloc(UI_MAX * 4)
ui_gap = mem_alloc(UI_MAX * 4)
ui_bg = mem_alloc(UI_MAX * 4)
ui_fg = mem_alloc(UI_MAX * 4)
ui_border = mem_alloc(UI_MAX * 4)
ui_align = mem_alloc(UI_MAX * 4)
ui_grow = mem_alloc(UI_MAX * 4)
ui_font = mem_alloc(UI_MAX * 4)
ui_size = mem_alloc(UI_MAX * 4)
ui_skin = mem_alloc(UI_MAX * 4)
ui_inset = mem_alloc(UI_MAX * 4)
ui_img = mem_alloc(UI_MAX * 4)
ui_focusable = mem_alloc(UI_MAX * 4)
ui_rx = mem_alloc(UI_MAX * 4)
ui_ry = mem_alloc(UI_MAX * 4)
ui_rw = mem_alloc(UI_MAX * 4)
ui_rh = mem_alloc(UI_MAX * 4)
ui_visible = mem_alloc(UI_MAX * 4)
ui_fired = mem_alloc(UI_MAX * 4)
ui_hasdyn = mem_alloc(UI_MAX * 4)
ui_dyn = mem_alloc(UI_MAX * 96)
ui_text = mem_alloc(UI_MAX * 8)
ui_type = words(UI_MAX)
ui_parent = words(UI_MAX)
ui_w = words(UI_MAX)
ui_h = words(UI_MAX)
ui_x = words(UI_MAX)
ui_y = words(UI_MAX)
ui_haspos = words(UI_MAX)
ui_pad = words(UI_MAX)
ui_gap = words(UI_MAX)
ui_bg = words(UI_MAX)
ui_fg = words(UI_MAX)
ui_border = words(UI_MAX)
ui_align = words(UI_MAX)
ui_grow = words(UI_MAX)
ui_font = words(UI_MAX)
ui_size = words(UI_MAX)
ui_skin = words(UI_MAX)
ui_inset = words(UI_MAX)
ui_img = words(UI_MAX)
ui_focusable = words(UI_MAX)
ui_rx = words(UI_MAX)
ui_ry = words(UI_MAX)
ui_rw = words(UI_MAX)
ui_rh = words(UI_MAX)
ui_visible = words(UI_MAX)
ui_fired = words(UI_MAX)
ui_hasdyn = words(UI_MAX)
ui_dyn = bytes(UI_MAX * 96)
ui_text = bytes(UI_MAX * 8)
}
# ---- build-time interface (called by compiler-emitted code) ---------------

View file

@ -149,7 +149,7 @@ fn ui_draw_node(i: int) -> void {
var ui_fl: words = null
fn ui_focusables() -> int {
if (ui_fl == null) { ui_fl = mem_alloc(UI_MAX * 4) }
if (ui_fl == null) { ui_fl = words(UI_MAX) }
var n = 0
for i in 0 .. ui_n {
if ui_focusable[i] == 1 {

View file

@ -7,7 +7,7 @@ property Buf { data: ptr = null, len: int = 0, cap: int = 0 }
fn buf_new() -> Buf {
let b = new Buf
b.cap = 256
b.data = mem_alloc(b.cap)
b.data = bytes(b.cap)
b.len = 0
return b
}

View file

@ -138,6 +138,17 @@ fn emit_call(e: Node) -> Val {
else { emit(" call i32 (ptr, ...) @printf(ptr @.fmt_int, i32 " + `{a.code})\n`) }
return val("0", "void")
}
if (name == "bytes") { # bytes(n): allocate n bytes -> a byte buffer
let n = emit_expr(e.kids[0])
let w = emit_bind(`zext i32 {n.code} to i64`)
return val(emit_bind(`call ptr @malloc(i64 {w})`), "ptr")
}
if (name == "words") { # words(n): allocate n 32-bit words
let n = emit_expr(e.kids[0])
let by = emit_bind(`mul i32 {n.code}, 4`)
let w = emit_bind(`zext i32 {by} to i64`)
return val(emit_bind(`call ptr @malloc(i64 {w})`), "words")
}
if (name == "fx") { let a = emit_expr(e.kids[0]); return val(emit_bind(`shl i32 {a.code}, 16`), "fixed") }
if (name == "flr") { let a = emit_expr(e.kids[0]); return val(emit_bind(`ashr i32 {a.code}, 16`), "int") }
if is_intrinsic(name) { return emit_intrinsic(name, e) }

View file

@ -7,7 +7,7 @@ var g_intrin_ok: bool = false
# is `name` a low-level intrinsic? A pure name check, so it can gate dispatch
# without evaluating arguments (which could clobber shared state).
fn is_intrinsic(name: ptr) -> bool {
if (name == "mem_alloc") or (name == "mem_realloc") { return true }
if (name == "mem_realloc") { return true }
if (name == "file_open") or (name == "file_read") or (name == "file_write") { return true }
if (name == "file_seek") or (name == "file_tell") or (name == "file_close") { return true }
if (name == "os_argc") or (name == "os_arg") or (name == "os_exit") or (name == "file_stderr") { return true }
@ -23,11 +23,7 @@ fn arg_code(e: Node, i: int) -> ptr { let v = emit_expr(e.kids[i]); return v.co
fn emit_intrinsic(name: ptr, e: Node) -> Val {
g_intrin_ok = true
# ptr_null / ptr_is_null are the `null` literal and `x == null` now.
if (name == "mem_alloc") {
let n = arg_code(e, 0)
let w = emit_bind(`zext i32 {n} to i64`)
return val(emit_bind(`call ptr @malloc(i64 {w})`), "ptr")
}
# mem_alloc is bytes(n) / words(n) now (see emit_call).
if (name == "mem_realloc") {
let p = arg_code(e, 0); let n = arg_code(e, 1)
let w = emit_bind(`zext i32 {n} to i64`)

View file

@ -7,7 +7,7 @@ fn read_file(path: str) -> ptr {
file_seek(f, 0, 2)
let n = file_tell(f)
file_seek(f, 0, 0)
let buf = mem_alloc(n + 1)
let buf = bytes(n + 1)
file_read(f, buf, n)
buf[n] = 0
file_close(f)

View file

@ -53,7 +53,7 @@ fn lex(src: ptr) -> void {
if c == 34 { # "string"
i = i + 1
let start = i
let out = mem_alloc(n)
let out = bytes(n)
var j = 0
while i < n and src[i] != 34 {
if src[i] == 92 { # backslash escape
@ -72,7 +72,7 @@ fn lex(src: ptr) -> void {
}
if c == 96 { # `interpolated string` — captured raw
i = i + 1
let out = mem_alloc(n)
let out = bytes(n)
var j = 0
while i < n and src[i] != 96 { out[j] = src[i]; j = j + 1; i = i + 1 }
i = i + 1

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,7 @@ fn ptype() -> ptr {
pi = pi + 1
eat_op("]")
let el = ptype()
let out = mem_alloc(len(el) + 3)
let out = bytes(len(el) + 3)
out[0] = 91; out[1] = 93 # "[]"
var i = 0
while el[i] != 0 { out[2 + i] = el[i]; i = i + 1 }
@ -75,7 +75,7 @@ fn parse_hole(inner: ptr) -> Node { # re-lex+parse an embedded exp
fn parse_interp(raw: ptr) -> Node {
let n = len(raw)
var acc: Node = null
let lit = mem_alloc(n + 1)
let lit = bytes(n + 1)
var lj = 0
var i = 0
while i < n {

View file

@ -14,16 +14,16 @@ fn char_is_alnum(c: int) -> bool { return char_is_alpha(c) or char_is_digit(c) }
# integer -> fresh decimal string
fn itoa(v: int) -> ptr {
if v == 0 { let z = mem_alloc(2); z[0] = 48; z[1] = 0; return z }
if v == 0 { let z = bytes(2); z[0] = 48; z[1] = 0; return z }
var neg = false
var x = v
if x < 0 { neg = true; x = 0 - x }
let tmp = mem_alloc(16)
let tmp = bytes(16)
var n = 0
while x > 0 { tmp[n] = 48 + x % 10; x = x / 10; n = n + 1 }
var total = n
if neg { total = total + 1 }
let out = mem_alloc(total + 1)
let out = bytes(total + 1)
var k = 0
if neg { out[0] = 45; k = 1 }
var i = 0

View file

@ -9,7 +9,7 @@ program T {
print(classify(90)) # 9
print((1 << 4)) # 16
print(((4 | 1) & 6)) # 4
let p = mem_alloc(16)
let p = bytes(16)
p[1] = 9999
print(p[1]) # 9999
}

View file

@ -137,7 +137,7 @@ compare("builtins", h_builtins | h_intrinsics, kotlin_set(kotlin, "BUILTINS"), "
# --- against the TextMate grammar ------------------------------------------
gpath = ["repository", "builtin", "patterns"]
compare("builtins", h_builtins, grammar_alternation(grammar, gpath, "rng_chance"), "ludic.tmLanguage.json")
compare("intrinsics", h_intrinsics, grammar_alternation(grammar, gpath, "mem_alloc"), "ludic.tmLanguage.json")
compare("intrinsics", h_intrinsics, grammar_alternation(grammar, gpath, "mem_free"), "ludic.tmLanguage.json")
kpath = ["repository", "keyword", "patterns"]
compare("phases", h_phases, grammar_alternation(grammar, kpath, "FixedUpdate"), "ludic.tmLanguage.json")
compare("primitive types", h_types, grammar_alternation(grammar, kpath, "fixed"), "ludic.tmLanguage.json")

View file

@ -66,7 +66,7 @@ object LudicVocabulary {
"ui_focused", "ui_visible", "key", "reg", "set_reg", "self", "save", "load",
"status", "print", "str", "quit",
// compiler intrinsics: the floor the Ludic-written runtime stands on
"mem_alloc", "mem_realloc", "mem_free", "mem_copy", "mem_set", "os_argc", "os_arg", "file_stderr", "file_stdout",
"bytes", "words", "mem_realloc", "mem_free", "mem_copy", "mem_set", "os_argc", "os_arg", "file_stderr", "file_stdout",
"peekp", "pokep", "peekf", "pokef", "ptr_add",
"as_fixed", "as_int", "file_open", "file_read", "file_write",
"file_seek", "file_tell", "file_close", "read_byte", "write_byte",

View file

@ -209,7 +209,7 @@
{
"comment": "compiler intrinsics — these lower straight to libc or the OS",
"name": "support.function.intrinsic.ludic",
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
"match": "\\b(bytes|words|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
}
]
},

View file

@ -209,7 +209,7 @@
{
"comment": "compiler intrinsics — these lower straight to libc or the OS",
"name": "support.function.intrinsic.ludic",
"match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
"match": "\\b(bytes|words|mem_realloc|mem_free|mem_copy|mem_set|peekp|pokep|peekf|pokef|ptr_add|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|str_len|os_exit|os_time|os_argc|os_arg|file_stderr|file_stdout|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()"
}
]
},

View file

@ -145,7 +145,8 @@ static const LBuiltin LUDIC_BUILTINS[] = {
};
static const LBuiltin LUDIC_INTRINSICS[] = {
{"mem_alloc","mem_alloc(n: int) -> ptr","Allocate n bytes (malloc)."},
{"bytes","bytes(n: int) -> ptr","Allocate a buffer of n bytes."},
{"words","words(n: int) -> words","Allocate a buffer of n 32-bit words."},
{"mem_realloc","mem_realloc(p: ptr, n: int) -> ptr","Resize a block to n bytes, preserving its contents (realloc)."},
{"os_argc","os_argc() -> int","Number of command-line arguments, argv[0] included."},
{"os_arg","os_arg(i: int) -> str","The i-th command-line argument."},