refactor: reduce coupling
This commit is contained in:
13
evaluator/nixjit_ir/Cargo.toml
Normal file
13
evaluator/nixjit_ir/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "nixjit_ir"
|
||||
description = "The core data structures for the nixjit intermediate representation (IR)."
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
derive_more = { version = "2.0", features = ["full"] }
|
||||
hashbrown = "0.15"
|
||||
rnix = "0.12"
|
||||
|
||||
nixjit_error = { path = "../nixjit_error" }
|
||||
nixjit_value = { path = "../nixjit_value" }
|
||||
255
evaluator/nixjit_ir/src/lib.rs
Normal file
255
evaluator/nixjit_ir/src/lib.rs
Normal file
@@ -0,0 +1,255 @@
|
||||
//! This crate defines the core data structures for the nixjit Intermediate Representation (IR).
|
||||
//!
|
||||
//! The IR provides a simplified, language-agnostic representation of Nix expressions,
|
||||
//! serving as a bridge between the high-level representation (HIR) and the low-level
|
||||
//! representation (LIR). It defines the fundamental building blocks like expression IDs,
|
||||
//! function IDs, and structures for various expression types (e.g., binary operations,
|
||||
//! attribute sets, function calls).
|
||||
//!
|
||||
//! These structures are designed to be generic and reusable across different stages of
|
||||
//! the compiler.
|
||||
|
||||
use rnix::ast;
|
||||
|
||||
use derive_more::TryUnwrap;
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use nixjit_value::Const as PubConst;
|
||||
|
||||
/// A type-safe wrapper for an index into an expression table.
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ExprId(usize);
|
||||
|
||||
/// A type-safe wrapper for an index into a function table.
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FuncId(usize);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ArgIdx(usize);
|
||||
|
||||
/// Represents a Nix attribute set.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AttrSet {
|
||||
/// Statically known attributes (key is a string).
|
||||
pub stcs: HashMap<String, ExprId>,
|
||||
/// Dynamically computed attributes, where both the key and value are expressions.
|
||||
pub dyns: Vec<(ExprId, ExprId)>,
|
||||
/// `true` if this is a recursive attribute set (`rec { ... }`).
|
||||
pub rec: bool,
|
||||
}
|
||||
|
||||
/// Represents a key in an attribute path.
|
||||
#[derive(Clone, Debug, TryUnwrap)]
|
||||
pub enum Attr {
|
||||
/// A dynamic attribute key, which is an expression that must evaluate to a string.
|
||||
Dynamic(ExprId),
|
||||
/// A static attribute key.
|
||||
Str(String),
|
||||
}
|
||||
|
||||
/// Represents a Nix list.
|
||||
#[derive(Debug)]
|
||||
pub struct List {
|
||||
/// The expressions that are elements of the list.
|
||||
pub items: Vec<ExprId>,
|
||||
}
|
||||
|
||||
/// Represents a "has attribute" check (`?` operator).
|
||||
#[derive(Debug)]
|
||||
pub struct HasAttr {
|
||||
/// The expression to check for the attribute (the left-hand side).
|
||||
pub lhs: ExprId,
|
||||
/// The attribute path to look for (the right-hand side).
|
||||
pub rhs: Vec<Attr>,
|
||||
}
|
||||
|
||||
/// Represents a binary operation.
|
||||
#[derive(Debug)]
|
||||
pub struct BinOp {
|
||||
pub lhs: ExprId,
|
||||
pub rhs: ExprId,
|
||||
pub kind: BinOpKind,
|
||||
}
|
||||
|
||||
/// The kinds of binary operations supported in Nix.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BinOpKind {
|
||||
// Arithmetic
|
||||
Add,
|
||||
Sub,
|
||||
Div,
|
||||
Mul,
|
||||
|
||||
// Comparison
|
||||
Eq,
|
||||
Neq,
|
||||
Lt,
|
||||
Gt,
|
||||
Leq,
|
||||
Geq,
|
||||
|
||||
// Logical
|
||||
And,
|
||||
Or,
|
||||
Impl,
|
||||
|
||||
// Set/String/Path operations
|
||||
Con, // List concatenation (`++`)
|
||||
Upd, // AttrSet update (`//`)
|
||||
|
||||
// Not standard, but part of rnix AST
|
||||
PipeL,
|
||||
PipeR,
|
||||
}
|
||||
|
||||
impl From<ast::BinOpKind> for BinOpKind {
|
||||
fn from(op: ast::BinOpKind) -> Self {
|
||||
use BinOpKind::*;
|
||||
use ast::BinOpKind as kind;
|
||||
match op {
|
||||
kind::Concat => Con,
|
||||
kind::Update => Upd,
|
||||
kind::Add => Add,
|
||||
kind::Sub => Sub,
|
||||
kind::Mul => Mul,
|
||||
kind::Div => Div,
|
||||
kind::And => And,
|
||||
kind::Equal => Eq,
|
||||
kind::Implication => Impl,
|
||||
kind::Less => Lt,
|
||||
kind::LessOrEq => Leq,
|
||||
kind::More => Gt,
|
||||
kind::MoreOrEq => Geq,
|
||||
kind::NotEqual => Neq,
|
||||
kind::Or => Or,
|
||||
kind::PipeLeft => PipeL,
|
||||
kind::PipeRight => PipeR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a unary operation.
|
||||
#[derive(Debug)]
|
||||
pub struct UnOp {
|
||||
pub rhs: ExprId,
|
||||
pub kind: UnOpKind,
|
||||
}
|
||||
|
||||
/// The kinds of unary operations.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UnOpKind {
|
||||
Neg, // Negation (`-`)
|
||||
Not, // Logical not (`!`)
|
||||
}
|
||||
|
||||
impl From<ast::UnaryOpKind> for UnOpKind {
|
||||
fn from(value: ast::UnaryOpKind) -> Self {
|
||||
match value {
|
||||
ast::UnaryOpKind::Invert => UnOpKind::Not,
|
||||
ast::UnaryOpKind::Negate => UnOpKind::Neg,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an attribute selection from an attribute set.
|
||||
#[derive(Debug)]
|
||||
pub struct Select {
|
||||
/// The expression that should evaluate to an attribute set.
|
||||
pub expr: ExprId,
|
||||
/// The path of attributes to select.
|
||||
pub attrpath: Vec<Attr>,
|
||||
/// An optional default value to return if the selection fails.
|
||||
pub default: Option<ExprId>,
|
||||
}
|
||||
|
||||
/// Represents an `if-then-else` expression.
|
||||
#[derive(Debug)]
|
||||
pub struct If {
|
||||
pub cond: ExprId,
|
||||
pub consq: ExprId, // Consequence (then branch)
|
||||
pub alter: ExprId, // Alternative (else branch)
|
||||
}
|
||||
|
||||
/// Represents a function value (a lambda).
|
||||
#[derive(Debug)]
|
||||
pub struct Func {
|
||||
/// The body of the function
|
||||
pub body: ExprId,
|
||||
pub param: Param,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Param {
|
||||
pub ident: Option<String>,
|
||||
pub required: Option<Vec<String>>,
|
||||
pub allowed: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Represents a function call.
|
||||
#[derive(Debug)]
|
||||
pub struct Call {
|
||||
/// The expression that evaluates to the function to be called.
|
||||
pub func: ExprId,
|
||||
/// The list of arguments to pass to the function.
|
||||
pub args: Vec<ExprId>,
|
||||
}
|
||||
|
||||
/// Represents a `with` expression.
|
||||
#[derive(Debug)]
|
||||
pub struct With {
|
||||
/// The namespace to bring into scope.
|
||||
pub namespace: ExprId,
|
||||
/// The expression to be evaluated within the new scope.
|
||||
pub expr: ExprId,
|
||||
}
|
||||
|
||||
/// Represents an `assert` expression.
|
||||
#[derive(Debug)]
|
||||
pub struct Assert {
|
||||
/// The condition to assert.
|
||||
pub assertion: ExprId,
|
||||
/// The expression to return if the assertion is true.
|
||||
pub expr: ExprId,
|
||||
}
|
||||
|
||||
/// Represents the concatenation of multiple string expressions.
|
||||
/// This is typically the result of downgrading an interpolated string.
|
||||
#[derive(Debug)]
|
||||
pub struct ConcatStrings {
|
||||
pub parts: Vec<ExprId>,
|
||||
}
|
||||
|
||||
/// Represents a constant value (e.g., integer, float, boolean, null).
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Const {
|
||||
pub val: PubConst,
|
||||
}
|
||||
|
||||
impl<T: Into<PubConst>> From<T> for Const {
|
||||
fn from(value: T) -> Self {
|
||||
Self { val: value.into() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a simple, non-interpolated string literal.
|
||||
#[derive(Debug)]
|
||||
pub struct Str {
|
||||
pub val: String,
|
||||
}
|
||||
|
||||
/// Represents a variable lookup by its name.
|
||||
#[derive(Debug)]
|
||||
pub struct Var {
|
||||
pub sym: String,
|
||||
}
|
||||
|
||||
/// Represents a path literal.
|
||||
#[derive(Debug)]
|
||||
pub struct Path {
|
||||
/// The expression that evaluates to the string content of the path.
|
||||
/// This can be a simple `Str` or a `ConcatStrings` for interpolated paths.
|
||||
pub expr: ExprId,
|
||||
}
|
||||
Reference in New Issue
Block a user