feat: debug thunk location

This commit is contained in:
2026-01-24 16:44:28 +08:00
parent 62ec37f3ad
commit 3d315cd050
5 changed files with 42 additions and 23 deletions

View File

@@ -40,6 +40,7 @@ pub(crate) trait CodegenContext {
fn get_current_dir(&self) -> &Path;
fn get_store_dir(&self) -> &str;
fn get_current_source_id(&self) -> usize;
fn get_current_source(&self) -> crate::error::Source;
}
trait EscapeQuote {
@@ -117,9 +118,19 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Ir {
Ir::Arg(x) => format!("arg{}", x.inner.0),
Ir::Let(x) => x.compile(ctx),
Ir::Select(x) => x.compile(ctx),
&Ir::Thunk(Thunk { inner: expr_id, .. }) => {
&Ir::Thunk(Thunk {
inner: expr_id,
span,
}) => {
let inner = ctx.get_ir(expr_id).compile(ctx);
format!("Nix.createThunk(()=>({}),\"expr{}\")", inner, expr_id.0)
format!(
"Nix.createThunk(()=>({}),\"expr{} {}:{}:{}\")",
inner,
expr_id.0,
ctx.get_current_source().get_name(),
usize::from(span.start()),
usize::from(span.end())
)
}
&Ir::ExprRef(ExprRef { inner: expr_id, .. }) => {
format!("expr{}", expr_id.0)

View File

@@ -230,6 +230,9 @@ impl CodegenContext for Ctx {
.checked_sub(1)
.expect("current_source not set")
}
fn get_current_source(&self) -> crate::error::Source {
self.sources.last().expect("current_source not set").clone()
}
fn get_store_dir(&self) -> &str {
self.store.as_store().get_store_dir()
}
@@ -322,8 +325,8 @@ impl DowngradeContext for DowngradeCtx<'_> {
ExprId(self.ctx.irs.len() + self.irs.len() - 1)
}
fn maybe_thunk(&mut self, id: ExprId) -> ExprId {
let ir = if id.0 < self.ctx.irs.len() {
fn get_ir(&self, id: ExprId) -> &Ir {
if id.0 < self.ctx.irs.len() {
self.ctx.irs.get(id.0).expect("unreachable")
} else {
self.irs
@@ -331,7 +334,11 @@ impl DowngradeContext for DowngradeCtx<'_> {
.expect("ExprId out of bounds")
.as_ref()
.expect("maybe_thunk called on an extracted expr")
};
}
}
fn maybe_thunk(&mut self, id: ExprId) -> ExprId {
let ir = self.get_ir(id);
match ir {
Ir::Builtin(_)
| Ir::Builtins(_)
@@ -449,7 +456,7 @@ impl DowngradeContext for DowngradeCtx<'_> {
})
}
fn extract_expr(&mut self, id: ExprId) -> Ir {
fn extract_ir(&mut self, id: ExprId) -> Ir {
let local_id = id.0 - self.ctx.irs.len();
self.irs
.get_mut(local_id)
@@ -458,7 +465,7 @@ impl DowngradeContext for DowngradeCtx<'_> {
.expect("extract_expr called on an already extracted expr")
}
fn replace_expr(&mut self, id: ExprId, expr: Ir) {
fn replace_ir(&mut self, id: ExprId, expr: Ir) {
let local_id = id.0 - self.ctx.irs.len();
let _ = self
.irs

View File

@@ -35,11 +35,7 @@ impl TryFrom<&str> for Source {
impl From<Source> for NamedSource<Arc<str>> {
fn from(value: Source) -> Self {
let name = match value.ty {
SourceType::Eval(_) => "«eval»".into(),
SourceType::Repl(_) => "«repl»".into(),
SourceType::File(path) => path.as_os_str().to_string_lossy().to_string(),
};
let name = value.get_name();
NamedSource::new(name, value.src.clone())
}
}
@@ -75,6 +71,14 @@ impl Source {
.expect("source file must have a parent dir"),
}
}
pub fn get_name(&self) -> String {
match &self.ty {
SourceType::Eval(_) => "«eval»".into(),
SourceType::Repl(_) => "«repl»".into(),
SourceType::File(path) => path.as_os_str().to_string_lossy().to_string(),
}
}
}
#[derive(Error, Debug, Diagnostic)]

View File

@@ -28,8 +28,9 @@ pub trait DowngradeContext {
fn get_sym(&self, id: SymId) -> &str;
fn lookup(&mut self, sym: SymId, span: TextRange) -> Result<ExprId>;
fn extract_expr(&mut self, id: ExprId) -> Ir;
fn replace_expr(&mut self, id: ExprId, expr: Ir);
fn get_ir(&self, id: ExprId) -> &Ir;
fn extract_ir(&mut self, id: ExprId) -> Ir;
fn replace_ir(&mut self, id: ExprId, expr: Ir);
fn reserve_slots(&mut self, slots: usize) -> impl Iterator<Item = ExprId> + Clone + use<Self>;
fn get_current_source(&self) -> Source;
@@ -124,7 +125,7 @@ impl AttrSet {
// If the next attribute is a static string.
if let Some(&id) = self.stcs.get(&ident) {
// If a sub-attrset already exists, recurse into it.
let mut ir = ctx.extract_expr(id);
let mut ir = ctx.extract_ir(id);
let result = ir
.as_mut()
.try_unwrap_attr_set()
@@ -139,7 +140,7 @@ impl AttrSet {
)
})
.and_then(|attrs| attrs._insert(path, name, value, ctx));
ctx.replace_expr(id, ir);
ctx.replace_ir(id, ir);
result?;
} else {
// Create a new sub-attrset because this path doesn't exist yet.

View File

@@ -405,21 +405,17 @@ where
for (sym, slot) in binding_keys.iter().copied().zip(slots.iter()) {
if let Some(&expr) = bindings.get(&sym) {
ctx.replace_expr(
ctx.replace_ir(
*slot,
Thunk {
inner: expr,
// span: ctx.get_span(expr),
// FIXME: span
span: synthetic_span(),
span: ctx.get_ir(expr).span(),
}
.to_ir(),
);
} else {
return Err(Error::downgrade_error(
return Err(Error::internal(
format!("binding '{}' not found", format_symbol(ctx.get_sym(sym))),
ctx.get_current_source(),
synthetic_span(),
));
}
}