Add a builtin prelude for List/Array/Map (no import required) #72

Closed
opened 2026-09-18 21:13:40 +00:00 by jacksonopp · 0 comments
Owner

Follow-up to #69 — split out during that issue's implementation.

#69 (and its follow-up #71 for Array's Comptime size) built the mechanism for comptime-evaluating a generic type-function call (List(Int) etc.) into a real Ty, via fn_decl looking up the callee's declaration and evaluate_generic_call substituting args into its body. But fn_decl only ever searches the SourceFile it's given — in every #69/#71 test, List's own fn List(T: type) -> type { struct { items: *T, len: Int } } is declared inline in the same source being checked. There is currently no way for a real program to use List(Int), or the [1, 2, 3]/[3]Int[...]/["a": 1] literal sugar (per syntax-notes.md) that desugars to it, without redeclaring List/Array/Map itself in every file.

This is not a standard-library/import feature. Per syntax-notes.md, List/Array/Map are used completely unqualified everywhere — the container-literal sugar desugars straight to List(Int)/Array(Int, 3)/Map(String, Int) with no import in sight, and import's own path-to-filesystem resolution is explicitly unbuilt (deferred per syntax-status.md). So this issue is scoped to a builtin/prelude set — analogous to how Vec in Rust doesn't need importing (it's ordinary Rust source, just glob-imported by the prelude), not analogous to Int/Bool/Float/String/Unit, which really are Rust-hardcoded compiler builtins (primitive_ty in ty.rs — a bare match, no backing declaration at all). List/Array/Map should stay real, parseable, comptime-evaluated Twill source, not join that hardcoded list — just be guaranteed findable without a user-written declaration.

Proposed shape:

  • Real .tw source file(s) (e.g. crates/twill-check/prelude/{list,array,map}.tw or one combined file) containing the actual definitions from syntax-notes.md.
  • include_str! them into a dedicated, fixed prelude SourceFile created once (not resolved through any runtime/filesystem import mechanism — sidesteps import's unbuilt path resolution entirely).
  • fn_decl (or a wrapper around it) gains a two-tier lookup: try the checked file's own Scope::source first, then fall back to the prelude SourceFile.

Explicitly out of scope: a general importable standard library, import path-to-filesystem resolution, and anything beyond this fixed, always-in-scope container set.

Follow-up to #69 — split out during that issue's implementation. #69 (and its follow-up #71 for `Array`'s `Comptime` size) built the mechanism for comptime-evaluating a generic type-function call (`List(Int)` etc.) into a real `Ty`, via `fn_decl` looking up the callee's declaration and `evaluate_generic_call` substituting args into its body. But `fn_decl` only ever searches the `SourceFile` it's given — in every #69/#71 test, `List`'s own `fn List(T: type) -> type { struct { items: *T, len: Int } }` is declared inline in the same source being checked. There is currently no way for a real program to use `List(Int)`, or the `[1, 2, 3]`/`[3]Int[...]`/`["a": 1]` literal sugar (per `syntax-notes.md`) that desugars to it, without redeclaring `List`/`Array`/`Map` itself in every file. **This is not a standard-library/import feature.** Per `syntax-notes.md`, `List`/`Array`/`Map` are used completely unqualified everywhere — the container-literal sugar desugars straight to `List(Int)`/`Array(Int, 3)`/`Map(String, Int)` with no `import` in sight, and `import`'s own path-to-filesystem resolution is explicitly unbuilt (deferred per `syntax-status.md`). So this issue is scoped to a **builtin/prelude** set — analogous to how `Vec` in Rust doesn't need importing (it's ordinary Rust source, just glob-imported by the prelude), not analogous to `Int`/`Bool`/`Float`/`String`/`Unit`, which really are Rust-hardcoded compiler builtins (`primitive_ty` in `ty.rs` — a bare match, no backing declaration at all). `List`/`Array`/`Map` should stay real, parseable, comptime-evaluated Twill source, not join that hardcoded list — just be guaranteed findable without a user-written declaration. Proposed shape: - Real `.tw` source file(s) (e.g. `crates/twill-check/prelude/{list,array,map}.tw` or one combined file) containing the actual definitions from `syntax-notes.md`. - `include_str!` them into a dedicated, fixed prelude `SourceFile` created once (not resolved through any runtime/filesystem import mechanism — sidesteps `import`'s unbuilt path resolution entirely). - `fn_decl` (or a wrapper around it) gains a two-tier lookup: try the checked file's own `Scope::source` first, then fall back to the prelude `SourceFile`. Explicitly out of scope: a general importable standard library, `import` path-to-filesystem resolution, and anything beyond this fixed, always-in-scope container set.
jacksonopp added this to the twill project 2026-09-18 21:24:30 +00:00
jacksonopp removed this from the twill project 2026-10-04 02:28:22 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jacksonopp/twill#72
No description provided.