From: Euan Lacy Date: Tue, 10 May 2022 16:54:15 +0000 (+0100) Subject: fix: remove unnecessary string & vec allocations X-Git-Tag: v0.9.1~34^2~1 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=c2a87f898e1ae54a10ae765f947c43d64e5b0c37;p=scryer-prolog.git fix: remove unnecessary string & vec allocations --- 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![]))