From: Mark Date: Sun, 16 Jul 2023 03:52:54 +0000 (-0600) Subject: re-factor options handling of read_term into read_term_body (#1887) X-Git-Tag: v0.9.2~49 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=de10ccfdeea33abb5d64d5a4bc33ee39b14ab002;p=scryer-prolog.git re-factor options handling of read_term into read_term_body (#1887) --- diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 5a8fc85d..499dce55 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -12,6 +12,7 @@ use crate::machine::machine_indices::*; use crate::machine::stack::*; use crate::machine::streams::*; use crate::parser::ast::*; +use crate::read::TermWriteResult; use crate::types::*; 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 - // 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; - - 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 { + pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult { fn push_var_eq_functors<'a>( heap: &mut Heap, iter: impl Iterator, @@ -521,118 +505,137 @@ impl MachineState { list_of_var_eqs } - self.check_stream_properties( - stream, - StreamType::Text, - Some(self.registers[2]), - atom!("read_term"), - 3, - )?; + 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) + } + ); - if stream.past_end_of_stream() { - if EOFAction::Reset != stream.options().eof_action() { - return Ok(()); - } else if self.fail { - return Ok(()); + 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 = 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); + } } } - loop { - match self.read(stream, &indices.op_dir) { - Ok(mut 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) - } - ); + for var in term_write_result.var_dict.values_mut() { + *var = heap_bound_deref(&self.heap, *var); + } - let term = self.registers[2]; - unify_fn!(*self, heap_loc, term); - let term = heap_loc; + 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, + ); - if self.fail { - return Ok(()); - } + let mut var_list = Vec::with_capacity(singleton_var_set.len()); - let mut singleton_var_set: IndexMap = IndexMap::new(); + 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)); + } + } - for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, term) { - let cell = unmark_cell_bits!(cell); + var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2)); - 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); - } - } - } + 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, + ); - for var in term_write_result.var_dict.values_mut() { - *var = heap_bound_deref(&self.heap, *var); - } + 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()) + ); - 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, - ); + unify_fn!(*self, singletons_offset, singleton_addr); - let mut var_list = Vec::with_capacity(singleton_var_set.len()); + if self.fail { + return Ok(()); + } - 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)); - } - } + 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)) + ); - var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2)); + unify_fn!(*self, vars_offset, vars_addr); - 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, - ); + if self.fail { + return Ok(()); + } - 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()) - ); + 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()) + ); - unify_fn!(*self, singletons_offset, singleton_addr); + return Ok(unify_fn!(*self, var_names_offset, var_names_addr)); + } - if self.fail { - return Ok(()); - } + // 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; - 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)) - ); + 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 + } + } - unify_fn!(*self, vars_offset, vars_addr); + unreachable!("Stream must be a Stream::Readline(_)") + } - if self.fail { - return Ok(()); - } + pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult { + self.check_stream_properties( + stream, + StreamType::Text, + Some(self.registers[2]), + atom!("read_term"), + 3, + )?; - 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()) - ); + if stream.past_end_of_stream() { + if EOFAction::Reset != stream.options().eof_action() { + return Ok(()); + } else if self.fail { + return Ok(()); + } + } - return Ok(unify_fn!(*self, var_names_offset, var_names_addr)); - } + loop { + match self.read(stream, &indices.op_dir) { + Ok(term_write_result) => return self.read_term_body(term_write_result), Err(err) => { match err { CompilationError::ParserError(e) if e.is_unexpected_eof() => { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 926557d7..f18a5464 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -5816,7 +5816,7 @@ impl Machine { 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"), 2); + let stub = functor_stub(atom!("read_from_chars"), 2); let e = self.machine_st.session_error(SessionError::from(e)); return Err(self.machine_st.error_form(e, stub)); @@ -5837,8 +5837,31 @@ impl Machine { #[inline(always)] 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]) { - let stream = Stream::from_owned_string(atom_or_string.to_string(), &mut self.machine_st.arena); - self.machine_st.read_term(stream, &mut self.indices) + let chars = CharReader::new(ByteStream::from_string(atom_or_string.to_string())); + 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 { unreachable!() }