Skip to content

Commit 017a2f7

Browse files
feat(stdlib): Argv — extern "env" pattern for wasm-host argv access (#86)
## Summary - Adds `stdlib/Argv.eph` declaring three host imports (`argv_count`, `argv_arg_len`, `argv_arg_get`) any wasm host embedding an ephapax module must implement. - Follows the WASI `args_get` / `args_sizes_get` buffer shape — hosts can either bridge to WASI directly or implement the symbols natively. - No compiler change. Existing `extern "env" { ... }` infrastructure in `src/ephapax-wasm/src/lib.rs` (`collect_extern_imports`) handles it. ## Why Phase 14a.1 of porting the gossamer CLI (`gossamer/cli/`) from native Zig to typed-wasm Ephapax. The CLI needs argv access for subcommand dispatch (`gossamer dev` vs `gossamer build` etc.). Doing it as a stdlib `extern "env"` pattern rather than a new compiler intrinsic keeps the compiler footprint zero while unblocking any wasm-host launcher. Higher-level helpers (slice→String, full `Array<String>` materialisation) are deferred until region-scoped String allocation and a List/Array story stabilise in the v2 stdlib. Documented in the module header. ## Test plan Verified end-to-end on this branch: - [x] \`ephapax parse stdlib/Argv.eph\` — 3 extern fns recognised - [x] \`ephapax compile stdlib/Argv.eph -o /tmp/argv.wasm\` — 727-byte .wasm - [x] Wasm Import section inspection shows \`env::argv_count\`, \`env::argv_arg_len\`, \`env::argv_arg_get\` emitted as proper host imports alongside the baseline \`env::print_i32\` / \`env::print_string\`. - [ ] Reviewer: confirm naming aligns with future WASI-compat plan (if any). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f60bd53 commit 017a2f7

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

stdlib/Argv.eph

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
//
4+
// Ephapax.Argv — command-line argument access for wasm modules
5+
// compiled by ephapax.
6+
//
7+
// Argv lives at the wasm-host boundary, so it is exposed as an
8+
// `extern "env" { ... }` block rather than a compiler intrinsic. Any
9+
// host that embeds an ephapax .wasm module (e.g. the gossamer launcher,
10+
// a wasmtime wrapper, a browser harness) must provide implementations of
11+
// `env::argv_count`, `env::argv_arg_len`, and `env::argv_arg_get`.
12+
//
13+
// Buffer convention follows the WASI args_get/args_sizes_get shape:
14+
// the host writes raw UTF-8 bytes into a caller-supplied region of the
15+
// wasm linear memory. This avoids any allocation contract between host
16+
// and guest.
17+
//
18+
// Host contract:
19+
// - argv_count() returns the number of CLI arguments, including argv[0].
20+
// - argv_arg_len(idx) returns the byte length of argument `idx`, or -1
21+
// when `idx` is out of range. The length excludes any trailing NUL.
22+
// - argv_arg_get(idx, buf_ptr, buf_len) copies argument `idx` into the
23+
// wasm linear-memory region [buf_ptr, buf_ptr + buf_len). Returns the
24+
// number of bytes actually written (== argv_arg_len(idx) on success),
25+
// or -1 if `idx` is out of range or `buf_len` is insufficient.
26+
//
27+
// Higher-level helpers (slice → String, full Array<String> materialisation)
28+
// will land once region-scoped String allocation and a List/Array story
29+
// stabilise in the v2 stdlib. For now, callers work at the byte level.
30+
31+
module Argv
32+
33+
extern "env" {
34+
fn argv_count(): I32
35+
fn argv_arg_len(idx: I32): I32
36+
fn argv_arg_get(idx: I32, buf_ptr: I32, buf_len: I32): I32
37+
}

0 commit comments

Comments
 (0)