re-factor options handling of read_term into read_term_body (#1887)
This commit is contained in:
@@ -12,6 +12,7 @@ use crate::machine::machine_indices::*;
|
|||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
use crate::machine::streams::*;
|
use crate::machine::streams::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
use crate::read::TermWriteResult;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use crate::parser::rug::Integer;
|
use crate::parser::rug::Integer;
|
||||||
@@ -482,24 +483,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr
|
pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult {
|
||||||
// will always be valid.
|
|
||||||
pub fn read_term_from_user_input(&mut self, 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);
|
|
||||||
let ret = self.read_term(stream, indices);
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unreachable!("Stream must be a Stream::Readline(_)")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
|
||||||
fn push_var_eq_functors<'a>(
|
fn push_var_eq_functors<'a>(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
iter: impl Iterator<Item = (&'a VarPtr, &'a HeapCellValue)>,
|
iter: impl Iterator<Item = (&'a VarPtr, &'a HeapCellValue)>,
|
||||||
@@ -521,6 +505,118 @@ impl MachineState {
|
|||||||
list_of_var_eqs
|
list_of_var_eqs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let heap_loc = read_heap_cell!(self.heap[term_write_result.heap_loc],
|
||||||
|
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
||||||
|
pstr_loc_as_cell!(term_write_result.heap_loc)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
heap_loc_as_cell!(term_write_result.heap_loc)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let term = self.registers[2];
|
||||||
|
unify_fn!(*self, heap_loc, term);
|
||||||
|
let term = heap_loc;
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
||||||
|
|
||||||
|
for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, term) {
|
||||||
|
let cell = unmark_cell_bits!(cell);
|
||||||
|
|
||||||
|
if let Some(var) = cell.as_var() {
|
||||||
|
if !singleton_var_set.contains_key(&var) {
|
||||||
|
singleton_var_set.insert(var, true);
|
||||||
|
} else {
|
||||||
|
singleton_var_set.insert(var, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for var in term_write_result.var_dict.values_mut() {
|
||||||
|
*var = heap_bound_deref(&self.heap, *var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let singleton_var_list = push_var_eq_functors(
|
||||||
|
&mut self.heap,
|
||||||
|
term_write_result.var_dict.iter().filter(|(_, binding)| {
|
||||||
|
if let Some(r) = binding.as_var() {
|
||||||
|
*singleton_var_set.get(&r).unwrap_or(&false)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
&mut self.atom_tbl,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut var_list = Vec::with_capacity(singleton_var_set.len());
|
||||||
|
|
||||||
|
for (var_name, addr) in term_write_result.var_dict {
|
||||||
|
if let Some(var) = addr.as_var() {
|
||||||
|
let idx = singleton_var_set.get_index_of(&var).unwrap();
|
||||||
|
var_list.push((var_name, addr, idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2));
|
||||||
|
|
||||||
|
let list_of_var_eqs = push_var_eq_functors(
|
||||||
|
&mut self.heap,
|
||||||
|
var_list.iter().map(|(var_name, var,_)| (var_name,var)),
|
||||||
|
&mut self.atom_tbl,
|
||||||
|
);
|
||||||
|
|
||||||
|
let singleton_addr = self.registers[3];
|
||||||
|
let singletons_offset = heap_loc_as_cell!(
|
||||||
|
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter())
|
||||||
|
);
|
||||||
|
|
||||||
|
unify_fn!(*self, singletons_offset, singleton_addr);
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let vars_addr = self.registers[4];
|
||||||
|
let vars_offset = heap_loc_as_cell!(
|
||||||
|
iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell))
|
||||||
|
);
|
||||||
|
|
||||||
|
unify_fn!(*self, vars_offset, vars_addr);
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let var_names_addr = self.registers[5];
|
||||||
|
let var_names_offset = heap_loc_as_cell!(
|
||||||
|
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter())
|
||||||
|
);
|
||||||
|
|
||||||
|
return Ok(unify_fn!(*self, var_names_offset, var_names_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safety: the atom_tbl lives for the lifetime of the machine, as does the helper, so the ptr
|
||||||
|
// will always be valid.
|
||||||
|
pub fn read_term_from_user_input(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
||||||
|
let atoms_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);
|
||||||
|
let ret = self.read_term(stream, indices);
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("Stream must be a Stream::Readline(_)")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
|
||||||
self.check_stream_properties(
|
self.check_stream_properties(
|
||||||
stream,
|
stream,
|
||||||
StreamType::Text,
|
StreamType::Text,
|
||||||
@@ -539,100 +635,7 @@ impl MachineState {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.read(stream, &indices.op_dir) {
|
match self.read(stream, &indices.op_dir) {
|
||||||
Ok(mut term_write_result) => {
|
Ok(term_write_result) => return self.read_term_body(term_write_result),
|
||||||
let heap_loc = read_heap_cell!(self.heap[term_write_result.heap_loc],
|
|
||||||
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
|
||||||
pstr_loc_as_cell!(term_write_result.heap_loc)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
heap_loc_as_cell!(term_write_result.heap_loc)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let term = self.registers[2];
|
|
||||||
unify_fn!(*self, heap_loc, term);
|
|
||||||
let term = heap_loc;
|
|
||||||
|
|
||||||
if self.fail {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
|
|
||||||
|
|
||||||
for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, term) {
|
|
||||||
let cell = unmark_cell_bits!(cell);
|
|
||||||
|
|
||||||
if let Some(var) = cell.as_var() {
|
|
||||||
if !singleton_var_set.contains_key(&var) {
|
|
||||||
singleton_var_set.insert(var, true);
|
|
||||||
} else {
|
|
||||||
singleton_var_set.insert(var, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for var in term_write_result.var_dict.values_mut() {
|
|
||||||
*var = heap_bound_deref(&self.heap, *var);
|
|
||||||
}
|
|
||||||
|
|
||||||
let singleton_var_list = push_var_eq_functors(
|
|
||||||
&mut self.heap,
|
|
||||||
term_write_result.var_dict.iter().filter(|(_, binding)| {
|
|
||||||
if let Some(r) = binding.as_var() {
|
|
||||||
*singleton_var_set.get(&r).unwrap_or(&false)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
&mut self.atom_tbl,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut var_list = Vec::with_capacity(singleton_var_set.len());
|
|
||||||
|
|
||||||
for (var_name, addr) in term_write_result.var_dict {
|
|
||||||
if let Some(var) = addr.as_var() {
|
|
||||||
let idx = singleton_var_set.get_index_of(&var).unwrap();
|
|
||||||
var_list.push((var_name, addr, idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2));
|
|
||||||
|
|
||||||
let list_of_var_eqs = push_var_eq_functors(
|
|
||||||
&mut self.heap,
|
|
||||||
var_list.iter().map(|(var_name, var,_)| (var_name,var)),
|
|
||||||
&mut self.atom_tbl,
|
|
||||||
);
|
|
||||||
|
|
||||||
let singleton_addr = self.registers[3];
|
|
||||||
let singletons_offset = heap_loc_as_cell!(
|
|
||||||
iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter())
|
|
||||||
);
|
|
||||||
|
|
||||||
unify_fn!(*self, singletons_offset, singleton_addr);
|
|
||||||
|
|
||||||
if self.fail {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let vars_addr = self.registers[4];
|
|
||||||
let vars_offset = heap_loc_as_cell!(
|
|
||||||
iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell))
|
|
||||||
);
|
|
||||||
|
|
||||||
unify_fn!(*self, vars_offset, vars_addr);
|
|
||||||
|
|
||||||
if self.fail {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let var_names_addr = self.registers[5];
|
|
||||||
let var_names_offset = heap_loc_as_cell!(
|
|
||||||
iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter())
|
|
||||||
);
|
|
||||||
|
|
||||||
return Ok(unify_fn!(*self, var_names_offset, var_names_addr));
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
match err {
|
match err {
|
||||||
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
|
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
|
||||||
|
|||||||
@@ -5816,7 +5816,7 @@ impl Machine {
|
|||||||
let term_write_result = match term_write_result {
|
let term_write_result = match term_write_result {
|
||||||
Ok(term_write_result) => term_write_result,
|
Ok(term_write_result) => term_write_result,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let stub = functor_stub(atom!("read_term_from_chars"), 2);
|
let stub = functor_stub(atom!("read_from_chars"), 2);
|
||||||
let e = self.machine_st.session_error(SessionError::from(e));
|
let e = self.machine_st.session_error(SessionError::from(e));
|
||||||
|
|
||||||
return Err(self.machine_st.error_form(e, stub));
|
return Err(self.machine_st.error_form(e, stub));
|
||||||
@@ -5837,8 +5837,31 @@ impl Machine {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn read_term_from_chars(&mut self) -> CallResult {
|
pub(crate) fn read_term_from_chars(&mut self) -> CallResult {
|
||||||
if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
|
if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
|
||||||
let stream = Stream::from_owned_string(atom_or_string.to_string(), &mut self.machine_st.arena);
|
let chars = CharReader::new(ByteStream::from_string(atom_or_string.to_string()));
|
||||||
self.machine_st.read_term(stream, &mut self.indices)
|
let mut parser = Parser::new(chars, &mut self.machine_st);
|
||||||
|
let op_dir = CompositeOpDir::new(&self.indices.op_dir, None);
|
||||||
|
|
||||||
|
let term_write_result = parser.read_term(&op_dir, Tokens::Default)
|
||||||
|
.map_err(CompilationError::from)
|
||||||
|
.and_then(|term| {
|
||||||
|
write_term_to_heap(
|
||||||
|
&term,
|
||||||
|
&mut self.machine_st.heap,
|
||||||
|
&mut self.machine_st.atom_tbl,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let term_write_result = match term_write_result {
|
||||||
|
Ok(term_write_result) => term_write_result,
|
||||||
|
Err(e) => {
|
||||||
|
let stub = functor_stub(atom!("read_term_from_chars"), 3);
|
||||||
|
let e = self.machine_st.session_error(SessionError::from(e));
|
||||||
|
|
||||||
|
return Err(self.machine_st.error_form(e, stub));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.machine_st.read_term_body(term_write_result)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user