Expand description
The Nix module system — typed border for the option-merge lattice.
This module names the load-bearing gap that blocks sui from
evaluating NixOS, nix-darwin, and home-manager configurations.
cppnix’s lib.evalModules runs a fixed-point over a set of
modules, each declaring options (typed slots) and config
(definitions for those slots) plus optional imports (recursive
module inclusion). The result is a merged config attrset that
system.build.toplevel (and its kin) consume.
Per the constructive-substrate-engineering pattern, the algorithm
lives here as a typed Rust border + a Lisp spec — both engines
will eventually drive the same (defmodule-eval-algorithm …),
so they cannot drift. The implementation in sui-eval is M2
work; today this module pins down the typed contract every M2
implementation must satisfy.
§Authoring surface
Three keyword forms compose into the full algorithm:
-
(defoption-type :name "..." :merge-strategy ... :check-kind ...)declares a type in the option-type registry (bool,int,str,path,listOf<T>,attrsOf<T>,submodule,oneOf [...],nullOr T,attrs,any). Themerge-strategydetermines how multiple definitions of the same option combine; thecheck-kinddetermines acceptance. -
(defpriority :name "..." :level N :origin ...)declares one priority rank in the priority lattice (mkDefault 1000,mkOverride 0,mkForce 50, normal=100 by default). Higherlevel= lower priority (matches cppnix). -
(defmodule-eval-algorithm cppnix-module-eval :name ... :phases (...))declares the fixed-point pipeline: collect-modules, resolve-imports, evaluate-options, group-definitions, resolve-priorities, merge-per-type, type-check, emit-config.
Future M2 implementation: replace the apply() stub with a real
interpreter that walks the phases against an evalModulesArgs.
Both sui-eval and sui-bytecode will call exactly that
function, with exactly the same spec.
Structs§
- Canonical
Specs - The three typed surfaces, loaded from one Lisp file.
- Definition
- One config definition — a value assigned to an option path, with
a priority rank. Wrappers like
mkDefault/mkForce/mkOverride Nproduce these directly with adjustedpriority. - Eval
Modules Args - Legacy
EvalModulesArgs— kept for backwards compatibility with theapply()surface. New code uses theModule+eval_modulesAPI directly. - Module
- A single module — the cppnix
{ options, config, imports }authoring shape, typed. - Module
Eval Algorithm - The module-evaluation algorithm authored as
(defmodule-eval-algorithm …). Phases compose left-to-right over anEvalModulesArgsscratchpad; later phases consume earlier-bound slots. - Module
Phase - One phase of the module-evaluation pipeline. Mirrors the shape
of
crate::derivation::Phasefor visual + cognitive consistency across spec domains. - Option
Decl - One option declaration — what cppnix’s
mkOptionreturns. - Option
Type Spec - One entry in the option-type registry. Each cppnix type
(
lib.types.<X>) becomes one(defoption-type …)form. - Priority
Rank - One rank in the priority lattice. cppnix uses
mkDefault 1000(lowest),default 100,mkOverride 50,mkForce 50— lowerlevelvalue = higher priority. This typed border lets the authored spec declare the canonical ranks once.
Enums§
- Merge
Strategy - How multiple definitions of one option fold into one value.
- Module
Phase Kind - The closed set of operations any module-eval algorithm composes. Adding a new variant IS adding a new primitive to the spec language.
- Priority
Origin - Where a definition’s priority comes from.
- Type
Check Kind - Per-definition acceptance check. Run before merging.
Constants§
Functions§
- apply
- Legacy
apply()— kept for backwards compatibility with the previous typed-NotYet API surface. Returns a typed not-yet error since the typed pipeline driven byalgo.phasesrequires the sui-eval Value type that lands at M2.1. New code should useeval_modulesdirectly. - eval_
modules - Evaluate a list of modules + their option-type registry, and return the merged config. M2.0 implementation: covers LastWins (bool, int, str, path, package, null), Concatenate (listOf), AttrsetMerge (attrsOf, attrs), and priority resolution (mkForce < normal < mkDefault). Submodules + recursion + transitive imports are M2.1 work.
- flatten_
imports - Flatten a tree of modules by resolving
importstransitively. Theresolverclosure receives an import name and must return the corresponding Module; returningNoneerrors. Imports are deduplicated by name — the same name imported from multiple modules contributes its options + config exactly once. - load_
canonical - Compile the canonical module-system specs. Returns
(algorithms, option_types, priorities).
Type Aliases§
- Config
- The output of
eval_modules— a path-keyed config attrset. - NixValue
- The substrate’s value type for module-system computation. M2.0
uses
serde_json::Valuebecause it covers Nix’s literal types (bool, int/float, string, list, attrset, null) with no extra machinery. When sui-eval consumes this layer (M2.1), it’ll swap to its lazyValuetype via an adapter trait.