refactor(downgrade): MaybeThunk
This commit is contained in:
+46
-88
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user