Implement the stdlib/runtime work needed to make Tonic materially more usable for real programs.
This loop should take the current state from:
- core data structures exist but stdlib exposure is uneven,
- some stdlib modules already have host-side implementations but are de-advertised,
- the pure-vs-host split is unclear,
- and native/backend parity is incomplete,
to a state where:
- the right modules are exposed,
- pure transforms are implemented in Tonic where appropriate,
- side-effecting/runtime-sensitive features are host-backed,
- map functionality is handled honestly,
- and run/compile/docs/tests all agree.
Do not treat this as a vague stdlib expansion. Treat it as a concrete usability milestone with an explicit split:
IO.*System.*- most or all of
Path.* - UTF-8/parsing-heavy
String.* - crypto/networking/process/time/filesystem primitives
List.*helpers that are pure structural transformsEnum.*helpers over lists/ranges that are pure transforms
Map.*- any
Enum.*behavior requiring generic map traversal
If you cannot implement a clean pure-Tonic Map story without adding new language/runtime support, do not fake it. Either:
- add the minimum bounded traversal support required and prove it.
- Implement the
Mapstory.
Prefer the smallest truthful design that lands usable functionality.
Read these first:
AGENTS.md.agents/summary/index.md.agents/summary/interfaces.md.agents/summary/components.mdsrc/manifest.rssrc/interop.rssrc/interop/system.rssrc/interop/string_mod.rssrc/interop/path_mod.rssrc/interop/io_mod.rssrc/interop/list_mod.rssrc/interop/map_mod.rssrc/interop/enum_mod.rssrc/c_backend/stubs.rstests/run_lazy_stdlib_loading_smoke.rstests/run_comprehensions_smoke.rstests/run_case_list_map_smoke.rstests/system_stdlib_http_input_smoke.rsexamples/parity/10-idiomatic/list_processing.tnexamples/parity/10-idiomatic/pipeline_transform.tnexamples/parity/10-idiomatic/closures_and_captures.tn
Use repo source as truth if docs and implementation diverge. Update docs as you progress.
Tonic already has more capability than its public stdlib surface suggests.
Today:
- lists and maps already exist as runtime values,
- pattern matching and comprehensions already exist,
System,String, andPathare lazily exposed,- host implementations for
IO,List,Map, andEnumalready exist in Rust, - but those modules are not properly exposed/wired,
- and there are clear backend-parity gaps.
This creates the worst combination:
- useful capabilities exist,
- users cannot rely on them consistently,
- and the implementation boundary is muddier than it should be.
- Expose the right stdlib modules.
- Implement pure collection transforms directly in Tonic where feasible.
- Keep side-effecting/runtime-sensitive surfaces host-backed.
- Handle
Map.*honestly given current traversal limitations. - Ensure interpreter, C backend, docs, and tests all agree.
- improve self-hosting posture by moving pure library logic into Tonic where appropriate,
- reduce unnecessary Rust glue for pure transforms,
- keep file sizes reasonable,
- and leave a clear boundary between library code and primitives.
- exposing
IO,List,Map, andEnumas public stdlib modules - deciding and implementing the correct pure-vs-host split
- implementing pure
List.*andEnum.*in Tonic if the language supports them cleanly - keeping
IO.*,System.*, and other external/runtime-sensitive features host-backed - wiring lazy stdlib loading for newly exposed modules
- registering all required host functions
- adding or completing native/C-backend host-call parity for host-backed surfaces
- updating docs generation so stdlib docs reflect the real exposed surface
- replacing de-advertising tests with truthful positive/negative coverage
- adding representative runtime and native parity tests
- a giant general-purpose stdlib redesign
- speculative optimizer work
- parser/typechecker rewrites unrelated to this milestone
- broad self-hosting work beyond pure stdlib modules
- ambitious map-iteration language design beyond the minimum bounded support needed
Implement using this split unless source evidence proves a better bounded alternative.
Expose at least:
IO.puts/1IO.inspect/1IO.gets/1IO.ansi_red/1IO.ansi_green/1IO.ansi_yellow/1IO.ansi_blue/1IO.ansi_reset/0
These should remain host-backed.
Keep host-backed. Do not attempt to reimplement external effects in Tonic.
Keep host-backed unless a function is trivial and clearly benefits from being pure. Default to host-backed.
Keep existing host-backed UTF-8/parsing-sensitive behavior unless there is a compelling reason otherwise.
Expose a usable Map module.
Default acceptable implementation for this milestone:
- host-backed
Map.keys/1 Map.values/1Map.merge/2Map.drop/2Map.take/2Map.has_key?/2Map.get/3Map.put/3Map.delete/2
Do not pretend Map.filter/2 or Map.reject/2 are production-ready if they still depend on missing runtime closure dispatch or missing traversal support.
Implement directly in Tonic if cleanly possible:
List.first/1List.last/1List.wrap/1List.flatten/1List.zip/2List.unzip/1
Implement directly in Tonic over lists/ranges if cleanly possible:
Enum.count/1Enum.sum/1Enum.join/2Enum.sort/1Enum.reverse/1Enum.take/2Enum.drop/2Enum.chunk_every/2Enum.unique/1Enum.into/2for list targets and any clearly supported target types- high-value transforms if feasible and safe:
Enum.map/2Enum.filter/2Enum.reduce/3
Pure Tonic cannot directly implement:
- stdin/stdout/stderr
- files
- env/argv
- networking
- time/sleep
- crypto/randomness
- process spawning
So IO.* and System.* are not candidates for a pure-Tonic implementation.
There does not appear to be a clean first-class way to:
- iterate map entries directly in Tonic,
- convert a map into an entry list in pure Tonic,
- or fold over a map generically.
That blocks or complicates pure implementations of much of Map.*.
- recursion depth and performance for pure library code
- closure-heavy parity across interpreter/C/LLVM backends
- sorting semantics if implemented purely in Tonic
- any attempt to widen map iteration beyond a small bounded change
Work in this order unless a small reorder clearly improves safety.
- audit current stdlib exposure and host registration
- wire
IO,List,Map, andEnuminto the exposed stdlib surface - update lazy-loading analysis so newly exposed modules load when referenced
- update docs-generation inputs so generated stdlib docs match reality
- replace the current de-advertising expectations with truthful tests
- move pure
List.*into Tonic source if feasible and cleaner than Rust-backed wrappers - move pure
Enum.*into Tonic source where the implementation is clean and parity-safe - keep
IO.*,System.*,Path.*, and relevantString.*host-backed - implement
Map.*as host-backed unless you first add the minimum bounded traversal support required to do better
- ensure every host-backed function exposed publicly has matching native/C-backend support in
src/c_backend/stubs.rs - verify interpreter and compiled behavior agree for representative cases
- make sure LLVM/C host-call paths do not silently lag the interpreter surface
- add representative examples demonstrating the final public surface
- update docs/comments/help text if the exposed stdlib changes
- leave explicit notes for any intentionally deferred APIs
Update embedded stdlib sources and module lists so the exposed surface is real. This likely includes:
- adding embedded source for
IO,List,Map, andEnum, or - moving pure-Tonic stdlib module sources into a cleaner arrangement if appropriate,
- updating
STDLIB_SOURCES, - updating
STDLIB_MODULE_NAMES, - updating the lazy-load module set in
load_run_source_from_project_root.
Wire in modules that already exist but are not registered:
io_modlist_modmap_modenum_mod
Register the host functions that remain part of the public host-backed surface. If you move some modules to pure Tonic, remove or narrow dead Rust-side plumbing so there is no misleading unused implementation.
Use these files as source of truth for host-backed behavior. Refine them as needed, but do not leave dead exported surfaces that the language never exposes.
Add host-call parity for every public host-backed function you expose. Do not ship interpreter-only stdlib behavior by accident.
Update and extend:
tests/run_lazy_stdlib_loading_smoke.rs- targeted runtime smoke tests
- targeted compile/native parity tests
- deterministic negative tests for intentionally unsupported APIs
Add or refresh small examples so the public surface is discoverable and believable.
At completion, the following should be true.
IO.inspect(123)works whenIOis referencedList.first([1, 2, 3])worksMap.keys(%{a: 1})worksEnum.count([1, 2, 3])works- stdlib docs reflect the exposed modules
- pure transforms live in Tonic where cleanly feasible
- side-effecting/runtime-sensitive behavior remains host-backed
Map.*is handled honestly rather than by wishful abstraction
- representative host-backed APIs work in interpreter mode
- representative host-backed APIs work in compiled/native mode
- no public stdlib function is interpreter-only unless explicitly documented and tested as unsupported elsewhere
- no dead plumbing left behind without reason
- no misleading tests asserting deliberate non-exposure of modules that are now public
- no warnings or obviously stale code paths
Run the smallest sufficient checks during each slice, then a focused final gate.
At minimum, expect to run relevant subsets of:
cargo test --test run_lazy_stdlib_loading_smokecargo test --test run_comprehensions_smokecargo test --test run_case_list_map_smokecargo test --test run_pipe_enum_smokecargo test --test system_stdlib_http_input_smoke- targeted new runtime tests for
IO,List,Map, andEnum - targeted compile/native parity tests for exposed host-backed surfaces
If the touched surface is broad enough, run:
cargo test
If you modify C backend host-call support, prove it with at least one compiled/native test that exercises the new public surface.
- Keep implementation files reasonably small; if a file grows past the repo preference, split it.
- Prefer pure Tonic for pure transforms, but do not force bad implementations just to avoid Rust.
- Do not claim pure
Map.*support unless you truly added the required language/runtime support. - Do not leave
Map.filter/2andMap.reject/2pretending to be complete if they are not. - Treat dead code and warnings as blockers.
- Commit when tests pass.
Emit LOOP_COMPLETE only when:
IO,List,Map, andEnumare exposed intentionally and truthfully,- the pure-vs-host split is implemented rather than merely discussed,
- pure
List/Enumfunctionality is in Tonic where feasible, - side-effecting/runtime-sensitive APIs remain host-backed,
Map.*is usable and honestly scoped,- native/backend parity exists for every public host-backed API shipped in this milestone,
- tests and docs reflect the real surface,
- and the repo is left in a cleaner, more credible usability state than before.
- Examples exist that exercise the implementation.
- Documentation has been updated.