commit e35b1b1a16b71422e03f71aadfd524f99fdac32b
parent b4426ef0ccab4bb22add7c35ce5b2547994e28a4
Author: James Eversole <james@eversole.co>
Date: Tue, 13 Oct 2026 20:12:40 -0500
Remove fixture-only patterns dependency from IO compiler closure
Unpublished source candidate. Nix fast gate, current-source IO dependency controls, and native server integration pass. Compiler pair, fixture relocation/publication and demo-site refresh follow at acceptance.
Diffstat:
6 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/bootstrap/compiler-source-map.v1 b/bootstrap/compiler-source-map.v1
@@ -2,7 +2,7 @@ arboricx.source-map.v1
native source_map source.map lib/source/map.tri prelude,io,source_object,source_module,source_resolve,source_build
native source_unit source.unit lib/source/unit.tri prelude,parser,source_order,source_compile,source_program,source_resolve,source_ast,source_stable
native prelude prelude lib/prelude.tri base,bytes,conversions
-native io io lib/io.tri base,patterns
+native io io lib/io.tri base
native source_object source.object lib/source/object.tri prelude,io,native_math
native source_module source.module lib/source/module.tri prelude,io,source_object,source_unit,source_resolve,source_lexer,parser
native source_resolve source.resolve lib/source/resolve.tri prelude,parser,source_parser,source_ast,source_lexer,source_core,source_equations,source_pattern
@@ -15,7 +15,6 @@ native source_ast source.ast lib/source/ast.tri prelude,source_lexer
native base base lib/base.tri native_math
native bytes bytes lib/bytes.tri base
native conversions conversions lib/conversions.tri base,native_math
-native patterns patterns lib/patterns.tri base
native source_lexer source.lexer lib/source/lexer.tri prelude,parser,lexer,native_math
native source_parser source.parser lib/source/parser.tri prelude,parser,source_lexer,source_ast,source_equations
native source_core source.core lib/source/core.tri prelude
diff --git a/docs/validation.md b/docs/validation.md
@@ -41,6 +41,20 @@ The compiled-source smoke example is in
It checks the native compiler-to-inspector path separately from independent wire
fixtures; inspection itself never loads a compiler or executes an exported tree.
+### Current-source IO dependencies
+
+```sh
+nix build .#
+PYTHONDONTWRITEBYTECODE=1 python3 test/io_dependencies.py result/bin/tricu
+```
+
+This opt-in probe compiles current `io`, `base`, and `native_math` sources with
+only those modules present in a temporary workspace. It checks IO constructor
+and conditional results and rejects an explicit import of the absent `patterns`
+module. It does not rebuild or publish compiler/support fixtures. The fast host
+policy tests separately check that the working compiler map is an exact closure
+and that IO depends only on `base`.
+
### Batch development loop
Agree on a substantial related module group, its intended interface/behavior
diff --git a/flake.nix b/flake.nix
@@ -71,7 +71,7 @@
mkdir workspace
${pkgs.lib.concatMapStringsSep "\n" (name:
"cp ${./lib}/${name}.tri workspace/${name}.tri") [
- "base" "prelude" "bytes" "conversions" "patterns" "io"
+ "base" "prelude" "bytes" "conversions" "io"
"parser" "http" "socket"
]}
cp ${./lib/math/native.tri} workspace/native_math.tri
diff --git a/lib/io.tri b/lib/io.tri
@@ -1,10 +1,6 @@
!import base *
-!import patterns *
!export *
--- Temporary build dependency: patterns remains in the compiler fixture cohort.
--- IO bodies do not use it; remove this edge when that cohort is split.
-
-- IO constructors for host-interpreted interaction trees.
-- Free-monad style: Bind is the single sequencing mechanism.
diff --git a/test/io_dependencies.py b/test/io_dependencies.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+"""Opt-in current-source IO dependency regression with the packaged compiler.
+
+No patterns source, ambient workspace, recovery frontend, or fixture publication.
+Usage: python3 test/io_dependencies.py result/bin/tricu
+"""
+import argparse
+from pathlib import Path
+import shutil
+import subprocess
+import tempfile
+
+ROOT = Path(__file__).resolve().parent.parent
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('tricu', type=Path)
+ args = parser.parse_args()
+ host = str(args.tricu.resolve())
+ with tempfile.TemporaryDirectory(prefix='tricu-io-dependencies-') as temporary:
+ workspace = Path(temporary)
+ for name, relative in [('base', 'lib/base.tri'), ('io', 'lib/io.tri'),
+ ('native_math', 'lib/math/native.tri')]:
+ shutil.copyfile(ROOT / relative, workspace / (name + '.tri'))
+ source = workspace / 'main.tri'
+ # Exercise actual IO definitions in a workspace lacking patterns.
+ source.write_text('''!import base *
+!import io as IO
+!export main
+main = if (and? (equal? (IO.pure 7) (pair 0 7))
+ (and? (equal? (IO.when true (IO.pure 9)) (IO.pure 9))
+ (and? (equal? (IO.unless true (IO.pure 9)) (IO.pure t))
+ (equal? (IO.putStr "hello") (pair 10 "hello"))))) 42 0
+''')
+ command = [host, 'eval', str(source), '--store', str(workspace / 'store'),
+ '--format', 'number', '+RTS', '-N1', '-M2048m', '-RTS']
+ reply = subprocess.run(command, cwd=workspace, capture_output=True,
+ text=True, timeout=180)
+ assert reply.returncode == 0, (reply.stdout, reply.stderr)
+ assert reply.stdout.strip() == '42', (reply.stdout, reply.stderr)
+ # A used missing dependency must still fail: this is not a relaxed
+ # resolver or an ambient-source fallback.
+ source.write_text('!import patterns *\n!export main\nmain = otherwise t\n')
+ reply = subprocess.run(command, cwd=workspace, capture_output=True,
+ text=True, timeout=180)
+ assert reply.returncode != 0, (reply.stdout, reply.stderr)
+ print('Current IO compiles without patterns; constructor/conditional and missing-dependency controls pass.')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/unit.py b/test/unit.py
@@ -610,6 +610,16 @@ class SupportPublicationControls(unittest.TestCase):
self.assertEqual(list(Path(directory).iterdir()), [marker])
+class CompilerDependencyTests(unittest.TestCase):
+ def test_current_map_is_exact_compiler_closure_without_patterns(self):
+ from bootstrap_generations import source_map
+ _, entries, required = source_map(
+ ROOT / 'bootstrap/compiler-source-map.v1', ROOT, 'source_map')
+ self.assertEqual(entries['io'][2], ['base'])
+ self.assertNotIn('patterns', entries)
+ self.assertEqual(set(entries), required)
+
+
class FixtureSourceTests(unittest.TestCase):
def setUp(self):
from fixture_sources import digest