refactor with
This commit is contained in:
@@ -98,7 +98,7 @@ impl<'a, Ctx: DisassemblerContext> Disassembler<'a, Ctx> {
|
||||
self.read_u32();
|
||||
}
|
||||
Builtins => {}
|
||||
ReplBinding | ScopedImportBinding | WithLookup => {
|
||||
ReplBinding | ScopedImportBinding => {
|
||||
self.read_u32();
|
||||
}
|
||||
}
|
||||
@@ -426,16 +426,14 @@ impl<'a, Ctx: DisassemblerContext> Disassembler<'a, Ctx> {
|
||||
let span_id = self.read_u32();
|
||||
("Assert", format!("text_id={} span={}", raw_idx, span_id))
|
||||
}
|
||||
Op::PushWith => {
|
||||
self.read_operand_data();
|
||||
("PushWith", String::new())
|
||||
}
|
||||
Op::PopWith => ("PopWith", String::new()),
|
||||
Op::PrepareWith => ("PrepareWith", String::new()),
|
||||
Op::LookupWith => {
|
||||
let idx = self.read_u32();
|
||||
let name = self.ctx.resolve_string(idx);
|
||||
("LookupWith", format!("{:?}", name))
|
||||
let n = self.read_u8();
|
||||
for _ in 0..n {
|
||||
self.read_operand_data();
|
||||
}
|
||||
("LookupWith", format!("sym={:?} n={}", name, n))
|
||||
}
|
||||
|
||||
Op::LoadBuiltins => ("LoadBuiltins", String::new()),
|
||||
|
||||
+19
-148
@@ -84,10 +84,7 @@ pub enum Op {
|
||||
|
||||
Assert,
|
||||
|
||||
PushWith,
|
||||
PopWith,
|
||||
LookupWith,
|
||||
PrepareWith,
|
||||
|
||||
LoadBuiltins,
|
||||
LoadBuiltin,
|
||||
@@ -120,7 +117,6 @@ pub enum OperandType {
|
||||
Builtins,
|
||||
ReplBinding,
|
||||
ScopedImportBinding,
|
||||
WithLookup,
|
||||
}
|
||||
|
||||
pub enum Const {
|
||||
@@ -152,7 +148,6 @@ pub enum InlineOperand {
|
||||
Builtins,
|
||||
ReplBinding(StringId),
|
||||
ScopedImportBinding(StringId),
|
||||
WithLookup(StringId),
|
||||
}
|
||||
|
||||
pub fn compile_bytecode(ir: RawIrRef<'_>, ctx: &mut impl BytecodeContext) -> InstructionPtr {
|
||||
@@ -203,7 +198,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
Builtins => InlineOperand::Builtins,
|
||||
ReplBinding(id) => InlineOperand::ReplBinding(id),
|
||||
ScopedImportBinding(id) => InlineOperand::ScopedImportBinding(id),
|
||||
WithLookup(id) => InlineOperand::WithLookup(id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,10 +234,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
self.emit_u8(OperandType::ScopedImportBinding as u8);
|
||||
self.emit_str_id(id);
|
||||
}
|
||||
WithLookup(id) => {
|
||||
self.emit_u8(OperandType::WithLookup as u8);
|
||||
self.emit_str_id(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,98 +343,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn count_with_thunks(&self, ir: RawIrRef<'_>) -> usize {
|
||||
match ir {
|
||||
Ir::With { thunks, body, .. } => thunks.len() + self.count_with_thunks(*body),
|
||||
Ir::TopLevel { thunks, body } => thunks.len() + self.count_with_thunks(*body),
|
||||
Ir::If { cond, consq, alter } => {
|
||||
self.count_with_thunks(*cond)
|
||||
+ self.count_with_thunks(*consq)
|
||||
+ self.count_with_thunks(*alter)
|
||||
}
|
||||
Ir::BinOp { lhs, rhs, .. } => {
|
||||
self.count_with_thunks(*lhs) + self.count_with_thunks(*rhs)
|
||||
}
|
||||
Ir::UnOp { rhs, .. } => self.count_with_thunks(*rhs),
|
||||
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, .. } => 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()
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_all_thunks<'ir>(
|
||||
&self,
|
||||
own_thunks: &[(ThunkId, RawIrRef<'ir>)],
|
||||
body: RawIrRef<'ir>,
|
||||
) -> Vec<(ThunkId, RawIrRef<'ir>)> {
|
||||
let mut all = Vec::from(own_thunks);
|
||||
self.collect_with_thunks_recursive(body, &mut all);
|
||||
let mut i = 0;
|
||||
while i < all.len() {
|
||||
let thunk_body = all[i].1;
|
||||
self.collect_with_thunks_recursive(thunk_body, &mut all);
|
||||
i += 1;
|
||||
}
|
||||
all
|
||||
}
|
||||
|
||||
fn collect_with_thunks_recursive<'ir>(
|
||||
&self,
|
||||
ir: RawIrRef<'ir>,
|
||||
out: &mut Vec<(ThunkId, RawIrRef<'ir>)>,
|
||||
) {
|
||||
match ir {
|
||||
Ir::With { thunks, body, .. } => {
|
||||
for &(id, inner) in thunks.iter() {
|
||||
out.push((id, inner));
|
||||
}
|
||||
self.collect_with_thunks_recursive(*body, out);
|
||||
}
|
||||
Ir::TopLevel { thunks, body } => {
|
||||
for &(id, inner) in thunks.iter() {
|
||||
out.push((id, inner));
|
||||
}
|
||||
self.collect_with_thunks_recursive(*body, out);
|
||||
}
|
||||
Ir::If { cond, consq, alter } => {
|
||||
self.collect_with_thunks_recursive(*cond, out);
|
||||
self.collect_with_thunks_recursive(*consq, out);
|
||||
self.collect_with_thunks_recursive(*alter, out);
|
||||
}
|
||||
Ir::BinOp { lhs, rhs, .. } => {
|
||||
self.collect_with_thunks_recursive(*lhs, out);
|
||||
self.collect_with_thunks_recursive(*rhs, out);
|
||||
}
|
||||
Ir::UnOp { rhs, .. } => self.collect_with_thunks_recursive(*rhs, out),
|
||||
Ir::Call { func, .. } => {
|
||||
self.collect_with_thunks_recursive(*func, out);
|
||||
}
|
||||
Ir::Assert {
|
||||
assertion, expr, ..
|
||||
} => {
|
||||
self.collect_with_thunks_recursive(*assertion, out);
|
||||
self.collect_with_thunks_recursive(*expr, out);
|
||||
}
|
||||
Ir::Select { expr, .. } => {
|
||||
self.collect_with_thunks_recursive(*expr, out);
|
||||
}
|
||||
Ir::HasAttr { lhs, .. } => self.collect_with_thunks_recursive(*lhs, out),
|
||||
Ir::ConcatStrings { parts, .. } => {
|
||||
for p in parts.iter() {
|
||||
self.collect_with_thunks_recursive(*p, out);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn push_scope(&mut self, has_arg: bool, thunk_ids: &[ThunkId]) {
|
||||
let depth = self.scope_stack.len().try_into().expect("scope too deep!");
|
||||
let thunk_base = if has_arg { 1u32 } else { 0u32 };
|
||||
@@ -463,17 +361,11 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
fn emit_toplevel(&mut self, ir: RawIrRef<'_>) {
|
||||
match ir {
|
||||
&Ir::TopLevel { body, ref thunks } => {
|
||||
let with_thunk_count = self.count_with_thunks(body);
|
||||
let total_slots = thunks.len() + with_thunk_count;
|
||||
|
||||
let all_thunks = self.collect_all_thunks(thunks, body);
|
||||
let thunk_ids: Vec<ThunkId> = all_thunks.iter().map(|&(id, _)| id).collect();
|
||||
|
||||
let thunk_ids: Vec<ThunkId> = thunks.iter().map(|&(id, _)| id).collect();
|
||||
self.push_scope(false, &thunk_ids);
|
||||
|
||||
if total_slots > 0 {
|
||||
if !thunks.is_empty() {
|
||||
self.emit_op(Op::AllocLocals);
|
||||
self.emit_u32(total_slots as u32);
|
||||
self.emit_u32(thunks.len().try_into().expect("too many thunks"));
|
||||
}
|
||||
|
||||
self.emit_scope_thunks(thunks);
|
||||
@@ -658,18 +550,20 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
self.emit_op(Op::LoadScopedBinding);
|
||||
self.emit_str_id(name);
|
||||
}
|
||||
&Ir::With {
|
||||
namespace,
|
||||
body,
|
||||
ref thunks,
|
||||
} => {
|
||||
self.emit_with(namespace, body, thunks);
|
||||
}
|
||||
&Ir::WithLookup(name) => {
|
||||
// TODO: specialize shallow with lookups
|
||||
self.emit_op(Op::PrepareWith);
|
||||
Ir::WithLookup { sym, namespaces } => {
|
||||
// counter
|
||||
self.emit_expr(&Ir::Int(0));
|
||||
self.emit_op(Op::LookupWith);
|
||||
self.emit_str_id(name);
|
||||
self.emit_str_id(*sym);
|
||||
self.emit_u8(
|
||||
namespaces
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("too many `with` namespaces"),
|
||||
);
|
||||
for namespace in namespaces {
|
||||
self.emit_maybe_thunk(namespace);
|
||||
}
|
||||
}
|
||||
&Ir::MaybeThunk(thunk) => {
|
||||
use MaybeThunk::*;
|
||||
@@ -723,12 +617,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
self.emit_op(Op::LoadScopedBinding);
|
||||
self.emit_str_id(name);
|
||||
}
|
||||
WithLookup(name) => {
|
||||
// TODO: specialize shallow with lookups
|
||||
self.emit_op(Op::PrepareWith);
|
||||
self.emit_op(Op::LookupWith);
|
||||
self.emit_str_id(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -822,11 +710,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
param: &Option<Param<'ir>>,
|
||||
body: RawIrRef<'ir>,
|
||||
) {
|
||||
let with_thunk_count = self.count_with_thunks(body);
|
||||
let total_slots = thunks.len() + with_thunk_count;
|
||||
|
||||
let all_thunks = self.collect_all_thunks(thunks, body);
|
||||
let thunk_ids: Vec<ThunkId> = all_thunks.iter().map(|&(id, _)| id).collect();
|
||||
let thunk_ids: Vec<ThunkId> = thunks.iter().map(|&(id, _)| id).collect();
|
||||
|
||||
let skip_patch = self.emit_jump_placeholder();
|
||||
let entry_point = self.ctx.get_code().len() as u32;
|
||||
@@ -845,7 +729,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
{
|
||||
self.emit_op(Op::MakePatternClosure);
|
||||
self.emit_u32(entry_point);
|
||||
self.emit_u32(total_slots as u32);
|
||||
self.emit_u32(thunks.len().try_into().expect("too many thunks"));
|
||||
self.emit_u16(required.len() as u16);
|
||||
self.emit_u16(optional.len() as u16);
|
||||
self.emit_bool(*ellipsis);
|
||||
@@ -864,7 +748,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
} else {
|
||||
self.emit_op(Op::MakeClosure);
|
||||
self.emit_u32(entry_point);
|
||||
self.emit_u32(total_slots as u32);
|
||||
self.emit_u32(thunks.len().try_into().expect("too many thunks"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,19 +875,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||
self.emit_op(Op::HasAttrResolve);
|
||||
}
|
||||
|
||||
fn emit_with(
|
||||
&mut self,
|
||||
namespace: &MaybeThunk,
|
||||
body: RawIrRef<'_>,
|
||||
thunks: &[(ThunkId, RawIrRef<'_>)],
|
||||
) {
|
||||
self.emit_op(Op::PushWith);
|
||||
self.emit_maybe_thunk(namespace);
|
||||
self.emit_scope_thunks(thunks);
|
||||
self.emit_expr(body);
|
||||
self.emit_op(Op::PopWith);
|
||||
}
|
||||
|
||||
fn emit_toplevel_inner(&mut self, body: RawIrRef<'_>, thunks: &[(ThunkId, RawIrRef<'_>)]) {
|
||||
self.emit_scope_thunks(thunks);
|
||||
self.emit_expr(body);
|
||||
|
||||
Reference in New Issue
Block a user