chore: comment
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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: ...`.
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
Reference in New Issue
Block a user