]> Repositorios git - scryer-prolog.git/commitdiff
re-factor options handling of read_term into read_term_body (#1887)
authorMark <[email protected]>
Sun, 16 Jul 2023 03:52:54 +0000 (21:52 -0600)
committerMark <[email protected]>
Sun, 16 Jul 2023 03:52:54 +0000 (21:52 -0600)
src/machine/machine_state.rs
src/machine/system_calls.rs

index 5a8fc85dd8039b407701bb90dda424d2a15c2e2b..499dce55ba54d458cf5b306f634362b461c2cacc 100644 (file)
@@ -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<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 {
+    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<Item = (&'a VarPtr, &'a HeapCellValue)>,
@@ -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<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);
+                }
             }
         }
 
-        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<Ref, bool> = 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<Atom>;
 
-                    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() => {
index 926557d76f237e9dff0a2e2a28a7f8b14de8481e..f18a54641098d9d10d09ee437b648078b656a6d9 100644 (file)
@@ -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!()
         }