[WIP] fix deadlock in AtomTable::build_with
This commit is contained in:
@@ -1003,11 +1003,8 @@ mod tests {
|
|||||||
|
|
||||||
// complete string
|
// complete string
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "ronan", &wam.machine_st.atom_tbl);
|
||||||
"ronan",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);
|
assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);
|
||||||
|
|||||||
@@ -46,16 +46,16 @@ impl From<bool> for Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl indexmap::Equivalent<Atom> for str {
|
impl indexmap::Equivalent<Atom> for LookupKey<'_, '_> {
|
||||||
fn equivalent(&self, atom: &Atom) -> bool {
|
fn equivalent(&self, key: &Atom) -> bool {
|
||||||
&*atom.as_str() == self
|
&*key.as_str_with_table(self.0) == self.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
|
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
|
||||||
const ATOM_TABLE_ALIGN: usize = 8;
|
const ATOM_TABLE_ALIGN: usize = 8;
|
||||||
|
|
||||||
pub fn global_atom_table() -> &'static RwLock<Weak<RwLock<AtomTable>>> {
|
fn global_atom_table() -> &'static RwLock<Weak<RwLock<AtomTable>>> {
|
||||||
#[cfg(feature = "rust_beta_channel")]
|
#[cfg(feature = "rust_beta_channel")]
|
||||||
{
|
{
|
||||||
// const Weak::new will be stabilized in 1.73 which is currently in beta,
|
// const Weak::new will be stabilized in 1.73 which is currently in beta,
|
||||||
@@ -71,6 +71,22 @@ pub fn global_atom_table() -> &'static RwLock<Weak<RwLock<AtomTable>>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn owned_atom_table_read_guard() -> Option<OwnedRwLockReadGuard<AtomTable>> {
|
||||||
|
let atom_table = global_atom_table().blocking_read().upgrade()?;
|
||||||
|
|
||||||
|
let guard = {
|
||||||
|
// some test don't start a Runtime
|
||||||
|
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(guard)
|
||||||
|
}
|
||||||
|
|
||||||
impl RawBlockTraits for AtomTable {
|
impl RawBlockTraits for AtomTable {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn init_size() -> usize {
|
fn init_size() -> usize {
|
||||||
@@ -184,36 +200,28 @@ impl Atom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_ptr(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
|
pub fn as_ptr_with_table<'at>(&self, atom_table: &'at AtomTable) -> Option<&'at u8> {
|
||||||
if self.is_static() {
|
if self.is_static() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let atom_table = global_atom_table()
|
unsafe {
|
||||||
.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
|
atom_table
|
||||||
.buf()
|
.buf()
|
||||||
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
|
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
}
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn as_ptr(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
|
||||||
|
if self.is_static() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let guard = owned_atom_table_read_guard()
|
||||||
|
.expect("We should only have an Atom while there is an AtomTable");
|
||||||
|
OwnedRwLockReadGuard::try_map(guard, |atom_table| self.as_ptr_with_table(atom_table))
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,10 +235,9 @@ impl Atom {
|
|||||||
if self.is_static() {
|
if self.is_static() {
|
||||||
STRINGS[(self.index >> 3) as usize].len()
|
STRINGS[(self.index >> 3) as usize].len()
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
let ptr = self.as_ptr().unwrap();
|
||||||
ptr::read(self.as_ptr().unwrap().deref() as *const u8 as *const AtomHeader).len()
|
let ptr = ptr.deref() as *const u8 as *const AtomHeader;
|
||||||
as _
|
unsafe { ptr::read(ptr) }.len() as _
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,34 +260,46 @@ impl Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn as_str(&self) -> AtomString<'static> {
|
pub fn as_str_with_table<'at>(&self, atom_table: &'at AtomTable) -> &'at str {
|
||||||
if let Some(ptr_guard) = self.as_ptr() {
|
if let Some(ptr) = self.as_ptr_with_table(atom_table) {
|
||||||
AtomString::Dynamic(OwnedRwLockReadGuard::map(ptr_guard, |ptr| {
|
let header = unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
|
||||||
let header =
|
let len = header.len() as usize;
|
||||||
unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
|
let buf = (unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize) })
|
||||||
let len = header.len() as usize;
|
as *mut u8;
|
||||||
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)) }
|
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
return AtomString::Static(STRINGS[(self.index >> 3) as usize]);
|
&STRINGS[(self.index >> 3) as usize]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn defrock_brackets(&self, atom_tbl: &mut AtomTable) -> Self {
|
#[track_caller]
|
||||||
|
#[inline]
|
||||||
|
pub fn as_str(&self) -> AtomString<'static> {
|
||||||
|
if self.is_static() {
|
||||||
|
AtomString::Static(STRINGS[(self.index >> 3) as usize])
|
||||||
|
} else {
|
||||||
|
let guard = owned_atom_table_read_guard()
|
||||||
|
.expect("We should only have an Atom while there is an AtomTable");
|
||||||
|
AtomString::Dynamic(OwnedRwLockReadGuard::map(guard, |atom_table| {
|
||||||
|
self.as_str_with_table(atom_table)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn defrock_brackets(&self, atom_tbl: &Arc<RwLock<AtomTable>>) -> Self {
|
||||||
let s = self.as_str();
|
let s = self.as_str();
|
||||||
|
|
||||||
let s = if s.starts_with('(') && s.ends_with(')') {
|
let sub_str = if s.starts_with('(') && s.ends_with(')') {
|
||||||
&s['('.len_utf8()..s.len() - ')'.len_utf8()]
|
&s['('.len_utf8()..s.len() - ')'.len_utf8()]
|
||||||
} else {
|
} else {
|
||||||
return *self;
|
return *self;
|
||||||
};
|
};
|
||||||
|
|
||||||
atom_tbl.build_with(s)
|
let val = sub_str.to_string();
|
||||||
|
drop(s); // wee need to drop s as it holds a read lock on the AtomTable and build_with may need to acquire a write lock
|
||||||
|
AtomTable::build_with(&atom_tbl, &val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +326,7 @@ impl Ord for Atom {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AtomTable {
|
pub struct AtomTable {
|
||||||
block: RawBlock<AtomTable>,
|
block: RawBlock<AtomTable>,
|
||||||
pub table: IndexSet<Atom>,
|
pub table: RwLock<IndexSet<Atom>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AtomTable {
|
impl Drop for AtomTable {
|
||||||
@@ -316,11 +335,19 @@ impl Drop for AtomTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LookupKey<'table, 'key>(&'table AtomTable, &'key str);
|
||||||
|
|
||||||
|
impl Hash for LookupKey<'_, '_> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.1.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AtomTable {
|
impl AtomTable {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Arc<RwLock<Self>> {
|
pub fn new() -> Arc<RwLock<Self>> {
|
||||||
let upgraded = global_atom_table().blocking_read().upgrade();
|
let upgraded = global_atom_table().blocking_read().upgrade();
|
||||||
// don't inline upgraded, temporary will be dropped too late in case of None
|
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
|
||||||
if let Some(atom_table) = upgraded {
|
if let Some(atom_table) = upgraded {
|
||||||
atom_table
|
atom_table
|
||||||
} else {
|
} else {
|
||||||
@@ -331,7 +358,7 @@ impl AtomTable {
|
|||||||
} else {
|
} else {
|
||||||
let atom_table = Arc::new(RwLock::new(Self {
|
let atom_table = Arc::new(RwLock::new(Self {
|
||||||
block: RawBlock::new(),
|
block: RawBlock::new(),
|
||||||
table: IndexSet::new(),
|
table: RwLock::new(IndexSet::new()),
|
||||||
}));
|
}));
|
||||||
*guard = Arc::downgrade(&atom_table);
|
*guard = Arc::downgrade(&atom_table);
|
||||||
atom_table
|
atom_table
|
||||||
@@ -350,15 +377,23 @@ impl AtomTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup_str(&self, string: &str) -> Option<Atom> {
|
fn lookup_str(self: &AtomTable, string: &str) -> Option<Atom> {
|
||||||
STATIC_ATOMS_MAP
|
STATIC_ATOMS_MAP.get(string).cloned().or_else(|| {
|
||||||
.get(string)
|
self.table
|
||||||
.or_else(|| self.table.get(string))
|
.blocking_read()
|
||||||
.cloned()
|
.get(&LookupKey(self, string))
|
||||||
|
.cloned()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_with(&mut self, string: &str) -> Atom {
|
pub fn build_with(atom_table: &RwLock<AtomTable>, string: &str) -> Atom {
|
||||||
if let Some(atom) = self.lookup_str(string) {
|
let mut atom_table = loop {
|
||||||
|
if let Ok(guard) = atom_table.try_write() {
|
||||||
|
break guard;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(atom) = atom_table.lookup_str(string) {
|
||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,16 +403,16 @@ impl AtomTable {
|
|||||||
let size = (size & !(align_offset - 1)) + align_offset;
|
let size = (size & !(align_offset - 1)) + align_offset;
|
||||||
|
|
||||||
let len_ptr = loop {
|
let len_ptr = loop {
|
||||||
let ptr = self.block.alloc(size);
|
let ptr = atom_table.block.alloc(size);
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
self.block.grow();
|
atom_table.block.grow();
|
||||||
} else {
|
} else {
|
||||||
break ptr;
|
break ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ptr_base = self.block.base as usize;
|
let ptr_base = atom_table.block.base as usize;
|
||||||
|
|
||||||
write_to_ptr(string, len_ptr);
|
write_to_ptr(string, len_ptr);
|
||||||
|
|
||||||
@@ -385,7 +420,16 @@ impl AtomTable {
|
|||||||
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
|
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.table.insert(atom);
|
// we need to downgrade to a read so that Atom::hash can read from the AtomTable,
|
||||||
|
// so that it can calculate the hash for inserting the atom
|
||||||
|
// we can't just drop the guard as otherwise another thread could race us with another atom insertion
|
||||||
|
let atom_table = atom_table.downgrade();
|
||||||
|
|
||||||
|
// NOTE: there is no race between downgrade and blocking write as table is only accessed writable in this function
|
||||||
|
// and only after the write lock is acquired as we have the guard and just convert it from a write to a read guard no writer can race us
|
||||||
|
atom_table.table.blocking_write().insert(atom);
|
||||||
|
|
||||||
|
drop(atom_table); // we need to keep the guard around till after the insert
|
||||||
|
|
||||||
atom
|
atom
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
TermRef::PartialString(lvl, cell, string, tail) => {
|
TermRef::PartialString(lvl, cell, string, tail) => {
|
||||||
self.marker
|
self.marker
|
||||||
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
|
.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
|
||||||
let atom = self.atom_tbl.blocking_write().build_with(&string);
|
let atom = AtomTable::build_with(&self.atom_tbl, &string);
|
||||||
|
|
||||||
target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
|
target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
|
||||||
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
|
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
|
||||||
@@ -1242,12 +1242,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let index = code.len();
|
let index = code.len();
|
||||||
|
|
||||||
if clauses_len > 1 || self.settings.is_extensible {
|
if clauses_len > 1 || self.settings.is_extensible {
|
||||||
code_offsets.index_term(
|
code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl);
|
||||||
arg,
|
|
||||||
index,
|
|
||||||
&mut clause_index_info,
|
|
||||||
&mut self.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ use fxhash::FxBuildHasher;
|
|||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -481,10 +483,10 @@ pub enum AtomOrString {
|
|||||||
|
|
||||||
impl AtomOrString {
|
impl AtomOrString {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_atom(&self, atom_tbl: &mut AtomTable) -> Atom {
|
pub fn as_atom(&self, atom_tbl: &RwLock<AtomTable>) -> Atom {
|
||||||
match self {
|
match self {
|
||||||
&AtomOrString::Atom(atom) => atom,
|
&AtomOrString::Atom(atom) => atom,
|
||||||
AtomOrString::String(string) => atom_tbl.build_with(&string),
|
AtomOrString::String(string) => AtomTable::build_with(atom_tbl, &string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -708,11 +708,8 @@ mod tests {
|
|||||||
|
|
||||||
// first a 'dangling' partial string, later modified to be a two-part complete string,
|
// first a 'dangling' partial string, later modified to be a two-part complete string,
|
||||||
// then a three-part cyclic string involving an uncompacted list of chars.
|
// then a three-part cyclic string involving an uncompacted list of chars.
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -733,11 +730,8 @@ mod tests {
|
|||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
@@ -1776,11 +1770,8 @@ mod tests {
|
|||||||
// two-part complete string, then a three-part cyclic string
|
// two-part complete string, then a three-part cyclic string
|
||||||
// involving an uncompacted list of chars.
|
// involving an uncompacted list of chars.
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1804,11 +1795,8 @@ mod tests {
|
|||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2375,11 +2363,8 @@ mod tests {
|
|||||||
// two-part complete string, then a three-part cyclic string
|
// two-part complete string, then a three-part cyclic string
|
||||||
// involving an uncompacted list of chars.
|
// involving an uncompacted list of chars.
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2402,11 +2387,8 @@ mod tests {
|
|||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2838,11 +2820,8 @@ mod tests {
|
|||||||
// two-part complete string, then a three-part cyclic string
|
// two-part complete string, then a three-part cyclic string
|
||||||
// involving an uncompacted list of chars.
|
// involving an uncompacted list of chars.
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2862,11 +2841,8 @@ mod tests {
|
|||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
|
|||||||
@@ -1588,7 +1588,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
print_struct(self, name, arity);
|
print_struct(self, name, arity);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
let name = self.atom_tbl.blocking_write().build_with(&String::from(c));
|
let name = AtomTable::build_with(&self.atom_tbl, &String::from(c));
|
||||||
print_struct(self, name, 0);
|
print_struct(self, name, 0);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Str, s) => {
|
(HeapCellValueTag::Str, s) => {
|
||||||
@@ -1950,11 +1950,7 @@ mod tests {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
put_partial_string(
|
put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
|
||||||
&mut wam.machine_st.heap,
|
|
||||||
"abc",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let printer = HCPrinter::new(
|
let printer = HCPrinter::new(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::instructions::*;
|
|||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
@@ -1093,7 +1094,7 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
|
|||||||
|
|
||||||
pub(crate) fn constant_key_alternatives(
|
pub(crate) fn constant_key_alternatives(
|
||||||
constant: Literal,
|
constant: Literal,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
// arena: &mut Arena,
|
// arena: &mut Arena,
|
||||||
) -> Vec<Literal> {
|
) -> Vec<Literal> {
|
||||||
let mut constants = vec![];
|
let mut constants = vec![];
|
||||||
@@ -1105,7 +1106,7 @@ pub(crate) fn constant_key_alternatives(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Literal::Char(c) => {
|
Literal::Char(c) => {
|
||||||
let atom = atom_tbl.build_with(&c.to_string());
|
let atom = AtomTable::build_with(&atom_tbl, &c.to_string());
|
||||||
constants.push(Literal::Atom(atom));
|
constants.push(Literal::Atom(atom));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -1454,7 +1455,7 @@ impl<I: Indexer> CodeOffsets<I> {
|
|||||||
|
|
||||||
fn index_constant(
|
fn index_constant(
|
||||||
&mut self,
|
&mut self,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
constant: Literal,
|
constant: Literal,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Vec<Literal> {
|
) -> Vec<Literal> {
|
||||||
@@ -1511,7 +1512,7 @@ impl<I: Indexer> CodeOffsets<I> {
|
|||||||
optimal_arg: &Term,
|
optimal_arg: &Term,
|
||||||
index: usize,
|
index: usize,
|
||||||
clause_index_info: &mut ClauseIndexInfo,
|
clause_index_info: &mut ClauseIndexInfo,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) {
|
) {
|
||||||
match optimal_arg {
|
match optimal_arg {
|
||||||
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {
|
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {
|
||||||
|
|||||||
@@ -1237,12 +1237,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
if let Some(path_str) = load_context.path.to_str() {
|
if let Some(path_str) = load_context.path.to_str() {
|
||||||
if !path_str.is_empty() {
|
if !path_str.is_empty() {
|
||||||
return Some(
|
return Some(AtomTable::build_with(
|
||||||
LS::machine_st(&mut self.payload)
|
&LS::machine_st(&mut self.payload).atom_tbl,
|
||||||
.atom_tbl
|
path_str,
|
||||||
.blocking_write()
|
));
|
||||||
.build_with(path_str),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,21 +406,15 @@ mod tests {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
|
|||||||
@@ -644,11 +644,8 @@ mod tests {
|
|||||||
// two-part complete string, then a three-part cyclic string
|
// two-part complete string, then a three-part cyclic string
|
||||||
// involving an uncompacted list of chars.
|
// involving an uncompacted list of chars.
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
|
mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
|
||||||
@@ -669,11 +666,8 @@ mod tests {
|
|||||||
|
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
|
mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
@@ -133,7 +135,7 @@ pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: u
|
|||||||
pub(crate) fn put_complete_string(
|
pub(crate) fn put_complete_string(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
s: &str,
|
s: &str,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> HeapCellValue {
|
) -> HeapCellValue {
|
||||||
match allocate_pstr(heap, s, atom_tbl) {
|
match allocate_pstr(heap, s, atom_tbl) {
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
@@ -160,7 +162,7 @@ pub(crate) fn put_complete_string(
|
|||||||
pub(crate) fn put_partial_string(
|
pub(crate) fn put_partial_string(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
s: &str,
|
s: &str,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> HeapCellValue {
|
) -> HeapCellValue {
|
||||||
match allocate_pstr(heap, s, atom_tbl) {
|
match allocate_pstr(heap, s, atom_tbl) {
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
@@ -176,7 +178,7 @@ pub(crate) fn put_partial_string(
|
|||||||
pub(crate) fn allocate_pstr(
|
pub(crate) fn allocate_pstr(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
mut src: &str,
|
mut src: &str,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
let orig_h = heap.len();
|
let orig_h = heap.len();
|
||||||
|
|
||||||
|
|||||||
@@ -1076,7 +1076,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
let export_list = machine_st.read_term_from_heap(cell)?;
|
let export_list = machine_st.read_term_from_heap(cell)?;
|
||||||
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
|
let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl;
|
||||||
let export_list = setup_module_export_list(export_list, &mut atom_tbl.blocking_write())?;
|
let export_list = setup_module_export_list(export_list, &atom_tbl)?;
|
||||||
|
|
||||||
Ok(export_list.into_iter().collect())
|
Ok(export_list.into_iter().collect())
|
||||||
}
|
}
|
||||||
@@ -1420,7 +1420,7 @@ impl MachineState {
|
|||||||
term_stack.push(Term::PartialString(Cell::default(), string, tail));
|
term_stack.push(Term::PartialString(Cell::default(), string, tail));
|
||||||
}
|
}
|
||||||
Ok((string, None)) => {
|
Ok((string, None)) => {
|
||||||
let atom = self.atom_tbl.blocking_write().build_with(&string);
|
let atom = AtomTable::build_with(&self.atom_tbl, &string);
|
||||||
term_stack.push(Term::CompleteString(Cell::default(), atom));
|
term_stack.push(Term::CompleteString(Cell::default(), atom));
|
||||||
}
|
}
|
||||||
Err(cons_term) => term_stack.push(cons_term),
|
Err(cons_term) => term_stack.push(cons_term),
|
||||||
@@ -1917,11 +1917,7 @@ impl Machine {
|
|||||||
pub(crate) fn load_context_source(&mut self) {
|
pub(crate) fn load_context_source(&mut self) {
|
||||||
if let Some(load_context) = self.load_contexts.last() {
|
if let Some(load_context) = self.load_contexts.last() {
|
||||||
let path_str = load_context.path.to_str().unwrap();
|
let path_str = load_context.path.to_str().unwrap();
|
||||||
let path_atom = self
|
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, path_str);
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(path_str);
|
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.unify_atom(path_atom, self.machine_st.registers[1]);
|
.unify_atom(path_atom, self.machine_st.registers[1]);
|
||||||
@@ -1935,11 +1931,8 @@ impl Machine {
|
|||||||
match load_context.path.file_name() {
|
match load_context.path.file_name() {
|
||||||
Some(file_name) if load_context.path.is_file() => {
|
Some(file_name) if load_context.path.is_file() => {
|
||||||
let file_name_str = file_name.to_str().unwrap();
|
let file_name_str = file_name.to_str().unwrap();
|
||||||
let file_name_atom = self
|
let file_name_atom =
|
||||||
.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, file_name_str);
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(file_name_str);
|
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.unify_atom(file_name_atom, self.machine_st.registers[1]);
|
.unify_atom(file_name_atom, self.machine_st.registers[1]);
|
||||||
@@ -1958,11 +1951,8 @@ impl Machine {
|
|||||||
if let Some(load_context) = self.load_contexts.last() {
|
if let Some(load_context) = self.load_contexts.last() {
|
||||||
if let Some(directory) = load_context.path.parent() {
|
if let Some(directory) = load_context.path.parent() {
|
||||||
let directory_str = directory.to_str().unwrap();
|
let directory_str = directory.to_str().unwrap();
|
||||||
let directory_atom = self
|
let directory_atom =
|
||||||
.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, directory_str);
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(directory_str);
|
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.unify_atom(directory_atom, self.machine_st.registers[1]);
|
.unify_atom(directory_atom, self.machine_st.registers[1]);
|
||||||
|
|||||||
@@ -205,12 +205,12 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
|
|||||||
fn push_var_eq_functors<'a>(
|
fn push_var_eq_functors<'a>(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
|
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Vec<HeapCellValue> {
|
) -> Vec<HeapCellValue> {
|
||||||
let mut list_of_var_eqs = vec![];
|
let mut list_of_var_eqs = vec![];
|
||||||
|
|
||||||
for (var, binding) in iter {
|
for (var, binding) in iter {
|
||||||
let var_atom = atom_tbl.build_with(&var.to_string());
|
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
|
||||||
let h = heap.len();
|
let h = heap.len();
|
||||||
|
|
||||||
heap.push(atom_as_cell!(atom!("="), 2));
|
heap.push(atom_as_cell!(atom!("="), 2));
|
||||||
@@ -531,7 +531,7 @@ impl MachineState {
|
|||||||
Some((var_name, var))
|
Some((var_name, var))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
&mut self.atom_tbl.blocking_write(),
|
&self.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
let singleton_addr = self.registers[3];
|
let singleton_addr = self.registers[3];
|
||||||
@@ -617,7 +617,7 @@ impl MachineState {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
&mut self.atom_tbl.blocking_write(),
|
&self.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
for var in term_write_result.var_dict.values_mut() {
|
for var in term_write_result.var_dict.values_mut() {
|
||||||
|
|||||||
@@ -1003,9 +1003,9 @@ impl MachineState {
|
|||||||
self.s_offset = 0;
|
self.s_offset = 0;
|
||||||
self.mode = MachineMode::Read;
|
self.mode = MachineMode::Read;
|
||||||
|
|
||||||
put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write())
|
put_partial_string(&mut self.heap, pstr, &self.atom_tbl)
|
||||||
} else {
|
} else {
|
||||||
put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write())
|
put_complete_string(&mut self.heap, pstr, &self.atom_tbl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1097,7 +1097,7 @@ impl MachineState {
|
|||||||
(name, 0, 0)
|
(name, 0, 0)
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
(self.atom_tbl.blocking_write().build_with(&c.to_string()), 0, 0)
|
(AtomTable::build_with(&self.atom_tbl, &c.to_string()), 0, 0)
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
||||||
let stub = functor_stub(atom!("call"), arity + 1);
|
let stub = functor_stub(atom!("call"), arity + 1);
|
||||||
@@ -1436,7 +1436,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
let c = self.atom_tbl.blocking_write().build_with(&c.to_string());
|
let c = AtomTable::build_with(&self.atom_tbl, &c.to_string());
|
||||||
|
|
||||||
self.try_functor_fabricate_struct(
|
self.try_functor_fabricate_struct(
|
||||||
c,
|
c,
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ impl Machine {
|
|||||||
pub fn load_file(&mut self, path: &str, stream: Stream) {
|
pub fn load_file(&mut self, path: &str, stream: Stream) {
|
||||||
self.machine_st.registers[1] = stream_as_cell!(stream);
|
self.machine_st.registers[1] = stream_as_cell!(stream);
|
||||||
self.machine_st.registers[2] =
|
self.machine_st.registers[2] =
|
||||||
atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(path));
|
atom_as_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, path));
|
||||||
|
|
||||||
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
|
self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2));
|
||||||
}
|
}
|
||||||
@@ -296,7 +296,7 @@ impl Machine {
|
|||||||
arg_pstrs.push(put_complete_string(
|
arg_pstrs.push(put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&arg,
|
&arg,
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
@@ -43,10 +45,9 @@ impl Into<Atom> for PartialString {
|
|||||||
|
|
||||||
impl PartialString {
|
impl PartialString {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new<'a>(src: &'a str, atom_tbl: &mut AtomTable) -> Option<(Self, &'a str)> {
|
pub(super) fn new<'a>(src: &'a str, atom_tbl: &RwLock<AtomTable>) -> Option<(Self, &'a str)> {
|
||||||
let terminator_idx = scan_for_terminator(src.chars());
|
let terminator_idx = scan_for_terminator(src.chars());
|
||||||
let pstr = PartialString(atom_tbl.build_with(&src[..terminator_idx]));
|
let pstr = PartialString(AtomTable::build_with(&atom_tbl, &src[..terminator_idx]));
|
||||||
|
|
||||||
Some(if terminator_idx < src.as_bytes().len() {
|
Some(if terminator_idx < src.as_bytes().len() {
|
||||||
(pstr, &src[terminator_idx + 1..])
|
(pstr, &src[terminator_idx + 1..])
|
||||||
} else {
|
} else {
|
||||||
@@ -805,11 +806,8 @@ mod test {
|
|||||||
fn pstr_iter_tests() {
|
fn pstr_iter_tests() {
|
||||||
let mut wam = MockWAM::new();
|
let mut wam = MockWAM::new();
|
||||||
|
|
||||||
let pstr_var_cell = put_partial_string(
|
let pstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
|
||||||
|
|
||||||
@@ -828,11 +826,8 @@ mod test {
|
|||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||||
|
|
||||||
let pstr_second_var_cell = put_partial_string(
|
let pstr_second_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
|
||||||
"def",
|
|
||||||
&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_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
|
||||||
|
|
||||||
@@ -913,21 +908,13 @@ mod test {
|
|||||||
// construct a structurally similar but different cyclic partial string
|
// construct a structurally similar but different cyclic partial string
|
||||||
// matching the one beginning at wam.machine_st.heap[0].
|
// matching the one beginning at wam.machine_st.heap[0].
|
||||||
|
|
||||||
put_partial_string(
|
put_partial_string(&mut wam.machine_st.heap, "ab", &wam.machine_st.atom_tbl);
|
||||||
&mut wam.machine_st.heap,
|
|
||||||
"ab",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
|
|
||||||
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
|
wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
|
||||||
|
|
||||||
put_partial_string(
|
put_partial_string(&mut wam.machine_st.heap, "c ", &wam.machine_st.atom_tbl);
|
||||||
&mut wam.machine_st.heap,
|
|
||||||
"c ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.pop();
|
wam.machine_st.heap.pop();
|
||||||
|
|
||||||
@@ -952,11 +939,7 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
put_partial_string(
|
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
|
||||||
&mut wam.machine_st.heap,
|
|
||||||
"abc ",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let pstr_cell = wam.machine_st.heap[0];
|
let pstr_cell = wam.machine_st.heap[0];
|
||||||
|
|
||||||
@@ -986,11 +969,8 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
let cstr_var_cell = put_complete_string(
|
let cstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
|
||||||
"abc",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
||||||
@@ -1015,11 +995,8 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
let cstr_var_cell = put_complete_string(
|
let cstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
|
||||||
"abc",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X
|
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X
|
||||||
@@ -1048,11 +1025,8 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
let cstr_var_cell = put_complete_string(
|
let cstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_complete_string(&mut wam.machine_st.heap, "d", &wam.machine_st.atom_tbl);
|
||||||
"d",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
||||||
wam.machine_st.heap.push(char_as_cell!('d'));
|
wam.machine_st.heap.push(char_as_cell!('d'));
|
||||||
@@ -1066,11 +1040,8 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
let cstr_var_cell = put_complete_string(
|
let cstr_var_cell =
|
||||||
&mut wam.machine_st.heap,
|
put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
|
||||||
"abc",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
wam.machine_st.heap.push(list_loc_as_cell!(2));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
||||||
@@ -1097,11 +1068,7 @@ mod test {
|
|||||||
|
|
||||||
wam.machine_st.heap.clear();
|
wam.machine_st.heap.clear();
|
||||||
|
|
||||||
put_complete_string(
|
put_complete_string(&mut wam.machine_st.heap, "abcdef", &wam.machine_st.atom_tbl);
|
||||||
&mut wam.machine_st.heap,
|
|
||||||
"abcdef",
|
|
||||||
&mut wam.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
|
wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
|
||||||
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use crate::machine::machine_errors::*;
|
|||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -27,17 +28,17 @@ pub(crate) fn to_op_decl(prec: u16, spec: Atom, name: Atom) -> Result<OpDecl, Co
|
|||||||
|
|
||||||
fn setup_op_decl(
|
fn setup_op_decl(
|
||||||
mut terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<OpDecl, CompilationError> {
|
) -> Result<OpDecl, CompilationError> {
|
||||||
let name = match terms.pop().unwrap() {
|
let name = match terms.pop().unwrap() {
|
||||||
Term::Literal(_, Literal::Atom(name)) => name,
|
Term::Literal(_, Literal::Atom(name)) => name,
|
||||||
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
|
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
|
||||||
_ => return Err(CompilationError::InconsistentEntry),
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
};
|
};
|
||||||
|
|
||||||
let spec = match terms.pop().unwrap() {
|
let spec = match terms.pop().unwrap() {
|
||||||
Term::Literal(_, Literal::Atom(name)) => name,
|
Term::Literal(_, Literal::Atom(name)) => name,
|
||||||
Term::Literal(_, Literal::Char(c)) => atom_tbl.build_with(&c.to_string()),
|
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
|
||||||
_ => return Err(CompilationError::InconsistentEntry),
|
_ => return Err(CompilationError::InconsistentEntry),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
|
|||||||
|
|
||||||
fn setup_module_export(
|
fn setup_module_export(
|
||||||
mut term: Term,
|
mut term: Term,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<ModuleExport, CompilationError> {
|
) -> Result<ModuleExport, CompilationError> {
|
||||||
setup_predicate_indicator(&mut term)
|
setup_predicate_indicator(&mut term)
|
||||||
.map(ModuleExport::PredicateKey)
|
.map(ModuleExport::PredicateKey)
|
||||||
@@ -111,7 +112,7 @@ pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
|
|||||||
|
|
||||||
pub(super) fn setup_module_export_list(
|
pub(super) fn setup_module_export_list(
|
||||||
mut export_list: Term,
|
mut export_list: Term,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<Vec<ModuleExport>, CompilationError> {
|
) -> Result<Vec<ModuleExport>, CompilationError> {
|
||||||
let mut exports = vec![];
|
let mut exports = vec![];
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ pub(super) fn setup_module_export_list(
|
|||||||
|
|
||||||
fn setup_module_decl(
|
fn setup_module_decl(
|
||||||
mut terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<ModuleDecl, CompilationError> {
|
) -> Result<ModuleDecl, CompilationError> {
|
||||||
let export_list = terms.pop().unwrap();
|
let export_list = terms.pop().unwrap();
|
||||||
let name = terms.pop().unwrap();
|
let name = terms.pop().unwrap();
|
||||||
@@ -164,7 +165,7 @@ type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
|
|||||||
|
|
||||||
fn setup_qualified_import(
|
fn setup_qualified_import(
|
||||||
mut terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<UseModuleExport, CompilationError> {
|
) -> Result<UseModuleExport, CompilationError> {
|
||||||
let mut export_list = terms.pop().unwrap();
|
let mut export_list = terms.pop().unwrap();
|
||||||
let module_src = match terms.pop().unwrap() {
|
let module_src = match terms.pop().unwrap() {
|
||||||
@@ -313,17 +314,11 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
|
|||||||
}
|
}
|
||||||
(atom!("module"), 2) => {
|
(atom!("module"), 2) => {
|
||||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||||
Ok(Declaration::Module(setup_module_decl(
|
Ok(Declaration::Module(setup_module_decl(terms, &atom_tbl)?))
|
||||||
terms,
|
|
||||||
&mut atom_tbl.blocking_write(),
|
|
||||||
)?))
|
|
||||||
}
|
}
|
||||||
(atom!("op"), 3) => {
|
(atom!("op"), 3) => {
|
||||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||||
Ok(Declaration::Op(setup_op_decl(
|
Ok(Declaration::Op(setup_op_decl(terms, &atom_tbl)?))
|
||||||
terms,
|
|
||||||
&mut atom_tbl.blocking_write(),
|
|
||||||
)?))
|
|
||||||
}
|
}
|
||||||
(atom!("non_counted_backtracking"), 1) => {
|
(atom!("non_counted_backtracking"), 1) => {
|
||||||
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
|
let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?;
|
||||||
@@ -332,8 +327,7 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
|
|||||||
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
|
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
|
||||||
(atom!("use_module"), 2) => {
|
(atom!("use_module"), 2) => {
|
||||||
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl;
|
||||||
let (name, exports) =
|
let (name, exports) = setup_qualified_import(terms, &atom_tbl)?;
|
||||||
setup_qualified_import(terms, &mut atom_tbl.blocking_write())?;
|
|
||||||
|
|
||||||
Ok(Declaration::UseQualifiedModule(name, exports))
|
Ok(Declaration::UseQualifiedModule(name, exports))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1529,7 +1529,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
let name = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string());
|
let name = AtomTable::build_with(&self.machine_st.atom_tbl,&c.to_string());
|
||||||
|
|
||||||
let h = self.machine_st.heap.len();
|
let h = self.machine_st.heap.len();
|
||||||
self.machine_st.heap.push(atom_as_cell!(name));
|
self.machine_st.heap.push(atom_as_cell!(name));
|
||||||
@@ -1804,7 +1804,7 @@ impl Machine {
|
|||||||
match hostname::get().ok() {
|
match hostname::get().ok() {
|
||||||
Some(host) => match host.to_str() {
|
Some(host) => match host.to_str() {
|
||||||
Some(host) => {
|
Some(host) => {
|
||||||
let hostname = self.machine_st.atom_tbl.blocking_write().build_with(host);
|
let hostname = AtomTable::build_with(&self.machine_st.atom_tbl, host);
|
||||||
|
|
||||||
let a1 = self.deref_register(1);
|
let a1 = self.deref_register(1);
|
||||||
self.machine_st.unify_atom(hostname, a1);
|
self.machine_st.unify_atom(hostname, a1);
|
||||||
@@ -1903,7 +1903,7 @@ impl Machine {
|
|||||||
for entry in entries {
|
for entry in entries {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
if let Some(name) = entry.file_name().to_str() {
|
if let Some(name) = entry.file_name().to_str() {
|
||||||
let name = self.machine_st.atom_tbl.blocking_write().build_with(name);
|
let name = AtomTable::build_with(&self.machine_st.atom_tbl, name);
|
||||||
files.push(atom_as_cstr_cell!(name));
|
files.push(atom_as_cstr_cell!(name));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -2144,11 +2144,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let current_atom = self
|
let current_atom = AtomTable::build_with(&self.machine_st.atom_tbl, ¤t);
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(¤t);
|
|
||||||
|
|
||||||
let a1 = self.deref_register(1);
|
let a1 = self.deref_register(1);
|
||||||
self.machine_st.unify_complete_string(current_atom, a1);
|
self.machine_st.unify_complete_string(current_atom, a1);
|
||||||
@@ -2189,7 +2185,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let canonical_atom = self.machine_st.atom_tbl.blocking_write().build_with(cs);
|
let canonical_atom = AtomTable::build_with(&self.machine_st.atom_tbl, cs);
|
||||||
|
|
||||||
let a2 = self.deref_register(2);
|
let a2 = self.deref_register(2);
|
||||||
self.machine_st.unify_complete_string(canonical_atom, a2);
|
self.machine_st.unify_complete_string(canonical_atom, a2);
|
||||||
@@ -2248,13 +2244,13 @@ impl Machine {
|
|||||||
let atom_cell = match str_like {
|
let atom_cell = match str_like {
|
||||||
AtomOrString::Atom(atom) => {
|
AtomOrString::Atom(atom) => {
|
||||||
atom_as_cell!(if atom == atom!("[]") {
|
atom_as_cell!(if atom == atom!("[]") {
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with("")
|
AtomTable::build_with(&self.machine_st.atom_tbl, "")
|
||||||
} else {
|
} else {
|
||||||
atom
|
atom
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
AtomOrString::String(string) => {
|
AtomOrString::String(string) => {
|
||||||
atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(&string))
|
atom_as_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, &string))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2316,7 +2312,7 @@ impl Machine {
|
|||||||
match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) {
|
match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) {
|
||||||
Ok(addrs) => {
|
Ok(addrs) => {
|
||||||
let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
|
let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
|
||||||
let atom = self.machine_st.atom_tbl.blocking_write().build_with(&string);
|
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &string);
|
||||||
|
|
||||||
self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
|
self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
|
||||||
}
|
}
|
||||||
@@ -2810,11 +2806,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let chars_atom = self
|
let chars_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &string.trim());
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&string.trim());
|
|
||||||
self.machine_st.unify_complete_string(chars_atom, chs);
|
self.machine_st.unify_complete_string(chars_atom, chs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3040,14 +3032,14 @@ impl Machine {
|
|||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
(atom!("to_upper"), 1) => {
|
(atom!("to_upper"), 1) => {
|
||||||
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
||||||
let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_uppercase().to_string());
|
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_uppercase().to_string());
|
||||||
let upper_str = string_as_cstr_cell!(atom);
|
let upper_str = string_as_cstr_cell!(atom);
|
||||||
unify!(self.machine_st, reg, upper_str);
|
unify!(self.machine_st, reg, upper_str);
|
||||||
self.machine_st.fail = false;
|
self.machine_st.fail = false;
|
||||||
}
|
}
|
||||||
(atom!("to_lower"), 1) => {
|
(atom!("to_lower"), 1) => {
|
||||||
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
|
||||||
let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_lowercase().to_string());
|
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_lowercase().to_string());
|
||||||
let lower_str = string_as_cstr_cell!(atom);
|
let lower_str = string_as_cstr_cell!(atom);
|
||||||
unify!(self.machine_st, reg, lower_str);
|
unify!(self.machine_st, reg, lower_str);
|
||||||
self.machine_st.fail = false;
|
self.machine_st.fail = false;
|
||||||
@@ -3570,11 +3562,7 @@ impl Machine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let output = self.deref_register(3);
|
let output = self.deref_register(3);
|
||||||
let atom = self
|
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &string);
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&string);
|
|
||||||
|
|
||||||
self.machine_st.unify_complete_string(atom, output);
|
self.machine_st.unify_complete_string(atom, output);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -4069,7 +4057,7 @@ impl Machine {
|
|||||||
cell_as_atom!(self.machine_st.heap[s])
|
cell_as_atom!(self.machine_st.heap[s])
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string())
|
AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_string())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -4431,15 +4419,14 @@ impl Machine {
|
|||||||
let h = self.machine_st.heap.len();
|
let h = self.machine_st.heap.len();
|
||||||
|
|
||||||
let header_term = functor!(
|
let header_term = functor!(
|
||||||
self.machine_st
|
AtomTable::build_with(
|
||||||
.atom_tbl
|
&self.machine_st.atom_tbl,
|
||||||
.blocking_write()
|
header_name.as_str()
|
||||||
.build_with(header_name.as_str()),
|
),
|
||||||
[cell(string_as_cstr_cell!(self
|
[cell(string_as_cstr_cell!(AtomTable::build_with(
|
||||||
.machine_st
|
&self.machine_st.atom_tbl,
|
||||||
.atom_tbl
|
header_value.to_str().unwrap()
|
||||||
.blocking_write()
|
)))]
|
||||||
.build_with(header_value.to_str().unwrap())))]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.heap.extend(header_term.into_iter());
|
self.machine_st.heap.extend(header_term.into_iter());
|
||||||
@@ -4458,10 +4445,7 @@ impl Machine {
|
|||||||
let reader = resp.bytes().unwrap().reader();
|
let reader = resp.bytes().unwrap().reader();
|
||||||
|
|
||||||
let mut stream = Stream::from_http_stream(
|
let mut stream = Stream::from_http_stream(
|
||||||
self.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, &address_string),
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&address_string),
|
|
||||||
Box::new(reader),
|
Box::new(reader),
|
||||||
&mut self.machine_st.arena,
|
&mut self.machine_st.arena,
|
||||||
);
|
);
|
||||||
@@ -4578,14 +4562,14 @@ impl Machine {
|
|||||||
Method::HEAD => atom!("head"),
|
Method::HEAD => atom!("head"),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let path_atom = self.machine_st.atom_tbl.blocking_write().build_with(request.request.uri().path());
|
let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, request.request.uri().path());
|
||||||
let path_cell = atom_as_cstr_cell!(path_atom);
|
let path_cell = atom_as_cstr_cell!(path_atom);
|
||||||
let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
|
let headers: Vec<HeapCellValue> = request.request.headers().iter().map(|(header_name, header_value)| {
|
||||||
let h = self.machine_st.heap.len();
|
let h = self.machine_st.heap.len();
|
||||||
|
|
||||||
let header_term = functor!(
|
let header_term = functor!(
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(header_name.as_str()),
|
AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()),
|
||||||
[cell(string_as_cstr_cell!(self.machine_st.atom_tbl.blocking_write().build_with(header_value.to_str().unwrap())))]
|
[cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]
|
||||||
);
|
);
|
||||||
|
|
||||||
self.machine_st.heap.extend(header_term.into_iter());
|
self.machine_st.heap.extend(header_term.into_iter());
|
||||||
@@ -4595,7 +4579,7 @@ impl Machine {
|
|||||||
let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.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_str = request.request.uri().query().unwrap_or("");
|
||||||
let query_atom = self.machine_st.atom_tbl.blocking_write().build_with(query_str);
|
let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, query_str);
|
||||||
let query_cell = string_as_cstr_cell!(query_atom);
|
let query_cell = string_as_cstr_cell!(query_atom);
|
||||||
|
|
||||||
let hyper_req = request.request;
|
let hyper_req = request.request;
|
||||||
@@ -4825,11 +4809,10 @@ impl Machine {
|
|||||||
unify!(self.machine_st, return_value, struct_value);
|
unify!(self.machine_st, return_value, struct_value);
|
||||||
}
|
}
|
||||||
Value::CString(cstr) => {
|
Value::CString(cstr) => {
|
||||||
let cstr = self
|
let cstr = AtomTable::build_with(
|
||||||
.machine_st
|
&self.machine_st.atom_tbl,
|
||||||
.atom_tbl
|
cstr.to_str().unwrap(),
|
||||||
.blocking_write()
|
);
|
||||||
.build_with(cstr.to_str().unwrap());
|
|
||||||
self.machine_st.unify_complete_string(cstr, return_value);
|
self.machine_st.unify_complete_string(cstr, return_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4858,11 +4841,10 @@ impl Machine {
|
|||||||
.map(|val| match val {
|
.map(|val| match val {
|
||||||
Value::Int(n) => fixnum_as_cell!(Fixnum::build_with(n)),
|
Value::Int(n) => fixnum_as_cell!(Fixnum::build_with(n)),
|
||||||
Value::Float(n) => HeapCellValue::from(float_alloc!(n, self.machine_st.arena)),
|
Value::Float(n) => HeapCellValue::from(float_alloc!(n, self.machine_st.arena)),
|
||||||
Value::CString(cstr) => atom_as_cell!(self
|
Value::CString(cstr) => atom_as_cell!(AtomTable::build_with(
|
||||||
.machine_st
|
&self.machine_st.atom_tbl,
|
||||||
.atom_tbl
|
&cstr.into_string().unwrap()
|
||||||
.blocking_write()
|
)),
|
||||||
.build_with(&cstr.into_string().unwrap())),
|
|
||||||
Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
|
Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -4918,7 +4900,7 @@ impl Machine {
|
|||||||
let src_sink = self.deref_register(1);
|
let src_sink = self.deref_register(1);
|
||||||
|
|
||||||
if let Some(file_spec) = self.machine_st.value_to_str_like(src_sink) {
|
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.blocking_write());
|
let file_spec = file_spec.as_atom(&*self.machine_st.atom_tbl);
|
||||||
|
|
||||||
let mut stream =
|
let mut stream =
|
||||||
self.machine_st
|
self.machine_st
|
||||||
@@ -4961,7 +4943,7 @@ impl Machine {
|
|||||||
|
|
||||||
let op = read_heap_cell!(self.deref_register(3),
|
let op = read_heap_cell!(self.deref_register(3),
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string())
|
AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_string())
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Atom, (name, _arity)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
name
|
name
|
||||||
@@ -6128,11 +6110,7 @@ impl Machine {
|
|||||||
.read_term(&op_dir, Tokens::Default)
|
.read_term(&op_dir, Tokens::Default)
|
||||||
.map_err(|err| error_after_read_term(err, 0, &parser))
|
.map_err(|err| error_after_read_term(err, 0, &parser))
|
||||||
.and_then(|term| {
|
.and_then(|term| {
|
||||||
write_term_to_heap(
|
write_term_to_heap(&term, &mut self.machine_st.heap, &self.machine_st.atom_tbl)
|
||||||
&term,
|
|
||||||
&mut self.machine_st.heap,
|
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
match term_write_result {
|
match term_write_result {
|
||||||
@@ -6296,7 +6274,7 @@ impl Machine {
|
|||||||
name
|
name
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(&match Number::try_from(port) {
|
AtomTable::build_with(&self.machine_st.atom_tbl, &match Number::try_from(port) {
|
||||||
Ok(Number::Fixnum(n)) => n.get_num().to_string(),
|
Ok(Number::Fixnum(n)) => n.get_num().to_string(),
|
||||||
Ok(Number::Integer(n)) => n.to_string(),
|
Ok(Number::Integer(n)) => n.to_string(),
|
||||||
_ => {
|
_ => {
|
||||||
@@ -6310,10 +6288,7 @@ impl Machine {
|
|||||||
atom!("127.0.0.1:80")
|
atom!("127.0.0.1:80")
|
||||||
} else {
|
} else {
|
||||||
let buffer = format!("{}:{}", socket_atom.as_str(), port.as_str());
|
let buffer = format!("{}:{}", socket_atom.as_str(), port.as_str());
|
||||||
self.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, &buffer)
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&buffer)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let alias = self.machine_st.registers[4];
|
let alias = self.machine_st.registers[4];
|
||||||
@@ -6495,7 +6470,7 @@ impl Machine {
|
|||||||
(ArenaHeaderTag::TcpListener, tcp_listener) => {
|
(ArenaHeaderTag::TcpListener, tcp_listener) => {
|
||||||
match tcp_listener.accept().ok() {
|
match tcp_listener.accept().ok() {
|
||||||
Some((tcp_stream, socket_addr)) => {
|
Some((tcp_stream, socket_addr)) => {
|
||||||
let client = self.machine_st.atom_tbl.blocking_write().build_with(&socket_addr.to_string());
|
let client = AtomTable::build_with(&self.machine_st.atom_tbl, &socket_addr.to_string());
|
||||||
|
|
||||||
let mut tcp_stream = Stream::from_tcp_stream(
|
let mut tcp_stream = Stream::from_tcp_stream(
|
||||||
client,
|
client,
|
||||||
@@ -7119,7 +7094,7 @@ impl Machine {
|
|||||||
let chars = put_complete_string(
|
let chars = put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&result,
|
&result,
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
let result_addr = self.deref_register(1);
|
let result_addr = self.deref_register(1);
|
||||||
@@ -7138,7 +7113,7 @@ impl Machine {
|
|||||||
use git_version::git_version;
|
use git_version::git_version;
|
||||||
|
|
||||||
let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
|
let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
|
||||||
let buffer_atom = self.machine_st.atom_tbl.blocking_write().build_with(buffer);
|
let buffer_atom = AtomTable::build_with(&self.machine_st.atom_tbl, buffer);
|
||||||
|
|
||||||
let a1 = self.deref_register(1);
|
let a1 = self.deref_register(1);
|
||||||
self.machine_st.unify_complete_string(buffer_atom, a1);
|
self.machine_st.unify_complete_string(buffer_atom, a1);
|
||||||
@@ -7503,11 +7478,7 @@ impl Machine {
|
|||||||
if buffer.len() == 0 {
|
if buffer.len() == 0 {
|
||||||
empty_list_as_cell!()
|
empty_list_as_cell!()
|
||||||
} else {
|
} else {
|
||||||
atom_as_cstr_cell!(self
|
atom_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, &buffer))
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&buffer))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7644,11 +7615,8 @@ impl Machine {
|
|||||||
if let Some(string) = self.machine_st.value_to_str_like(addr) {
|
if let Some(string) = self.machine_st.value_to_str_like(addr) {
|
||||||
for c in string.as_str().chars() {
|
for c in string.as_str().chars() {
|
||||||
if c as u32 > 255 {
|
if c as u32 > 255 {
|
||||||
let non_octet = self
|
let non_octet =
|
||||||
.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_string());
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&c.to_string());
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.unify_atom(non_octet, self.machine_st.registers[2]);
|
.unify_atom(non_octet, self.machine_st.registers[2]);
|
||||||
return;
|
return;
|
||||||
@@ -7705,7 +7673,7 @@ impl Machine {
|
|||||||
let cstr = put_complete_string(
|
let cstr = put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&value,
|
&value,
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[2], cstr);
|
unify!(self.machine_st, self.machine_st.registers[2], cstr);
|
||||||
@@ -7893,11 +7861,8 @@ impl Machine {
|
|||||||
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_str = path_buf.to_str().unwrap();
|
||||||
let library_path = self
|
let library_path =
|
||||||
.machine_st
|
AtomTable::build_with(&self.machine_st.atom_tbl, library_path_str);
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(library_path_str);
|
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
.unify_atom(library_path, self.machine_st.registers[3]);
|
.unify_atom(library_path, self.machine_st.registers[3]);
|
||||||
@@ -7994,11 +7959,8 @@ impl Machine {
|
|||||||
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
if let Some(path) = path.to_str() {
|
if let Some(path) = path.to_str() {
|
||||||
let path_string = put_complete_string(
|
let path_string =
|
||||||
&mut self.machine_st.heap,
|
put_complete_string(&mut self.machine_st.heap, path, &self.machine_st.atom_tbl);
|
||||||
path,
|
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
|
||||||
);
|
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[1], path_string);
|
unify!(self.machine_st, self.machine_st.registers[1], path_string);
|
||||||
return;
|
return;
|
||||||
@@ -8044,7 +8006,7 @@ impl Machine {
|
|||||||
fstr.push_str("finis].");
|
fstr.push_str("finis].");
|
||||||
let s = datetime.format(&fstr).to_string();
|
let s = datetime.format(&fstr).to_string();
|
||||||
|
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(&s)
|
AtomTable::build_with(&self.machine_st.atom_tbl, &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn string_encoding_bytes(
|
pub(super) fn string_encoding_bytes(
|
||||||
@@ -8068,21 +8030,17 @@ impl Machine {
|
|||||||
put_complete_string(
|
put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
node.text().unwrap(),
|
node.text().unwrap(),
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let mut avec = Vec::new();
|
let mut avec = Vec::new();
|
||||||
|
|
||||||
for attr in node.attributes() {
|
for attr in node.attributes() {
|
||||||
let name = self
|
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.name());
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(attr.name());
|
|
||||||
let value = put_complete_string(
|
let value = put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&attr.value(),
|
&attr.value(),
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
|
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
|
||||||
@@ -8108,11 +8066,7 @@ impl Machine {
|
|||||||
cvec.into_iter()
|
cvec.into_iter()
|
||||||
));
|
));
|
||||||
|
|
||||||
let tag = self
|
let tag = AtomTable::build_with(&self.machine_st.atom_tbl, node.tag_name().name());
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(node.tag_name().name());
|
|
||||||
|
|
||||||
let result = str_loc_as_cell!(self.machine_st.heap.len());
|
let result = str_loc_as_cell!(self.machine_st.heap.len());
|
||||||
|
|
||||||
@@ -8132,17 +8086,17 @@ impl Machine {
|
|||||||
None => put_complete_string(
|
None => put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&node.text(),
|
&node.text(),
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
),
|
),
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let mut avec = Vec::new();
|
let mut avec = Vec::new();
|
||||||
|
|
||||||
for attr in node.attrs() {
|
for attr in node.attrs() {
|
||||||
let name = self.machine_st.atom_tbl.blocking_write().build_with(attr.0);
|
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.0);
|
||||||
let value = put_complete_string(
|
let value = put_complete_string(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
&attr.1,
|
&attr.1,
|
||||||
&mut self.machine_st.atom_tbl.blocking_write(),
|
&self.machine_st.atom_tbl,
|
||||||
);
|
);
|
||||||
|
|
||||||
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
|
avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
|
||||||
@@ -8168,7 +8122,7 @@ impl Machine {
|
|||||||
cvec.into_iter()
|
cvec.into_iter()
|
||||||
));
|
));
|
||||||
|
|
||||||
let tag = self.machine_st.atom_tbl.blocking_write().build_with(name);
|
let tag = AtomTable::build_with(&self.machine_st.atom_tbl, name);
|
||||||
let result = str_loc_as_cell!(self.machine_st.heap.len());
|
let result = str_loc_as_cell!(self.machine_st.heap.len());
|
||||||
|
|
||||||
self.machine_st
|
self.machine_st
|
||||||
@@ -8189,11 +8143,7 @@ impl Machine {
|
|||||||
if buffer.len() == 0 {
|
if buffer.len() == 0 {
|
||||||
empty_list_as_cell!()
|
empty_list_as_cell!()
|
||||||
} else {
|
} else {
|
||||||
atom_as_cstr_cell!(self
|
atom_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, &buffer))
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&buffer))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::io::{Error as IOError, ErrorKind};
|
use std::io::{Error as IOError, ErrorKind};
|
||||||
use std::ops::{Deref, Neg};
|
use std::ops::{Deref, Neg};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use crate::parser::dashu::{Integer, Rational};
|
use crate::parser::dashu::{Integer, Rational};
|
||||||
@@ -18,6 +19,7 @@ use fxhash::FxBuildHasher;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use modular_bitfield::error::OutOfBounds;
|
use modular_bitfield::error::OutOfBounds;
|
||||||
use modular_bitfield::prelude::*;
|
use modular_bitfield::prelude::*;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
pub type Specifier = u32;
|
pub type Specifier = u32;
|
||||||
|
|
||||||
@@ -631,7 +633,7 @@ impl fmt::Display for Literal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn to_atom(&self, atom_tbl: &mut AtomTable) -> Option<Atom> {
|
pub fn to_atom(&self, atom_tbl: &Arc<RwLock<AtomTable>>) -> Option<Atom> {
|
||||||
match self {
|
match self {
|
||||||
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
|
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
@@ -637,9 +637,10 @@ impl<'a, R: CharRead> Lexer<'a, R> {
|
|||||||
if token.as_str() == "[]" {
|
if token.as_str() == "[]" {
|
||||||
Ok(Token::Literal(Literal::Atom(atom!("[]"))))
|
Ok(Token::Literal(Literal::Atom(atom!("[]"))))
|
||||||
} else {
|
} else {
|
||||||
Ok(Token::Literal(Literal::Atom(
|
Ok(Token::Literal(Literal::Atom(AtomTable::build_with(
|
||||||
self.machine_st.atom_tbl.blocking_write().build_with(&token),
|
&self.machine_st.atom_tbl,
|
||||||
)))
|
&token,
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,7 +1084,7 @@ impl<'a, R: CharRead> Lexer<'a, R> {
|
|||||||
|
|
||||||
if c == '"' {
|
if c == '"' {
|
||||||
let s = self.char_code_list_token(c)?;
|
let s = self.char_code_list_token(c)?;
|
||||||
let atom = self.machine_st.atom_tbl.blocking_write().build_with(&s);
|
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &s);
|
||||||
|
|
||||||
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
|
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
|
||||||
Ok(Token::Literal(Literal::Atom(atom)))
|
Ok(Token::Literal(Literal::Atom(atom)))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use dashu::Integer;
|
use dashu::Integer;
|
||||||
use dashu::Rational;
|
use dashu::Rational;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
@@ -285,17 +286,17 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
|
|||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomize_term(atom_tbl: &mut AtomTable, term: &Term) -> Option<Atom> {
|
fn atomize_term(atom_tbl: &RwLock<AtomTable>, term: &Term) -> Option<Atom> {
|
||||||
match term {
|
match term {
|
||||||
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
|
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomize_constant(atom_tbl: &mut AtomTable, c: Literal) -> Option<Atom> {
|
fn atomize_constant(atom_tbl: &RwLock<AtomTable>, c: Literal) -> Option<Atom> {
|
||||||
match c {
|
match c {
|
||||||
Literal::Atom(ref name) => Some(*name),
|
Literal::Atom(ref name) => Some(*name),
|
||||||
Literal::Char(c) => Some(atom_tbl.build_with(&c.to_string())),
|
Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -568,19 +569,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
let idx = self.terms.len() - arity;
|
let idx = self.terms.len() - arity;
|
||||||
|
|
||||||
if TokenType::Term == self.stack[stack_len].tt {
|
if TokenType::Term == self.stack[stack_len].tt {
|
||||||
if atomize_term(
|
if atomize_term(&self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() {
|
||||||
&mut self.lexer.machine_st.atom_tbl.blocking_write(),
|
|
||||||
&self.terms[idx - 1],
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
self.stack.truncate(stack_len + 1);
|
self.stack.truncate(stack_len + 1);
|
||||||
|
|
||||||
let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
|
let mut subterms: Vec<_> = self.terms.drain(idx..).collect();
|
||||||
|
|
||||||
if let Some(name) = self.terms.pop().and_then(|t| {
|
if let Some(name) = self
|
||||||
atomize_term(&mut self.lexer.machine_st.atom_tbl.blocking_write(), &t)
|
.terms
|
||||||
}) {
|
.pop()
|
||||||
|
.and_then(|t| atomize_term(&self.lexer.machine_st.atom_tbl, &t))
|
||||||
|
{
|
||||||
// reduce the '.' functor to a cons cell if it applies.
|
// reduce the '.' functor to a cons cell if it applies.
|
||||||
if name == atom!(".") && subterms.len() == 2 {
|
if name == atom!(".") && subterms.len() == 2 {
|
||||||
let tail = subterms.pop().unwrap();
|
let tail = subterms.pop().unwrap();
|
||||||
@@ -591,12 +589,10 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
Term::PartialString(Cell::default(), string_buf, tail)
|
Term::PartialString(Cell::default(), string_buf, tail)
|
||||||
}
|
}
|
||||||
Ok((string_buf, None)) => {
|
Ok((string_buf, None)) => {
|
||||||
let atom = self
|
let atom = AtomTable::build_with(
|
||||||
.lexer
|
&self.lexer.machine_st.atom_tbl,
|
||||||
.machine_st
|
&string_buf,
|
||||||
.atom_tbl
|
);
|
||||||
.blocking_write()
|
|
||||||
.build_with(&string_buf);
|
|
||||||
Term::CompleteString(Cell::default(), atom)
|
Term::CompleteString(Cell::default(), atom)
|
||||||
}
|
}
|
||||||
Err(term) => term,
|
Err(term) => term,
|
||||||
@@ -763,12 +759,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
Term::PartialString(Cell::default(), string_buf, tail)
|
Term::PartialString(Cell::default(), string_buf, tail)
|
||||||
}
|
}
|
||||||
Ok((string_buf, None)) => {
|
Ok((string_buf, None)) => {
|
||||||
let atom = self
|
let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
|
||||||
.lexer
|
|
||||||
.machine_st
|
|
||||||
.atom_tbl
|
|
||||||
.blocking_write()
|
|
||||||
.build_with(&string_buf);
|
|
||||||
Term::CompleteString(Cell::default(), atom)
|
Term::CompleteString(Cell::default(), atom)
|
||||||
}
|
}
|
||||||
Err(term) => term,
|
Err(term) => term,
|
||||||
@@ -984,8 +975,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
|n, arena| Literal::from(float_alloc!(n, arena)),
|
|n, arena| Literal::from(float_alloc!(n, arena)),
|
||||||
),
|
),
|
||||||
Token::Literal(c) => {
|
Token::Literal(c) => {
|
||||||
let atomized =
|
let atomized = atomize_constant(&self.lexer.machine_st.atom_tbl, c);
|
||||||
atomize_constant(&mut self.lexer.machine_st.atom_tbl.blocking_write(), c);
|
|
||||||
if let Some(name) = atomized {
|
if let Some(name) = atomized {
|
||||||
if !self.shift_op(name, op_dir)? {
|
if !self.shift_op(name, op_dir)? {
|
||||||
self.shift(Token::Literal(c), 0, TERM);
|
self.shift(Token::Literal(c), 0, TERM);
|
||||||
|
|||||||
11
src/read.rs
11
src/read.rs
@@ -81,7 +81,7 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inner.add_lines_read(num_lines_read);
|
inner.add_lines_read(num_lines_read);
|
||||||
write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl.blocking_write())
|
write_term_to_heap(&term, &mut self.heap, &self.atom_tbl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ impl CharRead for ReadlineStream {
|
|||||||
pub(crate) fn write_term_to_heap<'a, 'b>(
|
pub(crate) fn write_term_to_heap<'a, 'b>(
|
||||||
term: &'a Term,
|
term: &'a Term,
|
||||||
heap: &'b mut Heap,
|
heap: &'b mut Heap,
|
||||||
atom_tbl: &mut AtomTable,
|
atom_tbl: &RwLock<AtomTable>,
|
||||||
) -> Result<TermWriteResult, CompilationError> {
|
) -> Result<TermWriteResult, CompilationError> {
|
||||||
let term_writer = TermWriter::new(heap, atom_tbl);
|
let term_writer = TermWriter::new(heap, atom_tbl);
|
||||||
term_writer.write_term_to_heap(term)
|
term_writer.write_term_to_heap(term)
|
||||||
@@ -300,7 +300,7 @@ pub(crate) fn write_term_to_heap<'a, 'b>(
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TermWriter<'a, 'b> {
|
struct TermWriter<'a, 'b> {
|
||||||
heap: &'a mut Heap,
|
heap: &'a mut Heap,
|
||||||
atom_tbl: &'b mut AtomTable,
|
atom_tbl: &'b RwLock<AtomTable>,
|
||||||
queue: SubtermDeque,
|
queue: SubtermDeque,
|
||||||
var_dict: HeapVarDict,
|
var_dict: HeapVarDict,
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ pub struct TermWriteResult {
|
|||||||
|
|
||||||
impl<'a, 'b> TermWriter<'a, 'b> {
|
impl<'a, 'b> TermWriter<'a, 'b> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(heap: &'a mut Heap, atom_tbl: &'b mut AtomTable) -> Self {
|
fn new(heap: &'a mut Heap, atom_tbl: &'b RwLock<AtomTable>) -> Self {
|
||||||
TermWriter {
|
TermWriter {
|
||||||
heap,
|
heap,
|
||||||
atom_tbl,
|
atom_tbl,
|
||||||
@@ -435,7 +435,8 @@ impl<'a, 'b> TermWriter<'a, 'b> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
&TermRef::CompleteString(_, _, ref src) => {
|
&TermRef::CompleteString(_, _, ref src) => {
|
||||||
put_complete_string(self.heap, &src.as_str(), self.atom_tbl);
|
let src = src.as_str().to_owned();
|
||||||
|
put_complete_string(self.heap, &src, self.atom_tbl);
|
||||||
}
|
}
|
||||||
&TermRef::PartialString(lvl, _, ref src, _) => {
|
&TermRef::PartialString(lvl, _, ref src, _) => {
|
||||||
if let Level::Root = lvl {
|
if let Level::Root = lvl {
|
||||||
|
|||||||
@@ -70,11 +70,13 @@ impl Completer for Helper {
|
|||||||
if let Some(idx) = start_of_prefix {
|
if let Some(idx) = start_of_prefix {
|
||||||
let sub_str = line.get(idx..pos).unwrap();
|
let sub_str = line.get(idx..pos).unwrap();
|
||||||
|
|
||||||
let guard = tokio::runtime::Handle::current()
|
let atom_table = self.atoms.upgrade().unwrap();
|
||||||
.block_on(self.atoms.upgrade().unwrap().read_owned());
|
println!("locking atom table to load completions");
|
||||||
|
let guard = atom_table.blocking_read();
|
||||||
|
|
||||||
let mut matching = guard
|
let mut matching = guard
|
||||||
.table
|
.table
|
||||||
|
.blocking_read()
|
||||||
.iter()
|
.iter()
|
||||||
.chain(STATIC_ATOMS_MAP.values())
|
.chain(STATIC_ATOMS_MAP.values())
|
||||||
.map(|a| a.as_str())
|
.map(|a| a.as_str())
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
|
use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
|
||||||
use scryer_prolog::machine::Machine;
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
// issue #857
|
// issue #857
|
||||||
@@ -171,16 +170,3 @@ fn call_0() {
|
|||||||
" error(existence_error(procedure,call/0),call/0).\n",
|
" error(existence_error(procedure,call/0),call/0).\n",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// issue #1206
|
|
||||||
#[serial]
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "Overwriting atom table base pointer")]
|
|
||||||
fn atomtable_is_not_concurrency_safe() {
|
|
||||||
// this is basically the same test as scryer_prolog::atom_table::atomtable_is_not_concurrency_safe
|
|
||||||
// but for this integration test scryer_prolog is compiled with cfg!(not(test)) while for the unit test it is compiled with cfg!(test)
|
|
||||||
// as the atom table implementation differ between cfg!(test) and cfg!(not(test)) both test serve a pourpose
|
|
||||||
// Note: this integration test itself is compiled with cfg!(test) independent of scryer_prolog itself
|
|
||||||
let _machine_a = Machine::with_test_streams();
|
|
||||||
let _machine_b = Machine::with_test_streams();
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user