From 877ee21579d57e1dbdecdba94b64c11e76675e56 Mon Sep 17 00:00:00 2001 From: hl-valdemar Date: Fri, 23 Oct 2026 11:18:08 +0200 Subject: [PATCH] feat: restore sentinel-slice file path interfaces --- README.md | 2 +- source/main.hon | 17 +++++------------ std/io/file.hon | 6 +++--- std/io/io.hon | 2 +- std/process/arguments.hon | 9 ++++++--- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9d09329..90e8f9e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ main proc() int { this prints `42`. `main` must be a top-level function with no parameters; nonvoid results are printed, not used as process exit statuses. the current macOS bootstrap obtains arguments from the native startup environment. -source loading uses the supplied `io.Io` for opening, reading, and closing files. `io.open` accepts a borrowed zero-terminated pointer, including paths returned by `process.argument`. `io.read_all(allocator, reader, maximum)` reads to EOF into a caller-owned `ArrayList(u8)`; release it with `arraylist.deinit`. it frees partial storage on error and consumes one extra byte to distinguish an exact-size input from a limit violation. the driver maps `limit_exceeded` to `source_too_large` at its `u32` source-size limit. +source loading uses the supplied `io.Io` for opening, reading, and closing files. `io.open` accepts a borrowed zero-terminated slice (`[;0]u8`), including arguments returned by `process.argument` without copying their storage. the bootstrap supports checked sentinel-slice construction with `pointer[..length;0]`. `io.read_all(allocator, reader, maximum)` reads to EOF into a caller-owned `ArrayList(u8)`; release it with `arraylist.deinit`. it frees partial storage on error and consumes one extra byte to distinguish an exact-size input from a limit violation. the driver maps `limit_exceeded` to `source_too_large` at its `u32` source-size limit. the parser supports arithmetic expressions with nested parenthesized groups, such as `a + (b - c) * 2 / 3`. groups control precedence without adding AST nodes; inner expression spans exclude the grouping parentheses. parsing accepts integer division syntax, but type checking requires float operands for `/`. diff --git a/source/main.hon b/source/main.hon index e83a20d..086b910 100644 --- a/source/main.hon +++ b/source/main.hon @@ -47,7 +47,7 @@ main proc(init process.Init) i32 { return command(mem.c_allocator, init.io) catch |err| { if (process.argument(2)) |path| { io.print("{s}: infrastructure error: {s}\n", io.stderr(init.io), { - argument_text(path), infrastructure_message(err), + path, infrastructure_message(err), }) catch |_| {} } else { io.print("honey: infrastructure error: {s}\n", io.stderr(init.io), { @@ -82,7 +82,7 @@ command proc(allocator mem.Allocator, runtime io.Io) i32 ! DriverError { return 2 } if (process.argument(1)) |operation| { - if (!mem.eql(argument_text(operation), "run")) { + if (!mem.eql(operation, "run")) { try io.print("usage: honey run \n", io.stderr(runtime), {}) return 2 } @@ -94,14 +94,7 @@ command proc(allocator mem.Allocator, runtime io.Io) i32 ! DriverError { } @hide:file -argument_text proc(pointer [*;0]u8) []u8 { - length := usize(0) - while (pointer[length] != 0) length += 1 - return pointer[..length] -} - -@hide:file -read_source proc(allocator mem.Allocator, runtime io.Io, path [*;0]u8) arraylist.ArrayList(u8) ! DriverError { +read_source proc(allocator mem.Allocator, runtime io.Io, path [;0]u8) arraylist.ArrayList(u8) ! DriverError { file :: try io.open(runtime, path, .read_only) closing := false defer { @@ -136,7 +129,7 @@ compile proc(allocator mem.Allocator, source []u8, diagnostic_store @mut diagnos } @hide:file -run_file proc(allocator mem.Allocator, runtime io.Io, path [*;0]u8) i32 ! DriverError { +run_file proc(allocator mem.Allocator, runtime io.Io, path [;0]u8) i32 ! DriverError { source := try read_source(allocator, runtime, path) defer arraylist.deinit(&source) diagnostic_store := diagnostics.init(allocator) @@ -145,7 +138,7 @@ run_file proc(allocator mem.Allocator, runtime io.Io, path [*;0]u8) i32 ! Driver defer ir.deinit(&module) outcome :: try interpreter.run(allocator, &module, &diagnostic_store) if (outcome.trap == null) try print_result(io.stdout(runtime), outcome.value) - try report_diagnostics(allocator, io.stderr(runtime), argument_text(path), source.items, &diagnostic_store, outcome.trap) + try report_diagnostics(allocator, io.stderr(runtime), path, source.items, &diagnostic_store, outcome.trap) if (outcome.trap != null or diagnostics.count(&diagnostic_store) != 0) return 1 return 0 } diff --git a/std/io/file.hon b/std/io/file.hon index 7227ac4..a3059e0 100644 --- a/std/io/file.hon +++ b/std/io/file.hon @@ -20,7 +20,7 @@ CloseError :: enum { } #! open a caller-owned handle from a borrowed zero-terminated path; release it with close. -open proc(io Io, path [*;0]u8, mode FileMode) File ! OpenError { +open proc(io Io, path [;0]u8, mode FileMode) File ! OpenError { handle Handle :: try io.vtable.open(io.context, path, mode) return File{ io = io, handle = handle } } @@ -83,7 +83,7 @@ system_write proc(_ ?@mut anyopaque, handle Handle, bytes []u8) usize ! WriteErr } @hide:file -system_open proc(_ ?@mut anyopaque, path [*;0]u8, mode FileMode) Handle ! OpenError { +system_open proc(_ ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! OpenError { flags := c.O_RDONLY match mode { .read_only: flags = c.O_RDONLY @@ -91,7 +91,7 @@ system_open proc(_ ?@mut anyopaque, path [*;0]u8, mode FileMode) Handle ! OpenEr .read_write: flags = c.O_RDWR } while true { - fd c_int :: c.open(ptrcast!(path), flags) + fd c_int :: c.open(ptrcast!(path.ptr), flags) if (fd >= 0) return Handle{ file_desc = fd } if (c.__error()?^ != c.EINTR) return .open_failed } diff --git a/std/io/io.hon b/std/io/io.hon index 5b0fc81..d69d680 100644 --- a/std/io/io.hon +++ b/std/io/io.hon @@ -41,7 +41,7 @@ Io :: struct { IoVTable :: struct { read @proc(context ?@mut anyopaque, handle Handle, buffer []mut u8) usize ! ReadError write @proc(context ?@mut anyopaque, handle Handle, bytes []u8) usize ! WriteError - open @proc(context ?@mut anyopaque, path [*;0]u8, mode FileMode) Handle ! OpenError + open @proc(context ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! OpenError close @proc(context ?@mut anyopaque, handle Handle) void ! CloseError stdin @proc(context ?@mut anyopaque) Handle stdout @proc(context ?@mut anyopaque) Handle diff --git a/std/process/arguments.hon b/std/process/arguments.hon index c955584..b4870ce 100644 --- a/std/process/arguments.hon +++ b/std/process/arguments.hon @@ -9,8 +9,11 @@ argument_count proc() usize { return usize(_NSGetArgc()^) } -#! returns a borrowed, zero-terminated argument; storage lasts for the process lifetime. -argument proc(index usize) ?[*;0]u8 { +#! returns a borrowed, zero-terminated slice; storage lasts for the process lifetime. +argument proc(index usize) ?[;0]u8 { if (index >= argument_count()) return null - return _NSGetArgv()^[index] + pointer :: _NSGetArgv()^[index] + length := usize(0) + while (pointer[length] != 0) length += 1 + return pointer[..length;0] }