From 04b54a84435cdaa35b20766d51a105e6236df69f Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 17 May 2026 13:18:17 +0100 Subject: [PATCH] fix(stdlib): module visibility + imports per ADR-011 (#135 slice 8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #135 slice 8 — bring the remaining core stdlib under the ADR-011 module model so `use prelude::{…}` actually resolves: - prelude.affine: its public API is now `pub` (types Option/Result + the 14 list/numeric utilities). Previously non-`pub`, so importing modules hit `Resolve.VisibilityError` on `Result`/etc. - result.affine / option.affine: extend `use prelude::{…}` with `map` (both call prelude's `map`); was `UndefinedVariable map`. - collections.affine: add `module collections;` + `use prelude::{Option, Some, None, filter, map, range, any}` (had no module/use — pre-#133 flat-namespace assumption). - result.affine `try_map`: `map(f, list)` -> `map(list, f)` — genuine stdlib bug (prelude `map` is `map(arr, f)`; arg order was swapped, surfaced as a function-vs-`[T]` type error once imports resolved). Result: **prelude.affine compiles end-to-end**; result/option/ collections clear ALL import-resolution (VisibilityError/ImportError gone). result now reaches typecheck; collections reaches a *distinct* pre-existing defect — the resolver has no forward-reference support between top-level fns (`binary_search` → `binary_search_helper`), reproducible even without `module`; that is a new resolver slice, not slice 8. io still needs cross-module `split` (in string.affine) — slice 8 tail. Full suite green (230); no regression. Advances #135. Refs #128, #135. Co-Authored-By: Claude Opus 4.7 (1M context) --- stdlib/collections.affine | 6 ++++++ stdlib/option.affine | 2 +- stdlib/prelude.affine | 32 ++++++++++++++++---------------- stdlib/result.affine | 4 ++-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/stdlib/collections.affine b/stdlib/collections.affine index 10062528..a20ec927 100644 --- a/stdlib/collections.affine +++ b/stdlib/collections.affine @@ -3,6 +3,12 @@ // // Collections - Advanced list, array, and data structure operations +module collections; + +// `Option` + constructors and the generic list utilities are owned by +// `prelude` (ADR-011); collections is a consumer module (#135 slice 8). +use prelude::{Option, Some, None, filter, map, range, any}; + // ============================================================================ // List Operations // ============================================================================ diff --git a/stdlib/option.affine b/stdlib/option.affine index 001827a5..042a9608 100644 --- a/stdlib/option.affine +++ b/stdlib/option.affine @@ -6,7 +6,7 @@ module option; // `Option`/`Result` types + constructors are owned by `prelude` (ADR-011). -use prelude::{Option, Some, None, Result, Ok, Err}; +use prelude::{Option, Some, None, Result, Ok, Err, map}; // This module is the single canonical home for the Option *operations* // (is_some/is_none/unwrap/unwrap_or/map/filter/contains/…). #133 removed diff --git a/stdlib/prelude.affine b/stdlib/prelude.affine index e3705a76..5962c625 100644 --- a/stdlib/prelude.affine +++ b/stdlib/prelude.affine @@ -16,15 +16,15 @@ module prelude; // the single canonical bindings for those. // ============================================================================ -type Option = Some(T) | None +pub type Option = Some(T) | None -type Result = Ok(T) | Err(E) +pub type Result = Ok(T) | Err(E) // ============================================================================ // List utilities // ============================================================================ -fn map(arr: [T], f: T -> U) -> [U] { +pub fn map(arr: [T], f: T -> U) -> [U] { let mut result = []; for x in arr { result = result ++ [f(x)]; @@ -32,7 +32,7 @@ fn map(arr: [T], f: T -> U) -> [U] { result } -fn filter(arr: [T], predicate: T -> Bool) -> [T] { +pub fn filter(arr: [T], predicate: T -> Bool) -> [T] { let mut result = []; for x in arr { if predicate(x) { @@ -42,7 +42,7 @@ fn filter(arr: [T], predicate: T -> Bool) -> [T] { result } -fn fold(arr: [T], init: U, f: (U, T) -> U) -> U { +pub fn fold(arr: [T], init: U, f: (U, T) -> U) -> U { let mut acc = init; for x in arr { acc = f(acc, x); @@ -51,7 +51,7 @@ fn fold(arr: [T], init: U, f: (U, T) -> U) -> U { } /// Conforms to aLib collection/contains spec v1.0 -fn contains(arr: [T], element: T) -> Bool { +pub fn contains(arr: [T], element: T) -> Bool { for x in arr { if x == element { return true; @@ -60,11 +60,11 @@ fn contains(arr: [T], element: T) -> Bool { false } -fn sum(arr: [Int]) -> Int { +pub fn sum(arr: [Int]) -> Int { fold(arr, 0, |acc, x| acc + x) } -fn product(arr: [Int]) -> Int { +pub fn product(arr: [Int]) -> Int { fold(arr, 1, |acc, x| acc * x) } @@ -72,15 +72,15 @@ fn product(arr: [Int]) -> Int { // Comparison and ordering // ============================================================================ -fn min(a: Int, b: Int) -> Int { +pub fn min(a: Int, b: Int) -> Int { if a < b { a } else { b } } -fn max(a: Int, b: Int) -> Int { +pub fn max(a: Int, b: Int) -> Int { if a > b { a } else { b } } -fn clamp(value: Int, min_val: Int, max_val: Int) -> Int { +pub fn clamp(value: Int, min_val: Int, max_val: Int) -> Int { if value < min_val { min_val } else if value > max_val { @@ -94,11 +94,11 @@ fn clamp(value: Int, min_val: Int, max_val: Int) -> Int { // Boolean utilities // ============================================================================ -fn not(b: Bool) -> Bool { +pub fn not(b: Bool) -> Bool { if b { false } else { true } } -fn all(arr: [Bool]) -> Bool { +pub fn all(arr: [Bool]) -> Bool { for b in arr { if not(b) { return false; @@ -107,7 +107,7 @@ fn all(arr: [Bool]) -> Bool { true } -fn any(arr: [Bool]) -> Bool { +pub fn any(arr: [Bool]) -> Bool { for b in arr { if b { return true; @@ -120,7 +120,7 @@ fn any(arr: [Bool]) -> Bool { // Range and iteration utilities // ============================================================================ -fn range(start: Int, end: Int) -> [Int] { +pub fn range(start: Int, end: Int) -> [Int] { let mut result = []; let mut i = start; while i < end { @@ -130,7 +130,7 @@ fn range(start: Int, end: Int) -> [Int] { result } -fn repeat(value: T, n: Int) -> [T] { +pub fn repeat(value: T, n: Int) -> [T] { let mut result = []; let mut i = 0; while i < n { diff --git a/stdlib/result.affine b/stdlib/result.affine index 17078644..0945ed04 100644 --- a/stdlib/result.affine +++ b/stdlib/result.affine @@ -6,7 +6,7 @@ module result; // `Option`/`Result` types + constructors are owned by `prelude` (ADR-011). -use prelude::{Result, Ok, Err, Option, Some, None}; +use prelude::{Result, Ok, Err, Option, Some, None, map}; // This module is the single canonical home for the Result *operations* // (is_ok/is_err/unwrap/unwrap_or/map_ok/map_err/…). #133 removed the @@ -187,7 +187,7 @@ fn partition_results(results: [Result]) -> ([T], [E]) { /// Try to apply function to all elements, collecting errors fn try_map(f: T -> Result, list: [T]) -> Result<[U], E> { - let results = map(f, list); + let results = map(list, f); collect(results) }