From: Mark Thom Date: Mon, 10 Sep 2018 06:18:17 +0000 (-0600) Subject: make use of read_term in the repl X-Git-Tag: v0.8.110~387 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=3f06ff874bd1b34cd971489381aefc9b1e063089;p=scryer-prolog.git make use of read_term in the repl --- diff --git a/Cargo.lock b/Cargo.lock index 6fe939ce..42d1dbcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,7 +86,7 @@ dependencies = [ [[package]] name = "prolog_parser" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -113,7 +113,7 @@ dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prolog_parser 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", + "prolog_parser 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -152,7 +152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" -"checksum prolog_parser 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "277adc8aef82e87336a642a9bbd480cac9550e5ec63c99465eed7cbc7c165808" +"checksum prolog_parser 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "608b6d0e85a6ea8d4fda3679fc314a8b08efdb07f896438342a9d727b04b72d7" "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 32343230..9080870d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ license = "BSD-3-Clause" downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" -prolog_parser = "0.7.10" +prolog_parser = "0.7.11" [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/README.md b/README.md index b3f6384f..f81e7866 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,9 @@ false. and so do conjunctive queries: ``` prolog> f(X) :- g(X). -prolog> g(x). g(y). g(z). +prolog> :{ +g(x). g(y). g(z). +}: prolog> h(call(f, X)). prolog> ?- h(X), X. true . diff --git a/src/main.rs b/src/main.rs index 3c880a62..a4fce5f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,8 +7,11 @@ use prolog::instructions::*; mod prolog; use prolog::compile::*; -use prolog::io::*; use prolog::machine::*; +use prolog::read::*; +use prolog::write::*; + +use std::io::{Write, stdout}; #[cfg(test)] mod tests; @@ -20,7 +23,7 @@ fn parse_and_compile_line(wam: &mut Machine, buffer: &str) let result = compile_packet(wam, packet); print(wam, result); }, - Err(s) => println!("{:?}", s) + Err(e) => print(wam, EvalSession::from(e)) } } @@ -29,19 +32,28 @@ fn prolog_repl() { loop { print!("prolog> "); - - match read() { - Input::Line(line) => parse_and_compile_line(&mut wam, line.as_str()), - Input::Batch(batch) => - match compile_user_module(&mut wam, batch.as_str()) { - EvalSession::Error(e) => println!("{}", e), - _ => {} + stdout().flush().unwrap(); + + match read_toplevel(&mut wam) { + Ok(Input::Term(term)) => + match compile_term(&mut wam, term) { + Ok(packet) => { + let result = compile_packet(&mut wam, packet); + print(&mut wam, result); + }, + Err(e) => print(&mut wam, EvalSession::from(e)) }, - Input::Quit => break, - Input::Clear => { + Ok(Input::Line(line)) => parse_and_compile_line(&mut wam, line.as_str()), + Ok(Input::Batch(batch)) => { + let result = compile_user_module(&mut wam, batch.as_bytes()); + print(&mut wam, result); + }, + Ok(Input::Quit) => break, + Ok(Input::Clear) => { wam.clear(); continue; - } + }, + Err(e) => print(&mut wam, EvalSession::from(e)) }; wam.reset(); diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index eb57251c..c6c3c369 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -7,6 +7,7 @@ use prolog::machine::*; use prolog::toplevel::*; use std::collections::{HashMap, HashSet, VecDeque}; +use std::io::Read; use std::mem; #[allow(dead_code)] @@ -48,6 +49,11 @@ pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result Result { + let indices = machine_code_indices!(&mut wam.code_dir, &mut wam.op_dir, &mut HashMap::new()); + parse_term(term, indices) +} + // throw errors if declaration or query found. fn compile_relation(tl: &TopLevel, non_counted_bt: bool, flags: MachineFlags) -> Result { @@ -137,7 +143,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec) -> EvalSe try_eval_session!(compile_appendix(&mut code, queue, false, wam.machine_flags())); if !code.is_empty() { - wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap()) + wam.add_user_code(name, tl.arity(), code) } else { EvalSession::from(SessionError::ImpermissibleEntry(String::from("no code generated."))) } @@ -177,8 +183,8 @@ impl<'a> ListingCompiler<'a> { .unwrap_or(ClauseName::BuiltIn("user")) } - fn gen_code(&mut self, decls: Vec<(Predicate, VecDeque)>, code_dir: &mut CodeDir) - -> Result + fn generate_code(&mut self, decls: Vec<(Predicate, VecDeque)>, code_dir: &mut CodeDir) + -> Result { let mut code = vec![]; @@ -246,9 +252,9 @@ fn use_qualified_module(module: &mut Option, submodule: &Module, exports } pub -fn compile_listing(wam: &mut Machine, src_str: &str, mut indices: MachineCodeIndices) -> EvalSession +fn compile_listing(wam: &mut Machine, src: R, mut indices: MachineCodeIndices) -> EvalSession { - let mut worker = TopLevelBatchWorker::new(src_str.as_bytes(), wam.atom_tbl(), wam.machine_flags()); + let mut worker = TopLevelBatchWorker::new(src, wam.atom_tbl(), wam.machine_flags()); let mut compiler = ListingCompiler::new(wam); while let Some(decl) = try_eval_session!(worker.consume(&mut indices)) { @@ -279,13 +285,13 @@ fn compile_listing(wam: &mut Machine, src_str: &str, mut indices: MachineCodeInd } } - let code = try_eval_session!(compiler.gen_code(worker.results, &mut indices.code_dir)); + let code = try_eval_session!(compiler.generate_code(worker.results, &mut indices.code_dir)); compiler.add_code(code, indices); EvalSession::EntrySuccess } -pub fn compile_user_module(wam: &mut Machine, src_str: &str) -> EvalSession { +pub fn compile_user_module(wam: &mut Machine, src: R) -> EvalSession { let mut indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(), &mut HashMap::new()); @@ -295,5 +301,5 @@ pub fn compile_user_module(wam: &mut Machine, src_str: &str) -> EvalSession { return EvalSession::from(SessionError::ModuleNotFound); } - compile_listing(wam, src_str, indices) + compile_listing(wam, src, indices) } diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 770e23ae..1563648b 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -28,7 +28,7 @@ impl InlinedClauseType { &InlinedClauseType::IsAtom(..) => "atom", &InlinedClauseType::IsAtomic(..) => "atomic", &InlinedClauseType::IsCompound(..) => "compound", - &InlinedClauseType::IsInteger (..) => "integer", + &InlinedClauseType::IsInteger (..) => "integer", &InlinedClauseType::IsRational(..) => "rational", &InlinedClauseType::IsString(..) => "string", &InlinedClauseType::IsFloat (..) => "float", @@ -195,7 +195,7 @@ pub type ModuleCodeDir = HashMap; pub type CodeDir = HashMap; -pub type TermDir = HashMap; +//pub type TermDir = HashMap; pub type ModuleDir = HashMap; @@ -781,6 +781,7 @@ pub enum IndexPtr { pub struct CodeIndex(pub Rc>); impl CodeIndex { + #[inline] pub fn is_undefined(&self) -> bool { let index_ptr = &self.0.borrow().0; @@ -1140,15 +1141,6 @@ impl TopLevel { &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() } } - - pub fn as_predicate(self) -> Result { - match self { - TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])), - TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])), - TopLevel::Predicate(pred) => Ok(pred), - _ => Err(self) - } - } } #[derive(Clone, Copy)] @@ -1239,7 +1231,7 @@ pub enum SessionError { OpIsInfixAndPostFix, ParserError(ParserError), QueryFailure, - QueryFailureWithException(String) + QueryFailureWithException(String) } pub enum EvalSession { diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 692c6654..5bbed80f 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -61,48 +61,7 @@ impl MachineError { } pub(super) fn syntax_error(h: usize, err: ParserError) -> Self { - let err = match err { - ParserError::Arithmetic(_) => - vec![heap_atom!("arithmetic_error")], - ParserError::BackQuotedString => - vec![heap_atom!("back_quoted_string")], - ParserError::UnexpectedChar(c) => - functor!("unexpected_char", 1, [heap_char!(c)]), - ParserError::UnexpectedEOF => - vec![heap_atom!("unexpected_end_of_file")], - ParserError::ExpectedRel => - vec![heap_atom!("expected_relation")], - ParserError::InadmissibleFact => - vec![heap_atom!("inadmissible_fact")], - ParserError::InadmissibleQueryTerm => - vec![heap_atom!("inadmissible_query_term")], - ParserError::IncompleteReduction => - vec![heap_atom!("incomplete_reduction")], - ParserError::InconsistentEntry => - vec![heap_atom!("inconsistent_entry")], - ParserError::InvalidModuleDecl => - vec![heap_atom!("invalid_module_declaration")], - ParserError::InvalidModuleExport => - vec![heap_atom!("invalid_module_export")], - ParserError::InvalidModuleResolution => - vec![heap_atom!("invalid_module_resolution")], - ParserError::InvalidRuleHead => - vec![heap_atom!("invalid_head_of_rule")], - ParserError::InvalidUseModuleDecl => - vec![heap_atom!("invalid_use_module_declaration")], - ParserError::IO(_) => - vec![heap_atom!("input_output_error")], - ParserError::MissingQuote => - vec![heap_atom!("missing_quote")], - ParserError::NonPrologChar => - vec![heap_atom!("non_prolog_character")], - ParserError::ParseBigInt => - vec![heap_atom!("cannot_parse_big_int")], - ParserError::ParseFloat => - vec![heap_atom!("cannot_parse_float")], - ParserError::Utf8Conversion(_) => - vec![heap_atom!("utf8_conversion_error")] - }; + let err = vec![heap_atom!(err.as_str())]; let mut stub = if err.len() == 1 { functor!("syntax_error", 1) diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index f2e05c7b..a2a4c09e 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -9,12 +9,12 @@ use prolog::machine::MachineCodeIndices; use prolog::machine::machine_errors::*; use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::or_stack::*; -use prolog::read::*; use downcast::Any; use std::cell::RefCell; use std::cmp::Ordering; +use std::io::stdin; use std::mem::swap; use std::ops::{Index, IndexMut}; use std::rc::Rc; @@ -297,7 +297,7 @@ pub struct MachineState { pub(super) ball: Ball, pub(super) interms: Vec, // intermediate numbers. pub(super) last_call: bool, - pub(super) flags: MachineFlags + pub(crate) flags: MachineFlags } fn call_at_index(machine_st: &mut MachineState, module_name: ClauseName, arity: usize, idx: usize) @@ -570,25 +570,23 @@ 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(&indices.op_dir) { + &BuiltInClauseType::Read => { + match machine_st.read(stdin(), &indices.op_dir) { Ok(offset) => { - let addr = reader.machine_st[temp_v!(1)].clone(); - reader.machine_st.unify(addr, Addr::HeapCell(offset)); + let addr = machine_st[temp_v!(1)].clone(); + machine_st.unify(addr, Addr::HeapCell(offset)); }, Err(e) => { - let h = reader.machine_st.heap.h; + let h = machine_st.heap.h; let stub = MachineError::functor_stub(clause_name!("read"), 1); let err = MachineError::syntax_error(h, e); - let err = reader.machine_st.error_form(err, stub); + let err = machine_st.error_form(err, stub); return Err(err); } }; - return_from_clause!(reader.machine_st.last_call, reader.machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Writeq => { let output = machine_st.print_term(machine_st[temp_v!(1)].clone(), diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 5db6062e..8c9f16a4 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -62,7 +62,7 @@ pub struct Machine { code: Code, pub(super) code_dir: CodeDir, pub(super) op_dir: OpDir, - term_dir: TermDir, + // term_dir: TermDir, pub(super) modules: ModuleDir, cached_query: Option } @@ -116,7 +116,7 @@ impl Machine { code: Code::new(), code_dir: CodeDir::new(), op_dir: default_op_dir(), - term_dir: TermDir::new(), + // term_dir: TermDir::new(), modules: HashMap::new(), cached_query: None }; @@ -124,11 +124,11 @@ impl Machine { let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(), &mut HashMap::new()); - compile_listing(&mut wam, BUILTINS, indices); + compile_listing(&mut wam, BUILTINS.as_bytes(), indices); - compile_user_module(&mut wam, LISTS); - compile_user_module(&mut wam, CONTROL); - compile_user_module(&mut wam, QUEUES); + compile_user_module(&mut wam, LISTS.as_bytes()); + compile_user_module(&mut wam, CONTROL.as_bytes()); + compile_user_module(&mut wam, QUEUES.as_bytes()); wam.use_module_in_toplevel(clause_name!("builtins")); @@ -252,8 +252,7 @@ impl Machine { self.code.extend(code.into_iter()); } - pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code, pred: Predicate) - -> EvalSession + pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession { match self.code_dir.get(&(name.clone(), arity)) { Some(&CodeIndex (ref idx)) if idx.borrow().1 != clause_name!("user") => @@ -268,7 +267,7 @@ impl Machine { let offset = self.code.len(); self.code.extend(code.into_iter()); - self.term_dir.insert((name.clone(), arity), pred); + //self.term_dir.insert((name.clone(), arity), pred); let idx = self.code_dir.entry((name, arity)) .or_insert(CodeIndex::from((offset, clause_name!("user")))); diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 02b2629b..48712dfc 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -22,12 +22,6 @@ macro_rules! heap_integer { ) } -macro_rules! heap_char { - ($c:expr) => ( - HeapCellValue::Addr(Addr::Con(Constant::Char($c))) - ) -} - macro_rules! heap_atom { ($name:expr) => ( HeapCellValue::Addr(Addr::Con(atom!($name))) diff --git a/src/prolog/mod.rs b/src/prolog/mod.rs index 138b3e49..4c77f937 100644 --- a/src/prolog/mod.rs +++ b/src/prolog/mod.rs @@ -16,9 +16,9 @@ mod debray_allocator; mod fixtures; mod heap_iter; mod indexing; -pub mod io; +pub mod write; mod iterators; mod or_stack; pub mod heap_print; mod targets; -mod read; +pub mod read; diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 77629238..7432ec65 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -3,14 +3,11 @@ use prolog_parser::parser::*; use prolog::instructions::*; use prolog::iterators::*; -use prolog::machine::machine_state::*; +use prolog::machine::*; +use prolog::machine::machine_state::MachineState; use std::collections::VecDeque; -use std::io::stdin; - -pub struct Reader<'a> { - pub machine_st: &'a mut MachineState, -} +use std::io::{Read, stdin}; type SubtermDeque = VecDeque<(usize, usize)>; @@ -25,133 +22,137 @@ impl<'a> TermRef<'a> { } } -impl<'a> Reader<'a> { - pub fn new(machine_st: &'a mut MachineState) -> Self { - Reader { machine_st } - } +pub enum Input { + Quit, + Clear, + Line(String), + Batch(String), + Term(Term) +} - fn read_term(&self, buffer: &String, op_dir: &'a OpDir) -> Result { - let mut parser = Parser::new(buffer.as_bytes(), self.machine_st.atom_tbl.clone(), - self.machine_st.machine_flags()); +fn read_lines(buffer: &mut String, end_delim: &str) -> String { + let mut result = String::new(); + let stdin = stdin(); - parser.read_term(op_dir) - } - - fn read_term_loop(&mut self, buffer: &mut String, op_dir: &'a OpDir) -> Result { - let stdin = stdin(); - - loop { - match self.read_term(&buffer, op_dir) { - Err(ParserError::UnexpectedEOF) => {}, - result => return result - }; - - let mut append_buf = String::new(); - stdin.read_line(&mut append_buf).unwrap(); - *buffer += append_buf.as_str(); - } - } -/* - pub fn repl_read(&mut self, op_dir: &'a OpDir) -> Result, ParserError> { - let mut buffer = String::new(); + buffer.clear(); + stdin.read_line(buffer).unwrap(); - stdin().read_line(&mut buffer); + while &*buffer.trim() != end_delim { + result += buffer.as_str(); + buffer.clear(); + stdin.read_line(buffer).unwrap(); + } - if buffer.as_str() == "[user]" { - let locked = stdin().lock(); - let mut parser = Parser::new(locked, self.machine_st.atom_tbl.clone(), - self.machine_st.flags()); + result +} - parser.read(op_dir) - } else { - Ok(vec![self.read_term_loop(buffer, op_dir)?]) +pub fn read_toplevel(wam: &Machine) -> Result { + let mut buffer = String::new(); + + let stdin = stdin(); + stdin.read_line(&mut buffer).unwrap(); + + match &*buffer.trim() { + ":{" => Ok(Input::Line(read_lines(&mut buffer, "}:"))), + ":{{" => Ok(Input::Batch(read_lines(&mut buffer, "}}:"))), + "quit" => Ok(Input::Quit), + "clear" => Ok(Input::Clear), + _ => { + let mut parser = Parser::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags()); + + parser.add_to_top(buffer.as_str()); + Ok(Input::Term(parser.read_term(&wam.op_dir)?)) } } -*/ - pub fn read_stdin(&mut self, op_dir: &'a OpDir) -> Result +} + +impl MachineState { + pub fn read(&mut self, inner: R, op_dir: &OpDir) -> Result { - let term = self.read_term_loop(&mut String::new(), op_dir)?; - Ok(self.write_term_to_heap(term)) - } + let mut parser = Parser::new(inner, self.atom_tbl.clone(), self.flags); + let term = 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))); + Ok(write_term_to_heap(term, self)) } +} - 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)); +fn push_stub_addr(machine_st: &mut MachineState) { + let h = machine_st.heap.h; + machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); +} + +fn modify_head_of_queue(machine_st: &mut MachineState, queue: &mut SubtermDeque, term: TermRef, h: usize) +{ + if let Some((arity, site_h)) = queue.pop_front() { + machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h)); - if arity > 1 { - queue.push_front((arity - 1, site_h + 1)); - } + 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; +fn write_term_to_heap(term: Term, machine_st: &mut MachineState) -> usize { + let h = machine_st.heap.h; - let mut queue = SubtermDeque::new(); - let mut var_dict = HeapVarDict::new(); + let mut queue = SubtermDeque::new(); + let mut var_dict = HeapVarDict::new(); - for term in breadth_first_iter(&term, true) { - let h = self.machine_st.heap.h; + for term in breadth_first_iter(&term, true) { + let h = 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))); + match &term { + &TermRef::Cons(lvl, ..) => { + queue.push_back((2, h+1)); + machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h+1))); - self.push_stub_addr(); - self.push_stub_addr(); + push_stub_addr(machine_st); + push_stub_addr(machine_st); - 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()); + 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); + machine_st.heap.push(named); - for _ in 0 .. subterms.len() { - self.push_stub_addr(); - } + for _ in 0 .. subterms.len() { + push_stub_addr(machine_st); + } - 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)); - } + if let Level::Root = lvl { + continue; + } + }, + &TermRef::AnonVar(Level::Root) + | &TermRef::Var(Level::Root, ..) + | &TermRef::Constant(Level::Root, ..) => + 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() { + machine_st.heap[site_h] = HeapCellValue::Addr(addr); + } else { + var_dict.insert(var.clone(), Addr::HeapCell(site_h)); } - continue; - }, - _ => {} - }; + if arity > 1 { + queue.push_front((arity - 1, site_h + 1)); + } + } - self.modify_head_of_queue(&mut queue, term, h); - } + continue; + }, + _ => {} + }; - h + modify_head_of_queue(machine_st, &mut queue, term, h); } + + h } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index fac313b5..b07d8559 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -645,6 +645,16 @@ impl<'a, R: Read> TopLevelWorker<'a, R> { } } +pub fn parse_term(term: Term, mut indices: MachineCodeIndices) -> Result +{ + let mut rel_worker = RelationWorker::new(); + + let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?; + let results = rel_worker.parse_queue(&mut indices)?; + + Ok(deque_to_packet(tl, results)) +} + pub struct TopLevelBatchWorker { parser: Parser, rel_worker: RelationWorker, @@ -666,7 +676,7 @@ impl TopLevelBatchWorker { { let mut preds = vec![]; - while !self.parser.eof() { + while !self.parser.eof()? { self.parser.reset(); // empty the parser stack of token descriptions. let mut new_rel_worker = RelationWorker::new(); diff --git a/src/prolog/io.rs b/src/prolog/write.rs similarity index 92% rename from src/prolog/io.rs rename to src/prolog/write.rs index 6f7671c6..c9259dab 100644 --- a/src/prolog/io.rs +++ b/src/prolog/write.rs @@ -134,7 +134,7 @@ impl fmt::Display for ControlInstruction { &ControlInstruction::CallClause(ref ct, arity, pvs, true, false) => write!(f, "execute {}/{}, {}", ct, arity, pvs), &ControlInstruction::CallClause(ref ct, arity, pvs, false, false) => - write!(f, "call {}/{}, {}", ct, arity, pvs), + write!(f, "call {}/{}, {}", ct, arity, pvs), &ControlInstruction::Deallocate => write!(f, "deallocate"), &ControlInstruction::JmpBy(arity, offset, pvs, false) => @@ -162,7 +162,7 @@ impl fmt::Display for IndexedChoiceInstruction { impl fmt::Display for ChoiceInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { + match self { &ChoiceInstruction::TryMeElse(offset) => write!(f, "try_me_else {}", offset), &ChoiceInstruction::DefaultRetryMeElse(offset) => @@ -201,7 +201,7 @@ impl fmt::Display for SessionError { &SessionError::OpIsInfixAndPostFix => write!(f, "cannot define an op to be both postfix and infix."), &SessionError::NamelessEntry => write!(f, "the predicate head is not an atom or clause."), - &SessionError::ParserError(ref e) => write!(f, "{:?}", e) + &SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()), } } } @@ -281,59 +281,17 @@ impl fmt::Display for Level { } } -pub enum Input { - Quit, - Clear, - Line(String), - Batch(String) -} - -fn read_lines(buffer: &mut String, end_delim: &str) -> String { - let mut result = String::new(); - let stdin = stdin(); - - buffer.clear(); - stdin.read_line(buffer).unwrap(); - - while &*buffer.trim() != end_delim { - result += buffer.as_str(); - buffer.clear(); - stdin.read_line(buffer).unwrap(); - } - - result -} - -pub fn read() -> Input { - let _ = stdout().flush(); - let mut buffer = String::new(); - - let stdin = stdin(); - stdin.read_line(&mut buffer).unwrap(); - - match &*buffer.trim() { - ":{" => Input::Line(read_lines(&mut buffer, "}:")), - ":{{" => Input::Batch(read_lines(&mut buffer, "}}:")), - "quit" => Input::Quit, - "clear" => Input::Clear, - _ => Input::Line(buffer) - } -} - pub fn print(wam: &mut Machine, result: EvalSession) { match result { EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => { - print!("true"); - - if !wam.or_stack_is_empty() { - print!(" "); - } - - println!("."); - if heap_locs.is_empty() { + println!("true."); return; } + + if !wam.or_stack_is_empty() { + println!("true ."); + } loop { let mut result = EvalSession::from(SessionError::QueryFailure); diff --git a/src/tests.rs b/src/tests.rs index ea844659..e8e40271 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -129,7 +129,7 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool true, _ => false }, - Err(e) => panic!("parse error: {:?}", e) + Err(e) => panic!("syntax_error({})", e.as_str()) } } @@ -146,7 +146,7 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec EvalSession::EntrySuccess => true, _ => false }, - Err(e) => panic!("parse error: {:?}", e) + Err(e) => panic!("syntax_error({})", e.as_str()) } } @@ -166,7 +166,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str, EvalSession::EntrySuccess => true, _ => false }, - Err(e) => panic!("parse error: {:?}", e) + Err(e) => panic!("syntax_error({})", e.as_str()) } } @@ -1351,7 +1351,7 @@ fn test_queries_on_modules() local_member(X, Xs) :- member(X, Xs). reverse(Xs, Ys) :- lists:reverse(Xs, Ys). -"); +".as_bytes()); assert_prolog_success!(&mut wam, "?- my_lists:local_member(1, [1,2,3])."); assert_prolog_success!(&mut wam, "?- my_lists:reverse([a,b,c], [c,b,a])."); @@ -1359,13 +1359,11 @@ reverse(Xs, Ys) :- lists:reverse(Xs, Ys). compile_user_module(&mut wam, " :- use_module(library(my_lists), [local_member/2]). :- module(my_lists_2, [local_member/2]). -"); +".as_bytes()); assert_prolog_success!(&mut wam, "?- my_lists_2:local_member(1, [1,2,3])."); assert_prolog_success!(&mut wam, "?- catch(local_member(X, Xs), error(E, _), true).", [["X = _1", "E = existence_error(procedure, local_member/2)", "Xs = _2"]]); - - } #[test]