From 6bf902876325db28d1c1c7b85ac2de41c31af543 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 17 May 2026 06:46:52 +0100 Subject: [PATCH] fix(stdlib): single-ownership dedup of prelude/option/result (#133) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ADR-011 (#132): one canonical binding per name, module-owned. - prelude.affine: `module prelude;`. Keeps the core sum types `Option`/`Result` (+ constructors) as their canonical home and the generic list/numeric utilities. Removes the 8 duplicate/conflicting Option/Result *operations* it previously also defined (is_some, is_none, unwrap, unwrap_or, is_ok, is_err, unwrap_result, unwrap_or_result). - option.affine: `module option;` + `use prelude::{Option, Some, None, Result, Ok, Err};`. Now the single canonical home for Option ops. - result.affine: `module result;` + `use prelude::{Result, Ok, Err, Option, Some, None};`. Single canonical home for Result ops. The previous flat-namespace conflicts (`prelude.map(arr,f)` vs `option.map(f,opt)`; `prelude.unwrap`(Option) vs `result.unwrap`(Result)) are resolved by module ownership — each is now `module::name`, exactly one definition per owning module. Verified: no leftover dup defs, no prelude util calls a removed op, full suite green (214 tests). Note: this removes the prelude `unwrap`/`unwrap_result` that #134 (PR #150) patched; the sound, panicking versions are `option::unwrap` and `result::unwrap` (already correct). #150's regression tests remain valid against those. Merge-order: if #150 lands first, resolve the modify/delete in prelude.affine in favour of this deletion. Closes #133 Refs #128, #132 Co-Authored-By: Claude Opus 4.7 (1M context) --- stdlib/option.affine | 9 +++++- stdlib/prelude.affine | 72 +++++++------------------------------------ stdlib/result.affine | 10 +++++- 3 files changed, 28 insertions(+), 63 deletions(-) diff --git a/stdlib/option.affine b/stdlib/option.affine index 6af0420..001827a 100644 --- a/stdlib/option.affine +++ b/stdlib/option.affine @@ -3,7 +3,14 @@ // // Option - Utilities for Option type -// Option type is defined in prelude, but here are utilities +module option; + +// `Option`/`Result` types + constructors are owned by `prelude` (ADR-011). +use prelude::{Option, Some, None, Result, Ok, Err}; + +// This module is the single canonical home for the Option *operations* +// (is_some/is_none/unwrap/unwrap_or/map/filter/contains/…). #133 removed +// the duplicate copies that previously also lived in prelude.affine. // ============================================================================ // Combinators diff --git a/stdlib/prelude.affine b/stdlib/prelude.affine index cd62a4f..3dfed1b 100644 --- a/stdlib/prelude.affine +++ b/stdlib/prelude.affine @@ -2,74 +2,24 @@ // AffineScript Standard Library - Prelude // Common functions and utilities automatically available +module prelude; + // ============================================================================ -// Option type - represents optional values +// Core sum types (canonical home — ADR-011) +// +// `Option` and `Result` (and their constructors) are owned here, the +// foundational module. The `option` / `result` modules provide the +// *operations* over them and `use prelude::{...}` for the types. The +// duplicate/conflicting Option/Result ops that previously lived here +// (is_some, is_none, unwrap, unwrap_or, is_ok, is_err, unwrap_result, +// unwrap_or_result) were removed in #133: option::* and result::* are +// the single canonical bindings for those. // ============================================================================ type Option = Some(T) | None -fn is_some(opt: Option) -> Bool { - match opt { - Some(_) => true, - None => false - } -} - -fn is_none(opt: Option) -> Bool { - match opt { - Some(_) => false, - None => true - } -} - -fn unwrap(opt: Option) -> T { - match opt { - Some(value) => value, - None => panic("Called unwrap on None") - } -} - -fn unwrap_or(opt: Option, default: T) -> T { - match opt { - Some(value) => value, - None => default - } -} - -// ============================================================================ -// Result type - represents success or failure -// ============================================================================ - type Result = Ok(T) | Err(E) -fn is_ok(res: Result) -> Bool { - match res { - Ok(_) => true, - Err(_) => false - } -} - -fn is_err(res: Result) -> Bool { - match res { - Ok(_) => false, - Err(_) => true - } -} - -fn unwrap_result(res: Result) -> T { - match res { - Ok(value) => value, - Err(_) => panic("Called unwrap on Err") - } -} - -fn unwrap_or_result(res: Result, default: T) -> T { - match res { - Ok(value) => value, - Err(_) => default - } -} - // ============================================================================ // List utilities // ============================================================================ diff --git a/stdlib/result.affine b/stdlib/result.affine index bfb03f6..32cce91 100644 --- a/stdlib/result.affine +++ b/stdlib/result.affine @@ -3,7 +3,15 @@ // // Result - Error handling with Result type -// Result type is defined in prelude, but here are utilities +module result; + +// `Option`/`Result` types + constructors are owned by `prelude` (ADR-011). +use prelude::{Result, Ok, Err, Option, Some, None}; + +// 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 +// duplicate/redundant copies (is_ok/is_err/unwrap_result/unwrap_or_result) +// that previously also lived in prelude.affine. // ============================================================================ // Constructors and Conversions