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
+46 -88
View File
@@ -1,8 +1,8 @@
use std::ops::Deref;
use fix_builtins::{BUILTINS, BuiltinId};
use fix_builtins::BuiltinId;
use fix_common::StringId;
use fix_ir::{Attr, BinOpKind, Ir, Param, RawIrRef, ThunkId, UnOpKind};
use fix_ir::{Attr, BinOpKind, Ir, MaybeThunk, Param, RawIrRef, ThunkId, UnOpKind};
use hashbrown::HashMap;
use num_enum::TryFromPrimitive;
use rnix::TextRange;
@@ -151,40 +151,34 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
}
}
fn classify_value(&mut self, ir: RawIrRef<'_>) -> InlineOperand {
match ir.deref() {
&Ir::Int(x) => {
fn inline_maybe_thunk(&mut self, val: MaybeThunk) -> InlineOperand {
use MaybeThunk::*;
match val {
Int(x) => {
if x <= i32::MAX as i64 {
InlineOperand::Const(Const::Smi(x as i32))
} else {
InlineOperand::BigInt(x)
}
}
&Ir::Float(x) => InlineOperand::Const(Const::Float(x)),
&Ir::Bool(b) => InlineOperand::Const(Const::Bool(b)),
Ir::Null => InlineOperand::Const(Const::Null),
Ir::Str(s) => {
let sid = self.ctx.intern_string(s.deref());
InlineOperand::Const(Const::String(sid))
}
&Ir::Thunk(id) => {
Float(x) => InlineOperand::Const(Const::Float(x)),
Bool(b) => InlineOperand::Const(Const::Bool(b)),
Null => InlineOperand::Const(Const::Null),
Str(id) => InlineOperand::Const(Const::String(id)),
Thunk(id) => {
let (layer, local) = self.resolve_thunk(id);
InlineOperand::Local { layer, local }
}
&Ir::Arg { layer } => InlineOperand::Local {
Arg { layer } => InlineOperand::Local {
layer: layer.try_into().expect("scope too deep!"),
local: 0,
},
&Ir::Builtin(id) => {
let arity = BUILTINS[id as usize].1;
InlineOperand::Const(Const::PrimOp { id, arity })
}
Ir::Builtins => InlineOperand::Builtins,
_ => panic!("cannot classify IR node as inline operand"),
}
}
fn emit_inline_operand(&mut self, operand: InlineOperand) {
fn emit_maybe_thunk(&mut self, val: MaybeThunk) {
let operand = self.inline_maybe_thunk(val);
match operand {
InlineOperand::Const(val) => {
let idx = self.ctx.add_constant(val);
@@ -320,30 +314,15 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
self.count_with_thunks(*lhs) + self.count_with_thunks(*rhs)
}
Ir::UnOp { rhs, .. } => self.count_with_thunks(*rhs),
Ir::Call { func, arg, .. } => {
self.count_with_thunks(*func) + self.count_with_thunks(*arg)
}
Ir::Call { func, .. } => self.count_with_thunks(*func),
Ir::Assert {
assertion, expr, ..
} => self.count_with_thunks(*assertion) + self.count_with_thunks(*expr),
Ir::Select { expr, default, .. } => {
self.count_with_thunks(*expr) + default.map_or(0, |d| self.count_with_thunks(d))
}
Ir::Select { expr, .. } => self.count_with_thunks(*expr),
Ir::HasAttr { lhs, .. } => self.count_with_thunks(*lhs),
Ir::ConcatStrings { parts, .. } => {
parts.iter().map(|p| self.count_with_thunks(*p)).sum()
}
Ir::Path(p) => self.count_with_thunks(*p),
Ir::List { items } => items.iter().map(|item| self.count_with_thunks(*item)).sum(),
Ir::AttrSet { stcs, dyns } => {
stcs.iter()
.map(|(_, &(val, _))| self.count_with_thunks(val))
.sum::<usize>()
+ dyns
.iter()
.map(|&(k, v, _)| self.count_with_thunks(k) + self.count_with_thunks(v))
.sum::<usize>()
}
_ => 0,
}
}
@@ -392,9 +371,8 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
self.collect_with_thunks_recursive(*rhs, out);
}
Ir::UnOp { rhs, .. } => self.collect_with_thunks_recursive(*rhs, out),
Ir::Call { func, arg, .. } => {
Ir::Call { func, .. } => {
self.collect_with_thunks_recursive(*func, out);
self.collect_with_thunks_recursive(*arg, out);
}
Ir::Assert {
assertion, expr, ..
@@ -402,11 +380,8 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
self.collect_with_thunks_recursive(*assertion, out);
self.collect_with_thunks_recursive(*expr, out);
}
Ir::Select { expr, default, .. } => {
Ir::Select { expr, .. } => {
self.collect_with_thunks_recursive(*expr, out);
if let Some(d) = default {
self.collect_with_thunks_recursive(*d, out);
}
}
Ir::HasAttr { lhs, .. } => self.collect_with_thunks_recursive(*lhs, out),
Ir::ConcatStrings { parts, .. } => {
@@ -414,22 +389,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
self.collect_with_thunks_recursive(*p, out);
}
}
Ir::Path(p) => self.collect_with_thunks_recursive(*p, out),
Ir::List { items } => {
for item in items.iter() {
self.collect_with_thunks_recursive(*item, out);
}
}
Ir::AttrSet { stcs, dyns } => {
for (_, &(val, _)) in stcs.iter() {
self.collect_with_thunks_recursive(val, out);
}
for &(key, val, _) in dyns.iter() {
self.collect_with_thunks_recursive(key, out);
self.collect_with_thunks_recursive(val, out);
}
}
_ => {}
_ => (),
}
}
@@ -512,10 +472,9 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
&Ir::Bool(true) => self.emit_op(Op::PushTrue),
&Ir::Bool(false) => self.emit_op(Op::PushFalse),
Ir::Null => self.emit_op(Op::PushNull),
Ir::Str(s) => {
let idx = self.ctx.intern_string(s.deref());
&Ir::Str(id) => {
self.emit_op(Op::PushString);
self.emit_str_id(idx);
self.emit_str_id(id);
}
&Ir::Path(p) => {
self.emit_expr(p);
@@ -572,15 +531,14 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
self.emit_op(Op::MakeList);
self.emit_u32(items.len() as u32);
for &item in items.iter() {
let operand = self.classify_value(item);
self.emit_inline_operand(operand);
self.emit_maybe_thunk(item);
}
}
}
&Ir::Call { func, arg, .. } => {
self.emit_expr(arg);
self.emit_expr(func);
self.emit_op(Op::Call);
self.inline_maybe_thunk(arg);
}
&Ir::Arg { layer } => {
self.emit_load(layer.try_into().expect("scope too deep!"), 0);
@@ -616,16 +574,17 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
);
}
&Ir::ConcatStrings {
ref parts,
force_string,
parts: _,
force_string: _,
} => {
self.emit_op(Op::ConcatStrings);
self.emit_u16(parts.len() as u16);
self.emit_u8(if force_string { 1 } else { 0 });
for &part in parts.iter() {
let operand = self.classify_value(part);
self.emit_inline_operand(operand);
}
todo!("redesign ConcatStrings");
// self.emit_op(Op::ConcatStrings);
// self.emit_u16(parts.len() as u16);
// self.emit_u8(if force_string { 1 } else { 0 });
// for &part in parts.iter() {
// let operand = self.inline_maybe_thunk(part);
// self.emit_inline_operand(operand);
// }
}
&Ir::HasAttr { lhs, ref rhs } => {
self.emit_has_attr(lhs, rhs);
@@ -817,8 +776,8 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
fn emit_attrset(
&mut self,
stcs: &fix_ir::HashMap<'_, StringId, (RawIrRef<'_>, TextRange)>,
dyns: &[(RawIrRef<'_>, RawIrRef<'_>, TextRange)],
stcs: &fix_ir::HashMap<'_, StringId, (MaybeThunk, TextRange)>,
dyns: &[(RawIrRef<'_>, MaybeThunk, TextRange)],
) {
if stcs.is_empty() && dyns.is_empty() {
self.emit_op(Op::MakeEmptyAttrs);
@@ -832,19 +791,18 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
for (&sym, &(val, span)) in stcs.iter() {
self.emit_u8(AttrKeyType::Static as u8);
self.emit_str_id(sym);
let val_operand = self.classify_value(val);
self.emit_inline_operand(val_operand);
self.emit_maybe_thunk(val);
let span_id = self.ctx.register_span(span);
self.emit_u32(span_id);
}
for &(key, val, span) in dyns.iter() {
self.emit_u8(AttrKeyType::Dynamic as u8);
let key_operand = self.classify_value(key);
self.emit_inline_operand(key_operand);
let val_operand = self.classify_value(val);
self.emit_inline_operand(val_operand);
let span_id = self.ctx.register_span(span);
self.emit_u32(span_id);
for &(_key, _val, _span) in dyns.iter() {
todo!("redesign dynamic attr key");
// self.emit_u8(AttrKeyType::Dynamic as u8);
// self.emit_maybe_thunk(key);
// let val_operand = self.inline_maybe_thunk(val);
// self.emit_maybe_thunk(val);
// let span_id = self.ctx.register_span(span);
// self.emit_u32(span_id);
}
}
@@ -910,12 +868,12 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
fn emit_with(
&mut self,
namespace: RawIrRef<'_>,
namespace: MaybeThunk,
body: RawIrRef<'_>,
thunks: &[(ThunkId, RawIrRef<'_>)],
) {
self.emit_expr(namespace);
self.emit_op(Op::PushWith);
self.emit_maybe_thunk(namespace);
self.emit_scope_thunks(thunks);
self.emit_expr(body);
self.emit_op(Op::PopWith);