Documentation
¶
Overview ¶
Package core provides the shared language runner runtime: profile loading, alias resolution, interpreter discovery and installation, source materialization, and byte-oriented execution. Language-specific profiles and templates are owned by their respective language packages and composed into the public RunnerFiles() view used by runtime integrations.
Package lang provides reusable language runner discovery, registration, installation, and byte-oriented execution primitives. Flow-specific syntax and stream conversion live in the nexssflow subpackage.
Index ¶
- Variables
- func AutoInstallDisabled(ctx context.Context) bool
- func Execute(ctx context.Context, program Program, stdin []byte, executor Executor) (stdout, stderr string, err error)
- func Install(id, version string) (cmd string, args []string, err error)
- func LoadRunners() error
- func Register(l Language)
- func RegisterDefine(d Define) error
- func RegisterRunnerSpec(spec *RunnerSpec) error
- func Resolve(lang *Language, version string) (cmd string, args []string, err error)
- func ResolveAlias(tag string) (id, version string, ok bool)
- func RunnerFiles() fs.FS
- func WithAutoInstallDisabled(ctx context.Context) context.Context
- type Alias
- type Check
- type DefaultExecutor
- type Define
- type Ensure
- type EnsureFunc
- type ExecError
- type Executor
- type ExecutorFunc
- type Language
- type NotInstalledError
- type OSRecipe
- type Preflight
- type Program
- type Report
- type RunnerSpec
- type UnknownLanguageError
- type UnknownTagError
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = xerr.NotFound("interpreter not found")
ErrNotFound is the sentinel from lookPathCmd. Tests assert against this rather than a string match.
var Registry = map[string]*Language{}
Registry is the process-global table of known languages. Populated at init() by LoadRunners (from embedded runners/*.nflow) and at parse time by RegisterDefine (define.go) when @lang.define is used.
Keyed by (ID, Version) — versioned variants of the same language (python "", python "2", python "3") are distinct entries. The unversioned Lookup(id, "") returns the default variant.
Two languages with the same (ID, Version) panic — silent override would let a stale registration win and produce confusing runtime behavior.
Functions ¶
func AutoInstallDisabled ¶
AutoInstallDisabled reports whether automatic interpreter installation is disabled in ctx.
func Execute ¶
func Execute(ctx context.Context, program Program, stdin []byte, executor Executor) (stdout, stderr string, err error)
Execute runs a Program using raw stdin bytes and returns raw stdout bytes as a string. Value serialization/deserialization is intentionally left to the host adapter. Inline source is materialized in a private temporary directory; file-backed programs use their original path and contents.
func Install ¶
Install is the package-level entry point used by `nflow lang install <id>`. Wraps installEnsure so callers don't construct the type.
func LoadRunners ¶
func LoadRunners() error
LoadRunners parses every runners/*.nflow profile from the embed and registers each as a Language. The package calls this once at init; manual repeated calls return a duplicate-registration error.
func Register ¶
func Register(l Language)
Register adds a language to the Registry. Duplicate (ID, Version) panic, matching the project rule: "collisions panic; missing contracts fail loudly."
func RegisterDefine ¶
RegisterDefine adds a user-defined language to the Registry.
Called by the @lang.define directive. Go hosts may also register a language directly before compiling flows.
Returns an error rather than panicking: user-defined languages fail gracefully, while builtins (which the developer shipped intentionally) panic on duplicate registration via Register.
func RegisterRunnerSpec ¶
func RegisterRunnerSpec(spec *RunnerSpec) error
RegisterRunnerSpec validates and registers a runner profile and all of its aliases. Duplicate IDs or aliases return a Kernel Conflict error without partial mutation.
func Resolve ¶
Resolve is the default runtime entry point for "give me a runnable command."
It tries a find-only selector, preferring SelectContext when available. On miss, it calls ensureHook, which installs and re-resolves by default or returns a NotInstalledError if the runner has no recipe or installation fails. Context-scoped internal callers may disable installation without changing this production default. Preflight uses the find-only selector directly and never triggers installation.
func ResolveAlias ¶
ResolveAlias maps a runner keyword to its canonical language ID and version. The returned ok is false for an unknown alias.
func RunnerFiles ¶
RunnerFiles returns the embedded runner profile filesystem. Paths are rooted at "runners/" so adapters can expose the profiles as source modules.
Types ¶
type Alias ¶
Alias maps a runner keyword (for example, "py") to a canonical language ID and version. Aliases are derived from runner profiles, not hand-maintained.
type DefaultExecutor ¶
type DefaultExecutor struct{}
DefaultExecutor runs the selected interpreter with os/exec. Hosts can inject a different Executor into Execute to centralize subprocess policy.
type Define ¶
type Define struct {
ID string // required, e.g. "gleam"
Version string // optional, e.g. "3"
Ext string // required, including dot, e.g. ".gleam"
Aliases []string // optional, e.g. ["gleam", "beam"]
Find []string // required, e.g. ["gleam", "run"]
Stdin string // "json" (default) | "text" | "raw"
Stdout string // "json" (default) | "text" | "raw"
FileTemplate string // optional JSON-in/JSON-out source for .file :autocreate
Install OSRecipe // optional, per-OS install commands
Deps string // optional command template containing {file}
DepsMarker string // optional source marker that selects Deps
}
Define is the in-flow @lang.define directive's data model.
It lets users register a language the bundle doesn't ship built-in, without forking the repo or writing a runner file. Example DSL:
@lang.define "gleam" {
ext: ".gleam"
aliases: ["gleam"]
find: ["gleam run"]
stdin: "json"
stdout: "text"
}
{ "value": "x" } -> gleam"..."
This is the runtime equivalent of a runners/*.nflow file — same fields, same RunnerSpec underneath. Definitions update the process-wide registry and remain registered for the process lifetime; each (ID, Version) and alias must be declared only once.
type Ensure ¶
type Ensure interface {
Ensure(lang *Language, version string) (cmd string, args []string, err error)
}
Ensure is the auto-install seam.
Resolve calls Ensure when a language's Select (find-only) fails. The default installEnsure runs the runner's per-OS recipe and re-resolves the interpreter; tests or hosts can replace the hook when needed.
Pure Go: no nexssp/ensure, no Node.js. Recipes call winget/brew/apt/npm directly. See install.go.
func DefaultEnsure ¶
func DefaultEnsure() Ensure
DefaultEnsure returns the production installer, which executes the current platform's recipe declared by the runner profile and then resolves again.
type EnsureFunc ¶
EnsureFunc adapts a function to the Ensure interface.
type Executor ¶
type Executor interface {
Run(ctx context.Context, cmd string, args []string, stdin []byte) (stdout, stderr string, err error)
}
Executor runs one resolved program and returns stdout and stderr as strings. Implementations must honor context cancellation.
type ExecutorFunc ¶
ExecutorFunc adapts a function to the Executor interface.
type Language ¶
type Language struct {
// ID is the canonical language identifier, e.g. "python".
ID string
// Ext is the file extension used when materializing source to disk,
// including the leading dot, e.g. ".py".
Ext string
// Select is the legacy context-free, find-only selector for languages
// registered directly. Runner profiles use SelectContext instead.
Select func(version string) (cmd string, args []string, err error)
// SelectContext resolves a version while honoring the caller's context.
// Runtime and preflight resolution prefer this selector when available.
SelectContext func(ctx context.Context, version string) (cmd string, args []string, err error)
// Encode serializes the incoming stream value to bytes for stdin.
// JSON is the default; shell/raw languages use text.
Encode func(v any) ([]byte, error)
// Decode parses stdout back into a typed value the next atom sees.
// Takes string (not []byte) to avoid the []byte(string) copy from
// external.ExecResult.Stdout. JSON is the default; shell/raw return string.
Decode func(s string) (any, error)
// contains filtered or unexported fields
}
Language is the runtime view of a runner spec. One per (language, version). Tags are gone by here — runner file aliases are applied at parse time, and from this struct onward every code path speaks the canonical ID ("python"), never the tag ("py").
One struct, every language. New languages add a runners/<id>.nflow file, zero Go changes. See runners.go.
func Lookup ¶
Lookup returns the registered language for an (ID, Version) pair. The exact version is matched — Lookup("python", "3") returns the v3 variant, Lookup("python", "") returns the default.
func (*Language) Spec ¶
func (l *Language) Spec() (RunnerSpec, bool)
Spec returns a copy of the language's runner profile. Languages registered directly without a RunnerSpec return the zero value and false.
type NotInstalledError ¶
type NotInstalledError struct {
ID, Version string
Cause error // optional: why an auto-install attempt failed
}
NotInstalledError is the unified "interpreter missing" error. Preflight groups these into a single Report; the CLI prints the report and aborts.
func (*NotInstalledError) Error ¶
func (e *NotInstalledError) Error() string
func (*NotInstalledError) Unwrap ¶
func (e *NotInstalledError) Unwrap() error
type OSRecipe ¶
type OSRecipe struct {
Windows []string `json:"windows,omitempty"`
Darwin []string `json:"darwin,omitempty"`
Linux []string `json:"linux,omitempty"`
}
OSRecipe holds per-OS install commands. Each entry is a full command line; the first element is the binary, the rest are args.
type Preflight ¶
type Preflight struct {
// Installer, if non-nil, is invoked for missing interpreters. A nil
// Installer keeps preflight find-only.
Installer Ensure
}
Preflight checks interpreter availability for a set of programs. It has no compiler or AST dependency; host adapters decide when and how to invoke it.
type Program ¶
Program describes source to execute with a registered language runner. It contains no parser- or compiler-specific data.
func FileProgramForTag ¶
FileProgramForTag resolves a runner alias and constructs a program backed by an existing source file. The caller resolves the path relative to its own source file and supplies contents for preflight/dependency-marker inspection.
func ProgramForTag ¶
ProgramForTag resolves a runner alias and constructs a generic program. Interpreter discovery is intentionally deferred to Resolve or Execute.
type Report ¶
Report is the result of a preflight pass. Zero Missing entries means every requested interpreter is available (or was installed successfully).
func (Report) SelfTestSkipReason ¶
SelfTestSkipReason returns a skip reason only when missing interpreter tooling is the sole failure; unknown language/configuration errors remain failures.
type RunnerSpec ¶
type RunnerSpec struct {
ID string `json:"id,omitempty"`
Version string `json:"version,omitempty"`
Ext string `json:"ext"`
Aliases []string `json:"aliases,omitempty"`
Find []string `json:"find"`
Stdin string `json:"stdin,omitempty"`
Stdout string `json:"stdout,omitempty"`
FileTemplate string `json:"file_template,omitempty"`
FileTemplateFile string `json:"file_template_file,omitempty"`
FilePathMode string `json:"file_path_mode,omitempty"`
Install OSRecipe `json:"install,omitzero"`
Deps string `json:"deps,omitempty"`
DepsMarker string `json:"deps_marker,omitempty"`
}
RunnerSpec is the data model parsed from a @lang.runner block in a .nflow file. One RunnerSpec per (language, version). The Go side is generic — adding a language means shipping a runner profile and optional template asset, with no runtime-specific Go changes.
Native profile example:
@description "Python runner with JSON streams"
@lang.runner "python" {
ext: ".py"
aliases: ["py", "python"]
find: ["python3", "python", "py -3"]
stdin: "json"
stdout: "json"
file_template_file: "templates/python.py"
}
func ParseRunner ¶
func ParseRunner(src string) (*RunnerSpec, error)
ParseRunner parses one @lang.runner or @lang.define block using native NFlow key/value and list syntax.
func (RunnerSpec) Decode ¶
func (s RunnerSpec) Decode() (func(string) (any, error), error)
Decode resolves the stdout codec name to a function.
func (RunnerSpec) Encode ¶
func (s RunnerSpec) Encode() (func(any) ([]byte, error), error)
Encode resolves the stdin codec name to a function.
func (RunnerSpec) FindCmd ¶
func (s RunnerSpec) FindCmd() (cmd string, args []string, err error)
FindCmd tries each entry in Find via lookPathCmd. The first candidate that resolves to a usable interpreter wins; on Windows, py.exe is probed with its selected version and WSL is probed for a registered Bash distribution.
Each Find entry is split on whitespace; the first token is the binary, the rest are pre-args (for example, "py -3" becomes cmd="py", args=["-3"]). The materialized source path is appended later by the runtime.
func (RunnerSpec) FindCmdContext ¶
FindCmdContext probes interpreter candidates while honoring cancellation.
type UnknownLanguageError ¶
type UnknownLanguageError struct {
ID, Version string
}
UnknownLanguageError is returned by Lookup and ParseTag when the alias resolves to an (ID, Version) pair the Registry has no entry for. It surfaces as a compile-time SourceError via the parser hook.
func (*UnknownLanguageError) Error ¶
func (e *UnknownLanguageError) Error() string
func (*UnknownLanguageError) Unwrap ¶
func (e *UnknownLanguageError) Unwrap() error
type UnknownTagError ¶
type UnknownTagError struct{ Tag string }
UnknownTagError reports an alias which is not registered by a runner.
func (*UnknownTagError) Error ¶
func (e *UnknownTagError) Error() string