Mid rewrite

This commit is contained in:
UditDey
2026-10-13 11:52:02 +00:00
parent 2f21347088
commit d0c2f291e9
24 changed files with 752 additions and 3527 deletions
+22 -5
View File
@@ -1,3 +1,14 @@
//! QuickJS bytecode represents the program as a hierarchy. Each function has a set of child functions
//! that reference captured variables in their parent
//!
//! This module:
//! - flattens the hierarchy
//! - assigns an integer idx to each function
//! - converts child ownership to a reference by-idx
//! - extracts closure captures into a separate vec
//!
//! Also adds a synthetic entry point function that calls the top level fn generated by QuickJS
use crate::libqjs::parse::{
Atom, AtomRef, ClosureVar, Function, ImmOperand, Instr, JsValue, QuickJSBinary, opcodes::OpCode,
};
@@ -6,11 +17,16 @@ use crate::libqjs::parse::{
pub struct FlatFn {
pub name: AtomRef,
pub arg_count: usize,
pub var_count: usize,
pub local_count: usize,
pub cpool: Vec<JsValue>,
pub code: Vec<Instr>,
}
/// Flattens the binary
///
/// Returns:
/// - flat_fns[i] = the i'th flattened function
/// - captures[i] = the i'th fn's captures from its parent
pub fn flatten(bin: QuickJSBinary) -> (Vec<FlatFn>, Vec<Vec<ClosureVar>>, Vec<Atom>) {
let mut fns = vec![];
let mut captures = vec![];
@@ -27,18 +43,19 @@ fn walk(func: Function, flat_fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<Closu
flat_fns.push(FlatFn {
name: func.name,
arg_count: func.arg_count,
var_count: func.var_count,
local_count: func.var_count,
cpool: vec![],
code: func.byte_code,
});
captures.push(func.closure_vars);
// Every direct child ownership is replaced by a by-idx reference
let cpool = func
.cpool
.into_iter()
.map(|c| match c {
JsValue::Function(child) => JsValue::FnById(walk(child, flat_fns, captures)),
JsValue::Function(child) => JsValue::FnByIdx(walk(child, flat_fns, captures)),
other => other,
})
.collect();
@@ -82,8 +99,8 @@ fn add_entry_point(fns: &mut Vec<FlatFn>, captures: &mut Vec<Vec<ClosureVar>>) {
fns.push(FlatFn {
name: AtomRef::Predefined(0),
arg_count: 0,
var_count: 1,
cpool: vec![JsValue::FnById(0)],
local_count: 1,
cpool: vec![JsValue::FnByIdx(0)], // First fn is the top level <eval>
code,
});