hostname = ["dep:hostname"]
tls = ["dep:native-tls"]
http = ["dep:hyper", "dep:reqwest"]
+rust_beta_channel = []
[build-dependencies]
indexmap = "1.0.2"
let f_atom = atom!("f");
let g_atom = atom!("g");
- assert_eq!(f_atom.as_str(), "f");
- assert_eq!(g_atom.as_str(), "g");
+ assert_eq!(&*f_atom.as_str(), "f");
+ assert_eq!(&*g_atom.as_str(), "g");
let f_atom_cell = atom_as_cell!(f_atom);
let g_atom_cell = atom_as_cell!(g_atom);
match f_atom_cell.to_atom() {
Some(atom) => {
assert_eq!(f_atom, atom);
- assert_eq!(atom.as_str(), "f");
+ assert_eq!(&*atom.as_str(), "f");
}
None => {
assert!(false);
(HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(f_atom, atom);
assert_eq!(arity, 0);
- assert_eq!(atom.as_str(), "f");
+ assert_eq!(&*atom.as_str(), "f");
}
_ => { unreachable!() }
);
(HeapCellValueTag::Atom, (atom, arity)) => {
assert_eq!(g_atom, atom);
assert_eq!(arity, 0);
- assert_eq!(atom.as_str(), "g");
+ assert_eq!(&*atom.as_str(), "g");
}
_ => { unreachable!() }
);
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"ronan",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
match pstr_cell.to_pstr() {
Some(pstr) => {
- assert_eq!(pstr.as_str_from(0), "ronan");
+ assert_eq!(&*pstr.as_str_from(0), "ronan");
}
None => {
assert!(false);
read_heap_cell!(pstr_cell,
(HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom);
- assert_eq!(pstr.as_str_from(0), "ronan");
+ assert_eq!(&*pstr.as_str_from(0), "ronan");
}
_ => { unreachable!() }
);
read_heap_cell!(cell,
(HeapCellValueTag::Atom, (el, _arity)) => {
assert_eq!(el.flat_index(), empty_list_as_cell!().get_value());
- assert_eq!(el.as_str(), "[]");
+ assert_eq!(&*el.as_str(), "[]");
}
_ => { unreachable!() }
);
use crate::raw_block::*;
use crate::types::*;
-use std::borrow::Borrow;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::mem;
+use std::ops::Deref;
use std::ptr;
use std::slice;
use std::str;
+use std::sync::Arc;
+use std::sync::Weak;
use indexmap::IndexSet;
use modular_bitfield::prelude::*;
+use tokio::runtime::Handle;
+use tokio::sync::OwnedRwLockReadGuard;
+use tokio::sync::RwLock;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Atom {
}
}
-const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
-const ATOM_TABLE_ALIGN: usize = 8;
-
-#[cfg(test)]
-thread_local! {
- static ATOM_TABLE_BUF_BASE: std::cell::RefCell<*const u8> = std::cell::RefCell::new(ptr::null_mut());
+impl indexmap::Equivalent<Atom> for str {
+ fn equivalent(&self, atom: &Atom) -> bool {
+ &*atom.as_str() == self
+ }
}
-#[cfg(not(test))]
-static ATOM_TABLE_BUF_BASE: std::sync::atomic::AtomicPtr<u8> =
- std::sync::atomic::AtomicPtr::new(ptr::null_mut());
-
-fn set_atom_tbl_buf_base(old_ptr: *const u8, new_ptr: *const u8) -> Result<(), *const u8> {
- #[cfg(test)]
- {
- ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| {
- let mut borrow = atom_table_buf_base.borrow_mut();
- if *borrow != old_ptr {
- Err(*borrow)
- } else {
- *borrow = new_ptr;
- Ok(())
- }
- })?;
- };
- #[cfg(not(test))]
- {
- ATOM_TABLE_BUF_BASE
- .compare_exchange(
- old_ptr.cast_mut(),
- new_ptr.cast_mut(),
- std::sync::atomic::Ordering::Relaxed,
- std::sync::atomic::Ordering::Relaxed,
- )
- .map_err(|ptr| ptr.cast_const())
- }?;
- Ok(())
-}
+const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
+const ATOM_TABLE_ALIGN: usize = 8;
-pub(crate) fn get_atom_tbl_buf_base() -> *const u8 {
- #[cfg(test)]
+pub fn global_atom_table() -> &'static RwLock<Weak<RwLock<AtomTable>>> {
+ #[cfg(feature = "rust_beta_channel")]
{
- ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| *atom_table_buf_base.borrow())
+ // const Weak::new will be stabilized in 1.73 which is currently in beta,
+ // till then we need a OnceLock for initialization
+ static GLOBAL_ATOM_TABLE: RwLock<Weak<RwLock<AtomTable>>> = RwLock::new(Weak::new());
+ &GLOBAL_ATOM_TABLE
}
- #[cfg(not(test))]
+ #[cfg(not(feature = "rust_beta_channel"))]
{
- ATOM_TABLE_BUF_BASE.load(std::sync::atomic::Ordering::Relaxed)
+ use std::sync::OnceLock;
+ static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<RwLock<AtomTable>>>> = OnceLock::new();
+ GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
}
}
-#[test]
-#[should_panic(expected = "Overwriting atom table base pointer")]
-fn atomtable_is_not_concurrency_safe() {
- let _table_a = AtomTable::new();
- let _table_b = AtomTable::new();
-}
-
impl RawBlockTraits for AtomTable {
#[inline]
fn init_size() -> usize {
}
}
-impl Borrow<str> for Atom {
- #[inline]
- fn borrow(&self) -> &str {
- self.as_str()
- }
-}
-
impl Hash for Atom {
#[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) {
};
}
-impl Atom {
- #[inline]
- pub fn buf(self) -> *const u8 {
- let ptr = self.as_ptr();
+pub enum AtomString<'a> {
+ Static(&'a str),
+ Dynamic(OwnedRwLockReadGuard<AtomTable, str>),
+}
+
+impl AtomString<'_> {
+ pub fn map<F>(self, f: F) -> Self
+ where
+ for<'a> F: FnOnce(&'a str) -> &'a str,
+ {
+ match self {
+ Self::Static(reference) => Self::Static(f(reference)),
+ Self::Dynamic(guard) => Self::Dynamic(OwnedRwLockReadGuard::map(guard, f)),
+ }
+ }
+}
- if ptr.is_null() {
- return ptr::null();
+impl std::fmt::Debug for AtomString<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ std::fmt::Debug::fmt(self.deref(), f)
+ }
+}
+
+impl std::fmt::Display for AtomString<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ std::fmt::Display::fmt(self.deref(), f)
+ }
+}
+
+impl std::ops::Deref for AtomString<'_> {
+ type Target = str;
+ fn deref(&self) -> &Self::Target {
+ match self {
+ Self::Static(reference) => reference,
+ Self::Dynamic(guard) => guard.deref(),
}
+ }
+}
- (ptr as usize + mem::size_of::<AtomHeader>()) as *const u8
+impl rustyline::completion::Candidate for AtomString<'_> {
+ fn display(&self) -> &str {
+ self.deref()
+ }
+
+ fn replacement(&self) -> &str {
+ self.deref()
+ }
+}
+
+impl Atom {
+ #[inline]
+ pub fn buf(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
+ if let Some(guard) = self.as_ptr() {
+ Some(OwnedRwLockReadGuard::map(guard, |ptr| unsafe {
+ (ptr as *const u8)
+ .offset(mem::size_of::<AtomHeader>() as isize)
+ .as_ref()
+ .unwrap()
+ }))
+ } else {
+ None
+ }
}
#[inline(always)]
}
#[inline(always)]
- pub fn as_ptr(self) -> *const u8 {
+ pub fn as_ptr(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
if self.is_static() {
- ptr::null()
+ None
} else {
- (get_atom_tbl_buf_base() as usize + (self.index as usize) - (STRINGS.len() << 3))
- as *const u8
+ let atom_table = global_atom_table()
+ .blocking_read()
+ .upgrade()
+ .expect("We should only have an Atom while there is an AtomTable");
+
+ #[cfg(not(test))]
+ let guard = Handle::current().block_on(atom_table.read_owned());
+
+ #[cfg(test)]
+ let guard = {
+ if let Ok(handle) = Handle::try_current() {
+ handle.block_on(atom_table.read_owned())
+ } else {
+ tokio::runtime::Runtime::new()
+ .unwrap()
+ .block_on(atom_table.read_owned())
+ }
+ };
+
+ Some(OwnedRwLockReadGuard::map(guard, |atom_table| unsafe {
+ atom_table
+ .buf()
+ .offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
+ .as_ref()
+ .unwrap()
+ }))
}
}
if self.is_static() {
STRINGS[(self.index >> 3) as usize].len()
} else {
- unsafe { ptr::read(self.as_ptr() as *const AtomHeader).len() as _ }
+ unsafe {
+ ptr::read(self.as_ptr().unwrap().deref() as *const u8 as *const AtomHeader).len()
+ as _
+ }
}
}
}
#[inline]
- pub fn chars(&self) -> str::Chars {
- self.as_str().chars()
- }
-
- #[inline]
- pub fn as_str(&self) -> &str {
- unsafe {
- let ptr = self.as_ptr();
-
- if ptr.is_null() {
- return STRINGS[(self.index >> 3) as usize];
- }
-
- let header = ptr::read::<AtomHeader>(ptr as *const _);
- let len = header.len() as usize;
- let buf = (ptr as usize + mem::size_of::<AtomHeader>()) as *mut u8;
-
- str::from_utf8_unchecked(slice::from_raw_parts(buf, len))
+ pub fn as_str(&self) -> AtomString<'static> {
+ if let Some(ptr_guard) = self.as_ptr() {
+ AtomString::Dynamic(OwnedRwLockReadGuard::map(ptr_guard, |ptr| {
+ let header =
+ unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
+ let len = header.len() as usize;
+ let buf =
+ (unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize) })
+ as *mut u8;
+
+ unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
+ }))
+ } else {
+ return AtomString::Static(STRINGS[(self.index >> 3) as usize]);
}
}
impl Ord for Atom {
#[inline]
fn cmp(&self, other: &Atom) -> Ordering {
- self.as_str().cmp(other.as_str())
+ self.as_str().cmp(&*other.as_str())
}
}
pub table: IndexSet<Atom>,
}
-#[cold]
-fn atom_table_base_pointer_mismatch(expected: *const u8, got: *const u8) -> ! {
- assert_eq!(expected, got, "Overwriting atom table base pointer, expected old value to be {expected:p}, but found {got:p}");
- unreachable!("This should only be called in a case of a mismatch as such the assert_eq should have failed!")
-}
-
impl Drop for AtomTable {
fn drop(&mut self) {
- if let Err(got) = set_atom_tbl_buf_base(self.block.base, ptr::null()) {
- atom_table_base_pointer_mismatch(self.block.base, got);
- }
self.block.deallocate();
}
}
impl AtomTable {
#[inline]
- pub fn new() -> Self {
- let mut block = RawBlock::new();
-
- if let Err(got) = set_atom_tbl_buf_base(ptr::null(), block.base) {
- block.deallocate();
- atom_table_base_pointer_mismatch(ptr::null(), got);
- }
-
- Self {
- block,
- table: IndexSet::new(),
+ pub fn new() -> Arc<RwLock<Self>> {
+ let upgraded = global_atom_table().blocking_read().upgrade();
+ // don't inline upgraded, temporary will be dropped too late in case of None
+ if let Some(atom_table) = upgraded {
+ atom_table
+ } else {
+ let mut guard = global_atom_table().blocking_write();
+ // try to upgrade again in case we lost the race on the write lock
+ if let Some(atom_table) = guard.upgrade() {
+ atom_table
+ } else {
+ let atom_table = Arc::new(RwLock::new(Self {
+ block: RawBlock::new(),
+ table: IndexSet::new(),
+ }));
+ *guard = Arc::downgrade(&atom_table);
+ atom_table
+ }
}
}
let align_offset = 8 * mem::align_of::<AtomHeader>();
let size = (size & !(align_offset - 1)) + align_offset;
- let len_ptr = {
- let mut ptr;
-
- loop {
- ptr = self.block.alloc(size);
-
- if ptr.is_null() {
- let old_base = self.block.base;
- self.block.grow();
- if let Err(got) = set_atom_tbl_buf_base(old_base, self.block.base) {
- atom_table_base_pointer_mismatch(old_base, got);
- }
- } else {
- break;
- }
- }
+ let len_ptr = loop {
+ let ptr = self.block.alloc(size);
- ptr
+ if ptr.is_null() {
+ self.block.grow();
+ } else {
+ break ptr;
+ }
};
let ptr_base = self.block.base as usize;
}
}
+unsafe impl Send for AtomTable {}
+unsafe impl Sync for AtomTable {}
+
#[bitfield]
#[repr(u64)]
#[derive(Copy, Clone, Debug)]
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
+use tokio::sync::RwLock;
+
use std::cell::Cell;
use std::collections::VecDeque;
#[derive(Debug)]
pub(crate) struct CodeGenerator<'a> {
- pub(crate) atom_tbl: &'a mut AtomTable,
+ pub(crate) atom_tbl: &'a RwLock<AtomTable>,
marker: DebrayAllocator,
settings: CodeGenSettings,
pub(crate) skeleton: PredicateSkeleton,
}
impl<'b> CodeGenerator<'b> {
- pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
+ pub(crate) fn new(atom_tbl: &'b RwLock<AtomTable>, settings: CodeGenSettings) -> Self {
CodeGenerator {
atom_tbl,
marker: DebrayAllocator::new(),
TermRef::PartialString(lvl, cell, string, tail) => {
self.marker
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
- let atom = self.atom_tbl.build_with(&string);
+ let atom = self.atom_tbl.blocking_write().build_with(&string);
target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
let index = code.len();
if clauses_len > 1 || self.settings.is_extensible {
- code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl);
+ code_offsets.index_term(
+ arg,
+ index,
+ &mut clause_index_info,
+ &mut self.atom_tbl.blocking_write(),
+ );
}
}
atom!("ptr") => &mut types::pointer,
atom!("f32") => &mut types::float,
atom!("f64") => &mut types::double,
- struct_name => match self.structs.get_mut(struct_name.as_str()) {
+ struct_name => match self.structs.get_mut(&*struct_name.as_str()) {
Some(ref mut struct_type) => &mut struct_type.ffi_type,
None => unreachable!(),
},
let substruct = struct_type.atom_fields[i].as_str();
let struct_type = self
.structs
- .get(substruct)
+ .get(&*substruct)
.ok_or(FFIError::StructNotFound)?;
field_ptr = field_ptr
.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
- let struct_val = self.read_struct(field_ptr, substruct, struct_type);
+ let struct_val = self.read_struct(field_ptr, &*substruct, struct_type);
returns.push(struct_val?);
field_ptr = field_ptr.add(struct_type.ffi_type.size);
}
fn arity(&self) -> usize {
match self {
- Term::Clause(_, name, terms) => match name.as_str() {
+ Term::Clause(_, name, terms) => match &*name.as_str() {
":-" => match terms.len() {
1 => 0,
2 => terms[0].arity(),
}
#[inline]
- pub fn as_str(&self) -> &str {
+ pub fn as_str(&self) -> AtomString<'_> {
match self {
- AtomOrString::Atom(atom) if atom == &atom!("[]") => "",
+ AtomOrString::Atom(atom) if atom == &atom!("[]") => AtomString::Static(""),
AtomOrString::Atom(atom) => atom.as_str(),
- AtomOrString::String(string) => string.as_str(),
+ AtomOrString::String(string) => AtomString::Static(string.as_str()),
}
}
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
use indexmap::IndexMap;
+use tokio::sync::RwLock;
+
use std::cell::Cell;
use std::convert::TryFrom;
use std::iter::once;
use std::net::{IpAddr, TcpListener};
use std::rc::Rc;
+use std::sync::Arc;
/* contains the location, name, precision and Specifier of the parent op. */
#[derive(Debug, Copy, Clone)]
DirectedOp::Left(name, cell) => {
let (priority, spec) = cell.get();
- if name.as_str() == "-" {
+ if &*name.as_str() == "-" {
let child_assoc = child_desc.get_spec();
if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) {
return true;
pub struct HCPrinter<'a, Outputter> {
outputter: Outputter,
iter: StackfulPreOrderHeapIter<'a>,
- atom_tbl: &'a mut AtomTable,
+ atom_tbl: Arc<RwLock<AtomTable>>,
op_dir: &'a OpDir,
state_stack: Vec<TokenOrRedirect>,
toplevel_spec: Option<DirectedOp>,
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
pub fn new(
heap: &'a mut Heap,
- atom_tbl: &'a mut AtomTable,
+ atom_tbl: Arc<RwLock<AtomTable>>,
stack: &'a mut Stack,
op_dir: &'a OpDir,
output: Outputter,
self.state_stack.push(TokenOrRedirect::Op(name, spec));
}
} else {
- match name.as_str() {
+ match &*name.as_str() {
"|" => {
self.format_bar_separator_op(max_depth, name, spec);
return;
}
fn print_impromptu_atom(&mut self, atom: Atom) {
- let result = self.print_op_addendum(atom.as_str());
+ let result = self.print_op_addendum(&*atom.as_str());
push_space_if_amb!(self, result.as_str(), {
append_str!(self, &result);
for op in &[op, parent_op] {
if let Some(ref op) = &op {
if op.is_left()
- && (op.is_prefix() || requires_space(op.as_atom().as_str(), "("))
+ && (op.is_prefix() || requires_space(&*op.as_atom().as_str(), "("))
{
self.state_stack.push(TokenOrRedirect::Space);
return;
max_depth,
);
} else {
- push_space_if_amb!(printer, name.as_str(), {
+ push_space_if_amb!(printer, &*name.as_str(), {
printer.format_clause(max_depth, arity, name, None);
});
}
result.push('(');
}
- result += &printer.print_op_addendum(name.as_str());
+ result += &printer.print_op_addendum(&*name.as_str());
if op.is_some() {
result.push(')');
append_str!(printer, &result);
});
} else {
- push_space_if_amb!(printer, name.as_str(), {
+ push_space_if_amb!(printer, &*name.as_str(), {
printer.print_impromptu_atom(name);
});
}
print_struct(self, name, arity);
}
(HeapCellValueTag::Char, c) => {
- let name = self.atom_tbl.build_with(&String::from(c));
+ let name = self.atom_tbl.blocking_write().build_with(&String::from(c));
print_struct(self, name, 0);
}
(HeapCellValueTag::Str, s) => {
max_depth,
);
} else {
- push_space_if_amb!(self, name.as_str(), {
+ push_space_if_amb!(self, &*name.as_str(), {
self.format_clause(max_depth, arity, name, None);
});
}
TokenOrRedirect::BarAsOp => append_str!(self, " | "),
TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c),
TokenOrRedirect::Op(atom, op) => {
- self.print_op(atom.as_str());
+ self.print_op(&*atom.as_str());
if is_prefix!(op.get_spec()) {
self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op)));
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
put_partial_string(
&mut wam.machine_st.heap,
"abc",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- &mut wam.machine_st.atom_tbl,
+ Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
return Some(
LS::machine_st(&mut self.payload)
.atom_tbl
+ .blocking_write()
.build_with(path_str),
);
}
let clause = self.try_term_to_tl(term, &mut preprocessor)?;
// let queue = preprocessor.parse_queue(self)?;
- let mut cg = CodeGenerator::new(&mut LS::machine_st(&mut self.payload).atom_tbl, settings);
+ let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let clause_code = cg.compile_predicate(vec![clause])?;
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
}
- let mut cg = CodeGenerator::new(&mut LS::machine_st(&mut self.payload).atom_tbl, settings);
+ let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
let mut code = cg.compile_predicate(clauses)?;
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
pub(crate) fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => {
- let mut path_buf = PathBuf::from(filename.as_str());
+ let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)?;
ListingSource::File(filename, path_buf),
)
}
- ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) {
+ ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => {
if let Some(ref module) = self.wam_prelude.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = &module.listing_src {
) -> Result<(), SessionError> {
let (stream, listing_src) = match module_src {
ModuleSource::File(filename) => {
- let mut path_buf = PathBuf::from(filename.as_str());
+ let mut path_buf = PathBuf::from(&*filename.as_str());
path_buf.set_extension("pl");
let file = File::open(&path_buf)?;
ListingSource::File(filename, path_buf),
)
}
- ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) {
+ ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) {
Some(code) => {
if self.wam_prelude.indices.modules.contains_key(&library) {
return self.import_qualified_module(library, exports);
let export_list = machine_st.read_term_from_heap(cell)?;
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
- let export_list = setup_module_export_list(export_list, atom_tbl)?;
+ let export_list = setup_module_export_list(export_list, &mut atom_tbl.blocking_write())?;
Ok(export_list.into_iter().collect())
}
term_stack.push(Term::PartialString(Cell::default(), string, tail));
}
Ok((string, None)) => {
- let atom = self.atom_tbl.build_with(&string);
+ let atom = self.atom_tbl.blocking_write().build_with(&string);
term_stack.push(Term::CompleteString(Cell::default(), atom));
}
Err(cons_term) => term_stack.push(cons_term),
.store(self.machine_st.deref(self.machine_st.registers[2])));
self.load_contexts
- .push(LoadContext::new(path.as_str(), stream));
+ .push(LoadContext::new(&*path.as_str(), stream));
Ok(())
}
pub(crate) fn load_context_source(&mut self) {
if let Some(load_context) = self.load_contexts.last() {
let path_str = load_context.path.to_str().unwrap();
- let path_atom = self.machine_st.atom_tbl.build_with(path_str);
+ let path_atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(path_str);
self.machine_st
.unify_atom(path_atom, self.machine_st.registers[1]);
match load_context.path.file_name() {
Some(file_name) if load_context.path.is_file() => {
let file_name_str = file_name.to_str().unwrap();
- let file_name_atom = self.machine_st.atom_tbl.build_with(file_name_str);
+ let file_name_atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(file_name_str);
self.machine_st
.unify_atom(file_name_atom, self.machine_st.registers[1]);
if let Some(load_context) = self.load_contexts.last() {
if let Some(directory) = load_context.path.parent() {
let directory_str = directory.to_str().unwrap();
- let directory_atom = self.machine_st.atom_tbl.build_with(directory_str);
+ let directory_atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(directory_str);
self.machine_st
.unify_atom(directory_atom, self.machine_st.registers[1]);
use crate::parser::dashu::Integer;
use indexmap::IndexMap;
+use tokio::sync::RwLock;
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Index, IndexMut};
+use std::sync::Arc;
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
}
pub struct MachineState {
- pub atom_tbl: AtomTable,
+ pub atom_tbl: Arc<RwLock<AtomTable>>,
pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>,
pub(super) s: HeapPtr,
Some((var_name, var))
}
}),
- &mut self.atom_tbl,
+ &mut self.atom_tbl.blocking_write(),
);
let singleton_addr = self.registers[3];
false
}
}),
- &mut self.atom_tbl,
+ &mut self.atom_tbl.blocking_write(),
);
for var in term_write_result.var_dict.values_mut() {
stream: Stream,
indices: &mut IndexStore,
) -> CallResult {
- let atoms_ptr = (&self.atom_tbl.table) as *const indexmap::IndexSet<Atom>;
-
if let Stream::Readline(ptr) = stream {
unsafe {
let readline = ptr.as_ptr().as_mut().unwrap();
- readline.set_atoms_for_completion(atoms_ptr);
+ readline.set_atoms_for_completion(&self.atom_tbl);
return self.read_term(
stream,
indices,
}
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
- var_names.insert(var, VarPtr::from(name.as_str()));
+ var_names.insert(var, VarPtr::from(&*name.as_str()));
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
- var_names.insert(var, VarPtr::from(name.as_str()));
+ var_names.insert(var, VarPtr::from(&*name.as_str()));
}
_ => {
unreachable!();
let mut printer = HCPrinter::new(
&mut self.heap,
- &mut self.atom_tbl,
+ Arc::clone(&self.atom_tbl),
&mut self.stack,
op_dir,
PrinterOutputter::new(),
} else {
self.pdl.clear();
return Some(
- n1.chars().next().cmp(&Some(c2))
+ n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater)
);
}
} else {
self.pdl.clear();
return Some(
- Some(c1).cmp(&n2.chars().next())
+ Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less)
);
}
} else {
self.pdl.clear();
return Some(
- Some(c1).cmp(&n2.chars().next())
+ Some(c1).cmp(&n2.as_str().chars().next())
.then(Ordering::Less)
);
}
} else {
self.pdl.clear();
return Some(
- n1.chars().next().cmp(&Some(c2))
+ n1.as_str().chars().next().cmp(&Some(c2))
.then(Ordering::Greater)
);
}
let s = string.as_str();
- match heap_pstr_iter.compare_pstr_to_string(s) {
+ match heap_pstr_iter.compare_pstr_to_string(&*s) {
Some(PStrPrefixCmpResult {
focus,
offset,
self.s_offset = 0;
self.mode = MachineMode::Read;
- put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl)
+ put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write())
} else {
- put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl)
+ put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write())
}
}
(name, 0, 0)
}
(HeapCellValueTag::Char, c) => {
- (self.atom_tbl.build_with(&c.to_string()), 0, 0)
+ (self.atom_tbl.blocking_write().build_with(&c.to_string()), 0, 0)
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub = functor_stub(atom!("call"), arity + 1);
}
}
(HeapCellValueTag::Char, c) => {
- let c = self.atom_tbl.build_with(&c.to_string());
+ let c = self.atom_tbl.blocking_write().build_with(&c.to_string());
self.try_functor_fabricate_struct(
c,
use crate::read::*;
pub use crate::types::*;
+use std::sync::Arc;
+
#[cfg(test)]
use crate::machine::copier::CopierTarget;
let mut printer = HCPrinter::new(
&mut self.machine_st.heap,
- &mut self.machine_st.atom_tbl,
+ Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack,
&self.op_dir,
PrinterOutputter::new(),
pub fn load_file(&mut self, path: &str, stream: Stream) {
self.machine_st.registers[1] = stream_as_cell!(stream);
- self.machine_st.registers[2] = atom_as_cell!(self.machine_st.atom_tbl.build_with(path));
+ self.machine_st.registers[2] =
+ atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(path));
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
}
arg_pstrs.push(put_complete_string(
&mut self.machine_st.heap,
&arg,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
));
}
}
#[inline(always)]
- pub(crate) fn as_str_from(&self, n: usize) -> &str {
- &self.0.as_str()[n..]
+ pub(crate) fn as_str_from(&self, n: usize) -> AtomString {
+ self.0.as_str().map(|str| &str[n..])
}
}
let s = &s[result.prefix_len..];
if s.len() >= t.len() {
- if s.starts_with(t) {
+ if (&*s).starts_with(&*t) {
result.prefix_len += t.len();
result.offset += t.len();
} else {
}
PStrIteratee::PStrSegment(_, pstr_atom, n) => {
let pstr = PartialString::from(pstr_atom);
- buf += pstr.as_str_from(n);
+ buf += &*pstr.as_str_from(n);
}
}
}
let str2 = pstr2.as_str_from(n2);
match str1.len().cmp(&str2.len()) {
- Ordering::Equal if str1 == str2 => {
+ Ordering::Equal if &*str1 == &*str2 => {
cycle_detection_step(i1, i2, &step_1);
let both_cyclic = cycle_detection_step(i2, i1, &step_2);
continue;
}
}
- Ordering::Less if str2.starts_with(str1) => {
+ Ordering::Less if str2.starts_with(&*str1) => {
step_2.iteratee =
PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
let c1_result = cycle_detection_step(i1, i2, &step_1);
continue;
}
}
- Ordering::Greater if str1.starts_with(str2) => {
+ Ordering::Greater if str1.starts_with(&*str2) => {
step_1.iteratee =
PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
let c2_result = cycle_detection_step(i2, i1, &step_2);
}
}
_ => {
- return PStrCmpResult::Ordered(str1.cmp(str2));
+ return PStrCmpResult::Ordered(str1.cmp(&*str2));
}
}
}
let pstr_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
let pstr_second_var_cell = put_partial_string(
&mut wam.machine_st.heap,
"def",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
// construct a structurally similar but different cyclic partial string
// matching the one beginning at wam.machine_st.heap[0].
- put_partial_string(&mut wam.machine_st.heap, "ab", &mut wam.machine_st.atom_tbl);
+ put_partial_string(
+ &mut wam.machine_st.heap,
+ "ab",
+ &mut wam.machine_st.atom_tbl.blocking_write(),
+ );
wam.machine_st.heap.pop();
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
- put_partial_string(&mut wam.machine_st.heap, "c ", &mut wam.machine_st.atom_tbl);
+ put_partial_string(
+ &mut wam.machine_st.heap,
+ "c ",
+ &mut wam.machine_st.atom_tbl.blocking_write(),
+ );
wam.machine_st.heap.pop();
put_partial_string(
&mut wam.machine_st.heap,
"abc ",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
let pstr_cell = wam.machine_st.heap[0];
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
wam.machine_st.heap.push(list_loc_as_cell!(2));
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.clear();
- let cstr_var_cell =
- put_complete_string(&mut wam.machine_st.heap, "d", &mut wam.machine_st.atom_tbl);
+ let cstr_var_cell = put_complete_string(
+ &mut wam.machine_st.heap,
+ "d",
+ &mut wam.machine_st.atom_tbl.blocking_write(),
+ );
wam.machine_st.heap.push(list_loc_as_cell!(2));
wam.machine_st.heap.push(char_as_cell!('d'));
let cstr_var_cell = put_complete_string(
&mut wam.machine_st.heap,
"abc",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
wam.machine_st.heap.push(list_loc_as_cell!(2));
put_complete_string(
&mut wam.machine_st.heap,
"abcdef",
- &mut wam.machine_st.atom_tbl,
+ &mut wam.machine_st.atom_tbl.blocking_write(),
);
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
}
(atom!("module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
- Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?))
+ Ok(Declaration::Module(setup_module_decl(
+ terms,
+ &mut atom_tbl.blocking_write(),
+ )?))
}
(atom!("op"), 3) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
- Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?))
+ Ok(Declaration::Op(setup_op_decl(
+ terms,
+ &mut atom_tbl.blocking_write(),
+ )?))
}
(atom!("non_counted_backtracking"), 1) => {
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
(atom!("use_module"), 2) => {
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
- let (name, exports) = setup_qualified_import(terms, atom_tbl)?;
+ let (name, exports) =
+ setup_qualified_import(terms, &mut atom_tbl.blocking_write())?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
}
};
- let file = match open_options.open(file_spec.as_str()) {
+ let file = match open_options.open(&*file_spec.as_str()) {
Ok(file) => file,
Err(err) => {
match err.kind() {
}
}
(HeapCellValueTag::Char, c) => {
- let name = self.machine_st.atom_tbl.build_with(&c.to_string());
+ let name = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string());
let h = self.machine_st.heap.len();
self.machine_st.heap.push(atom_as_cell!(name));
match hostname::get().ok() {
Some(host) => match host.to_str() {
Some(host) => {
- let hostname = self.machine_st.atom_tbl.build_with(host);
+ let hostname = self.machine_st.atom_tbl.blocking_write().build_with(host);
let a1 = self.deref_register(1);
self.machine_st.unify_atom(hostname, a1);
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- let path = std::path::Path::new(dir.as_str());
+ let str = dir.as_str();
+ let path = std::path::Path::new(&*str);
let mut files = Vec::new();
if let Ok(entries) = fs::read_dir(path) {
for entry in entries {
if let Ok(entry) = entry {
if let Some(name) = entry.file_name().to_str() {
- let name = self.machine_st.atom_tbl.build_with(name);
+ let name = self.machine_st.atom_tbl.blocking_write().build_with(name);
files.push(atom_as_cstr_cell!(name));
continue;
.value_to_str_like(self.machine_st.registers[1])
{
let len = Number::arena_from(
- fs::metadata(file.as_str()).unwrap().len(),
+ fs::metadata(&*file.as_str()).unwrap().len(),
&mut self.machine_st.arena,
);
{
let file_str = file.as_str();
- if !std::path::Path::new(file_str).exists()
- || !fs::metadata(file_str).unwrap().is_file()
+ if !std::path::Path::new(&*file_str).exists()
+ || !fs::metadata(&*file_str).unwrap().is_file()
{
self.machine_st.fail = true;
}
{
let dir_str = dir.as_str();
- if !std::path::Path::new(dir_str).exists() || !fs::metadata(dir_str).unwrap().is_dir() {
+ if !std::path::Path::new(&*dir_str).exists()
+ || !fs::metadata(&*dir_str).unwrap().is_dir()
+ {
self.machine_st.fail = true;
}
} else {
{
let which = cell_as_atom!(self.deref_register(2));
- if let Ok(md) = fs::metadata(file.as_str()) {
+ if let Ok(md) = fs::metadata(&*file.as_str()) {
if let Ok(time) = match which {
atom!("modification") => md.modified(),
atom!("access") => md.accessed(),
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match fs::create_dir(dir.as_str()) {
+ match fs::create_dir(&*dir.as_str()) {
Ok(_) => {}
_ => {
self.machine_st.fail = true;
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match fs::create_dir_all(dir.as_str()) {
+ match fs::create_dir_all(&*dir.as_str()) {
Ok(_) => {}
_ => {
self.machine_st.fail = true;
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match fs::remove_file(file.as_str()) {
+ match fs::remove_file(&*file.as_str()) {
Ok(_) => {}
_ => {
self.machine_st.fail = true;
.machine_st
.value_to_str_like(self.machine_st.registers[2])
{
- if fs::rename(file.as_str(), renamed.as_str()).is_ok() {
+ if fs::rename(&*file.as_str(), &*renamed.as_str()).is_ok() {
return;
}
}
.machine_st
.value_to_str_like(self.machine_st.registers[2])
{
- if fs::copy(file.as_str(), copied.as_str()).is_ok() {
+ if fs::copy(&*file.as_str(), &*copied.as_str()).is_ok() {
return;
}
}
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match fs::remove_dir(dir.as_str()) {
+ match fs::remove_dir(&*dir.as_str()) {
Ok(_) => {}
_ => {
self.machine_st.fail = true;
}
};
- let current_atom = self.machine_st.atom_tbl.build_with(¤t);
+ let current_atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(¤t);
let a1 = self.deref_register(1);
self.machine_st.unify_complete_string(current_atom, a1);
let target = self.deref_register(2);
if let Some(next) = self.machine_st.value_to_str_like(target) {
- if env::set_current_dir(std::path::Path::new(next.as_str())).is_ok() {
+ if env::set_current_dir(std::path::Path::new(&*next.as_str())).is_ok() {
return Ok(());
}
}
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match fs::canonicalize(path.as_str()) {
+ match fs::canonicalize(&*path.as_str()) {
Ok(canonical) => {
let cs = match canonical.to_str() {
Some(s) => s,
}
};
- let canonical_atom = self.machine_st.atom_tbl.build_with(cs);
+ let canonical_atom = self.machine_st.atom_tbl.blocking_write().build_with(cs);
let a2 = self.deref_register(2);
self.machine_st.unify_complete_string(canonical_atom, a2);
let atom_cell = match str_like {
AtomOrString::Atom(atom) => {
atom_as_cell!(if atom == atom!("[]") {
- self.machine_st.atom_tbl.build_with("")
+ self.machine_st.atom_tbl.blocking_write().build_with("")
} else {
atom
})
}
AtomOrString::String(string) => {
- atom_as_cell!(self.machine_st.atom_tbl.build_with(&string))
+ atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(&string))
}
};
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
+ let name = name.as_str();
let iter = name.chars()
.map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
.get_name_and_arity();
if arity == 0 {
+ let name = name.as_str();
let iter = name.chars()
.map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) {
Ok(addrs) => {
let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
- let atom = self.machine_st.atom_tbl.build_with(&string);
+ let atom = self.machine_st.atom_tbl.blocking_write().build_with(&string);
self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
}
.get_name_and_arity();
if arity == 0 {
- name.chars().count() as i64
+ name.as_str().chars().count() as i64
} else {
self.machine_st.fail = true;
return;
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
- name.chars().count() as i64
+ name.as_str().chars().count() as i64
} else {
self.machine_st.fail = true;
return;
let atom_or_string = self.machine_st.value_to_str_like(a1).unwrap();
self.machine_st
- .parse_number_from_string(atom_or_string.as_str(), &self.indices, stub_gen)
+ .parse_number_from_string(&*atom_or_string.as_str(), &self.indices, stub_gen)
}
#[inline(always)]
}
};
- let chars_atom = self.machine_st.atom_tbl.build_with(&string.trim());
+ let chars_atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&string.trim());
self.machine_st.unify_complete_string(chars_atom, chs);
}
match (name, arity) {
(atom!("to_upper"), 1) => {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
- let atom = self.machine_st.atom_tbl.build_with(&c.to_uppercase().to_string());
+ let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_uppercase().to_string());
let upper_str = string_as_cstr_cell!(atom);
unify!(self.machine_st, reg, upper_str);
self.machine_st.fail = false;
}
(atom!("to_lower"), 1) => {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
- let atom = self.machine_st.atom_tbl.build_with(&c.to_lowercase().to_string());
+ let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_lowercase().to_string());
let lower_str = string_as_cstr_cell!(atom);
unify!(self.machine_st, reg, lower_str);
self.machine_st.fail = false;
};
let output = self.deref_register(3);
- let atom = self.machine_st.atom_tbl.build_with(&string);
+ let atom = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&string);
self.machine_st.unify_complete_string(atom, output);
Ok(())
cell_as_atom!(self.machine_st.heap[s])
}
(HeapCellValueTag::Char, c) => {
- self.machine_st.atom_tbl.build_with(&c.to_string())
+ self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string())
}
_ => {
unreachable!()
(HeapCellValueTag::Str, s) => {
let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name();
let value = self.machine_st.value_to_str_like(self.machine_st.heap[s + 1]).unwrap();
- header_map.insert(HeaderName::from_str(name.as_str()).unwrap(), HeaderValue::from_str(value.as_str()).unwrap());
+ header_map.insert(HeaderName::from_str(&*name.as_str()).unwrap(), HeaderValue::from_str(&*value.as_str()).unwrap());
}
_ => {
unreachable!()
let h = self.machine_st.heap.len();
let header_term = functor!(
- self.machine_st.atom_tbl.build_with(header_name.as_str()),
+ self.machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(header_name.as_str()),
[cell(string_as_cstr_cell!(self
.machine_st
.atom_tbl
+ .blocking_write()
.build_with(header_value.to_str().unwrap())))]
);
let reader = resp.bytes().unwrap().reader();
let mut stream = Stream::from_http_stream(
- self.machine_st.atom_tbl.build_with(&address_string),
+ self.machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&address_string),
Box::new(reader),
&mut self.machine_st.arena,
);
Method::HEAD => atom!("head"),
_ => unreachable!(),
};
- let path_atom = self.machine_st.atom_tbl.build_with(request.request.uri().path());
+ let path_atom = self.machine_st.atom_tbl.blocking_write().build_with(request.request.uri().path());
let path_cell = atom_as_cstr_cell!(path_atom);
let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
let h = self.machine_st.heap.len();
let header_term = functor!(
- self.machine_st.atom_tbl.build_with(header_name.as_str()),
- [cell(string_as_cstr_cell!(self.machine_st.atom_tbl.build_with(header_value.to_str().unwrap())))]
+ self.machine_st.atom_tbl.blocking_write().build_with(header_name.as_str()),
+ [cell(string_as_cstr_cell!(self.machine_st.atom_tbl.blocking_write().build_with(header_value.to_str().unwrap())))]
);
self.machine_st.heap.extend(header_term.into_iter());
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
let query_str = request.request.uri().query().unwrap_or("");
- let query_atom = self.machine_st.atom_tbl.build_with(query_str);
+ let query_atom = self.machine_st.atom_tbl.blocking_write().build_with(query_str);
let query_cell = string_as_cstr_cell!(query_atom);
let hyper_req = request.request;
(HeapCellValueTag::Str, s) => {
let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name();
let value = self.machine_st.value_to_str_like(self.machine_st.heap[s + 1]).unwrap();
- header_map.insert(HeaderName::from_str(name.as_str()).unwrap(), HeaderValue::from_str(value.as_str()).unwrap());
+ header_map.insert(HeaderName::from_str(&*name.as_str()).unwrap(), HeaderValue::from_str(&*value.as_str()).unwrap());
}
_ => {
unreachable!()
}
if let Ok(_) = self
.foreign_function_table
- .load_library(library_name.as_str(), &functions)
+ .load_library(&*library_name.as_str(), &functions)
{
return Ok(());
}
_ => {
let stub_gen = || functor_stub(atom!("foreign_call"), 3);
if let Some(string) = machine_st.value_to_str_like(source) {
- Value::CString(CString::new(string.as_str()).unwrap())
+ Value::CString(CString::new(&*string.as_str()).unwrap())
} else {
match machine_st.try_from_list(source, stub_gen) {
Ok(args) => {
.collect();
match self
.foreign_function_table
- .exec(function_name.as_str(), args)
+ .exec(&*function_name.as_str(), args)
{
Ok(result) => {
match result {
unify!(self.machine_st, return_value, struct_value);
}
Value::CString(cstr) => {
- let cstr =
- self.machine_st.atom_tbl.build_with(cstr.to_str().unwrap());
+ let cstr = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(cstr.to_str().unwrap());
self.machine_st.unify_complete_string(cstr, return_value);
}
}
Value::CString(cstr) => atom_as_cell!(self
.machine_st
.atom_tbl
+ .blocking_write()
.build_with(&cstr.into_string().unwrap())),
Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
})
Err(e) => return Err(e),
};
self.foreign_function_table
- .define_struct(struct_name.as_str(), fields);
+ .define_struct(&*struct_name.as_str(), fields);
return Ok(());
}
self.machine_st.fail = true;
let src_sink = self.deref_register(1);
if let Some(file_spec) = self.machine_st.value_to_str_like(src_sink) {
- let file_spec = file_spec.as_atom(&mut self.machine_st.atom_tbl);
+ let file_spec = file_spec.as_atom(&mut self.machine_st.atom_tbl.blocking_write());
let mut stream =
self.machine_st
let op = read_heap_cell!(self.deref_register(3),
(HeapCellValueTag::Char, c) => {
- self.machine_st.atom_tbl.build_with(&c.to_string())
+ self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string())
}
(HeapCellValueTag::Atom, (name, _arity)) => {
name
write_term_to_heap(
&term,
&mut self.machine_st.heap,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
)
});
name
}
_ => {
- self.machine_st.atom_tbl.build_with(&match Number::try_from(port) {
+ self.machine_st.atom_tbl.blocking_write().build_with(&match Number::try_from(port) {
Ok(Number::Fixnum(n)) => n.get_num().to_string(),
Ok(Number::Integer(n)) => n.to_string(),
_ => {
atom!("127.0.0.1:80")
} else {
let buffer = format!("{}:{}", socket_atom.as_str(), port.as_str());
- self.machine_st.atom_tbl.build_with(&buffer)
+ self.machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&buffer)
};
let alias = self.machine_st.registers[4];
}
}
- let stream = match TcpStream::connect(socket_addr.as_str()).map_err(|e| e.kind()) {
+ let stream = match TcpStream::connect(&*socket_addr.as_str()).map_err(|e| e.kind()) {
Ok(tcp_stream) => {
let mut stream =
Stream::from_tcp_stream(socket_addr, tcp_stream, &mut self.machine_st.arena);
(ArenaHeaderTag::TcpListener, tcp_listener) => {
match tcp_listener.accept().ok() {
Some((tcp_stream, socket_addr)) => {
- let client = self.machine_st.atom_tbl.build_with(&socket_addr.to_string());
+ let client = self.machine_st.atom_tbl.blocking_write().build_with(&socket_addr.to_string());
let mut tcp_stream = Stream::from_tcp_stream(
client,
)?;
let connector = TlsConnector::new().unwrap();
- let stream = match connector.connect(hostname.as_str(), stream0) {
+ let stream = match connector.connect(&*hostname.as_str(), stream0) {
Ok(tls_stream) => tls_stream,
Err(_) => {
return Err(self.machine_st.open_permission_error(
.machine_st
.value_to_str_like(self.machine_st.registers[2])
{
- let identity = match Identity::from_pkcs12(&pkcs12, password.as_str()) {
+ let identity = match Identity::from_pkcs12(&pkcs12, &*password.as_str()) {
Ok(identity) => identity,
Err(_) => {
return Err(self.machine_st.open_permission_error(
let chars = put_complete_string(
&mut self.machine_st.heap,
&result,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
);
let result_addr = self.deref_register(1);
use git_version::git_version;
let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
- let buffer_atom = self.machine_st.atom_tbl.build_with(buffer);
+ let buffer_atom = self.machine_st.atom_tbl.blocking_write().build_with(buffer);
let a1 = self.deref_register(1);
self.machine_st.unify_complete_string(buffer_atom, a1);
if buffer.len() == 0 {
empty_list_as_cell!()
} else {
- atom_as_cstr_cell!(self.machine_st.atom_tbl.build_with(&buffer))
+ atom_as_cstr_cell!(self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&buffer))
}
};
if let Some(string) = self.machine_st.value_to_str_like(addr) {
for c in string.as_str().chars() {
if c as u32 > 255 {
- let non_octet = self.machine_st.atom_tbl.build_with(&c.to_string());
+ let non_octet = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&c.to_string());
self.machine_st
.unify_atom(non_octet, self.machine_st.registers[2]);
return;
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match roxmltree::Document::parse(string.as_str()) {
+ match roxmltree::Document::parse(&*string.as_str()) {
Ok(doc) => {
let result = self.xml_node_to_term(doc.root_element());
unify!(self.machine_st, self.machine_st.registers[2], result);
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
- match env::var(key.as_str()) {
+ match env::var(&*key.as_str()) {
Ok(value) => {
let cstr = put_complete_string(
&mut self.machine_st.heap,
&value,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
);
unify!(self.machine_st, self.machine_st.registers[2], cstr);
.value_to_str_like(self.machine_st.registers[2])
.unwrap();
- env::set_var(key.as_str(), value.as_str());
+ env::set_var(&*key.as_str(), &*value.as_str());
}
#[inline(always)]
.machine_st
.value_to_str_like(self.machine_st.registers[1])
.unwrap();
- env::remove_var(key.as_str());
+ env::remove_var(&*key.as_str());
}
#[inline(always)]
Ok(value) => {
let command = process::Command::new(&value)
.arg("-c")
- .arg(command.as_str())
+ .arg(&*command.as_str())
.status();
command_result(&mut self.machine_st, command);
}
Ok(value) => {
let command = process::Command::new(&value)
.arg("/C")
- .arg(command.as_str())
+ .arg(&*command.as_str())
.status();
command_result(&mut self.machine_st, command);
}
.machine_st
.value_to_str_like(self.machine_st.registers[2])
.unwrap();
- let bytes = base64::decode_config(b64.as_str(), config);
+ let bytes = base64::decode_config(&*b64.as_str(), config);
match bytes {
Ok(bs) => {
use crate::machine::LIBRARIES;
- match LIBRARIES.borrow().get(library_name.as_str()) {
+ match LIBRARIES.borrow().get(&*library_name.as_str()) {
Some(library) => {
let lib_stream = Stream::from_static_string(library, &mut self.machine_st.arena);
unify!(
let mut path_buf = machine::current_dir();
path_buf.push("/lib");
- path_buf.push(library_name.as_str());
+ path_buf.push(&*library_name.as_str());
let library_path_str = path_buf.to_str().unwrap();
- let library_path = self.machine_st.atom_tbl.build_with(library_path_str);
+ let library_path = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(library_path_str);
self.machine_st
.unify_atom(library_path, self.machine_st.registers[3]);
let path_string = put_complete_string(
&mut self.machine_st.heap,
path,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
);
unify!(self.machine_st, self.machine_st.registers[1], path_string);
fstr.push_str("finis].");
let s = datetime.format(&fstr).to_string();
- self.machine_st.atom_tbl.build_with(&s)
+ self.machine_st.atom_tbl.blocking_write().build_with(&s)
}
pub(super) fn string_encoding_bytes(
put_complete_string(
&mut self.machine_st.heap,
node.text().unwrap(),
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
)
} else {
let mut avec = Vec::new();
for attr in node.attributes() {
- let name = self.machine_st.atom_tbl.build_with(attr.name());
+ let name = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(attr.name());
let value = put_complete_string(
&mut self.machine_st.heap,
&attr.value(),
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
);
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
cvec.into_iter()
));
- let tag = self.machine_st.atom_tbl.build_with(node.tag_name().name());
+ let tag = self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(node.tag_name().name());
let result = str_loc_as_cell!(self.machine_st.heap.len());
None => put_complete_string(
&mut self.machine_st.heap,
&node.text(),
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
),
Some(name) => {
let mut avec = Vec::new();
for attr in node.attrs() {
- let name = self.machine_st.atom_tbl.build_with(attr.0);
+ let name = self.machine_st.atom_tbl.blocking_write().build_with(attr.0);
let value = put_complete_string(
&mut self.machine_st.heap,
&attr.1,
- &mut self.machine_st.atom_tbl,
+ &mut self.machine_st.atom_tbl.blocking_write(),
);
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
cvec.into_iter()
));
- let tag = self.machine_st.atom_tbl.build_with(name);
+ let tag = self.machine_st.atom_tbl.blocking_write().build_with(name);
let result = str_loc_as_cell!(self.machine_st.heap.len());
self.machine_st
if buffer.len() == 0 {
empty_list_as_cell!()
} else {
- atom_as_cstr_cell!(self.machine_st.atom_tbl.build_with(&buffer))
+ atom_as_cstr_cell!(self
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&buffer))
}
}
}
Ok(Token::Literal(Literal::Atom(atom!("[]"))))
} else {
Ok(Token::Literal(Literal::Atom(
- self.machine_st.atom_tbl.build_with(&token),
+ self.machine_st.atom_tbl.blocking_write().build_with(&token),
)))
}
}
if c == '"' {
let s = self.char_code_list_token(c)?;
- let atom = self.machine_st.atom_tbl.build_with(&s);
+ let atom = self.machine_st.atom_tbl.blocking_write().build_with(&s);
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
Ok(Token::Literal(Literal::Atom(atom)))
tail_ref = tail;
}
Term::CompleteString(_, cstr) => {
- string += cstr.as_str();
+ string += &*cstr.as_str();
tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
break;
}
Term::AnonVar | Term::Var(..) => Ok((string, Some(Box::new(tail)))),
Term::Literal(_, Literal::Atom(atom!("[]"))) => Ok((string, None)),
Term::Literal(_, Literal::String(tail)) => {
- string += tail.as_str();
+ string += &*tail.as_str();
Ok((string, None))
}
_ => Ok((string, Some(Box::new(tail)))),
let idx = self.terms.len() - arity;
if TokenType::Term == self.stack[stack_len].tt {
- if atomize_term(&mut self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() {
+ if atomize_term(
+ &mut self.lexer.machine_st.atom_tbl.blocking_write(),
+ &self.terms[idx - 1],
+ )
+ .is_some()
+ {
self.stack.truncate(stack_len + 1);
let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
- if let Some(name) = self
- .terms
- .pop()
- .and_then(|t| atomize_term(&mut self.lexer.machine_st.atom_tbl, &t))
- {
+ if let Some(name) = self.terms.pop().and_then(|t| {
+ atomize_term(&mut self.lexer.machine_st.atom_tbl.blocking_write(), &t)
+ }) {
// reduce the '.' functor to a cons cell if it applies.
if name == atom!(".") && subterms.len() == 2 {
let tail = subterms.pop().unwrap();
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
- let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
+ let atom = self
+ .lexer
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
- let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
+ let atom = self
+ .lexer
+ .machine_st
+ .atom_tbl
+ .blocking_write()
+ .build_with(&string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
|n, arena| Literal::from(float_alloc!(n, arena)),
),
Token::Literal(c) => {
- if let Some(name) = atomize_constant(&mut self.lexer.machine_st.atom_tbl, c) {
+ let atomized =
+ atomize_constant(&mut self.lexer.machine_st.atom_tbl.blocking_write(), c);
+ if let Some(name) = atomized {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
}
use fxhash::FxBuildHasher;
-use indexmap::IndexSet;
+use tokio::sync::RwLock;
+
+use std::sync::Arc;
#[cfg(feature = "repl")]
use rustyline::error::ReadlineError;
};
inner.add_lines_read(num_lines_read);
- write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl)
+ write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl.blocking_write())
}
}
}
impl ReadlineStream {
- #[cfg(feature = "repl")]
#[inline]
pub fn new(pending_input: &str, add_history: bool) -> Self {
- let config = Config::builder().check_cursor_position(true).build();
+ #[cfg(feature = "repl")]
+ {
+ let config = Config::builder().check_cursor_position(true).build();
- let helper = Helper::new();
+ let helper = Helper::new();
- let mut rl = Editor::with_config(config).unwrap();
- rl.set_helper(Some(helper));
+ let mut rl = Editor::with_config(config).unwrap();
+ rl.set_helper(Some(helper));
- if let Some(mut path) = dirs_next::home_dir() {
- path.push(HISTORY_FILE);
- if path.exists() && rl.load_history(&path).is_err() {
- println!("Warning: loading history failed");
+ if let Some(mut path) = dirs_next::home_dir() {
+ path.push(HISTORY_FILE);
+ if path.exists() && rl.load_history(&path).is_err() {
+ println!("Warning: loading history failed");
+ }
}
- }
- ReadlineStream {
- rl,
- pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
- add_history: add_history,
+ ReadlineStream {
+ rl,
+ pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
+ add_history: add_history,
+ }
}
- }
- #[cfg(not(feature = "repl"))]
- #[inline]
- pub fn new(pending_input: &str, add_history: bool) -> Self {
- ReadlineStream {
- pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
- add_history: add_history,
+ #[cfg(not(feature = "repl"))]
+ {
+ ReadlineStream {
+ pending_input: CharReader::new(Cursor::new(pending_input.to_owned())),
+ add_history: add_history,
+ }
}
}
- #[cfg(feature = "repl")]
- pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) {
- let helper = self.rl.helper_mut().unwrap();
- helper.atoms = atoms;
+ pub fn set_atoms_for_completion(&mut self, atoms: &Arc<RwLock<AtomTable>>) {
+ #[cfg(feature = "repl")]
+ {
+ let helper = self.rl.helper_mut().unwrap();
+ helper.atoms = Arc::downgrade(atoms);
+ }
}
- #[cfg(not(feature = "repl"))]
- pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet<Atom>) {}
-
#[inline]
pub fn reset(&mut self) {
self.pending_input.reset_buffer();
continue;
}
&TermRef::CompleteString(_, _, ref src) => {
- put_complete_string(self.heap, src.as_str(), self.atom_tbl);
+ put_complete_string(self.heap, &src.as_str(), self.atom_tbl);
}
&TermRef::PartialString(lvl, _, ref src, _) => {
if let Level::Root = lvl {
-use indexmap::IndexSet;
-use rustyline::completion::{Candidate, Completer};
+use rustyline::completion::Completer;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::Hinter;
use rustyline::validate::Validator;
use rustyline::{Context, Helper as RlHelper, Result};
-use crate::atom_table::{Atom, STATIC_ATOMS_MAP};
+use tokio::sync::RwLock;
+
+use std::sync::Weak;
+
+use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
// TODO: Maybe add validation to the helper
pub struct Helper {
highligher: MatchingBracketHighlighter,
- pub atoms: *const IndexSet<Atom>,
+ pub atoms: Weak<RwLock<AtomTable>>,
}
impl Helper {
pub fn new() -> Self {
Self {
highligher: MatchingBracketHighlighter::new(),
- atoms: std::ptr::null(),
+ atoms: Weak::new(),
}
}
}
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 = StrPtr;
+ type Candidate = AtomString<'static>;
fn complete(
&self,
let start_of_prefix = get_prefix(line, pos);
if let Some(idx) = start_of_prefix {
let sub_str = line.get(idx..pos).unwrap();
- Ok((idx, unsafe {
- let mut matching = (*self.atoms)
- .iter()
- .chain(STATIC_ATOMS_MAP.values())
- .filter(|a| a.as_str().starts_with(sub_str))
- .map(|s| StrPtr(s.as_str()))
- .collect::<Vec<_>>();
-
- matching.sort_unstable_by(|a, b| Ord::cmp(&(*a.0).len(), &(*b.0).len()));
- matching
- }))
+
+ let guard = tokio::runtime::Handle::current()
+ .block_on(self.atoms.upgrade().unwrap().read_owned());
+
+ let mut matching = guard
+ .table
+ .iter()
+ .chain(STATIC_ATOMS_MAP.values())
+ .map(|a| a.as_str())
+ .filter(|a| a.starts_with(sub_str))
+ .collect::<Vec<_>>();
+
+ matching.sort_unstable_by(|a, b| Ord::cmp(&a.len(), &b.len()));
+
+ Ok((idx, matching))
} else {
Ok((0, vec![]))
}