diff --git a/README.md b/README.md index ab608d7..56ecb20 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,9 @@ main proc() int { this prints `42`. interpreted `main` must be a top-level function with no parameters; nonvoid results are printed, not used as process exit statuses. -the native bootstrap accepts either a no-argument `main` or `main proc(init process.Init)`. it supplies `init.io` and `init.args` directly from native startup `argc`/`argv`. `process.Args` borrows the argument pointer array and zero-terminated strings without allocation or copying; native startup storage lasts for the process lifetime. `process.argument_count(init.args)` includes the executable name, and `process.argument(init.args, index)` returns a borrowed `[;0]u8` or `null` when out of range. callers can supply their own `process.Args { values = pointers[..] }` for testing. +the native bootstrap accepts either a no-argument `main` or `main proc(init process.Init)`. it supplies `init.io` and `init.args` from native startup `argc`/`argv`. startup scans each argument once into a heap-allocated array of borrowed zero-terminated slices (`process.Args.values: [][;0]u8`), without copying strings. the descriptor array and borrowed strings remain valid until `main` returns; startup then frees the descriptors, including on a fallible return. allocation failure exits with status `2`. `init.args.values.len` includes the executable name, and `init.args.values[index]` directly accesses an argument after a length guard. callers can supply their own `process.Args { values = slices[..] }` for testing. -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. +source loading uses the supplied `io.Io` for opening, reading, and closing files. `io.open` accepts a borrowed zero-terminated slice (`[;0]u8`), including `init.args.values[index]` without copying its 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 0b71bce..64abaf1 100644 --- a/source/main.hon +++ b/source/main.hon @@ -46,9 +46,9 @@ DriverError :: alias ( main proc(init process.Init) i32 { return command(mem.c_allocator, init.io, init.args) catch |err| { - if (process.argument(init.args, 2)) |path| { + if (init.args.values.len > 2) { io.print("{s}: infrastructure error: {s}\n", io.stderr(init.io), { - path, infrastructure_message(err), + init.args.values[2], infrastructure_message(err), }) catch |_| {} } else { io.print("honey: infrastructure error: {s}\n", io.stderr(init.io), { @@ -78,20 +78,15 @@ infrastructure_message proc(error DriverError) []u8 { @hide:file command proc(allocator mem.Allocator, runtime io.Io, args process.Args) i32 ! DriverError { - if (process.argument_count(args) != 3) { + if (args.values.len != 3) { try io.print("usage: honey run \n", io.stderr(runtime), {}) return 2 } - if (process.argument(args, 1)) |operation| { - if (!mem.eql(operation, "run")) { - try io.print("usage: honey run \n", io.stderr(runtime), {}) - return 2 - } - } else { + if (!mem.eql(args.values[1], "run")) { + try io.print("usage: honey run \n", io.stderr(runtime), {}) return 2 } - if (process.argument(args, 2)) |path| return try run_file(allocator, runtime, path) - return 2 + return try run_file(allocator, runtime, args.values[2]) } @hide:file diff --git a/std/process/arguments.hon b/std/process/arguments.hon deleted file mode 100644 index 2a281f3..0000000 --- a/std/process/arguments.hon +++ /dev/null @@ -1,12 +0,0 @@ -argument_count proc(args Args) usize { - return args.values.len -} - -#! returns a borrowed, zero-terminated slice, valid while the supplied argument storage lives. -argument proc(args Args, index usize) ?[;0]u8 { - if (index >= argument_count(args)) return null - pointer :: args.values[index] - length := usize(0) - while (pointer[length] != 0) length += 1 - return pointer[..length;0] -} diff --git a/std/process/arguments.test.hon b/std/process/arguments.test.hon deleted file mode 100644 index 057bba0..0000000 --- a/std/process/arguments.test.hon +++ /dev/null @@ -1,27 +0,0 @@ -import "@std/testing" -import "@std/mem" - -borrows_supplied_arguments test { - first [3;0]mut u8 := ['r', 'u', 'n'] - empty [0;0]u8 := [] - spaced [9;0]u8 := ['t', 'w', 'o', ' ', 'w', 'o', 'r', 'd', 's'] - pointers [3][*;0]u8 :: [(&first).ptr, (&empty).ptr, (&spaced).ptr] - args :: Args{ values = pointers[..] } - try testing.expect_equal(usize(3), argument_count(args)) - if (argument(args, 0)) |value| { - first[0] = 'f' - try testing.expect(mem.eql(value, "fun")) - } else { try testing.expect(false) } - if (argument(args, 1)) |value| { - try testing.expect_equal(usize(0), value.len) - } else { try testing.expect(false) } - if (argument(args, 2)) |value| { - try testing.expect(mem.eql(value, "two words")) - } else { try testing.expect(false) } - try testing.expect(argument(args, 3) == null) - try testing.expect(argument(args, maxval!(usize)) == null) - - none :: Args{ values = pointers[0..0] } - try testing.expect_equal(usize(0), argument_count(none)) - try testing.expect(argument(none, 0) == null) -} diff --git a/std/process/process.hon b/std/process/process.hon index bee8187..443c441 100644 --- a/std/process/process.hon +++ b/std/process/process.hon @@ -5,7 +5,7 @@ Init :: struct { args Args } -#! borrows the argument pointer array and its zero-terminated strings; owns no storage. +#! borrows argument slices and their zero-terminated strings, valid until main returns. Args :: struct { - values [][*;0]u8 + values [][;0]u8 }