refactor(downgrade): MaybeThunk

This commit is contained in:
2026-04-12 16:19:29 +08:00
parent e34cfc7add
commit 9d4c37950e
5 changed files with 226 additions and 221 deletions
+32 -22
View File
@@ -7,7 +7,7 @@ use fix_codegen::{BytecodeContext, InstructionPtr};
use fix_common::{StringId, Symbol};
use fix_error::{Error, Result, Source};
use fix_ir::downgrade::{Downgrade as _, DowngradeContext};
use fix_ir::{Ir, IrRef, RawIrRef, ThunkId};
use fix_ir::{Ir, IrRef, MaybeThunk, RawIrRef, ThunkId};
use fix_vm::{ForceMode, StaticValue, Vm, VmContext};
use ghost_cell::{GhostCell, GhostToken};
use hashbrown::{HashMap, HashSet};
@@ -294,56 +294,66 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
IrRef::new(self.bump.alloc(GhostCell::new(expr)))
}
fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> IrRef<'id, 'ir> {
if !should_thunk(ir, &self.token) {
return ir;
fn maybe_thunk(&mut self, ir: IrRef<'id, 'ir>) -> MaybeThunk {
use MaybeThunk::*;
match *ir.borrow(&self.token) {
Ir::Builtin(x) => return Builtin(x),
Ir::Int(x) => return Int(x),
Ir::Float(x) => return Float(x),
Ir::Bool(x) => return Bool(x),
Ir::Str(x) => return Str(x),
Ir::Thunk(x) => return Thunk(x),
Ir::Arg { layer } => return Arg { layer },
Ir::Builtins => return Builtins,
Ir::Null => return Null,
_ => (),
}
let id = ThunkId(*self.thunk_count);
*self.thunk_count = self.thunk_count.checked_add(1).expect("thunk id overflow");
self.thunk_scopes
.last_mut()
.expect("no active cache scope")
.add_binding(id, ir, &self.token);
IrRef::alloc(self.bump, Ir::Thunk(id))
Thunk(id)
}
fn new_sym(&mut self, sym: String) -> StringId {
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId {
StringId(self.strings.get_or_intern(sym))
}
fn get_sym(&self, id: StringId) -> Symbol<'_> {
fn resolve_sym(&self, id: StringId) -> Symbol<'_> {
self.strings.resolve(id.0).expect("no symbol found").into()
}
fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result<IrRef<'id, 'ir>> {
fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result<MaybeThunk> {
for scope in self.scopes.iter().rev() {
match scope {
&Scope::Global(global_scope) => {
use MaybeThunk::*;
if let Some(expr) = global_scope.get(&sym) {
let ir = match expr {
Ir::Builtins => Ir::Builtins,
Ir::Builtin(s) => Ir::Builtin(*s),
Ir::Bool(b) => Ir::Bool(*b),
Ir::Null => Ir::Null,
let val = match expr {
Ir::Builtins => Builtins,
Ir::Builtin(s) => Builtin(*s),
Ir::Bool(b) => Bool(*b),
Ir::Null => Null,
_ => unreachable!("globals should only contain leaf IR nodes"),
};
return Ok(self.new_expr(ir));
return Ok(val);
}
}
&Scope::Repl(repl_bindings) => {
if repl_bindings.contains(&sym) {
return Ok(self.new_expr(Ir::ReplBinding(sym)));
return Ok(MaybeThunk::ReplBinding(sym));
}
}
Scope::ScopedImport(scoped_bindings) => {
if scoped_bindings.contains(&sym) {
return Ok(self.new_expr(Ir::ScopedImportBinding(sym)));
return Ok(MaybeThunk::ScopedImportBinding(sym));
}
}
Scope::Let(let_scope) => {
if let Some(&expr) = let_scope.get(&sym) {
return Ok(self.new_expr(Ir::Thunk(expr)));
return Ok(MaybeThunk::Thunk(expr));
}
}
&Scope::Param {
@@ -351,19 +361,19 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
abs_layer,
} => {
if param_sym == sym {
return Ok(self.new_expr(Ir::Arg {
return Ok(MaybeThunk::Arg {
layer: self.thunk_scopes.len() - abs_layer,
}));
});
}
}
}
}
if self.with_scope_count > 0 {
Ok(self.new_expr(Ir::WithLookup(sym)))
Ok(MaybeThunk::WithLookup(sym))
} else {
Err(Error::downgrade_error(
format!("'{}' not found", self.get_sym(sym)),
format!("'{}' not found", self.resolve_sym(sym)),
self.get_current_source(),
span,
))