]> Repositorios git - scryer-prolog.git/commitdiff
preliminary read support
authorMark Thom <[email protected]>
Wed, 25 Jul 2018 23:12:07 +0000 (17:12 -0600)
committerMark Thom <[email protected]>
Wed, 25 Jul 2018 23:12:07 +0000 (17:12 -0600)
README.md
src/prolog/arithmetic.rs
src/prolog/ast.rs
src/prolog/iterators.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/mod.rs
src/prolog/parser
src/prolog/read.rs [new file with mode: 0644]
src/prolog/targets.rs

index eb04d83ee7e9dd551d3f4c3537c929135ab3bd86..155e930e6105ab2d34248314c14a3ed366d45487 100644 (file)
--- a/README.md
+++ b/README.md
@@ -149,6 +149,7 @@ The following predicates are built-in to rusty-wam.
 * `nonvar/1`
 * `once/1`
 * `rational/1`
+* `read/1`
 * `repeat/0`
 * `reverse/2`
 * `select/3`
index 436772fcbeffae0f2af2c87e1faf0a17bcea96eb..79ca2c90325009fe4390674ac8ba5636c94e5746 100644 (file)
@@ -31,7 +31,7 @@ impl<'a> ArithInstructionIterator<'a> {
             &Term::Cons(_, _, _) =>
                 return Err(ArithmeticError::InvalidTerm),
             &Term::Var(ref cell, ref var) =>
-                TermIterState::Var(Level::Shallow, cell, (*var).clone())
+                TermIterState::Var(Level::Shallow, cell, var.clone())
         };
 
         Ok(ArithInstructionIterator { state_stack: vec![state] })
index f60639bc3c9f3f604adf1c119beac82c5373d355..620a0ef7605363ad7097b5cc1d58127e255d1d5c 100644 (file)
@@ -803,6 +803,7 @@ pub enum BuiltInClauseType {
     Is(RegType, ArithmeticTerm),
     KeySort,
     NotEq,
+    Read,
     Sort,
 }
 
@@ -906,6 +907,7 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Is(..)  => clause_name!("is"),
             &BuiltInClauseType::KeySort => clause_name!("keysort"),
             &BuiltInClauseType::NotEq => clause_name!("\\=="),
+            &BuiltInClauseType::Read => clause_name!("read"),
             &BuiltInClauseType::Sort => clause_name!("sort"),
         }
     }
@@ -925,6 +927,7 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Is(..) => 2,
             &BuiltInClauseType::KeySort => 2,
             &BuiltInClauseType::NotEq => 2,
+            &BuiltInClauseType::Read => 1,
             &BuiltInClauseType::Sort => 2,
         }
     }
@@ -950,6 +953,7 @@ impl BuiltInClauseType {
             ("keysort", 2) => Some(BuiltInClauseType::KeySort),
             ("\\==", 2) => Some(BuiltInClauseType::NotEq),
             ("sort", 2) => Some(BuiltInClauseType::Sort),
+            ("read", 1) => Some(BuiltInClauseType::Read),
             _ => None
         }
     }
@@ -1015,7 +1019,7 @@ pub enum TermRef<'a> {
     Var(Level, &'a Cell<VarReg>, Rc<Var>)
 }
 
-impl<'a> TermRef<'a> {
+impl<'a> TermRef<'a> {    
     pub fn level(self) -> Level {
         match self {
             TermRef::AnonVar(lvl)
@@ -1796,7 +1800,7 @@ impl<'a> TermIterState<'a> {
             &Term::Constant(ref cell, ref constant) =>
                 TermIterState::Constant(lvl, cell, constant),
             &Term::Var(ref cell, ref var) =>
-                TermIterState::Var(lvl, cell, (*var).clone())
+                TermIterState::Var(lvl, cell, var.clone())
         }
     }
 }
index c887b4d87caa2d35c4e5e4792e36c278bcb03801..dfa1994d6bfdd8653db999e1c74507bf7639280b 100644 (file)
@@ -6,7 +6,7 @@ use std::rc::Rc;
 use std::vec::Vec;
 
 pub struct QueryIterator<'a> {
-    state_stack: Vec<TermIterState<'a>>
+    state_stack: Vec<TermIterState<'a>>,
 }
 
 impl<'a> QueryIterator<'a> {
@@ -120,6 +120,7 @@ impl<'a> Iterator for QueryIterator<'a> {
 
 pub struct FactIterator<'a> {
     state_queue: VecDeque<TermIterState<'a>>,
+    iterable_root: bool
 }
 
 impl<'a> FactIterator<'a> {
@@ -132,10 +133,10 @@ impl<'a> FactIterator<'a> {
             .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
             .collect();
 
-        FactIterator { state_queue }
+        FactIterator { state_queue, iterable_root: false }
     }
 
-    fn new(term: &'a Term) -> Self {
+    fn new(term: &'a Term, iterable_root: bool) -> Self {
         let states = match term {
             &Term::AnonVar =>
                 vec![TermIterState::AnonVar(Level::Root)],
@@ -151,7 +152,7 @@ impl<'a> FactIterator<'a> {
                 vec![TermIterState::Var(Level::Root, cell, var.clone())]
         };
 
-        FactIterator { state_queue: VecDeque::from(states) }
+        FactIterator { state_queue: VecDeque::from(states), iterable_root }
     }
 }
 
@@ -169,7 +170,7 @@ impl<'a> Iterator for FactIterator<'a> {
                     }
 
                     match lvl {
-                        Level::Root => continue,
+                        Level::Root if !self.iterable_root => continue,
                         _ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
                     };
                 },
@@ -196,8 +197,8 @@ impl Term {
         QueryIterator::from_term(self)
     }
 
-    pub fn breadth_first_iter(&self) -> FactIterator {
-        FactIterator::new(self)
+    pub fn breadth_first_iter(&self, iterable_root: bool) -> FactIterator {
+        FactIterator::new(self, iterable_root)
     }
 }
 
index 859a6a4055f7fd3462125260f9d6f2e4f46c84d1..ce63ccf62225500cfcd19fc56aeac5c143dfe140 100644 (file)
@@ -5,12 +5,12 @@ use prolog::heap_print::*;
 use prolog::machine::machine_errors::*;
 use prolog::num::{BigInt, BigUint, Zero, One};
 use prolog::or_stack::*;
+use prolog::read::*;
 use prolog::tabled_rc::*;
 
 use downcast::Any;
 
 use std::cmp::Ordering;
-use std::collections::HashMap;
 use std::mem::swap;
 use std::ops::{Index, IndexMut};
 use std::rc::Rc;
@@ -32,13 +32,14 @@ impl Ball {
 }
 
 pub(crate) struct CodeDirs<'a> {
-    code_dir: &'a CodeDir,
-    modules: &'a ModuleDir
+    pub code_dir: &'a CodeDir,
+    pub op_dir: &'a OpDir,
+    pub modules: &'a ModuleDir
 }
 
 impl<'a> CodeDirs<'a> {
-    pub(super) fn new(code_dir: &'a CodeDir, modules: &'a HashMap<ClauseName, Module>) -> Self {
-        CodeDirs { code_dir, modules }
+    pub(super) fn new(code_dir: &'a CodeDir, op_dir: &'a OpDir, modules: &'a ModuleDir) -> Self {
+        CodeDirs { code_dir, op_dir, modules }
     }
 
     pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
@@ -202,7 +203,7 @@ pub(super) enum MachineMode {
 }
 
 pub struct MachineState {
-    pub(super) atom_tbl: TabledData<Atom>,
+    pub(crate) atom_tbl: TabledData<Atom>,
     pub(super) s: usize,
     pub(super) p: CodePtr,
     pub(super) b: usize,
@@ -449,7 +450,8 @@ pub(crate) trait CallPolicy: Any {
         Ok(())
     }
 
-    fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
+    fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
+                        code_dirs: CodeDirs<'a>)
                         -> CallResult
     {
         match ct {
@@ -492,6 +494,19 @@ pub(crate) trait CallPolicy: Any {
                 machine_st.fail = !machine_st.is_cyclic_term(addr);
                 return_from_clause!(machine_st.last_call, machine_st)
             },
+            &BuiltInClauseType::Read => {
+                let mut reader = Reader::new(machine_st);
+
+                match reader.read_stdin(code_dirs.op_dir) {
+                    Ok(offset) => {
+                        let addr = reader.machine_st[temp_v!(1)].clone();
+                        reader.machine_st.unify(addr, Addr::HeapCell(offset));
+                    },
+                    Err(err) => println!("{:?}", err)
+                };
+
+                return_from_clause!(reader.machine_st.last_call, reader.machine_st)
+            },
             &BuiltInClauseType::Writeq => {
                 let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
                                                    WriteqFormatter {},
@@ -645,10 +660,11 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
         self.increment()
     }
 
-    fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType)
+    fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
+                        code_dirs: CodeDirs<'a>)
                         -> CallResult
     {
-        self.prev_policy.call_builtin(machine_st, ct)?;
+        self.prev_policy.call_builtin(machine_st, ct, code_dirs)?;
         self.increment()
     }
 
index 2ee034c0e791a4ddac110f1899b14ca48b4cc57b..290c4137ece6d9ae3aa57e8bc1cfa8aa10a502e4 100644 (file)
@@ -1825,7 +1825,7 @@ impl MachineState {
             },
             &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => {
                 self.last_call = lco;
-                try_or_fail!(self, call_policy.call_builtin(self, ct));
+                try_or_fail!(self, call_policy.call_builtin(self, ct, code_dirs));
             },
             &ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) =>
                 self.execute_inlined(ct),
index dc3bdd1962f3a863566082d054c2ffceb0581156..734baedcfa401bdbe55a3ae6fc207dfac8aa205c 100644 (file)
@@ -298,7 +298,8 @@ impl Machine {
             Line::Cut(ref cut_instr) =>
                 self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
             Line::Control(ref control_instr) => {
-                let code_dirs = CodeDirs::new(&self.code_dir, &self.modules);
+                let code_dirs = CodeDirs::new(&self.code_dir, &self.op_dir,
+                                              &self.modules);
                 self.ms.execute_ctrl_instr(code_dirs, &mut self.call_policy,
                                            &mut self.cut_policy, control_instr)
             },
index 13412102406f8fadf0a7df95d53769a04955228e..6d16892d72ea814460bd70b1888bc88c5064851c 100644 (file)
@@ -26,3 +26,4 @@ pub mod parser;
 pub mod heap_print;
 pub mod targets;
 pub mod tabled_rc;
+pub mod read;
index 6a7545257bbfc660b37a0bc3d7a72edb244dda86..3fb28efa315852734613fcf34ee3467c5be8545c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6a7545257bbfc660b37a0bc3d7a72edb244dda86
+Subproject commit 3fb28efa315852734613fcf34ee3467c5be8545c
diff --git a/src/prolog/read.rs b/src/prolog/read.rs
new file mode 100644 (file)
index 0000000..03280b4
--- /dev/null
@@ -0,0 +1,120 @@
+use prolog::ast::*;
+use prolog::machine::machine_state::*;
+use prolog::parser::parser::*;
+
+use std::collections::VecDeque;
+use std::io::stdin;
+
+pub struct Reader<'a> {
+    pub machine_st: &'a mut MachineState,
+}
+
+type SubtermDeque = VecDeque<(usize, usize)>;
+
+impl<'a> TermRef<'a> {
+    fn as_addr(&self, h: usize) -> Addr {
+        match self {
+            &TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
+            &TermRef::Cons(..) => Addr::HeapCell(h),
+            &TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
+            &TermRef::Clause(..) => Addr::Str(h),
+        }
+    }
+}
+
+impl<'a> Reader<'a> {
+    pub fn new(machine_st: &'a mut MachineState) -> Self {
+        Reader { machine_st }
+    }
+
+    pub fn read_stdin(&mut self, op_dir: &'a OpDir) -> Result<usize, ParserError> {
+        let mut buffer = String::new();
+
+        let stdin = stdin();
+        stdin.read_line(&mut buffer).unwrap();
+
+        let mut parser = Parser::new(buffer.as_bytes(), self.machine_st.atom_tbl.clone());
+        Ok(self.write_term_to_heap(parser.read_term(op_dir)?))
+    }
+
+    fn push_stub_addr(&mut self) {
+        let h = self.machine_st.heap.h;
+        self.machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
+    }
+
+    fn modify_head_of_queue(&mut self, queue: &mut SubtermDeque, term: TermRef, h: usize) {
+        if let Some((arity, site_h)) = queue.pop_front() {
+            self.machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
+
+            if arity > 1 {
+                queue.push_front((arity - 1, site_h + 1));
+            }
+        }
+    }
+
+    fn write_term_to_heap(&mut self, term: Term) -> usize {
+        let h = self.machine_st.heap.h;
+
+        let mut queue = SubtermDeque::new();
+        let mut var_dict = HeapVarDict::new();
+
+        for term in term.breadth_first_iter(true) {
+            let h = self.machine_st.heap.h;
+
+            match &term {
+                &TermRef::Cons(lvl, ..) => {                    
+                    queue.push_back((2, h+1));
+                    self.machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
+
+                    self.push_stub_addr();
+                    self.push_stub_addr();
+
+                    if let Level::Root = lvl {
+                        continue;
+                    }
+                },
+                &TermRef::Clause(lvl, _, ref ct, subterms) => {
+                    queue.push_back((subterms.len(), h+1));
+                    let named = HeapCellValue::NamedStr(subterms.len(), ct.name(),
+                                                        ct.fixity());
+
+                    self.machine_st.heap.push(named);
+
+                    for _ in 0 .. subterms.len() {
+                        self.push_stub_addr();
+                    }
+
+                    if let Level::Root = lvl {
+                        continue;
+                    }
+                },
+                &TermRef::AnonVar(Level::Root)
+              | &TermRef::Var(Level::Root, ..)
+              | &TermRef::Constant(Level::Root, ..) =>
+                    self.machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h))),
+                &TermRef::AnonVar(_) =>
+                    continue,
+                &TermRef::Var(_, _, ref var) => {
+                    if let Some((arity, site_h)) = queue.pop_front() {
+                        if let Some(addr) = var_dict.get(var).cloned() {
+                            self.machine_st.heap[site_h] = HeapCellValue::Addr(addr);
+                        } else {
+                            var_dict.insert(var.clone(), Addr::HeapCell(site_h));
+                        }
+                        
+                        if arity > 1 {
+                            queue.push_front((arity - 1, site_h + 1));
+                        }
+                    }
+                        
+                    continue;
+                },
+                _ => {}
+            };
+
+            self.modify_head_of_queue(&mut queue, term, h);
+        }
+
+        h
+    }
+}
index 9999c42905d730a1c2a3f0b40dc985c2e36f257a..f6d1fb3637aa0a32f755cfedd6b713b7477cc204 100644 (file)
@@ -32,7 +32,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
     type Iterator = FactIterator<'a>;
 
     fn iter(term: &'a Term) -> Self::Iterator {
-        term.breadth_first_iter()
+        term.breadth_first_iter(false) // do not iterate over the root clause if one exists.
     }
 
     fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {