refactor: reduce coupling

This commit is contained in:
2025-07-28 21:37:27 +08:00
parent 78e3c5a26e
commit 7afb2a7b1c
53 changed files with 2964 additions and 3444 deletions

View File

@@ -0,0 +1,16 @@
[package]
name = "nixjit_lir"
version = "0.1.0"
edition = "2024"
[dependencies]
derive_more = { version = "2.0", features = ["full"] }
hashbrown = "0.15"
itertools = "0.14"
rnix = "0.12"
nixjit_error = { path = "../nixjit_error" }
nixjit_ir = { path = "../nixjit_ir" }
nixjit_hir = { path = "../nixjit_hir" }
nixjit_macros = { path = "../nixjit_macros" }
nixjit_value = { path = "../nixjit_value" }

View File

@@ -0,0 +1,244 @@
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use nixjit_error::{Error, Result};
use nixjit_hir as hir;
use nixjit_ir::*;
use nixjit_macros::ir;
use nixjit_value::format_symbol;
ir! {
Lir,
AttrSet,
List,
HasAttr,
BinOp,
UnOp,
Select,
If,
Call,
With,
Assert,
ConcatStrings,
Const,
Str,
Var,
Path,
ExprRef(ExprId),
FuncRef(ExprId),
ArgRef(ArgIdx),
}
pub enum LookupResult {
Expr(ExprId),
Arg(ArgIdx),
Unknown,
NotFound,
}
pub trait ResolveContext {
fn new_dep(&mut self, expr: ExprId, dep: ExprId);
fn new_func(&mut self, body: ExprId, param: Param);
fn resolve(&mut self, expr: ExprId) -> Result<()>;
fn lookup(&self, name: &str) -> LookupResult;
fn with_with_env<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> (bool, T);
fn with_let_env<'a, T>(
&mut self,
bindings: impl IntoIterator<Item = (&'a String, &'a ExprId)>,
f: impl FnOnce(&mut Self) -> T,
) -> T;
fn with_param_env<'a, T>(
&mut self,
ident: Option<&'a str>,
f: impl FnOnce(&mut Self) -> T,
) -> T;
}
pub trait Resolve<Ctx: ResolveContext> {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir>;
}
impl<Ctx: ResolveContext> Resolve<Ctx> for hir::Hir {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
use hir::Hir::*;
match self {
AttrSet(x) => x.resolve(ctx),
List(x) => x.resolve(ctx),
HasAttr(x) => x.resolve(ctx),
BinOp(x) => x.resolve(ctx),
UnOp(x) => x.resolve(ctx),
Select(x) => x.resolve(ctx),
If(x) => x.resolve(ctx),
Func(x) => x.resolve(ctx),
Call(x) => x.resolve(ctx),
With(x) => x.resolve(ctx),
Assert(x) => x.resolve(ctx),
ConcatStrings(x) => x.resolve(ctx),
Const(x) => Ok(Lir::Const(x)),
Str(x) => Ok(Lir::Str(x)),
Var(x) => x.resolve(ctx),
Path(x) => x.resolve(ctx),
Let(x) => x.resolve(ctx),
Arg(_) => todo!(),
}
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for AttrSet {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
if self.rec {
todo!()
} else {
for (_, &v) in self.stcs.iter() {
ctx.resolve(v)?;
}
for &(k, v) in self.dyns.iter() {
ctx.resolve(k)?;
ctx.resolve(v)?;
}
Ok(self.to_lir())
}
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for List {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
for &item in self.items.iter() {
ctx.resolve(item)?;
}
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for HasAttr {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.lhs)?;
for attr in self.rhs.iter() {
if let &Attr::Dynamic(expr) = attr {
ctx.resolve(expr)?;
}
}
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for BinOp {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.lhs)?;
ctx.resolve(self.rhs)?;
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for UnOp {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.rhs)?;
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Select {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.expr)?;
for attr in self.attrpath.iter() {
if let &Attr::Dynamic(expr) = attr {
ctx.resolve(expr)?;
}
}
if let Some(expr) = self.default {
ctx.resolve(expr)?;
}
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for If {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.cond)?;
ctx.resolve(self.consq)?;
ctx.resolve(self.alter)?;
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Func {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.with_param_env(self.param.ident.as_deref(), |ctx| ctx.resolve(self.body))?;
ctx.new_func(self.body, self.param);
Ok(Lir::FuncRef(self.body))
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Call {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.func)?;
for &arg in self.args.iter() {
ctx.resolve(arg)?;
}
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for With {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.namespace)?;
let (env_used, res) = ctx.with_with_env(|ctx| ctx.resolve(self.expr));
res?;
if env_used {
Ok(self.to_lir())
} else {
Ok(Lir::ExprRef(self.expr))
}
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Assert {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.assertion)?;
ctx.resolve(self.expr)?;
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for ConcatStrings {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
for &part in self.parts.iter() {
ctx.resolve(part)?;
}
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Var {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
use LookupResult::*;
match ctx.lookup(&self.sym) {
Expr(expr) => Ok(Lir::ExprRef(expr)),
Arg(arg) => Ok(Lir::ArgRef(arg)),
Unknown => Ok(self.to_lir()),
NotFound => Err(Error::ResolutionError(format!(
"undefined variable '{}'",
format_symbol(&self.sym)
))),
}
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for Path {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.resolve(self.expr)?;
Ok(self.to_lir())
}
}
impl<Ctx: ResolveContext> Resolve<Ctx> for hir::Let {
fn resolve(self, ctx: &mut Ctx) -> Result<Lir> {
ctx.with_let_env(self.bindings.iter(), |ctx| {
for &id in self.bindings.values() {
ctx.resolve(id)?;
}
ctx.resolve(self.body)
})?;
Ok(Lir::ExprRef(self.body))
}
}