refactor: with_thunk_scope

This commit is contained in:
2026-02-08 12:41:34 +08:00
parent 1346ae5405
commit d09b84676c
2 changed files with 62 additions and 52 deletions

View File

@@ -518,7 +518,7 @@ impl DowngradeContext for DowngradeCtx<'_> {
fn downgrade(mut self, root: rnix::ast::Expr) -> Result<ExprId> {
use crate::ir::TopLevel;
let body = root.downgrade(&mut self)?;
let thunks = self.pop_thunk_scope();
let thunks = self.thunk_scopes.pop().expect("no thunk scope left???");
let span = self.get_ir(body).span();
let top_level = self.new_expr(TopLevel { body, thunks, span }.to_ir());
self.ctx.irs.extend(self.irs);
@@ -553,14 +553,16 @@ impl DowngradeContext for DowngradeCtx<'_> {
f(guard.as_ctx())
}
fn push_thunk_scope(&mut self) {
fn with_thunk_scope<F, R>(&mut self, f: F) -> (R, Vec<(ExprId, ExprId)>)
where
F: FnOnce(&mut Self) -> R,
{
self.thunk_scopes.push(Vec::new());
}
fn pop_thunk_scope(&mut self) -> Vec<(ExprId, ExprId)> {
self.thunk_scopes
.pop()
.expect("pop_thunk_scope without active scope")
let ret = f(self);
(
ret,
self.thunk_scopes.pop().expect("no thunk scope left???"),
)
}
fn register_thunk(&mut self, slot: ExprId, inner: ExprId) {

View File

@@ -18,6 +18,7 @@ pub trait DowngradeContext {
fn new_expr(&mut self, expr: Ir) -> ExprId;
fn new_arg(&mut self, span: TextRange) -> ExprId;
fn maybe_thunk(&mut self, id: ExprId) -> ExprId;
fn register_thunk(&mut self, slot: ExprId, inner: ExprId);
fn new_sym(&mut self, sym: String) -> SymId;
fn get_sym(&self, id: SymId) -> Symbol<'_>;
@@ -37,10 +38,9 @@ pub trait DowngradeContext {
fn with_with_scope<F, R>(&mut self, namespace: ExprId, f: F) -> R
where
F: FnOnce(&mut Self) -> R;
fn push_thunk_scope(&mut self);
fn pop_thunk_scope(&mut self) -> Vec<(ExprId, ExprId)>;
fn register_thunk(&mut self, slot: ExprId, inner: ExprId);
fn with_thunk_scope<F, R>(&mut self, f: F) -> (R, Vec<(ExprId, ExprId)>)
where
F: FnOnce(&mut Self) -> R;
}
pub trait Downgrade<Ctx: DowngradeContext> {
@@ -419,48 +419,56 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Lambda {
let raw_param = self.param().unwrap();
let arg = ctx.new_arg(raw_param.syntax().text_range());
ctx.push_thunk_scope();
let param;
let body;
match raw_param {
ast::Param::IdentParam(id) => {
// Simple case: `x: body`
let param_sym = ctx.new_sym(id.to_string());
param = None;
// Downgrade body in Param scope
body = ctx
.with_param_scope(param_sym, arg, |ctx| self.body().unwrap().downgrade(ctx))?;
}
ast::Param::Pattern(pattern) => {
let alias = pattern
.pat_bind()
.map(|alias| ctx.new_sym(alias.ident().unwrap().to_string()));
let ellipsis = pattern.ellipsis_token().is_some();
let pat_entries = pattern.pat_entries();
let PatternBindings {
body: inner_body,
required,
optional,
} = downgrade_pattern_bindings(pat_entries, alias, arg, ctx, |ctx, _| {
self.body().unwrap().downgrade(ctx)
})?;
param = Some(Param {
required,
optional,
ellipsis,
});
body = inner_body;
}
struct Ret {
param: Option<Param>,
body: ExprId,
}
let thunks = ctx.pop_thunk_scope();
let (ret, thunks) = ctx.with_thunk_scope(|ctx| {
let param;
let body;
match raw_param {
ast::Param::IdentParam(id) => {
// Simple case: `x: body`
let param_sym = ctx.new_sym(id.to_string());
param = None;
// Downgrade body in Param scope
body = ctx.with_param_scope(param_sym, arg, |ctx| {
self.body().unwrap().downgrade(ctx)
})?;
}
ast::Param::Pattern(pattern) => {
let alias = pattern
.pat_bind()
.map(|alias| ctx.new_sym(alias.ident().unwrap().to_string()));
let ellipsis = pattern.ellipsis_token().is_some();
let pat_entries = pattern.pat_entries();
let PatternBindings {
body: inner_body,
required,
optional,
} = downgrade_pattern_bindings(pat_entries, alias, arg, ctx, |ctx, _| {
self.body().unwrap().downgrade(ctx)
})?;
param = Some(Param {
required,
optional,
ellipsis,
});
body = inner_body;
}
}
Result::Ok(Ret { param, body })
});
let Ret { param, body } = ret?;
let span = self.syntax().text_range();
Ok(ctx.new_expr(
Func {