feat: preprocess native argv into sentinel slices

This commit is contained in:
2026-10-23 12:07:23 +02:00
parent eddca5c3bf
commit 8ebbf72388
8 changed files with 167 additions and 93 deletions
+2 -2
View File
@@ -289,7 +289,7 @@ exactly once. Bare functions named `memcopy` or `memset` remain ordinary user fu
- `std/meta` reflection records plus `EnumFieldStruct(E, Field, default ?Field)`, implemented with `struct_type!`; it produces a record with one field per native enum member in declaration order, where outer `null` means no field default
- `std/io` explicit `Io` capabilities, provider-bound `Reader`/`Writer` handles, existing-file open/close operations, allocation-free `write_all`, and comptime-expanded writer-first `print`; formatting supports natural `{}`, byte `{s}`, decimal `{d}`, integer `{b}` / `{o}` / `{x}` / `{X}`, byte-character `{c}`, scientific float `{e}`, recursively scalar-backed distinct values, and `{{` / `}}`, with malformed formats and incompatible tuple fields rejected at comptime
- entry points are either `main func() ...` or `main func(init process.Init) ...`; their success channel is `void`, `i32`, or `int` and may have an error channel; an unhandled entry error exits with status 1. `std/process.Init` contains exactly `io io.Io` and `args Args`, while the system provider remains hidden inside `std/io`
- `std/process.Args` contains exactly `values [][*;0]u8`, borrowing native `argv` and its `argc` count without allocation or copying; index 0 is the executable name when present. `argument_count(args Args) usize` returns the count, and `argument(args Args, index usize) ?[;0]u8` scans only the requested argument and returns a borrowed sentinel slice (including empty arguments), or null out of range; borrowed views remain valid while the supplied storage lives
- `std/process.Args` contains exactly `values [][;0]u8`; use `args.values.len` and direct indexing. Native startup scans each argument once into heap-owned slice descriptors while borrowing, not copying, the strings; index 0 is the executable name when present, and empty arguments remain empty slices. The descriptors and their borrowed views are valid until `main` returns; the native wrapper frees the descriptors on both success and error
- `std/debug.print` is an allocation-free, failure-ignoring stderr escape hatch independent of `process.Init`
- `std/testing` supplies fallible `expect`, expected-first `expect_equal`, and exact compile-time `expect_type`; direct calls through
an alias of exactly `@std/testing` receive compiler-injected source locations
@@ -300,7 +300,7 @@ exactly once. Bare functions named `memcopy` or `memset` remain ordinary user fu
- lazy semantic checking of demanded function specializations
- static, eager runtime, mutable runtime, and deferred problematic globals with cycle diagnostics
- demand-driven LLVM declarations for referenced foreign functions
- root `main` may be parameterless or accept canonical `@std/process Init`; the generated C entry point accepts native `argc`/`argv`, obtains the hidden system I/O provider, and constructs the init value using computed record layout. Both `Init` and `Args` must have their canonical auto-layout record shapes
- root `main` may be parameterless or accept canonical `@std/process Init`; the generated C entry point accepts native `argc`/`argv`, obtains the hidden system I/O provider, and constructs the init value using computed record layout. Both `Init` and `Args` must have their canonical auto-layout record shapes. Descriptor allocation is size-checked, zero-count safe, and exits with status 2 on overflow or allocation failure; parameterless `main` does not prepare arguments
- `brolang test [root]` reuses `build.bro`, discovers only explicit test-import edges, skips the
application entry point, and runs tests sequentially while continuing after assertion failures
- replaceable dynamically loaded libclang C-import backend