feat: rec attrset

This commit is contained in:
2025-08-08 12:12:23 +08:00
parent 67cdcfea33
commit a9cfddbf5c
13 changed files with 147 additions and 180 deletions

View File

@@ -41,7 +41,7 @@ pub trait DowngradeContext {
fn with_expr<T>(&self, id: ExprId, f: impl FnOnce(&Hir, &Self) -> T) -> T;
/// Provides temporary mutable access to an expression.
fn with_expr_mut<T>(&mut self, id: &ExprId, f: impl FnOnce(&mut Hir, &mut Self) -> T) -> T;
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.
@@ -128,7 +128,7 @@ impl Attrs for AttrSet {
match attr {
Attr::Str(ident) => {
// If the next attribute is a static string.
if let Some(id) = self.stcs.get(&ident) {
if let Some(&id) = self.stcs.get(&ident) {
// If a sub-attrset already exists, recurse into it.
ctx.with_expr_mut(id, |expr, ctx| {
expr.as_mut()

View File

@@ -4,7 +4,9 @@
//! They are helpers to the main `Downgrade` trait implementations.
use hashbrown::HashMap;
use hashbrown::hash_map::Entry;
use nixjit_value::format_symbol;
use rnix::ast;
use nixjit_error::{Error, Result};
@@ -128,19 +130,22 @@ pub fn downgrade_inherit(
// If `from` is None, `inherit foo;` becomes `foo = foo;`.
|| Var { sym: ident.clone() }.to_hir(),
// If `from` is Some, `inherit (from) foo;` becomes `foo = from.foo;`.
|expr| {
|&expr| {
Select {
expr: unsafe { expr.clone() },
expr,
attrpath: vec![Attr::Str(ident.clone())],
default: None,
}
.to_hir()
},
);
if stcs.insert(ident, ctx.new_expr(expr)).is_some() {
// TODO: Handle or error on duplicate attribute definitions.
todo!()
}
match stcs.entry(ident) {
Entry::Occupied(occupied) => return Err(Error::EvalError(format!(
"attribute '{}' already defined",
format_symbol(occupied.key())
))),
Entry::Vacant(vacant) => vacant.insert(ctx.new_expr(expr))
};
}
Ok(())
}