chore: comment

This commit is contained in:
2025-08-07 21:00:32 +08:00
parent f946cb2fd1
commit 67cdcfea33
24 changed files with 734 additions and 105 deletions

View File

@@ -58,6 +58,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for Expr {
}
}
/// Downgrades an `assert` expression.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Assert {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let assertion = self.condition().unwrap().downgrade(ctx)?;
@@ -66,6 +67,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Assert {
}
}
/// Downgrades an `if-then-else` expression.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::IfElse {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let cond = self.condition().unwrap().downgrade(ctx)?;
@@ -131,6 +133,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Str {
}
}
/// Downgrades a literal value (integer, float, or URI).
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Literal {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
Ok(ctx.new_expr(match self.kind() {
@@ -144,6 +147,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Literal {
}
}
/// Downgrades an identifier to a variable lookup.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Ident {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let sym = self.ident_token().unwrap().to_string();
@@ -151,6 +155,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Ident {
}
}
/// Downgrades an attribute set.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::AttrSet {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let rec = self.rec_token().is_some();
@@ -160,6 +165,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::AttrSet {
}
}
/// Downgrades a list.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::List {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let mut items = Vec::with_capacity(self.items().size_hint().0);
@@ -170,6 +176,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::List {
}
}
/// Downgrades a binary operation.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::BinOp {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let lhs = self.lhs().unwrap().downgrade(ctx)?;
@@ -179,6 +186,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::BinOp {
}
}
/// Downgrades a "has attribute" (`?`) expression.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::HasAttr {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let lhs = self.expr().unwrap().downgrade(ctx)?;
@@ -187,6 +195,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::HasAttr {
}
}
/// Downgrades a unary operation.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::UnaryOp {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let rhs = self.expr().unwrap().downgrade(ctx)?;
@@ -195,6 +204,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::UnaryOp {
}
}
/// Downgrades an attribute selection (`.`).
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Select {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let expr = self.expr().unwrap().downgrade(ctx)?;
@@ -235,6 +245,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LegacyLet {
}
}
/// Downgrades a `let ... in ...` expression.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LetIn {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let body = self.body().unwrap().downgrade(ctx)?;
@@ -243,6 +254,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LetIn {
}
}
/// Downgrades a `with` expression.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::With {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let namespace = self.namespace().unwrap().downgrade(ctx)?;
@@ -251,6 +263,8 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::With {
}
}
/// Downgrades a lambda (function) expression.
/// This involves desugaring pattern-matching arguments into `let` bindings.
impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
fn downgrade(self, ctx: &mut Ctx) -> Result<ExprId> {
let param = downgrade_param(self.param().unwrap(), ctx)?;
@@ -261,6 +275,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
let allowed;
match param {
Param::Ident(id) => {
// Simple case: `x: body`
ident = Some(id);
required = None;
allowed = None;
@@ -270,6 +285,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
ellipsis,
alias,
} => {
// Complex case: `{ a, b ? 2, ... }@args: body`
ident = alias.clone();
required = Some(
formals
@@ -279,7 +295,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
.collect(),
);
allowed = if ellipsis {
None
None // `...` means any attribute is allowed.
} else {
Some(formals.iter().map(|(k, _)| k.clone()).collect())
};
@@ -319,7 +335,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
}
}
let param = ir::Param {
let param = IrParam {
ident,
required,
allowed,

View File

@@ -6,10 +6,11 @@
//! towards the lower-level IR (`nixjit_lir`).
//!
//! The key components are:
//! - `Hir`: An enum representing all possible expression types in the HIR.
//! - `Hir`: An enum representing all possible expression types in the HIR. This is
//! generated by the `ir!` macro.
//! - `Downgrade`: A trait for converting `rnix::ast` nodes into HIR expressions.
//! - `DowngradeContext`: A trait that provides the necessary context for the conversion,
//! such as allocating new expressions and functions.
//! such as allocating new expressions.
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use hashbrown::HashMap;
@@ -17,7 +18,7 @@ use hashbrown::HashMap;
use nixjit_error::{Error, Result};
use nixjit_ir::{
Assert, Attr, AttrSet, BinOp, Call, ConcatStrings, Const, ExprId, Func, HasAttr, If, List,
Path, Select, Str, UnOp, Var, With,
Param as IrParam, Path, Select, Str, UnOp, Var, With,
};
use nixjit_macros::ir;
use nixjit_value::format_symbol;
@@ -30,7 +31,7 @@ pub use downgrade::Downgrade;
/// A context for the AST-to-HIR downgrading process.
///
/// This trait abstracts the storage of HIR expressions and functions, allowing the
/// This trait abstracts the storage of HIR expressions, allowing the
/// `downgrade` implementations to be generic over the specific context implementation.
pub trait DowngradeContext {
/// Allocates a new HIR expression in the context and returns its ID.
@@ -43,6 +44,8 @@ pub trait DowngradeContext {
fn with_expr_mut<T>(&mut self, id: &ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T;
}
// The `ir!` macro generates the `Hir` enum and related structs and traits.
// This reduces boilerplate for defining the IR structure.
ir! {
Hir,
@@ -80,10 +83,12 @@ ir! {
Path,
// Represents a `let ... in ...` binding.
Let { pub bindings: HashMap<String, ExprId>, pub body: ExprId },
// Represents a function argument lookup.
// Represents a function argument lookup within the body of a function.
Arg,
}
/// A placeholder struct for the `Arg` HIR variant. It signifies that at this point
/// in the expression tree, we should be looking up a function argument.
#[derive(Debug)]
pub struct Arg;
@@ -91,8 +96,8 @@ pub struct Arg;
trait Attrs {
/// Inserts a value into the attribute set at a given path.
///
/// # Example
/// `insert([a, b], value)` corresponds to `a.b = value;`.
/// This method handles the creation of nested attribute sets as needed.
/// For example, `insert([a, b], value)` on an empty set results in `{ a = { b = value; }; }`.
fn insert(
&mut self,
path: Vec<Attr>,
@@ -129,10 +134,10 @@ impl Attrs for AttrSet {
expr.as_mut()
.try_unwrap_attr_set()
.map_err(|_| {
// This path segment exists but is not an attrset.
// This path segment exists but is not an attrset, which is an error.
Error::DowngradeError(format!(
r#"attribute '{}' already defined"#,
format_symbol(&ident)
"attribute '{}' already defined but is not an attribute set",
format_symbol(ident)
))
})
.and_then(|attrs| attrs._insert(path, name, value, ctx))
@@ -147,7 +152,8 @@ impl Attrs for AttrSet {
Ok(())
}
Attr::Dynamic(dynamic) => {
// If the next attribute is a dynamic expression.
// If the next attribute is a dynamic expression, we must create a new sub-attrset.
// We cannot merge with existing dynamic attributes at this stage.
let mut attrs = AttrSet::default();
attrs._insert(path, name, value, ctx)?;
self.dyns.push((dynamic, ctx.new_expr(attrs.to_hir())));
@@ -160,8 +166,8 @@ impl Attrs for AttrSet {
Attr::Str(ident) => {
if self.stcs.insert(ident.clone(), value).is_some() {
return Err(Error::DowngradeError(format!(
r#"attribute '{}' already defined"#,
format_symbol(&ident)
"attribute '{}' already defined",
format_symbol(ident)
)));
}
}
@@ -186,6 +192,7 @@ impl Attrs for AttrSet {
}
}
/// Represents the different kinds of parameters a function can have in the HIR stage.
#[derive(Debug)]
enum Param {
/// A simple parameter, e.g., `x: ...`.

View File

@@ -10,9 +10,8 @@ use rnix::ast;
use nixjit_error::{Error, Result};
use nixjit_ir::{Attr, AttrSet, ConcatStrings, ExprId, Select, Str, Var};
use super::ToHir;
use super::downgrade::Downgrade;
use super::{Attrs, DowngradeContext, Param};
use super::{Attrs, DowngradeContext, Param, ToHir};
/// Downgrades a function parameter from the AST.
pub fn downgrade_param(param: ast::Param, ctx: &mut impl DowngradeContext) -> Result<Param> {
@@ -215,7 +214,7 @@ pub fn downgrade_static_attrpathvalue(
let path = downgrade_attrpath(value.attrpath().unwrap(), ctx)?;
if path.iter().any(|attr| matches!(attr, Attr::Dynamic(_))) {
return Err(Error::DowngradeError(
"dynamic attributes not allowed".to_string(),
"dynamic attributes not allowed in let bindings".to_string(),
));
}
let value = value.value().unwrap().downgrade(ctx)?;