Overhaul import loading semantics - #203
Open
rTreutlein wants to merge 21 commits into
Open
rTreutlein wants to merge 21 commits into
rTreutlein wants to merge 21 commits into
Conversation
Imports used to resolve against a single global working_dir set once at startup, so a file imported from another directory could not find its own relative dependencies. load_metta_file now maintains a stack of working directories (pushed on entry, popped via setup_call_cleanup), making both MeTTa and Python imports resolve relative to the file that declares them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
import! previously swallowed every failure via catch(_, fail), so a missing file, a syntax error in a dependency, or a failing Python module import all passed silently. Imports now resolve their target to a canonical path and throw existence_error when it is missing; errors from loading a dependency propagate wrapped with the offending filename. Since a throwing import! no longer fails into backtracking, library/2 now prefers the candidate whose source file actually exists instead of relying on backtracking across registered library paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Importing the same file twice into the same space re-asserted all of its clauses, and two files importing each other recursed until the stack blew. import! now tracks per-space load state keyed by the canonical file path: a loaded entry turns repeated imports into no-ops, a loading entry breaks cycles, and failed loads clear their entry so the source can be repaired and the import retried within the same session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
git-import! piped clone and build output into discarded strings and never checked the exit status, so a failed clone or build step passed silently and left the import broken. Both steps now inherit the caller's stdio and throw process_error on a nonzero exit. The repository path is registered canonicalized and only once, also removing a stray debug print. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Definitions compile expression heads that are not registered functions into plain symbols, so a function imported or defined after its first use is silently never called by the already-compiled expressions. The translator now records atoms it compiles as symbol heads, and registering a function whose name was already compiled that way prints a warning telling the user to move the import or definition above the first use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dent imports Fix issue #181 on top of PR #203. A definition referencing a not-yet-registered function compiles the reference as inert data, so cross-file meaning depended on import order. Scanning imports upfront cannot work: files fetched by git-import! or generated at runtime are invisible to a scan on a fresh machine but visible once a previous run created them, making program behavior depend on leftover on-disk state. Instead, when a function name registers after stored definitions already compiled it as plain data, those definitions are recompiled from their source terms. Definitions then mean the same thing on every machine regardless of import order, including for libraries that only become loadable at runtime. Expressions that already executed cannot be recompiled retroactively and keep the warning.
A (git-dependency url rev [build [basedir]]) form declares a repository the file needs at an exact commit. Declarations are collected after parsing and satisfied before any form runs, the way cargo fetches its locked dependency graph before compiling: checkouts are staged, verified against the pinned commit, retargeted when the pin changes, and refused when locally modified, so a fresh clone and a machine with a leftover checkout behave identically. A checkout may declare its own dependencies in deps.metta at its repository root, which are acquired transitively; the same url pinned to two commits in one run is an error. The machinery lives in src/gitimport.pl; the runnable git-import! in lib_import.pl remains for dynamic acquisition.
This was referenced Jul 23, 2026
Collaborator
currently leads to |
Signed-off-by: Patrick Hammer <patham9@gmail.com>
…but loaded by default
…but loaded by default
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reworks
import!around runtime, in-order resolution. Replaces #201 with a cleaner approach after review discussion.Changes
load_metta_filemaintains a working-directory stack (exception-safe viasetup_call_cleanup), so a file imported from another directory finds its own relative MeTTa and Python dependencies. Previously a single globalworking_dirwas set once at startup.existence_error; syntax errors and Python import failures in dependencies propagate wrapped with the offending filename. Because a throwingimport!no longer backtracks,library/2now prefers the candidate path whose source file exists across all registered library paths.git-import!(unchanged location,lib_import.pl) now checks clone/build exit status and throwsprocess_errorinstead of discarding output; repository paths register canonicalized.Testing
test.sh: all 149 examples pass, no spurious warnings across the corpus (new examples cover relative-import nesting, error surfacing, duplicate/cycle imports, and per-space import identity)python/tests: 5 pass, including new tests for retry-after-failed-import and the use-before-import warning🤖 Generated with Claude Code