resolver

package
v1.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package resolver provides file resolution infrastructure for the Scheme compiler. It owns the concrete FileResolver implementations that locate and open source files on the OS filesystem, embedded filesystems, and virtual fs.FS instances.

The resolver package deals in file paths, not library names. Library identity and semantics are handled by the compilation package.

FileResolver is defined in environment.FileResolver and is not redeclared here. The FileEnumerator interface extends resolvers with file discovery capability.

Index

Constants

View Source
const SchemeIncludePathEnv = "SCHEME_INCLUDE_PATH"

SchemeIncludePathEnv is the environment variable name for the Scheme include path.

Variables

This section is empty.

Functions

func IsNotFound added in v1.20.0

func IsNotFound(err error) bool

IsNotFound reports whether err means the file is genuinely absent, which always licenses continuing a search: falling through to the next resolver in a chain, or from a library's .sld to its .scm. (A chain continues past a denial too, under the narrower condition ChainFileResolver.continuesPast states; absence is the unconditional half.)

It accepts both sentinels because both are minted for absence and neither implies the other: werr.ErrFileNotFound is a bare static sentinel with no fs.ErrNotExist in its chain, and a raw fs.ErrNotExist arrives from the virtual-filesystem side without ever being relabelled.

func LibraryExtensions

func LibraryExtensions() []string

LibraryExtensions returns a copy of the recognized Scheme library file extensions.

func SelectAuthorizer added in v1.20.0

func SelectAuthorizer(ctx context.Context, env *environment.EnvironmentFrame) security.Authorizer

SelectAuthorizer returns the Authorizer that governs this resolution. It is the resolver-side selection point for the security policy, and it exists for the same reason SelectLoadStack does: the env a resolver holds is the ROOT env captured once at engine construction, not the caller's. A caller with a stricter policy — a child Namespace, or a root whose authorizer was tightened after construction — can only reach the resolver through ctx.

The two-branch shape here is deliberate and is NOT SelectLoadStack's (whose env fallback was deleted): LoadLibrary is the only installer, so every other caller leaves ctx bare and gets the captured env's authorizer, unchanged.

func SelectLoadStack

func SelectLoadStack(ctx context.Context) *sourceload.LoadStack

SelectLoadStack returns the LoadStack that governs directory-relative resolution for this call. It is the single selection point shared by the FS/OS resolvers (which read the current directory from it) and the (include …) compiler (which pushes the included file onto it), so the push target and the read target are guaranteed to be the same object — that identity is what closes the per-thread include-resolution race.

The stack is carried on ctx and nowhere else, so it is per load CHAIN: concurrent library loads, concurrent (load …) calls on separate SRFI-18 threads, and an embedder's own Engine.ContextWithLoadPath each get their own. Returns nil outside any load, which is not an error — a top-level (include …) with no enclosing load resolves against the search paths.

This used to fall back to a single LoadStack hung off the Namespace when ctx carried none. That stack was shared by every thread in the engine, so two threads loading files in different directories interleaved their pushes and one compiled the other's file — a source substitution, invisible to -race because it is not a data race. The fallback is gone and the per-namespace stack with it; there is one discipline now, not two.

func WalkOSSchemeFiles

func WalkOSSchemeFiles(baseDir string, auth security.Authorizer, fn func(relPath string)) error

WalkOSSchemeFiles walks baseDir on the OS filesystem, calling fn with the slash-separated path of each .sld/.scm file relative to baseDir. Hidden directories and unauthorized files are silently skipped. Returns the WalkDir error so callers can observe unexpected walk failures.

Types

type ChainFileResolver

type ChainFileResolver struct {
	// contains filtered or unexported fields
}

ChainFileResolver tries multiple resolvers in order, falling through to the next on absence, and on a denial only when some later resolver will re-ask under a different source (see continuesPast). Anything else — a permission failure, any other I/O error — propagates immediately, so a higher-priority file that exists but cannot be read is never silently replaced by a lower-priority one.

func NewChainFileResolver

func NewChainFileResolver(resolvers []environment.FileResolver) *ChainFileResolver

NewChainFileResolver creates a resolver that tries each resolver in order. Panics if resolvers is empty.

func (*ChainFileResolver) EnumerateFiles

func (p *ChainFileResolver) EnumerateFiles() ([]string, error)

EnumerateFiles unions file enumerations from all child resolvers that implement FileEnumerator. Results are concatenated in resolver order with no deduplication; ordering implies priority. Best-effort: walk errors are accumulated and returned alongside partial results, matching OSFileResolver and FSFileResolver semantics.

func (*ChainFileResolver) ResolveAndOpen

func (p *ChainFileResolver) ResolveAndOpen(ctx context.Context, path string) (fs.File, string, error)

ResolveAndOpen tries each resolver in order, returning the first successful result. The reported failure is the last resolver's, which is the only one that searched to the end of the chain.

type EmbedFileResolver

type EmbedFileResolver struct {
	// contains filtered or unexported fields
}

EmbedFileResolver resolves files from an embedded filesystem (or any fs.FS). No path resolution or security checks — paths are looked up directly.

EmbedFileResolver does NOT implement FileEnumerator because embedded filesystems typically contain a known, fixed set of files that do not need runtime discovery.

func NewEmbedFileResolver

func NewEmbedFileResolver(fsys fs.FS) *EmbedFileResolver

NewEmbedFileResolver creates a resolver backed by the given filesystem. Panics if fsys is nil.

func (*EmbedFileResolver) ResolveAndOpen

func (p *EmbedFileResolver) ResolveAndOpen(_ context.Context, path string) (fs.File, string, error)

ResolveAndOpen finds a file by name and returns an open handle plus the resolved path.

type FSFileResolver

type FSFileResolver struct {
	// contains filtered or unexported fields
}

FSFileResolver resolves files from a virtual filesystem (fs.FS). Used when an embedder provides WithSourceFS. All paths are relative to the FS root. Absolute paths are rejected.

Resolution priority:

  1. Relative to current load directory (from LoadPathStack)
  2. Library registry search paths
  3. Relative to FS root (path as-is)

func NewFSFileResolver

func NewFSFileResolver(fsys fs.FS, env *environment.EnvironmentFrame) *FSFileResolver

NewFSFileResolver creates a resolver backed by the given filesystem. Panics if fsys is nil.

func (*FSFileResolver) AuthorizedSource added in v1.20.0

func (*FSFileResolver) AuthorizedSource() string

AuthorizedSource reports the source every candidate is authorized under: the virtual filesystem this resolver serves. See SourceGate.

func (*FSFileResolver) EnumerateFiles

func (p *FSFileResolver) EnumerateFiles() ([]string, error)

EnumerateFiles walks the virtual filesystem to discover all .sld/.scm files. When registry search paths are configured, only those directories are walked. When no registry paths exist, the FS root "." is walked as a fallback. Hidden directories (starting with ".") are skipped.

Best-effort: non-existent directories and unauthorized files are skipped. Walk errors are joined and returned alongside partial results.

func (*FSFileResolver) ResolveAndOpen

func (p *FSFileResolver) ResolveAndOpen(ctx context.Context, path string) (fs.File, string, error)

ResolveAndOpen finds a file by name and returns an open handle plus the resolved path.

type FileEnumerator

type FileEnumerator interface {
	EnumerateFiles() ([]string, error)
}

FileEnumerator is an optional interface that FileResolvers can implement to support file discovery. EnumerateFiles returns slash-separated relative paths to .sld/.scm files found by the resolver.

Results are returned in discovery order with no deduplication; callers are responsible for library-level dedup and interpretation of paths.

type OSFileResolver

type OSFileResolver struct {
	// contains filtered or unexported fields
}

OSFileResolver resolves files from the operating system filesystem, using the load path stack, library registry, SCHEME_INCLUDE_PATH, and CWD as fallback directories. It also enforces security authorization.

func NewOSFileResolver

func NewOSFileResolver(env *environment.EnvironmentFrame) *OSFileResolver

NewOSFileResolver creates a resolver that finds files on the OS filesystem.

func (*OSFileResolver) AuthorizedSource added in v1.20.0

func (*OSFileResolver) AuthorizedSource() string

AuthorizedSource reports the source every candidate is authorized under: the host OS filesystem, which security.AccessRequest spells as the zero value. See SourceGate.

func (*OSFileResolver) EnumerateFiles

func (p *OSFileResolver) EnumerateFiles() ([]string, error)

EnumerateFiles walks the OS filesystem to discover .sld/.scm files. Searches osSearchDirs: library registry paths, SCHEME_INCLUDE_PATH, and CWD. Unlike ResolveAndOpen it does NOT consult the load-path stack's current directory, nor fall back to the filesystem root.

Best-effort: non-existent directories and unauthorized files are skipped. Walk errors are joined and returned alongside partial results.

func (*OSFileResolver) ResolveAndOpen

func (p *OSFileResolver) ResolveAndOpen(ctx context.Context, path string) (fs.File, string, error)

ResolveAndOpen finds a file by name and returns an open handle plus the resolved path.

Both arms — absolute path and search-path-relative — order identically: authorize the candidate, then open it. The open goes through os.Root when the authorizer confines filesystem access (see confined.go), so a path component swapped between the check and the open cannot redirect the open out of the confinement root.

type SourceGate added in v1.20.0

type SourceGate interface {
	AuthorizedSource() string
}

SourceGate is implemented by a FileResolver that authorizes every candidate before opening it, and names the security.AccessRequest.TargetSource it authorizes them under ("" = the host OS filesystem).

It exists so ChainFileResolver can tell a refusal it may look past from one it may not: a resolver that implements SourceGate under a different source asks the authorizer a different question, while one that does not implement it asks none at all (EmbedFileResolver) and must never be reached with a denial standing. ChainFileResolver itself deliberately does not implement it: a chain authorizes under as many sources as it has members, so there is no single answer, and the conservative reading of "not gated" is the safe one.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL