diff --git a/src/int_allocator.rs b/src/int_allocator.rs index afa9e60b..85fe58fc 100644 --- a/src/int_allocator.rs +++ b/src/int_allocator.rs @@ -6,9 +6,10 @@ pub struct IntAtomBuf { end: u32, } -enum NodePtr { - Atom(IntAtomBuf), - Pair(u32, u32), +#[derive(Clone, Copy)] +pub struct IntPair { + first: i32, + rest: i32, } pub struct IntAllocator { @@ -16,7 +17,14 @@ pub struct IntAllocator { // are immutable, so once they are created, they will stay around until the // program completes u8_vec: Vec, - node_vec: Vec, + + // storage for all pairs (positive indices) + pair_vec: Vec, + + // storage for all atoms (negative indices). + // node index -1 refers to index 0 in this vector, -2 refers to 1 and so + // on. + atom_vec: Vec, } impl Default for IntAllocator { @@ -29,44 +37,45 @@ impl IntAllocator { pub fn new() -> Self { let mut r = IntAllocator { u8_vec: Vec::new(), - node_vec: Vec::new(), + pair_vec: Vec::new(), + atom_vec: Vec::new(), }; r.u8_vec.reserve(1024 * 1024); + r.atom_vec.reserve(256); + r.pair_vec.reserve(256); r.u8_vec.push(1_u8); // Preallocated empty list - r.node_vec - .push(NodePtr::Atom(IntAtomBuf { start: 0, end: 0 })); + r.atom_vec.push(IntAtomBuf { start: 0, end: 0 }); // Preallocated 1 - r.node_vec - .push(NodePtr::Atom(IntAtomBuf { start: 0, end: 1 })); + r.atom_vec.push(IntAtomBuf { start: 0, end: 1 }); r } } impl Allocator for IntAllocator { - type Ptr = u32; + type Ptr = i32; type AtomBuf = IntAtomBuf; fn new_atom(&mut self, v: &[u8]) -> Self::Ptr { let start = self.u8_vec.len() as u32; self.u8_vec.extend_from_slice(v); let end = self.u8_vec.len() as u32; - let r = self.node_vec.len() as u32; - self.node_vec.push(NodePtr::Atom(IntAtomBuf { start, end })); - r + self.atom_vec.push(IntAtomBuf { start, end }); + -(self.atom_vec.len() as i32) } fn new_pair(&mut self, first: Self::Ptr, rest: Self::Ptr) -> Self::Ptr { - let r: u32 = self.node_vec.len() as u32; - self.node_vec.push(NodePtr::Pair(first, rest)); + let r = self.pair_vec.len() as i32; + self.pair_vec.push(IntPair { first, rest }); r } fn atom<'a>(&'a self, node: &'a Self::Ptr) -> &'a [u8] { - match self.node_vec[*node as usize] { - NodePtr::Atom(IntAtomBuf { start, end }) => &self.u8_vec[start as usize..end as usize], - _ => panic!("expected atom, got pair"), + if *node >= 0 { + panic!("expected atom, got pair"); } + let atom = self.atom_vec[(-*node - 1) as usize]; + &self.u8_vec[atom.start as usize..atom.end as usize] } fn buf<'a>(&'a self, node: &'a Self::AtomBuf) -> &'a [u8] { @@ -74,17 +83,20 @@ impl Allocator for IntAllocator { } fn sexp(&self, node: &Self::Ptr) -> SExp { - match self.node_vec[*node as usize] { - NodePtr::Atom(atombuf) => SExp::Atom(atombuf), - NodePtr::Pair(left, right) => SExp::Pair(left, right), + if *node >= 0 { + let pair = self.pair_vec[*node as usize]; + SExp::Pair(pair.first, pair.rest) + } else { + let atom = self.atom_vec[(-*node - 1) as usize]; + SExp::Atom(atom) } } fn null(&self) -> Self::Ptr { - 0 + -1 } fn one(&self) -> Self::Ptr { - 1 + -2 } } diff --git a/src/py/run_program.rs b/src/py/run_program.rs index 0c47bebb..93102ad9 100644 --- a/src/py/run_program.rs +++ b/src/py/run_program.rs @@ -4,7 +4,7 @@ use crate::int_allocator::IntAllocator; use crate::more_ops::op_unknown; use crate::node::Node; use crate::py::f_table::{make_f_lookup, FLookup}; -use crate::reduction::{EvalErr, Reduction}; +use crate::reduction::Response; use crate::run_program::{run_program, OperatorHandler}; use crate::serialize::{node_from_bytes, node_to_bytes}; use lazy_static::lazy_static; @@ -26,8 +26,8 @@ impl OperatorHandler for OperatorHandlerWithMode { &self, allocator: &mut IntAllocator, o: ::AtomBuf, - argument_list: &u32, - ) -> Result, EvalErr> { + argument_list: &::Ptr, + ) -> Response<::Ptr> { let op = &allocator.buf(&o); if op.len() == 1 { if let Some(f) = F_TABLE[op[0] as usize] { @@ -58,11 +58,10 @@ pub fn serialize_and_run_program( let f: Box> = Box::new(OperatorHandlerWithMode { strict: (flags & STRICT_MODE) != 0, }); - let program: u32 = node_from_bytes(&mut allocator, program).unwrap(); + let program = node_from_bytes(&mut allocator, program).unwrap(); + let args = node_from_bytes(&mut allocator, args).unwrap(); - let args: u32 = node_from_bytes(&mut allocator, args).unwrap(); - - let r: Result, EvalErr> = run_program( + let r = run_program( &mut allocator, &program, &args,