]> Repositorios git - scryer-prolog.git/commitdiff
prepare for batch processing.
authorMark Thom <[email protected]>
Tue, 30 Jan 2018 05:04:51 +0000 (22:04 -0700)
committerMark Thom <[email protected]>
Tue, 30 Jan 2018 05:04:51 +0000 (22:04 -0700)
README.md
src/main.rs
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/io.rs
src/prolog/machine/mod.rs
src/prolog/parser

index 4a68be18867906bf52f8d11181ad7e86fc20cdb7..a7cc1599e59c608979b7b7f753880bad851e82dd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Extend rusty-wam to include the following, among other features:
 * Built-in control operators (`,`, `;`, `->`, etc.) (_done_).
 * Built-in predicates for list processing and top-level declarative
   control (`setup_call_control/3`, `call_with_inference_limit/3`,
-  etc.)
+  etc.) (_in progress_).
 * Add a rudimentary module system.  
 * Attributed variables using the SICStus Prolog interface and
   semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.
@@ -84,7 +84,7 @@ The following predicates are built-in to rusty-wam.
 * `(;)/2`
 * `arg/3`
 * `atomic/1`
-* `call/N` (1 <= N <= 63)
+* `call/1..63`
 * `catch/3`
 * `display/1`
 * `duplicate_term/2`
@@ -171,7 +171,7 @@ Lastly, rusty-wam supports dynamic operators. Using the built-in
 arithmetic operators with the usual precedences,
 
 ```
-prolog> ?- X = -5 + 3 - (2 * 4) // 8.
+prolog> ?- display(-5 + 3 - (2 * 4) // 8).
+'-'('+'('-'(5), 3), '//'('*'(2, 4), 8))
 true.
-X = -(+(-(5), 3), //(*(2, 4), 8)).
 ```
\ No newline at end of file
index c9ce711c2b15e04537e46623b9db412b4d2eb5f7..2a223d85cbd647ddbf7ab677180401a9193a3f0a 100644 (file)
@@ -7,6 +7,10 @@ mod prolog;
 use prolog::io::*;
 use prolog::machine::*;
 
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+
 #[cfg(test)]
 mod tests;
 
@@ -24,6 +28,8 @@ fn process_buffer(wam: &mut Machine, buffer: &str)
 fn prolog_repl() {
     let mut wam = Machine::new();
 
+    load_init_file(&mut wam, "lists.pl");
+               
     loop {
         print!("prolog> ");
 
index 1cb783e06d156017b1f9f77808f7d9b631022fcd..7574e536c48be2020c9a21f3684959f25d9826e0 100644 (file)
@@ -409,6 +409,8 @@ pub struct Rule {
     pub clauses: Vec<QueryTerm>
 }
 
+
+
 #[derive(Clone, Copy)]
 pub enum ClauseType<'a> {
     Arg,
index 811ddbecca40bf515f5caf32fce18dcf295c7a64..460a2a47e37f2f339f943b10202ae359b020f1d3 100644 (file)
@@ -16,21 +16,31 @@ pub struct CodeGenerator<'a, TermMarker> {
     var_count: HashMap<&'a Var, usize>
 }
 
-pub enum EvalSession<'a> {
+pub enum EvalError {
     OpIsInfixAndPostFix,
     NamelessEntry,
     ParserError(ParserError),
     ImpermissibleEntry(String),
-    EntrySuccess,
-    InitialQuerySuccess(AllocVarDict<'a>, HeapVarDict<'a>),
     QueryFailure,
-    QueryFailureWithException(String),
+    QueryFailureWithException(String)
+}
+
+pub enum EvalSession<'a> {    
+    EntrySuccess,
+    Error(EvalError),
+    InitialQuerySuccess(AllocVarDict<'a>, HeapVarDict<'a>),    
     SubsequentQuerySuccess,
 }
 
+impl<'a> From<EvalError> for EvalSession<'a> {
+    fn from(err: EvalError) -> Self {
+        EvalSession::Error(err)
+    }
+}
+
 impl<'a> From<ParserError> for EvalSession<'a> {
     fn from(err: ParserError) -> Self {
-        EvalSession::ParserError(err)
+        EvalSession::from(EvalError::ParserError(err))
     }
 }
 
index 185eb3f76487b3d457a3737d64cfe084ad46f5d0..694176de81af9c9b767190cb8d45141577313f5e 100644 (file)
@@ -243,6 +243,20 @@ impl fmt::Display for IndexingInstruction {
     }
 }
 
+impl fmt::Display for EvalError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &EvalError::QueryFailure => write!(f, "false."),
+            &EvalError::QueryFailureWithException(ref e) => write!(f, "{}", error_string(e)),
+            &EvalError::ImpermissibleEntry(ref msg) => write!(f, "cannot overwrite builtin {}", msg),
+            &EvalError::OpIsInfixAndPostFix =>
+                write!(f, "cannot define an op to be both postfix and infix."),
+            &EvalError::NamelessEntry => write!(f, "the predicate head is not an atom or clause."),
+            &EvalError::ParserError(ref e) => write!(f, "{:?}", e)
+        }
+    }
+}
+
 impl fmt::Display for ArithmeticTerm {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
@@ -370,6 +384,12 @@ pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, Par
     worker.parse_code(buffer)
 }
 
+pub fn parse_batch(wam: &mut Machine, buffer: &str) -> Result<Vec<TopLevelPacket>, ParserError>
+{
+    let mut worker = TopLevelWorker::new(wam.atom_tbl(), wam.op_dir());
+    worker.parse_batch(buffer)
+}
+
 pub fn read() -> String {
     let _ = stdout().flush();
 
@@ -419,7 +439,7 @@ fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
 fn set_first_index(code: &mut Code)
 {
     let code_len = code.len();
-    
+
     for (idx, line) in code.iter_mut().enumerate() {
         match line {
             &mut Line::Control(ControlInstruction::JmpByExecute(_, ref mut offset))
@@ -446,27 +466,22 @@ fn compile_query<'a>(terms: &'a Vec<QueryTerm>, queue: &'a Vec<TopLevel>)
                      -> Result<(Code, AllocVarDict<'a>), ParserError>
 {
     let mut cg = CodeGenerator::<DebrayAllocator>::new();
-    let mut code = try!(cg.compile_query(terms));    
-    
+    let mut code = try!(cg.compile_query(terms));
+
     compile_appendix(&mut code, queue)?;
 
     Ok((code, cg.take_vars()))
 }
 
-pub fn compile<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevelPacket) -> EvalSession<'b>
+fn compile_decl<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel, queue: &'b Vec<TopLevel>)
+                            -> EvalSession<'b>
 {
     match tl {
-        &TopLevelPacket::Query(ref terms, ref queue) =>
-            match compile_query(terms, queue) {
-                Ok((code, vars)) => wam.submit_query(code, vars),
-                Err(e) => EvalSession::from(e)
-            },
-        &TopLevelPacket::Decl(TopLevel::Declaration(ref decl), _) =>
-            wam.submit_decl(decl),
-        &TopLevelPacket::Decl(ref tl, ref queue) => {
+        &TopLevel::Declaration(ref decl) => wam.submit_decl(decl),
+        _ => {
             let mut code = match compile_relation(tl) {
                 Ok(code) => code,
-                Err(e) => return EvalSession::ParserError(e)
+                Err(e) => return EvalSession::from(EvalError::ParserError(e))
             };
 
             if let Err(e) = compile_appendix(&mut code, queue) {
@@ -477,15 +492,48 @@ pub fn compile<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevelPacket) -> Eval
                 if let Some(name) = tl.name() {
                     wam.add_user_code(name, tl.arity(), code)
                 } else {
-                    EvalSession::NamelessEntry
+                    EvalSession::from(EvalError::NamelessEntry)
                 }
             } else {
-                EvalSession::ImpermissibleEntry(String::from("no code generated."))
+                EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
             }
         }
     }
 }
 
+pub fn compile<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevelPacket) -> EvalSession<'b>
+{
+    match tl {
+        &TopLevelPacket::Query(ref terms, ref queue) =>
+            match compile_query(terms, queue) {
+                Ok((code, vars)) => wam.submit_query(code, vars),
+                Err(e) => EvalSession::from(e)
+            },
+        &TopLevelPacket::Decl(ref tl, ref queue) =>
+            compile_decl(wam, tl, queue)
+    }
+}
+
+pub fn compile_batch<'a, 'b: 'a>(wam: &'a mut Machine, tls: &'b Vec<TopLevelPacket>)
+                                 -> EvalSession<'b>
+{
+    for tl in tls {
+        match tl {
+            &TopLevelPacket::Query(..) =>
+                return EvalSession::from(ParserError::ExpectedRel),
+            &TopLevelPacket::Decl(ref tl, ref queue) => {
+                let result = compile_decl(wam, tl, queue);
+
+                if let &EvalSession::Error(_) = &result {
+                    return result;
+                }
+            }
+        }
+    }
+
+    EvalSession::EntrySuccess
+}
+
 fn error_string(e: &String) -> String {
     format!("error: exception thrown: {}", e)
 }
@@ -506,7 +554,7 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
             }
 
             loop {
-                let mut result = EvalSession::QueryFailure;
+                let mut result = EvalSession::from(EvalError::QueryFailure);
                 let mut output = PrinterOutputter::new();
 
                 let bindings = wam.heap_view(&heap_locs, output).result();
@@ -535,13 +583,15 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
                         }
                     }
 
-                    if let &EvalSession::QueryFailure = &result {
+                    if let &EvalSession::Error(EvalError::QueryFailure) = &result
+                    {
                         write!(stdout, "false.\n\r").unwrap();
                         stdout.flush().unwrap();
                         return;
                     }
 
-                    if let &EvalSession::QueryFailureWithException(ref e) = &result {
+                    if let &EvalSession::Error(EvalError::QueryFailureWithException(ref e)) = &result
+                    {
                         write!(stdout, "{}\n\r", error_string(e)).unwrap();
                         stdout.flush().unwrap();
                         return;
@@ -553,12 +603,7 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
 
             write!(stdout(), ".\n").unwrap();
         },
-        EvalSession::QueryFailure => println!("false."),
-        EvalSession::QueryFailureWithException(e) => println!("{}", error_string(&e)),
-        EvalSession::ImpermissibleEntry(msg) => println!("cannot overwrite builtin {}", msg),
-        EvalSession::OpIsInfixAndPostFix => println!("cannot define an op to be both postfix and infix."),
-        EvalSession::NamelessEntry => println!("the predicate head is not an atom or clause."),
-        EvalSession::ParserError(e) => println!("{:?}", e),
+        EvalSession::Error(e) => println!("{}", e),
         _ => {}
     };
 }
index fe05da8e0da746497d61bf139659c8058c842de3..11ff6cab1105c1eb594c50c851ba33fbbcb02fb2 100644 (file)
@@ -39,9 +39,10 @@ impl Index<CodePtr> for Machine {
 
 impl Machine {
     pub fn new() -> Self {
-        let atom_tbl = Rc::new(RefCell::new(HashSet::new()));        
+        let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
         let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
-
+        
+        
         Machine {
             ms: machine_state::MachineState::new(atom_tbl),
             code,
@@ -64,7 +65,7 @@ impl Machine {
     {
         match self.code_dir.get(&(name.clone(), arity)) {
             Some(&(PredicateKeyType::BuiltIn, _)) =>
-                return EvalSession::ImpermissibleEntry(format!("{}/{}", name, arity)),
+                return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
             _ => {}
         };
 
@@ -72,7 +73,7 @@ impl Machine {
 
         self.code.append(&mut code);
         self.code_dir.insert((name, arity), (PredicateKeyType::User, offset));
-        
+
         EvalSession::EntrySuccess
     }
 
@@ -209,7 +210,7 @@ impl Machine {
                     },
                     _ => {}
                 }
-                
+
                 self.ms.p = CodePtr::TopLevel(cn, p);
             }
 
@@ -232,10 +233,10 @@ impl Machine {
                                          TermFormatter {},
                                          PrinterOutputter::new())
                           .result();
-            
-            EvalSession::QueryFailureWithException(msg)
+
+            EvalSession::from(EvalError::QueryFailureWithException(msg))
         } else {
-            EvalSession::QueryFailure
+            EvalSession::from(EvalError::QueryFailure)
         }
     }
 
@@ -245,14 +246,14 @@ impl Machine {
             &Declaration::Op(prec, spec, ref name) => {
                 if is_infix!(spec) {
                     match self.op_dir.get(&(name.clone(), Fixity::Post)) {
-                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
+                        Some(_) => return EvalSession::from(EvalError::OpIsInfixAndPostFix),
                         _ => {}
                     };
                 }
 
                 if is_postfix!(spec) {
                     match self.op_dir.get(&(name.clone(), Fixity::In)) {
-                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
+                        Some(_) => return EvalSession::from(EvalError::OpIsInfixAndPostFix),
                         _ => {}
                     };
                 }
@@ -298,7 +299,7 @@ impl Machine {
             self.ms.p = self.ms.or_stack[b].bp;
 
             if let CodePtr::TopLevel(_, 0) = self.ms.p {
-                return EvalSession::QueryFailure;
+                return EvalSession::from(EvalError::QueryFailure);
             }
 
             self.run_query(alloc_l, heap_l);
@@ -309,7 +310,7 @@ impl Machine {
                 EvalSession::SubsequentQuerySuccess
             }
         } else {
-            EvalSession::QueryFailure
+            EvalSession::from(EvalError::QueryFailure)
         }
     }
 
@@ -318,10 +319,10 @@ impl Machine {
     {
         for (var, addr) in var_dir {
             output.begin_new_var();
-            
+
             output.append(var.as_str());
             output.append(" = ");
-            
+
             output = self.ms.print_term(addr.clone(), TermFormatter {}, output);
         }
 
index f2e730cbbabead3c432883c8c2317d76cd426220..64866ff3ef1982d996a56e1330c4c2ac3ecd9d41 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f2e730cbbabead3c432883c8c2317d76cd426220
+Subproject commit 64866ff3ef1982d996a56e1330c4c2ac3ecd9d41