chore: comment
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
//! The central evaluation context for the nixjit interpreter.
|
||||
//!
|
||||
//! This module defines the `Context` struct, which holds all the state
|
||||
//! necessary for the evaluation of a Nix expression. It manages the
|
||||
//! Intermediate Representations (IRs), scopes, evaluation stack, and
|
||||
//! the Just-In-Time (JIT) compiler.
|
||||
//!
|
||||
//! The `Context` implements various traits (`DowngradeContext`, `ResolveContext`, etc.)
|
||||
//! to provide the necessary services for each stage of the compilation and
|
||||
//! evaluation pipeline.
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -19,15 +29,22 @@ use nixjit_lir::{Lir, LookupResult, Resolve, ResolveContext};
|
||||
use nixjit_jit::{JITCompiler, JITContext, JITFunc};
|
||||
use replace_with::replace_with_and_return;
|
||||
|
||||
/// Represents a lexical scope during name resolution.
|
||||
enum Scope {
|
||||
/// A `with` expression scope.
|
||||
With,
|
||||
/// A `let` binding scope, mapping variable names to their expression IDs.
|
||||
Let(HashMap<String, ExprId>),
|
||||
/// A function argument scope. `Some` holds the name of the argument set if present.
|
||||
Arg(Option<String>),
|
||||
}
|
||||
|
||||
/// Represents an expression at different stages of compilation.
|
||||
#[derive(Debug, Unwrap)]
|
||||
enum Ir {
|
||||
/// An expression in the High-Level Intermediate Representation (HIR).
|
||||
Hir(Hir),
|
||||
/// An expression in the Low-Level Intermediate Representation (LIR).
|
||||
Lir(Lir),
|
||||
}
|
||||
|
||||
@@ -81,20 +98,37 @@ impl Ir {
|
||||
}
|
||||
}
|
||||
|
||||
/// The main evaluation context.
|
||||
///
|
||||
/// This struct orchestrates the entire Nix expression evaluation process,
|
||||
/// from parsing and semantic analysis to interpretation and JIT compilation.
|
||||
pub struct Context {
|
||||
/// Arena for all expressions, which can be either HIR or LIR.
|
||||
/// `RefCell` is used for interior mutability to allow on-demand resolution.
|
||||
irs: Vec<RefCell<Ir>>,
|
||||
/// Tracks whether an `ExprId` has been resolved from HIR to LIR.
|
||||
resolved: Vec<bool>,
|
||||
/// The stack of lexical scopes used for name resolution.
|
||||
scopes: Vec<Scope>,
|
||||
/// The number of arguments in the current function call scope.
|
||||
args_count: usize,
|
||||
/// A table of primitive operation implementations.
|
||||
primops: Vec<fn(&mut Context, Vec<Value>) -> Result<Value>>,
|
||||
/// Maps a function's body `ExprId` to its parameter definition.
|
||||
funcs: HashMap<ExprId, Param>,
|
||||
/// A dependency graph between expressions.
|
||||
graph: DiGraph<ExprId, ()>,
|
||||
/// Maps an `ExprId` to its corresponding `NodeIndex` in the dependency graph.
|
||||
nodes: Vec<NodeIndex>,
|
||||
|
||||
/// The call stack for function evaluation, where each frame holds arguments.
|
||||
stack: Vec<Vec<Value>>,
|
||||
/// A stack of namespaces for `with` expressions during evaluation.
|
||||
with_scopes: Vec<Rc<HashMap<String, Value>>>,
|
||||
|
||||
/// The Just-In-Time (JIT) compiler.
|
||||
jit: JITCompiler<Self>,
|
||||
/// A cache for JIT-compiled functions, indexed by `ExprId`.
|
||||
compiled: Vec<OnceCell<JITFunc<Self>>>,
|
||||
}
|
||||
|
||||
@@ -111,9 +145,7 @@ impl Default for Context {
|
||||
.enumerate()
|
||||
.map(|(id, (k, _))| (k.to_string(), unsafe { ExprId::from(id) }))
|
||||
.chain(global.iter().enumerate().map(|(idx, (k, _, _))| {
|
||||
(k.to_string(), unsafe {
|
||||
ExprId::from(idx + CONSTS_LEN)
|
||||
})
|
||||
(k.to_string(), unsafe { ExprId::from(idx + CONSTS_LEN) })
|
||||
}))
|
||||
.chain(core::iter::once(("builtins".to_string(), unsafe {
|
||||
ExprId::from(CONSTS_LEN + GLOBAL_LEN + SCOPED_LEN)
|
||||
@@ -162,10 +194,18 @@ impl Default for Context {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Creates a new, default `Context`.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// The main entry point for evaluating a Nix expression string.
|
||||
///
|
||||
/// This function performs the following steps:
|
||||
/// 1. Parses the expression string into an `rnix` AST.
|
||||
/// 2. Downgrades the AST to the High-Level IR (HIR).
|
||||
/// 3. Resolves the HIR to the Low-Level IR (LIR).
|
||||
/// 4. Evaluates the LIR to produce a final `Value`.
|
||||
pub fn eval(mut self, expr: &str) -> Result<nixjit_value::Value> {
|
||||
let root = rnix::Root::parse(expr);
|
||||
if !root.errors().is_empty() {
|
||||
@@ -364,9 +404,7 @@ impl EvalContext for Context {
|
||||
}
|
||||
|
||||
fn call_primop(&mut self, id: nixjit_ir::PrimOpId, args: Vec<Value>) -> Result<Value> {
|
||||
unsafe {
|
||||
(self.primops.get_unchecked(id.raw()))(self, args)
|
||||
}
|
||||
unsafe { (self.primops.get_unchecked(id.raw()))(self, args) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user