From c2a87f898e1ae54a10ae765f947c43d64e5b0c37 Mon Sep 17 00:00:00 2001 From: Euan Lacy Date: Tue, 10 May 2022 17:54:15 +0100 Subject: [PATCH] fix: remove unnecessary string & vec allocations --- src/machine/machine_state.rs | 6 ++- src/read.rs | 3 +- src/repl_helper.rs | 82 +++++++++++------------------------- 3 files changed, 31 insertions(+), 60 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index f33f0901..d19242f2 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -454,13 +454,15 @@ impl MachineState { self.b0 = self.b; } + // Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr + // will always be valid. pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult { - let atoms: Vec<_> = self.atom_tbl.table.iter().map(|a| a.as_str().to_string()).collect(); + let atoms_ptr = (&self.atom_tbl.table) as *const indexmap::IndexSet; if let Stream::Readline(ptr) = stream { unsafe { let readline = ptr.as_ptr().as_mut().unwrap(); - readline.set_atoms_for_completion(atoms); + readline.set_atoms_for_completion(atoms_ptr); let ret = self.read_term(stream, indices); return ret } diff --git a/src/read.rs b/src/read.rs index 399d9280..5ef89d04 100644 --- a/src/read.rs +++ b/src/read.rs @@ -14,6 +14,7 @@ use crate::types::*; use fxhash::FxBuildHasher; +use indexmap::IndexSet; use rustyline::error::ReadlineError; use rustyline::{Config, Editor}; @@ -108,7 +109,7 @@ impl ReadlineStream { } } - pub fn set_atoms_for_completion(&mut self, atoms: Vec) { + pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet) { let helper = self.rl.helper_mut().unwrap(); helper.atoms = atoms; } diff --git a/src/repl_helper.rs b/src/repl_helper.rs index 96f63efa..91347020 100644 --- a/src/repl_helper.rs +++ b/src/repl_helper.rs @@ -1,75 +1,25 @@ -use rustyline::completion::Completer; +use indexmap::IndexSet; +use rustyline::completion::{Completer, Candidate}; use rustyline::hint::Hinter; use rustyline::validate::Validator; use rustyline::highlight::{MatchingBracketHighlighter, Highlighter}; use rustyline::{Helper as RlHelper, Result, Context}; -// pub struct Atoms { -// atoms: *const *const str, -// len: usize, -// } - -// impl Atoms { -// pub fn new() -> Self { -// Self { -// atoms: std::ptr::null(), -// len: 0, -// } -// } -// } - -// pub struct AtomsIterator<'a> { -// atoms: &'a Atoms, -// idx: usize, -// } - -// impl<'a> Iterator for AtomsIterator<'a> { -// type Item = &'a str; - -// fn next(&mut self) -> Option { -// self.idx += 1; - -// if self.idx == self.atoms.len { -// None -// } else { -// unsafe { -// let next = self.atoms.atoms.offset(self.idx as isize); -// (*next).as_ref() -// } -// } -// } -// } - -// impl<'a> IntoIterator for &'a Atoms { -// type Item = &'a str; -// type IntoIter = AtomsIterator<'a>; - -// fn into_iter(self) -> Self::IntoIter { -// Self::IntoIter { -// atoms: self, -// idx: 0, -// } -// } -// } +use crate::machine::mock_wam::Atom; // TODO: Maybe add validation to the helper pub struct Helper { highligher: MatchingBracketHighlighter, - pub atoms: Vec, + pub atoms: *const IndexSet, } impl Helper { pub fn new() -> Self { Self { highligher: MatchingBracketHighlighter::new(), - atoms: vec![], + atoms: std::ptr::null(), } } - - // pub fn set_atoms(&mut self, atoms_ptr: *const *const str, len: usize) { - // self.atoms.atoms = atoms_ptr; - // self.atoms.len = len; - // } } impl RlHelper for Helper {} @@ -104,14 +54,32 @@ fn get_prefix(line: &str, pos: usize) -> Option { start_of_atom } +pub struct StrPtr(*const str); + +impl Candidate for StrPtr { + fn display(&self) -> &str { + unsafe { + self.0.as_ref().unwrap() + } + } + + fn replacement(&self) -> &str { + unsafe { + self.0.as_ref().unwrap() + } + } +} + impl Completer for Helper { - type Candidate = String; + type Candidate = StrPtr; fn complete(&self, line: &str, pos: usize, _ctx: &Context<'_>) -> Result<(usize, Vec)> { let start_of_prefix = get_prefix(line, pos); if let Some(idx) = start_of_prefix { let sub_str = line.get(idx..pos).unwrap(); - let matching = self.atoms.iter().filter(|a| a.starts_with(sub_str)).map(|s| s.to_string()).collect(); + let matching = unsafe { + (*self.atoms).iter().filter(|a| a.as_str().starts_with(sub_str)).map(|s| StrPtr(s.as_str())).collect() + }; Ok((idx, matching)) } else { Ok((0, vec![])) -- 2.54.0