From ae905543786052755ec328a1146900a2bf5d48b4 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 13 Apr 2019 18:40:17 -0600 Subject: [PATCH] read from streams. --- Cargo.toml | 6 +- src/main.rs | 49 +- src/prolog/clause_types.rs | 18 +- src/prolog/heap_print.rs | 8 +- src/prolog/lib/builtins.pl | 19 +- src/prolog/lib/dif.pl | 7 +- src/prolog/machine/and_stack.rs | 10 +- src/prolog/machine/attributed_variables.rs | 25 +- src/prolog/machine/code_repo.rs | 4 +- src/prolog/machine/compile.rs | 27 +- src/prolog/machine/dynamic_database.rs | 5 +- src/prolog/machine/heap.rs | 12 + src/prolog/machine/machine_errors.rs | 3 +- src/prolog/machine/machine_indices.rs | 36 +- src/prolog/machine/machine_state.rs | 45 +- src/prolog/machine/machine_state_impl.rs | 128 +- src/prolog/machine/mod.rs | 327 +++- src/prolog/machine/or_stack.rs | 6 + src/prolog/machine/system_calls.rs | 128 +- src/prolog/machine/term_expansion.rs | 41 +- src/prolog/machine/toplevel.rs | 32 +- src/prolog/read.rs | 203 ++- src/prolog/toplevel.pl | 19 + src/prolog/write.rs | 110 +- src/tests.rs | 1751 ++++++++++---------- 25 files changed, 1679 insertions(+), 1340 deletions(-) create mode 100644 src/prolog/toplevel.pl diff --git a/Cargo.toml b/Cargo.toml index e9944e99..ae82d3a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.51" +version = "0.8.52" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." @@ -14,8 +14,8 @@ cfg-if = "0.1.7" downcast = "0.10.0" num = "0.2" ordered-float = "0.5.0" -prolog_parser = "0.8.18" -readline_rs_compat = { version = "0.1.7", optional = true } +prolog_parser = { version = "0.8.19", path = "../prolog_parser" } +readline_rs_compat = { version = "0.1.8", path = "../readline.rs", optional = true } ref_thread_local = "0.0.0" [dependencies.termion] diff --git a/src/main.rs b/src/main.rs index ebfe87c2..a339ad10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,59 +14,16 @@ extern crate termion; mod prolog; use prolog::machine::*; -use prolog::machine::compile::*; use prolog::machine::machine_errors::*; -use prolog::machine::toplevel::string_to_toplevel; use prolog::read::*; -use prolog::write::*; #[cfg(test)] mod tests; -fn prolog_repl() { - let mut wam = Machine::new(); - - loop { - #[cfg(feature = "readline_rs_compat")] - readline::set_line_mode(readline::LineMode::Single); - - match toplevel_read_line() { - Ok(Input::TermString(buffer)) => { - let result = match string_to_toplevel(buffer.as_bytes(), &mut wam) { - Ok(packet) => compile_term(&mut wam, packet), - Err(e) => EvalSession::from(e) - }; - - print(&mut wam, result) - }, - Ok(Input::Batch) => { - #[cfg(feature = "readline_rs_compat")] - readline::set_line_mode(readline::LineMode::Multi); - - let src = match readline::read_batch("") { - Ok(src) => src, - Err(e) => { - println!("{}", e); - continue; - } - }; - - let result = compile_user_module(&mut wam, &src[0 ..]); - print(&mut wam, result); - }, - Ok(Input::Clear) => { - wam.clear(); - continue; - }, - Err(e) => print(&mut wam, EvalSession::from(e)) - }; - - wam.reset(); - } -} - fn main() { #[cfg(feature = "readline_rs_compat")] readline::readline_initialize(); - prolog_repl(); + + let mut wam = Machine::new(readline::input_stream()); + wam.run_toplevel(); } diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 7eb0a03c..fc78dfd3 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -130,7 +130,7 @@ ref_thread_local! { m.insert(("partial_string", 2), ClauseType::BuiltIn(BuiltInClauseType::PartialString)); m.insert(("read", 1), ClauseType::BuiltIn(BuiltInClauseType::Read)); m.insert(("sort", 2), ClauseType::BuiltIn(BuiltInClauseType::Sort)); - + m }; } @@ -177,7 +177,7 @@ pub enum SystemClauseType { FetchGlobalVar, GetChar, TruncateIfNoLiftedHeapGrowthDiff, - TruncateIfNoLiftedHeapGrowth, + TruncateIfNoLiftedHeapGrowth, GetAttributedVariableList, GetAttrVarQueueDelimiter, GetAttrVarQueueBeyond, @@ -201,6 +201,8 @@ pub enum SystemClauseType { ModuleRetractClause, NoSuchPredicate, OpDeclaration, + REPL(REPLCodePtr), + ReadTerm, RedoAttrVarBindings, RemoveCallPolicyCheck, RemoveInferenceCounter, @@ -236,7 +238,7 @@ impl SystemClauseType { pub fn name(&self) -> ClauseName { match self { &SystemClauseType::AbolishClause => clause_name!("$abolish_clause"), - &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"), + &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"), &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"), &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"), &SystemClauseType::AtomChars => clause_name!("$atom_chars"), @@ -246,6 +248,9 @@ impl SystemClauseType { &SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"), &SystemClauseType::CharCode => clause_name!("char_code"), &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), + &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"), + &SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults) => + clause_name!("$submit_query_and_print_results"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"), @@ -296,6 +301,7 @@ impl SystemClauseType { &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), &SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"), + &SystemClauseType::ReadTerm => clause_name!("$read_term"), &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"), &SystemClauseType::RetractClause => clause_name!("$retract_clause"), &SystemClauseType::ResetBlock => clause_name!("$reset_block"), @@ -326,6 +332,7 @@ impl SystemClauseType { ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), ("$char_code", 2) => Some(SystemClauseType::CharCode), ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint), + ("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)), ("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap), ("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute), ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute), @@ -375,6 +382,7 @@ impl SystemClauseType { ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), + ("$read_term", 2) => Some(SystemClauseType::ReadTerm), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey), ("$retract_clause", 4) => Some(SystemClauseType::RetractClause), @@ -385,6 +393,8 @@ impl SystemClauseType { ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), + ("$submit_query_and_print_results", 2) => + Some(SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults)), ("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), @@ -397,7 +407,7 @@ impl SystemClauseType { #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] pub enum BuiltInClauseType { AcyclicTerm, - Arg, + Arg, Compare, CompareTerm(CompareTermQT), CyclicTerm, diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 79319e95..a106ded1 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -398,6 +398,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> printer } + pub fn drop_toplevel_spec(&mut self) { + self.toplevel_spec = None; + } + #[inline] pub fn see_all_locs(&mut self) { for key in self.heap_locs.keys().cloned() { @@ -559,8 +563,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option { iter.stack().last().cloned().and_then(|addr| { - let addr = self.machine_st.store(self.machine_st.deref(addr)); - + let addr = self.machine_st.store(self.machine_st.deref(addr)); + match self.heap_locs.get(&addr).cloned() { Some(var) => if !self.printed_vars.contains(&addr) { self.printed_vars.insert(addr); diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 6e87ff66..8036284e 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -12,7 +12,7 @@ char_code/2, clause/2, current_predicate/1, current_op/3, current_prolog_flag/2, expand_goal/2, expand_term/2, findall/3, findall/4, get_char/1, halt/0, once/1, op/3, - repeat/0, retract/1, set_prolog_flag/2, setof/3, + read_term/2, repeat/0, retract/1, set_prolog_flag/2, setof/3, setup_call_cleanup/3, term_variables/2, throw/1, true/0, false/0, write/1, write_canonical/1, writeq/1, write_term/2]). @@ -231,10 +231,23 @@ inst_member_or([X|Xs], Y, _) :- ; throw(instantiation_error) ). % 8.14.2.3 b) inst_member_or([], Y, Y). +%% TODO: complete the predicate! Most read options are missing. +read_term(Term, Options) :- + '$skip_max_list'(_, -1, Options, Options0), + ( Options0 == [] -> true + ; var(Options0) -> throw(error(instantiation_error, read_term/2)) % 8.14.1.3 b) + ; throw(error(type_error(list, Options), read_term/2)) % 8.14.1.3 d) + ), + ( Options = [variable_names(VarList)] -> '$read_term'(Term, VarList) + ; Options = [] -> read(Term) + ; false + ). + write_term(Term, Options) :- '$skip_max_list'(_, -1, Options, Options0), - ( Options0 == [] -> true - ; throw(error(type_error(list, Options), write_term/2)) ), % 8.14.2.3 c) + ( Options0 == [] -> true + ; throw(error(type_error(list, Options), write_term/2)) + ), % 8.14.2.3 c) inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)), inst_member_or(Options, numbervars(NumberVars), numbervars(false)), inst_member_or(Options, quoted(Quoted), quoted(false)), diff --git a/src/prolog/lib/dif.pl b/src/prolog/lib/dif.pl index 75dd8a17..15508363 100644 --- a/src/prolog/lib/dif.pl +++ b/src/prolog/lib/dif.pl @@ -1,16 +1,13 @@ :- module(dif, [dif/2]). :- use_module(library(atts)). -:- use_module(library(ordsets)). :- attribute dif/1. put_dif_att(Var, X, Y) :- ( get_atts(Var, +dif(Z)) -> - ord_add_element(Z, X \== Y, NewZ), - ( Z == NewZ -> true - ; put_atts(Var, +dif(NewZ)) - ) + sort([X \== Y | Z], NewZ), + put_atts(Var, +dif(NewZ)) ; put_atts(Var, +dif([X \== Y])) ). diff --git a/src/prolog/machine/and_stack.rs b/src/prolog/machine/and_stack.rs index 747fc532..40318a12 100644 --- a/src/prolog/machine/and_stack.rs +++ b/src/prolog/machine/and_stack.rs @@ -1,5 +1,6 @@ use prolog::machine::machine_indices::*; +use std::mem; use std::ops::{Index, IndexMut}; use std::vec::Vec; @@ -8,7 +9,7 @@ pub struct Frame { pub global_index: usize, pub e: usize, pub cp: LocalCodePtr, - pub special_form_cp: LocalCodePtr, + pub interrupt_cp: LocalCodePtr, perms: Vec } @@ -18,7 +19,7 @@ impl Frame { global_index, e: e, cp: cp, - special_form_cp: LocalCodePtr::default(), + interrupt_cp: LocalCodePtr::default(), perms: (1 .. n+1).map(|i| Addr::StackCell(fr, i)).collect() } } @@ -36,6 +37,11 @@ impl AndStack { AndStack(Vec::new()) } + #[inline] + pub(crate) fn take(&mut self) -> Self { + AndStack(mem::replace(&mut self.0, vec![])) + } + pub fn push(&mut self, global_index: usize, e: usize, cp: LocalCodePtr, n: usize) { let len = self.0.len(); self.0.push(Frame::new(global_index, len, e, cp, n)); diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index 9301fdff..70628760 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -57,14 +57,6 @@ impl MachineState { (var_list_addr, value_list_addr) } - pub(super) - fn calculate_register_threshold(&self) -> usize { - /* for all we know, all registers might be valid when we - * return from the verify_attributes interrupt. we currently - * lack a more precise way of determining this. */ - MAX_ARITY - } - fn verify_attributes(&mut self) { for (h, _) in &self.attr_var_init.bindings { @@ -122,17 +114,17 @@ impl MachineState { pub(super) fn verify_attr_interrupt(&mut self, p: usize) { - let rs = self.calculate_register_threshold(); + let rs = MAX_ARITY; - // store temp vars in perm vars slots along with - // self.b0 and self.num_of_args. why self.bo? if we return to a - // NeckCut after finishing the interrupt, it won't - // work correctly if self.b == self.b0. we must - // change it back when we return, as if nothing happened. + // store temp vars in perm vars slots along with self.b0 and + // self.num_of_args. why self.b0? if we return to a NeckCut + // after finishing the interrupt, it won't work correctly if + // self.b == self.b0. we must change it back when we return, + // as if nothing happened. self.allocate(rs + 2); let e = self.e; - self.and_stack[e].special_form_cp = self.attr_var_init.cp; + self.and_stack[e].interrupt_cp = self.attr_var_init.cp; for i in 1 .. rs + 1 { self.and_stack[e][i] = self[RegType::Temp(i)].clone(); @@ -193,7 +185,8 @@ impl Machine { self.machine_st[temp_v!(2)] = attr_vars; self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); - self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo); + self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo, + &mut readline::input_stream()); self.machine_st.print_attribute_goals_string(var_dict) } diff --git a/src/prolog/machine/code_repo.rs b/src/prolog/machine/code_repo.rs index 23884595..dce28eaa 100644 --- a/src/prolog/machine/code_repo.rs +++ b/src/prolog/machine/code_repo.rs @@ -32,7 +32,7 @@ impl CodeRepo { term_dir: TermDir::new() } } - + #[inline] pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) { self.term_dir.get(&key) @@ -105,6 +105,8 @@ impl CodeRepo { Some(RefOrOwned::Borrowed(&self.in_situ_code[p])), &CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.code[p])), + &CodePtr::REPL(..) => + None, &CodePtr::BuiltInClause(ref built_in, _) => { let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()), built_in.arity(), diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 559985fb..b2b1af20 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -123,6 +123,7 @@ fn compile_query(terms: Vec, queue: VecDeque, flags: Machin let mut code = try!(cg.compile_query(&terms)); compile_appendix(&mut code, &queue, false, flags)?; + Ok((code, cg.take_vars())) } @@ -214,7 +215,8 @@ fn setup_module_expansions(wam: &mut Machine, module_name: ClauseName) } pub(super) -fn compile_into_module(wam: &mut Machine, module_name: ClauseName, src: R, name: ClauseName) +fn compile_into_module(wam: &mut Machine, module_name: ClauseName, + src: ParsingStream, name: ClauseName) -> EvalSession { let mut indices = default_index_store!(wam.atom_tbl_of(&name)); @@ -232,7 +234,8 @@ fn compile_into_module(wam: &mut Machine, module_name: ClauseName, src: } fn compile_into_module_impl(wam: &mut Machine, compiler: &mut ListingCompiler, - module_name: ClauseName, src: R, mut indices: IndexStore) + module_name: ClauseName, src: ParsingStream, + mut indices: IndexStore) -> Result<(), SessionError> { setup_module_expansions(wam, module_name.clone()); @@ -556,7 +559,7 @@ impl ListingCompiler { let spec = get_desc(op_decl.name(), composite_op!(self.module.is_some(), &wam_indices.op_dir, &mut indices.op_dir)); - + op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir) }, Declaration::UseModule(name) => @@ -597,12 +600,13 @@ impl ListingCompiler { } pub(crate) - fn gather_items(&mut self, wam: &mut Machine, src: R, indices: &mut IndexStore) + fn gather_items(&mut self, wam: &mut Machine, mut src: ParsingStream, + indices: &mut IndexStore) -> Result { let flags = wam.machine_flags(); let atom_tbl = indices.atom_tbl.clone(); - let mut worker = TopLevelBatchWorker::new(src, atom_tbl.clone(), flags, + let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags, &mut wam.indices, &mut wam.policies, &mut wam.code_repo); @@ -649,8 +653,8 @@ impl ListingCompiler { } } -fn compile_work(compiler: &mut ListingCompiler, wam: &mut Machine, src: R, - mut indices: IndexStore) +fn compile_work(compiler: &mut ListingCompiler, wam: &mut Machine, + src: ParsingStream, mut indices: IndexStore) -> EvalSession { let mut results = try_eval_session!(compiler.gather_items(wam, src, &mut indices)); @@ -693,7 +697,8 @@ fn compile_work(compiler: &mut ListingCompiler, wam: &mut Machine, src: /* This is a truncated version of compile_user_module, used for compiling code composing special forms, ie. the code that calls M:verify_attributes on attributed variables. */ -pub fn compile_special_form(wam: &mut Machine, src: R) -> Result +pub fn compile_special_form(wam: &mut Machine, src: ParsingStream) + -> Result { let mut indices = default_index_store!(wam.indices.atom_tbl.clone()); setup_indices(wam, clause_name!("builtins"), &mut indices)?; @@ -705,7 +710,9 @@ pub fn compile_special_form(wam: &mut Machine, src: R) -> Result(wam: &mut Machine, src: R, indices: IndexStore) -> EvalSession +pub +fn compile_listing(wam: &mut Machine, src: ParsingStream, indices: IndexStore) + -> EvalSession { let mut compiler = ListingCompiler::new(&wam.code_repo); @@ -733,7 +740,7 @@ fn setup_indices(wam: &mut Machine, module: ClauseName, indices: &mut IndexStore } } -pub fn compile_user_module(wam: &mut Machine, src: R) -> EvalSession { +pub fn compile_user_module(wam: &mut Machine, src: ParsingStream) -> EvalSession { let mut indices = default_index_store!(wam.indices.atom_tbl.clone()); try_eval_session!(setup_indices(wam, clause_name!("builtins"), &mut indices)); compile_listing(wam, src, indices) diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index 169613b4..abbb421d 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -17,7 +17,8 @@ impl Machine { } } - fn compile_into_machine(&mut self, src: R, name: ClauseName, arity: usize) -> EvalSession + fn compile_into_machine(&mut self, src: ParsingStream, name: ClauseName, arity: usize) + -> EvalSession { match name.owning_module().as_str() { "user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() { @@ -118,7 +119,7 @@ impl Machine { { let machine_st = mem::replace(&mut self.machine_st, MachineState::new()); - let result = self.compile_into_machine(pred_str.as_bytes(), name, arity); + let result = self.compile_into_machine(parsing_stream(pred_str.as_bytes()), name, arity); self.machine_st = machine_st; if let EvalSession::Error(err) = result { diff --git a/src/prolog/machine/heap.rs b/src/prolog/machine/heap.rs index b5141f08..d64654d9 100644 --- a/src/prolog/machine/heap.rs +++ b/src/prolog/machine/heap.rs @@ -2,6 +2,7 @@ use prolog_parser::ast::*; use prolog::machine::machine_indices::*; +use std::mem; use std::ops::{Index, IndexMut}; pub struct Heap { @@ -21,6 +22,17 @@ impl Heap { self.h += 1; } + #[inline] + pub(crate) fn take(&mut self) -> Self { + let h = self.h; + self.h = 0; + + Heap { + heap: mem::replace(&mut self.heap, vec![]), + h + } + } + #[inline] pub fn truncate(&mut self, h: usize) { self.h = h; diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index d69bfef6..b37fb637 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -385,8 +385,6 @@ pub enum SessionError { NamelessEntry, OpIsInfixAndPostFix(ClauseName), ParserError(ParserError), - QueryFailure, - QueryFailureWithException(ClauseName), UserPrompt } @@ -394,6 +392,7 @@ pub enum EvalSession { EntrySuccess, Error(SessionError), InitialQuerySuccess(AllocVarDict, HeapVarDict), + QueryFailure, SubsequentQuerySuccess, } diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index 00945f0d..07b1f25c 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -124,6 +124,24 @@ impl Add for Addr { } } +impl Sub for Addr { + type Output = Addr; + + fn sub(self, rhs: i64) -> Self::Output { + if rhs < 0 { + match self { + Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize), + Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize), + Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize), + Addr::Str(s) => Addr::Str(s + rhs.abs() as usize), + _ => self + } + } else { + self.sub(rhs as usize) + } + } +} + impl Sub for Addr { type Output = Addr; @@ -260,13 +278,20 @@ pub enum DynamicTransactionType { Retract // dynamic index of the clause to remove. } +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] +pub enum REPLCodePtr { + CompileBatch, + SubmitQueryAndPrintResults +} + #[derive(Clone, PartialEq)] pub enum CodePtr { BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. CallN(usize, LocalCodePtr), // arity, local. Local(LocalCodePtr), DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer. - VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir. + REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer. + VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir. } impl CodePtr { @@ -276,7 +301,8 @@ impl CodePtr { | &CodePtr::CallN(_, ref local) | &CodePtr::Local(ref local) => local.clone(), &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p), - &CodePtr::DynamicTransaction(_, p) => p + &CodePtr::REPL(_, p) + | &CodePtr::DynamicTransaction(_, p) => p } } } @@ -367,7 +393,8 @@ impl Add for CodePtr { fn add(self, rhs: usize) -> Self::Output { match self { - p @ CodePtr::VerifyAttrInterrupt(_) + p @ CodePtr::REPL(..) + | p @ CodePtr::VerifyAttrInterrupt(_) | p @ CodePtr::DynamicTransaction(..) => p, CodePtr::Local(local) => CodePtr::Local(local + rhs), CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs) @@ -412,7 +439,7 @@ pub struct IndexStore { pub(super) global_variables: GlobalVarDir, pub(super) in_situ_code_dir: InSituCodeDir, pub(super) modules: ModuleDir, - pub(super) op_dir: OpDir, + pub(super) op_dir: OpDir, } impl IndexStore { @@ -475,6 +502,7 @@ impl IndexStore { in_situ_code_dir: InSituCodeDir::new(), op_dir: default_op_dir(), modules: ModuleDir::new(), +// parsing_stream: readline::parsing_stream(String::new()) } } diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 656563c0..c6200b7e 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -12,12 +12,13 @@ use prolog::machine::machine_indices::*; use prolog::machine::modules::*; use prolog::machine::or_stack::*; use prolog::num::{BigInt, BigUint, Zero, One}; +use prolog::read::{PrologStream, readline}; use downcast::Any; use std::cmp::Ordering; -use std::io::{Write, stdin, stdout}; -use std::mem::swap; +use std::io::{Write, stdout}; +use std::mem; use std::ops::{Index, IndexMut}; use std::rc::Rc; @@ -35,6 +36,16 @@ impl Ball { self.boundary = 0; self.stub.clear(); } + + pub(super) fn take(&mut self) -> Ball { + let boundary = self.boundary; + self.boundary = 0; + + Ball { + boundary, + stub: mem::replace(&mut self.stub, vec![]) + } + } } pub(super) struct CopyTerm<'a> { @@ -88,7 +99,7 @@ pub(super) struct CopyBallTerm<'a> { and_stack: &'a mut AndStack, heap: &'a mut Heap, heap_boundary: usize, - stub: &'a mut MachineStub, + stub: &'a mut MachineStub, } impl<'a> CopyBallTerm<'a> { @@ -227,7 +238,7 @@ pub struct MachineState { pub(crate) flags: MachineFlags } -impl MachineState { +impl MachineState { fn call_at_index(&mut self, arity: usize, p: usize) { self.cp.assign_if_local(self.p.clone() + 1); @@ -518,7 +529,7 @@ pub(crate) trait CallPolicy: Any { } fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, - indices: &mut IndexStore) + indices: &mut IndexStore, parsing_stream: &mut PrologStream) -> CallResult { match ct { @@ -572,10 +583,12 @@ pub(crate) trait CallPolicy: Any { return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Read => { - match machine_st.read(stdin(), indices.atom_tbl.clone(), &indices.op_dir) { + readline::toggle_prompt(false); + + match machine_st.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) { Ok(offset) => { let addr = machine_st[temp_v!(1)].clone(); - machine_st.unify(addr, Addr::HeapCell(offset)); + machine_st.unify(addr, Addr::HeapCell(offset.heap_loc)); }, Err(e) => { let h = machine_st.heap.h; @@ -695,7 +708,8 @@ pub(crate) trait CallPolicy: Any { Ok(()) } - fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore) + fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore, + parsing_stream: &mut PrologStream) -> CallResult { if let Some((name, arity)) = machine_st.setup_call_n(arity) { @@ -711,7 +725,7 @@ pub(crate) trait CallPolicy: Any { }, ClauseType::BuiltIn(built_in) => { machine_st.setup_built_in_call(built_in.clone()); - self.call_builtin(machine_st, &built_in, indices)?; + self.call_builtin(machine_st, &built_in, indices, parsing_stream)?; }, ClauseType::Inlined(inlined) => { machine_st.execute_inlined(&inlined); @@ -781,17 +795,18 @@ impl CallPolicy for CWILCallPolicy { } fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, - indices: &mut IndexStore) + indices: &mut IndexStore, parsing_stream: &mut PrologStream) -> CallResult { - self.prev_policy.call_builtin(machine_st, ct, indices)?; + self.prev_policy.call_builtin(machine_st, ct, indices, parsing_stream)?; self.increment(machine_st) } - fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore) + fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore, + parsing_stream: &mut PrologStream) -> CallResult { - self.prev_policy.call_n(machine_st, arity, indices)?; + self.prev_policy.call_n(machine_st, arity, indices, parsing_stream)?; self.increment(machine_st) } } @@ -813,7 +828,7 @@ impl CWILCallPolicy { pub(crate) fn new_in_place(policy: &mut Box) { let mut prev_policy: Box = Box::new(DefaultCallPolicy {}); - swap(&mut prev_policy, policy); + mem::swap(&mut prev_policy, policy); let new_policy = CWILCallPolicy { prev_policy, count: BigUint::zero(), @@ -870,7 +885,7 @@ impl CWILCallPolicy { pub(crate) fn into_inner(&mut self) -> Box { let mut new_inner: Box = Box::new(DefaultCallPolicy {}); - swap(&mut self.prev_policy, &mut new_inner); + mem::swap(&mut self.prev_policy, &mut new_inner); new_inner } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index a59e3f14..59c70510 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -17,9 +17,11 @@ use prolog::machine::machine_state::*; use prolog::num::{Integer, Signed, ToPrimitive, One, Zero}; use prolog::num::bigint::{BigInt, BigUint}; use prolog::num::rational::Ratio; +use prolog::read::PrologStream; use std::cmp::{max, Ordering}; use std::collections::{HashMap, HashSet}; +use std::mem; use std::rc::Rc; macro_rules! try_or_fail { @@ -65,6 +67,36 @@ impl MachineState { } } + pub(crate) fn with_capacity(capacity: usize) -> Self { + MachineState { + s: 0, + p: CodePtr::default(), + b: 0, + b0: 0, + e: 0, + num_of_args: 0, + cp: LocalCodePtr::default(), + attr_var_init: AttrVarInitializer::new(0, 0), + fail: false, + heap: Heap::with_capacity(capacity), + mode: MachineMode::Write, + and_stack: AndStack::new(), + or_stack: OrStack::new(), + registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used. + trail: vec![], + pstr_trail: vec![], + pstr_tr: 0, + tr: 0, + hb: 0, + block: 0, + ball: Ball::new(), + lifted_heap: Vec::with_capacity(capacity), + interms: vec![Number::default(); 0], + last_call: false, + flags: MachineFlags::default() + } + } + #[allow(dead_code)] pub fn print_heap(&self) { for h in 0 .. self.heap.h { @@ -182,19 +214,6 @@ impl MachineState { output } - pub(super) - fn print_exception(&self, addr: Addr, var_dict: &HeapVarDict, output: Outputter) - -> Outputter - where Outputter: HCValueOutputter - { - let mut printer = HCPrinter::from_heap_locs(&self, output, var_dict); - - printer.see_all_locs(); - printer.quoted = true; - - printer.print(addr) - } - pub(super) fn unify_strings(&mut self, pdl: &mut Vec, s1: &mut StringList, s2: &mut StringList) -> bool { @@ -1546,27 +1565,24 @@ impl MachineState { self.fail = true; } - fn heap_ball_boundary_diff(&self) -> usize { - if self.ball.boundary > self.heap.h { - self.ball.boundary - self.heap.h - } else { - self.heap.h - self.ball.boundary - } + fn heap_ball_boundary_diff(&self) -> i64 { + self.ball.boundary as i64 - self.heap.h as i64 } - pub(super) fn copy_and_align_ball_to_heap(&mut self, from: usize) -> usize { + pub(super) fn copy_and_align_ball(&self) -> MachineStub { let diff = self.heap_ball_boundary_diff(); + let mut stub = vec![]; - for index in from .. self.ball.stub.len() { + for index in 0 .. self.ball.stub.len() { let heap_value = self.ball.stub[index].clone(); - self.heap.push(match heap_value { + stub.push(match heap_value { HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff), _ => heap_value }); } - diff + stub } pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool { @@ -2363,6 +2379,7 @@ impl MachineState { fn handle_call_clause(&mut self, indices: &mut IndexStore, call_policy: &mut Box, cut_policy: &mut Box, + parsing_stream: &mut PrologStream, ct: &ClauseType, arity: usize, lco: bool, @@ -2379,9 +2396,9 @@ impl MachineState { match ct { &ClauseType::BuiltIn(ref ct) => - try_or_fail!(self, call_policy.call_builtin(self, ct, indices)), + try_or_fail!(self, call_policy.call_builtin(self, ct, indices, parsing_stream)), &ClauseType::CallN => - try_or_fail!(self, call_policy.call_n(self, arity, indices)), + try_or_fail!(self, call_policy.call_n(self, arity, indices, parsing_stream)), &ClauseType::Hook(ref hook) => try_or_fail!(self, call_policy.compile_hook(self, hook)), &ClauseType::Inlined(ref ct) => { @@ -2395,13 +2412,15 @@ impl MachineState { try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(), indices)), &ClauseType::System(ref ct) => - try_or_fail!(self, self.system_call(ct, indices, call_policy, cut_policy)) + try_or_fail!(self, self.system_call(ct, indices, call_policy, cut_policy, + parsing_stream)) }; } pub(super) fn execute_ctrl_instr(&mut self, indices: &mut IndexStore, call_policy: &mut Box, cut_policy: &mut Box, + parsing_stream: &mut PrologStream, instr: &ControlInstruction) { match instr { @@ -2409,7 +2428,8 @@ impl MachineState { self.allocate(num_cells), &ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) => self.handle_call_clause(indices, call_policy, cut_policy, - ct, arity, lco, use_default_cp), + parsing_stream, ct, arity, lco, + use_default_cp), &ControlInstruction::Deallocate => self.deallocate(), &ControlInstruction::JmpBy(arity, offset, _, lco) => { if !lco { @@ -2569,4 +2589,58 @@ impl MachineState { self.ball.reset(); self.lifted_heap.clear(); } + + pub(super) + fn sink_to_snapshot(&mut self) -> MachineState { + let mut snapshot = MachineState::with_capacity(0); + + snapshot.hb = self.hb; + snapshot.e = self.e; + snapshot.b = self.b; + snapshot.b0 = self.b0; + snapshot.s = self.s; + snapshot.tr = self.tr; + snapshot.pstr_tr = self.pstr_tr; + snapshot.num_of_args = self.num_of_args; + + snapshot.fail = self.fail; + snapshot.trail = mem::replace(&mut self.trail, vec![]); + snapshot.pstr_trail = mem::replace(&mut self.pstr_trail, vec![]); + snapshot.heap = self.heap.take(); + snapshot.mode = self.mode; + snapshot.and_stack = self.and_stack.take(); + snapshot.or_stack = self.or_stack.take(); + snapshot.registers = mem::replace(&mut self.registers, vec![]); + snapshot.block = self.block; + + snapshot.ball = self.ball.take(); + snapshot.lifted_heap = mem::replace(&mut self.lifted_heap, vec![]); + + snapshot + } + + pub(super) + fn absorb_snapshot(&mut self, mut snapshot: MachineState) { + self.hb = snapshot.hb; + self.e = snapshot.e; + self.b = snapshot.b; + self.b0 = snapshot.b0; + self.s = snapshot.s; + self.tr = snapshot.tr; + self.pstr_tr = snapshot.pstr_tr; + self.num_of_args = snapshot.num_of_args; + + self.fail = snapshot.fail; + self.trail = mem::replace(&mut snapshot.trail, vec![]); + self.pstr_trail = mem::replace(&mut snapshot.pstr_trail, vec![]); + self.heap = snapshot.heap.take(); + self.mode = snapshot.mode; + self.and_stack = snapshot.and_stack.take(); + self.or_stack = snapshot.or_stack.take(); + self.registers = mem::replace(&mut snapshot.registers, vec![]); + self.block = snapshot.block; + + self.ball = snapshot.ball.take(); + self.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]); + } } diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index cc9d6f67..c359efb5 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -6,6 +6,8 @@ use prolog::fixtures::*; use prolog::forms::*; use prolog::heap_print::*; use prolog::instructions::*; +use prolog::read::*; +use prolog::write::{ContinueResult, next_keypress}; pub mod machine_indices; pub mod heap; @@ -32,12 +34,17 @@ use prolog::machine::machine_errors::*; use prolog::machine::machine_indices::*; use prolog::machine::machine_state::*; use prolog::machine::modules::*; +use prolog::machine::toplevel::stream_to_toplevel; +use prolog::read::PrologStream; use std::collections::{HashMap, VecDeque}; +use std::io::{Read, Write, stdout}; use std::mem; use std::ops::Index; use std::rc::Rc; +use termion::raw::{IntoRawMode}; + pub struct MachinePolicies { call_policy: Box, cut_policy: Box, @@ -57,7 +64,9 @@ pub struct Machine { pub(super) machine_st: MachineState, pub(super) policies: MachinePolicies, pub(super) indices: IndexStore, - pub(super) code_repo: CodeRepo + pub(super) code_repo: CodeRepo, + pub(super) toplevel_idx: usize, + pub(super) prolog_stream: ParsingStream> } impl Index for CodeRepo { @@ -157,9 +166,11 @@ static REIF: &str = include_str!("../lib/reif.pl"); static ASSOC: &str = include_str!("../lib/assoc.pl"); static ORDSETS: &str = include_str!("../lib/ordsets.pl"); +static TOPLEVEL: &str = include_str!("../toplevel.pl"); + impl Machine { fn compile_special_forms(&mut self) { - match compile_special_form(self, VERIFY_ATTRS.as_bytes()) { + match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes())) { Ok(code) => { self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len(); self.code_repo.code.extend(code.into_iter()); @@ -167,7 +178,7 @@ impl Machine { Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS") } - match compile_special_form(self, PROJECT_ATTRS.as_bytes()) { + match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes())) { Ok(code) => { self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len(); self.code_repo.code.extend(code.into_iter()); @@ -176,37 +187,57 @@ impl Machine { } } + fn compile_top_level(&mut self) { + self.toplevel_idx = self.code_repo.code.len(); + compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes())); + } + fn compile_libraries(&mut self) { - compile_user_module(self, NON_ISO.as_bytes()); - compile_user_module(self, LISTS.as_bytes()); - compile_user_module(self, QUEUES.as_bytes()); - compile_user_module(self, ERROR.as_bytes()); - compile_user_module(self, BETWEEN.as_bytes()); - compile_user_module(self, TERMS.as_bytes()); - compile_user_module(self, DCGS.as_bytes()); - compile_user_module(self, ATTS.as_bytes()); - compile_user_module(self, ORDSETS.as_bytes()); - compile_user_module(self, DIF.as_bytes()); - compile_user_module(self, FREEZE.as_bytes()); - compile_user_module(self, REIF.as_bytes()); - compile_user_module(self, ASSOC.as_bytes()); - } - - pub fn new() -> Self { + compile_user_module(self, parsing_stream(NON_ISO.as_bytes())); + compile_user_module(self, parsing_stream(LISTS.as_bytes())); + compile_user_module(self, parsing_stream(QUEUES.as_bytes())); + compile_user_module(self, parsing_stream(ERROR.as_bytes())); + compile_user_module(self, parsing_stream(BETWEEN.as_bytes())); + compile_user_module(self, parsing_stream(TERMS.as_bytes())); + compile_user_module(self, parsing_stream(DCGS.as_bytes())); + compile_user_module(self, parsing_stream(ATTS.as_bytes())); + compile_user_module(self, parsing_stream(ORDSETS.as_bytes())); + compile_user_module(self, parsing_stream(DIF.as_bytes())); + compile_user_module(self, parsing_stream(FREEZE.as_bytes())); + compile_user_module(self, parsing_stream(REIF.as_bytes())); + compile_user_module(self, parsing_stream(ASSOC.as_bytes())); + } + + #[cfg(test)] + pub fn reset(&mut self) { + self.prolog_stream = readline::input_stream(); + self.policies.cut_policy = Box::new(DefaultCutPolicy {}); + self.machine_st.reset(); + } + + pub fn run_toplevel(&mut self) { + self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx)); + self.run_query(&AllocVarDict::new(), &mut HeapVarDict::new()); + } + + pub fn new(prolog_stream: PrologStream) -> Self { let mut wam = Machine { machine_st: MachineState::new(), policies: MachinePolicies::new(), indices: IndexStore::new(), - code_repo: CodeRepo::new() + code_repo: CodeRepo::new(), + toplevel_idx: 0, + prolog_stream }; let atom_tbl = wam.indices.atom_tbl.clone(); - compile_listing(&mut wam, BUILTINS.as_bytes(), + compile_listing(&mut wam, parsing_stream(BUILTINS.as_bytes()), default_index_store!(atom_tbl.clone())); wam.compile_libraries(); wam.compile_special_forms(); + wam.compile_top_level(); wam } @@ -251,7 +282,7 @@ impl Machine { Ok(()) } - + pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) { // error detection has finished, so update the master index of keys. @@ -283,33 +314,15 @@ impl Machine { self.code_repo.code.extend(code.into_iter()); } - fn fail(&mut self) -> EvalSession - { - if self.machine_st.ball.stub.len() > 0 { - let h = self.machine_st.heap.h; - self.machine_st.copy_and_align_ball_to_heap(0); - - let err_str = self.machine_st.print_exception(Addr::HeapCell(h), - &HeapVarDict::new(), - PrinterOutputter::new()) - .result(); - - let err_str = clause_name!(err_str, self.indices.atom_tbl()); - EvalSession::from(SessionError::QueryFailureWithException(err_str)) - } else { - EvalSession::from(SessionError::QueryFailure) - } - } - pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession { - let mut heap_locs = HashMap::new(); + let mut heap_locs = HeapVarDict::new(); self.code_repo.cached_query = code; self.run_query(&alloc_locs, &mut heap_locs); if self.machine_st.fail { - self.fail() + EvalSession::QueryFailure } else { EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) } @@ -341,6 +354,194 @@ impl Machine { } } + pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) { + let h = self.machine_st.heap.h; + + let err = MachineError::session_error(h, err); + let stub = MachineError::functor_stub(key.0, key.1); + let err = self.machine_st.error_form(err, stub); + + self.machine_st.throw_exception(err); + return; + } + + fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) + { + match code_ptr { + REPLCodePtr::CompileBatch => { + #[cfg(feature = "readline_rs_compat")] + readline::set_line_mode(readline::LineMode::Multi); + + let src = match readline::read_batch("") { + Ok(src) => src, + Err(e) => { + self.throw_session_error(e, (clause_name!("repl"), 0)); + return; + } + }; + + #[cfg(feature = "readline_rs_compat")] + readline::set_line_mode(readline::LineMode::Single); + + match compile_user_module(self, parsing_stream(&src[0 ..])) { + EvalSession::Error(e) => + self.throw_session_error(e, (clause_name!("repl"), 0)), + _ => {} + }; + }, + REPLCodePtr::SubmitQueryAndPrintResults => { + let term = self.machine_st[temp_v!(1)].clone(); + let stub = MachineError::functor_stub(clause_name!("repl"), 0); + + let s = match self.machine_st.try_from_list(temp_v!(2), stub) { + Ok(addrs) => { + let mut var_dict = HeapVarDict::new(); + + for addr in addrs { + match addr { + Addr::Str(s) => { + let var_atom = match self.machine_st.heap[s+1].as_addr(s+1) { + Addr::Con(Constant::Atom(var_atom, _)) => + Rc::new(var_atom.to_string()), + _ => unreachable!() + }; + + let var_addr = self.machine_st.heap[s+2].as_addr(s+2); + var_dict.insert(var_atom, var_addr); + }, + _ => unreachable!() + }; + } + + let term_output = self.machine_st.print_with_locs(term, &var_dict); + term_output.result() + }, + Err(err_stub) => { + self.machine_st.throw_exception(err_stub); + return; + } + }; + + let stream = parsing_stream(s.as_bytes()); + + let snapshot = self.machine_st.sink_to_snapshot(); + self.machine_st.reset(); + + let result = match stream_to_toplevel(stream, self) { + Ok(packet) => compile_term(self, packet), + Err(e) => EvalSession::from(e) + }; + + self.handle_eval_session(result, snapshot); + } + } + + self.machine_st.p = CodePtr::Local(p); + } + + fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) { + match result { + EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => + loop { + let bindings = { + let mut output = PrinterOutputter::new(); + self.toplevel_heap_view(&heap_locs, output).result() + }; + + let attr_goals = self.attribute_goals(&heap_locs); + + if !(self.machine_st.b > 0) { + if bindings.is_empty() { + if !attr_goals.is_empty() { + println!("{}.", attr_goals); + } else { + println!("true."); + } + + self.machine_st.absorb_snapshot(snapshot); + return; + } + } else if bindings.is_empty() && attr_goals.is_empty() { + print!("true"); + stdout().flush().unwrap(); + } + + let mut raw_stdout = stdout().into_raw_mode().unwrap(); + + if !attr_goals.is_empty() { + if bindings.is_empty() { + write!(raw_stdout, "{}", attr_goals).unwrap(); + } else { + write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap(); + } + } else if !bindings.is_empty() { + write!(raw_stdout, "{}", bindings).unwrap(); + } + + if self.machine_st.b > 0 { + raw_stdout.flush().unwrap(); + + let result = match next_keypress(raw_stdout) { + ContinueResult::ContinueQuery => + self.continue_query(&alloc_locs, &mut heap_locs), + ContinueResult::Conclude => { + self.machine_st.absorb_snapshot(snapshot); + return; + } + }; + + let mut raw_stdout = stdout().into_raw_mode().unwrap(); + + match result { + EvalSession::QueryFailure => { + write!(raw_stdout, "false.\r\n").unwrap(); + raw_stdout.flush().unwrap(); + + self.machine_st.absorb_snapshot(snapshot); + return; + }, + EvalSession::Error(err) => { + self.machine_st.absorb_snapshot(snapshot); + self.throw_session_error(err, (clause_name!("repl"), 0)); + return; + }, + _ => {} + } + } else { + if bindings.is_empty() && attr_goals.is_empty() { + write!(raw_stdout, "true.\r\n").unwrap(); + } else { + write!(raw_stdout, ".\r\n").unwrap(); + } + + break; + } + }, + EvalSession::Error(err) => { + self.machine_st.absorb_snapshot(snapshot); + self.throw_session_error(err, (clause_name!("repl"), 0)); + return; + }, + EvalSession::QueryFailure => + if self.machine_st.ball.stub.len() > 0 { + let ball = self.machine_st.ball.take(); + + self.machine_st.absorb_snapshot(snapshot); + self.machine_st.ball = ball; + + let stub = self.machine_st.copy_and_align_ball(); + self.machine_st.throw_exception(stub); + + return; + } else { + println!("false."); + }, + _ => {} + } + + self.machine_st.absorb_snapshot(snapshot); + } + pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict) { @@ -359,10 +560,13 @@ impl Machine { self.machine_st.p = top_level_code_ptr!(cn, p); } - self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo); + self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo, + &mut self.prolog_stream); match self.machine_st.p { CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}, + CodePtr::REPL(code_ptr, p) => + self.handle_toplevel_command(code_ptr, p), CodePtr::DynamicTransaction(trans_type, p) => { // self.code_repo.cached_query is about to be overwritten by the term expander, // so hold onto it locally and restore it after the compiler has finished. @@ -399,21 +603,22 @@ impl Machine { self.machine_st.p = self.machine_st.or_stack[b].bp.clone(); if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p { - return EvalSession::from(SessionError::QueryFailure); + self.machine_st.fail = true; + return EvalSession::QueryFailure; } self.run_query(alloc_l, heap_l); if self.machine_st.fail { - self.fail() + EvalSession::QueryFailure } else { EvalSession::SubsequentQuerySuccess } } else { - EvalSession::from(SessionError::QueryFailure) + EvalSession::QueryFailure } } - + pub fn toplevel_heap_view(&self, var_dir: &HeapVarDict, mut output: Outputter) -> Outputter where Outputter: HCValueOutputter { @@ -422,11 +627,6 @@ impl Machine { for (var, addr) in sorted_vars { let addr = self.machine_st.store(self.machine_st.deref(addr.clone())); - -// if addr.is_ref() { -// continue; -// } - output = self.machine_st.print_var_eq(var.clone(), addr, var_dir, output); } @@ -450,22 +650,12 @@ impl Machine { pub fn or_stack_is_empty(&self) -> bool { self.machine_st.b == 0 } - - pub fn clear(&mut self) { - let mut machine = Machine::new(); - mem::swap(self, &mut machine); - } - - pub fn reset(&mut self) { - self.policies.cut_policy = Box::new(DefaultCutPolicy {}); - self.machine_st.reset(); - } } impl MachineState { fn execute_instr(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, - code_repo: &CodeRepo) + code_repo: &CodeRepo, prolog_stream: &mut PrologStream) { let instr = match code_repo.lookup_instr(self.last_call, &self.p) { Some(instr) => instr, @@ -481,7 +671,8 @@ impl MachineState { self.execute_cut_instr(cut_instr, &mut policies.cut_policy), &Line::Control(ref control_instr) => self.execute_ctrl_instr(indices, &mut policies.call_policy, - &mut policies.cut_policy, control_instr), + &mut policies.cut_policy, prolog_stream, + control_instr), &Line::Fact(ref fact_instr) => { self.execute_fact_instr(&fact_instr); self.p += 1; @@ -516,10 +707,10 @@ impl MachineState { } fn query_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, - code_repo: &mut CodeRepo) + code_repo: &mut CodeRepo, prolog_stream: &mut PrologStream) { loop { - self.execute_instr(indices, policies, code_repo); + self.execute_instr(indices, policies, code_repo, prolog_stream); if self.fail { self.backtrack(); @@ -538,7 +729,7 @@ impl MachineState { self.fail = true, CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) if p < code_repo.in_situ_code.len() => {}, - CodePtr::Local(_) => + CodePtr::Local(_) | CodePtr::REPL(..) => break, CodePtr::VerifyAttrInterrupt(p) => self.verify_attr_interrupt(p), @@ -546,7 +737,7 @@ impl MachineState { // prevent use of dynamic transactions from // succeeding in expansions. this will be toggled // back to true later. - self.fail = true; + self.fail = true; break; }, _ => {} diff --git a/src/prolog/machine/or_stack.rs b/src/prolog/machine/or_stack.rs index 4c189548..5fc9fab0 100644 --- a/src/prolog/machine/or_stack.rs +++ b/src/prolog/machine/or_stack.rs @@ -1,5 +1,6 @@ use prolog::machine::machine_indices::*; +use std::mem; use std::ops::{Index, IndexMut}; use std::vec::Vec; @@ -74,6 +75,11 @@ impl OrStack { self.0.push(Frame::new(global_index, e, cp, attr_var_init_b, b, bp, tr, pstr_tr, h, b0, n)); } + #[inline] + pub(crate) fn take(&mut self) -> Self { + OrStack(mem::replace(&mut self.0, vec![])) + } + pub fn len(&self) -> usize { self.0.len() } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index ebf42e07..de4f6e75 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -11,11 +11,12 @@ use prolog::machine::machine_state::*; use prolog::machine::toplevel::to_op_decl; use prolog::num::{FromPrimitive, ToPrimitive, Zero}; use prolog::num::bigint::{BigInt}; +use prolog::read::{PrologStream, readline}; use ref_thread_local::RefThreadLocal; use std::collections::HashSet; -use std::io::{stdout, Read, Write}; +use std::io::{stdout, Write}; use std::iter::once; use std::mem; use std::rc::Rc; @@ -201,6 +202,17 @@ impl MachineState { threshold + lh_offset + 2 } + fn repl_redirect(&mut self, repl_code_ptr: REPLCodePtr) -> CallResult { + let p = if self.last_call { + self.cp + } else { + self.p.local() + 1 + }; + + self.p = CodePtr::REPL(repl_code_ptr, p); + return Ok(()); + } + fn truncate_if_no_lifted_heap_diff(&mut self, addr_constr: AddrConstr) where AddrConstr: Fn(usize) -> Addr { @@ -301,7 +313,8 @@ impl MachineState { ct: &SystemClauseType, indices: &mut IndexStore, call_policy: &mut Box, - cut_policy: &mut Box) + cut_policy: &mut Box, + parsing_stream: &mut PrologStream) -> CallResult { match ct { @@ -498,7 +511,7 @@ impl MachineState { }, ref addr if addr.is_ref() => { let a2 = self[temp_v!(2)].clone(); - + match self.store(self.deref(a2)) { Addr::Con(Constant::CharCode(code)) => self.unify(Addr::Con(Constant::Char(code as char)), addr.clone()), @@ -542,23 +555,21 @@ impl MachineState { }; }, &SystemClauseType::GetChar => { - let c = std::io::stdin() - .bytes() - .next() - .and_then(|result| result.ok()); + readline::toggle_prompt(false); + let result = parsing_stream.next(); let a1 = self[temp_v!(1)].clone(); - - match c { - Some(c) => self.unify(Addr::Con(Constant::Char(c as char)), a1), - None => { + + match result { + Some(Ok(b)) => self.unify(Addr::Con(Constant::Char(b as char)), a1), + _ => { let stub = MachineError::functor_stub(clause_name!("get_char"), 1); let err = MachineError::representation_error(RepFlag::Character); let err = self.error_form(err, stub); return Err(err); } - } + } }, &SystemClauseType::GetModuleClause => { let module = self[temp_v!(3)].clone(); @@ -1228,6 +1239,8 @@ impl MachineState { None => panic!("remove_inference_counter: requires \\ CWILCallPolicy.") }, + &SystemClauseType::REPL(repl_code_ptr) => + return self.repl_redirect(repl_code_ptr), &SystemClauseType::ModuleRetractClause => { let p = self.cp; let trans_type = DynamicTransactionType::ModuleRetract; @@ -1249,7 +1262,6 @@ impl MachineState { }, &SystemClauseType::ReturnFromVerifyAttr => { let e = self.e; - let frame_len = self.and_stack[e].len(); for i in 1 .. frame_len - 1 { @@ -1264,7 +1276,7 @@ impl MachineState { self.num_of_args = num_of_args; } - self.p = CodePtr::Local(self.and_stack[e].special_form_cp); + self.p = CodePtr::Local(self.and_stack[e].interrupt_cp); self.deallocate(); return Ok(()); @@ -1334,7 +1346,8 @@ impl MachineState { let h = self.heap.h; if self.ball.stub.len() > 0 { - self.copy_and_align_ball_to_heap(0); + let stub = self.copy_and_align_ball(); + self.heap.append(stub); } else { self.fail = true; return Ok(()); @@ -1391,6 +1404,51 @@ impl MachineState { &SystemClauseType::InstallNewBlock => { self.install_new_block(temp_v!(1)); }, + &SystemClauseType::ReadTerm => { + readline::toggle_prompt(true); + + match self.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) { + Ok(term_write_result) => { + let a1 = self[temp_v!(1)].clone(); + self.unify(Addr::HeapCell(term_write_result.heap_loc), a1); + + if self.fail { + return Ok(()); + } + + let mut list_of_var_eqs = vec![]; + + for (var, binding) in term_write_result.var_dict { + let var_atom = clause_name!(var.to_string(), indices.atom_tbl); + let var_atom = Constant::Atom(var_atom, None); + + let h = self.heap.h; + let op_desc = Some(SharedOpDesc::new(700, XFX)); + + self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), op_desc)); + self.heap.push(HeapCellValue::Addr(Addr::Con(var_atom))); + self.heap.push(HeapCellValue::Addr(binding)); + + list_of_var_eqs.push(Addr::Str(h)); + } + + let a2 = self[temp_v!(2)].clone(); + let list_offset = Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter())); + + self.unify(list_offset, a2); + }, + Err(err) => { + // reset the input stream after an input failure. + *parsing_stream = readline::input_stream(); + + let h = self.heap.h; + let syntax_error = MachineError::syntax_error(h, err); + let stub = MachineError::functor_stub(clause_name!("read_term"), 2); + + return Err(self.error_form(syntax_error, stub)); + } + } + }, &SystemClauseType::ResetBlock => { let addr = self.deref(self[temp_v!(1)].clone()); self.reset_block(addr); @@ -1414,43 +1472,19 @@ impl MachineState { &SystemClauseType::Succeed => {}, &SystemClauseType::TermVariables => { let a1 = self[temp_v!(1)].clone(); - let mut vars = Vec::new(); - - { - let iter = self.acyclic_pre_order_iter(a1); - - for item in iter { - match item { - HeapCellValue::Addr(Addr::AttrVar(h)) => - vars.push(Ref::AttrVar(h)), - HeapCellValue::Addr(Addr::HeapCell(h)) => - vars.push(Ref::HeapCell(h)), - HeapCellValue::Addr(Addr::StackCell(fr, sc)) => - vars.push(Ref::StackCell(fr, sc)), - _ => {} - } - } - } - - let mut h = self.heap.h; - let outcome = Addr::HeapCell(h); - let mut seen_vars = HashSet::new(); - for r in vars { - if seen_vars.contains(&r) { - continue; + for item in self.acyclic_pre_order_iter(a1) { + match item { + HeapCellValue::Addr(addr) => + if addr.is_ref() { + seen_vars.insert(addr); + }, + _ => {} } - - self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1))); - self.heap.push(HeapCellValue::Addr(r.as_addr())); - - h += 2; - - seen_vars.insert(r); } - self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList))); + let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); let a2 = self[temp_v!(2)].clone(); self.unify(a2, outcome); diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index d94569fb..72999709 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -4,7 +4,6 @@ use prolog_parser::parser::*; use prolog::machine::*; use prolog::machine::machine_indices::HeapCellValue; use prolog::num::*; -use prolog::read::*; use std::cell::Cell; use std::collections::VecDeque; @@ -74,7 +73,7 @@ pub struct TermStream<'a, R: Read> { pub(crate) indices: &'a mut IndexStore, policies: &'a mut MachinePolicies, pub(crate) code_repo: &'a mut CodeRepo, - parser: Parser, + parser: Parser<'a, R>, in_module: bool, pub(crate) flags: MachineFlags, term_expansion_lens: (usize, usize), @@ -111,7 +110,7 @@ impl<'a, R: Read> Drop for TermStream<'a, R> { } impl<'a, R: Read> TermStream<'a, R> { - pub fn new(src: R, atom_tbl: TabledData, flags: MachineFlags, + pub fn new(src: &'a mut ParsingStream, atom_tbl: TabledData, flags: MachineFlags, indices: &'a mut IndexStore, policies: &'a mut MachinePolicies, code_repo: &'a mut CodeRepo) -> Self @@ -129,6 +128,11 @@ impl<'a, R: Read> TermStream<'a, R> { } } + #[inline] + pub fn add_to_top(&mut self, buf: &str) { + self.parser.add_to_top(buf); + } + #[inline] pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) { match hook { @@ -185,14 +189,16 @@ impl<'a, R: Read> TermStream<'a, R> { }, Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Ok(self.stack.push(term)), - _ => Err(ParserError::ExpectedTopLevelTerm) + _ => + Err(ParserError::ExpectedTopLevelTerm) } } fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result { - let mut parser = Parser::new(term_string.trim().as_bytes(), self.parser.get_atom_tbl(), - self.flags); + let mut stream = parsing_stream(term_string.trim().as_bytes()); + let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags); + parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir)) } @@ -230,24 +236,23 @@ impl<'a, R: Read> TermStream<'a, R> { match term { Term::Clause(cell, name, mut terms, arity) => { let mut new_terms = { - let old_terms = if name.as_str() == ":-" && terms.len() == 2 { - let comma_term = *terms.pop().unwrap(); - unfold_by_str(comma_term, ",") - } else if name.as_str() == "?-" && terms.len() == 1 { - let comma_term = *terms.pop().unwrap(); - unfold_by_str(comma_term, ",") - } else { - return Ok(Term::Clause(cell, name, terms, arity)); + let old_terms = match (name.as_str(), terms.len()) { + (":-", 2) => { + let comma_term = *terms.pop().unwrap(); + unfold_by_str(comma_term, ",") + }, + ("?-", 1) => + unfold_by_str(*terms.pop().unwrap(), ","), + _ => return Ok(Term::Clause(cell, name, terms, arity)) }; self.expand_goals(machine_st, op_dir, VecDeque::from(old_terms))? }; let initial_term = new_terms.pop().unwrap(); - terms.push(Box::new(fold_by_str(new_terms.into_iter(), initial_term, clause_name!(",")))); - Ok(Term::Clause(cell, name, terms, None)) + Ok(Term::Clause(cell, name, terms, arity)) }, _ => Ok(term) @@ -302,6 +307,8 @@ impl MachineState { // style variable names will be longer than the keys of the var_dict, and therefore // not equal to any of them. printer.numbervars_offset = pow(BigInt::from(10), max_var_length) * 26; + printer.drop_toplevel_spec(); + printer.see_all_locs(); let mut output = printer.print(addr); @@ -324,7 +331,7 @@ impl MachineState { let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)]; code_repo.cached_query = code; - self.query_stepper(indices, policies, code_repo); + self.query_stepper(indices, policies, code_repo, &mut readline::input_stream()); if self.fail { self.reset(); diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index 0b2ba52e..65ed9c9a 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -681,6 +681,18 @@ impl RelationWorker { } } + fn try_term_to_query(&mut self, indices: &mut CompositeIndices, terms: Vec>, blocks_cuts: bool) + -> Result + { + match setup_declaration(terms.iter().cloned().collect()) { + Ok(Declaration::Op(..)) => {}, // this is now a predicate call in the query context. + Ok(decl) => return Ok(TopLevel::Declaration(decl)), + _ => {} + }; + + Ok(TopLevel::Query(self.setup_query(indices, terms, blocks_cuts)?)) + } + fn try_term_to_tl(&mut self, indices: &mut CompositeIndices, term: Term, blocks_cuts: bool) -> Result { @@ -692,13 +704,7 @@ impl RelationWorker { Ok(TopLevel::Declaration(Declaration::Hook(hook, clause, queue))) } else if name.as_str() == "?-" { - match setup_declaration(terms.iter().cloned().collect()) { - Ok(Declaration::Op(..)) => {}, // this is now a predicate call in the query context. - Ok(decl) => return Ok(TopLevel::Declaration(decl)), - _ => {} - }; - - Ok(TopLevel::Query(self.setup_query(indices, terms, blocks_cuts)?)) + self.try_term_to_query(indices, terms, blocks_cuts) } else if name.as_str() == ":-" && terms.len() == 2 { Ok(TopLevel::Rule(self.setup_rule(indices, terms, blocks_cuts, true)?)) } else if name.as_str() == ":-" && terms.len() == 1 { @@ -770,21 +776,24 @@ fn term_to_toplevel(term_stream: &mut TermStream, code_dir: &mut CodeDir, let mut indices = composite_indices!(false, term_stream.indices, code_dir); let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?; + Ok((tl, rel_worker)) } pub -fn string_to_toplevel(buffer: R, wam: &mut Machine) -> Result +fn stream_to_toplevel(mut buffer: ParsingStream, wam: &mut Machine) + -> Result { - let mut term_stream = TermStream::new(buffer, wam.indices.atom_tbl(), + let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(), wam.machine_flags(), &mut wam.indices, &mut wam.policies, &mut wam.code_repo); + term_stream.add_to_top("?- "); + let term = term_stream.read_term(&OpDir::new())?; let mut code_dir = CodeDir::new(); let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term)?; - rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?; let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir); @@ -804,7 +813,8 @@ pub struct TopLevelBatchWorker<'a, R: Read> { } impl<'a, R: Read> TopLevelBatchWorker<'a, R> { - pub fn new(inner: R, atom_tbl: TabledData, + + pub fn new(inner: &'a mut ParsingStream, atom_tbl: TabledData, flags: MachineFlags, indices: &'a mut IndexStore, policies: &'a mut MachinePolicies, code_repo: &'a mut CodeRepo) -> Self diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 15064868..88087136 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -4,7 +4,6 @@ use prolog_parser::tabled_rc::TabledData; use prolog::forms::*; use prolog::iterators::*; -use prolog::machine::machine_errors::*; use prolog::machine::machine_indices::*; use prolog::machine::machine_state::MachineState; @@ -24,16 +23,14 @@ impl<'a> TermRef<'a> { } } -pub enum Input { - Clear, - Batch, - TermString(String) -} +pub type PrologStream = ParsingStream>; #[cfg(feature = "readline_rs_compat")] pub mod readline { + use prolog_parser::ast::*; use readline_rs_compat::readline::*; + use std::io::{Error, Read}; #[derive(Clone, Copy)] pub enum LineMode { @@ -41,9 +38,74 @@ pub mod readline Multi } + pub struct ReadlineStream { + pending_input: String + } + + impl ReadlineStream { + #[inline] + fn new(pending_input: String) -> Self { + ReadlineStream { pending_input } + } + + fn call_readline(&mut self, prompt: &str, buf: &mut [u8]) -> std::io::Result { + match readline_rl(prompt) { + Some(text) => { + self.pending_input += &text; + Ok(self.write_to_buf(buf)) + }, + None => Err(Error::last_os_error()) + } + } + + fn split_pending(&mut self, buf: &mut [u8], split_idx: usize) -> usize { + let (outgoing, _) = self.pending_input.split_at(split_idx); + + for (idx, b) in outgoing.bytes().enumerate() { + buf[idx] = b; + } + + outgoing.len() + } + + fn write_to_buf(&mut self, buf: &mut [u8]) -> usize { + let split_idx = std::cmp::min(self.pending_input.len(), buf.len()); + let output_len = self.split_pending(buf, split_idx); + + if split_idx < self.pending_input.len() { + self.pending_input = self.pending_input[split_idx ..].to_string(); + } else { + self.pending_input.clear(); + } + + output_len + } + } + + impl Read for ReadlineStream { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + if self.pending_input.is_empty() { + let prompt = unsafe { + if PRINT_PROMPT { "?- " } else { "" } + }; + + self.call_readline(prompt, buf) + } else { + Ok(self.write_to_buf(buf)) + } + } + } + + static mut PRINT_PROMPT: bool = true; static mut LINE_MODE: LineMode = LineMode::Single; static mut END_OF_LINE: bool = false; + pub fn toggle_prompt(on_or_off: bool) { + unsafe { + PRINT_PROMPT = on_or_off; + } + } + pub fn set_line_mode(mode: LineMode) { unsafe { LINE_MODE = mode; @@ -52,13 +114,6 @@ pub mod readline } } - fn is_directive(buf: &str) -> bool { - match buf { - "?- [user]." | "?- [clear]." => true, - _ => false - } - } - unsafe extern "C" fn bind_end_chord(_: i32, _: i32) -> i32 { if let LineMode::Multi = LINE_MODE { rl_done = 1; @@ -67,26 +122,9 @@ pub mod readline 0 } - unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 { - insert_text_rl("."); - - if let LineMode::Single = LINE_MODE { - END_OF_LINE = true; - } - - 0 - } - unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 { - if END_OF_LINE { - if let Some(buf) = rl_line_buffer_as_str() { - if is_directive(buf) { - println!(""); - rl_done = 1; - return 0; - } - } - + if let LineMode::Single = LINE_MODE { + insert_text_rl("\n"); println!(""); rl_done = 1; } else { @@ -103,24 +141,11 @@ pub mod readline panic!("initialize_rl() failed with return code {}", rc); } - unsafe { - rl_startup_hook = insert_query_prompt; - } - - bind_key_rl('.' as i32, bind_end_key); bind_key_rl('\n' as i32, bind_cr); bind_key_rl('\r' as i32, bind_cr); bind_keyseq_rl("\\C-d", bind_end_chord); } - unsafe extern "C" fn insert_query_prompt() -> i32 { - if let LineMode::Single = LINE_MODE { - insert_text_rl("?- "); - } - - 0 - } - pub fn read_batch(prompt: &str) -> Result, ::SessionError> { match readline_rl(prompt) { Some(input) => Ok(Vec::from(input.as_bytes())), @@ -128,18 +153,41 @@ pub mod readline } } - pub fn read_line(prompt: &str) -> Result { - match readline_rl(prompt) { - Some(input) => Ok(String::from(input)), - None => Err(::SessionError::UserPrompt) - } + #[inline] + pub fn input_stream() -> ::PrologStream { + let reader: Box = Box::new(ReadlineStream::new(String::from(""))); + parsing_stream(reader) } } #[cfg(not(feature = "readline_rs_compat"))] pub mod readline { - use std::io::{BufRead, Read, stdin, stdout, Write}; + use prolog_parser::ast::*; + use std::io::{BufReader, Read, Stdin, Write, stdin, stdout}; + + static mut PRINT_PROMPT: bool = false; + + struct StdinWrapper { + buf: BufReader + } + + fn print_prompt() { + unsafe { + if PRINT_PROMPT { + print!("?- "); + stdout().flush().unwrap(); + PRINT_PROMPT = false; + } + } + } + + impl Read for StdinWrapper { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + print_prompt(); + self.buf.read(buf) + } + } pub fn read_batch(_: &str) -> Result, ::SessionError> { let mut buf = vec![]; @@ -153,54 +201,30 @@ pub mod readline } } - pub fn read_line(_: &str) -> Result { - print!("?- "); - stdout().flush().unwrap(); - - let stdin = stdin(); - let stdin = stdin.lock(); + #[inline] + pub fn input_stream() -> ::PrologStream { + print_prompt(); - let mut buf = "?- ".to_string(); + let reader: Box = Box::new(StdinWrapper { buf: BufReader::new(stdin()) }); + parsing_stream(reader) + } - for line in stdin.lines() { - match line { - Ok(line) => { - buf += &line; - if line.trim().ends_with(".") { - break; - } - }, - _ => return Err(::SessionError::UserPrompt) - } + pub fn toggle_prompt(on_or_off: bool) { + unsafe { + PRINT_PROMPT = on_or_off; } - - Ok(buf) } } -pub fn toplevel_read_line() -> Result -{ - let buffer = readline::read_line("")?; - - Ok(match &*buffer.trim() { - "?- [clear]." => Input::Clear, - "?- [user]." => { - println!("(type Enter + Ctrl-D to terminate the stream when finished)"); - Input::Batch - }, - _ => Input::TermString(buffer) - }) -} - impl MachineState { - pub fn read(&mut self, inner: R, atom_tbl: TabledData, op_dir: &OpDir) - -> Result + pub fn read(&mut self, inner: &mut PrologStream, atom_tbl: TabledData, op_dir: &OpDir) + -> Result { let mut parser = Parser::new(inner, atom_tbl, self.flags); let term = parser.read_term(composite_op!(op_dir))?; - Ok(write_term_to_heap(&term, self).heap_loc) + Ok(write_term_to_heap(&term, self)) } } @@ -220,12 +244,13 @@ fn modify_head_of_queue(machine_st: &mut MachineState, queue: &mut SubtermDeque, } } -pub(crate) struct TermWriteResult { +pub struct TermWriteResult { pub(crate) heap_loc: usize, pub(crate) var_dict: HeapVarDict, } -pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult +pub(crate) +fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult { let heap_loc = machine_st.heap.h; diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl new file mode 100644 index 00000000..55a044d7 --- /dev/null +++ b/src/prolog/toplevel.pl @@ -0,0 +1,19 @@ +repl :- + catch(read_and_match, E, '$print_exception'(E)), + false. %% this is for GC, until we get actual GC. +repl :- repl. + +read_and_match :- + read_term(Term, [variable_names(VarList)]), + '$instruction_match'(Term, VarList). + +'$instruction_match'([user], []) :- + !, '$compile_batch'. +'$instruction_match'(Term, VarList) :- + '$submit_query_and_print_results'(Term, VarList), + !. + +'$print_exception'(E) :- + write_term('error: exception thrown: ', [quoted(false)]), + writeq(E), + nl. diff --git a/src/prolog/write.rs b/src/prolog/write.rs index cc83ad03..682e7e03 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -1,22 +1,16 @@ use prolog::clause_types::*; use prolog::forms::*; -use prolog::heap_print::*; use prolog::instructions::*; -use prolog::machine::*; use prolog::machine::machine_errors::*; use prolog::machine::machine_indices::*; -use termion::raw::{IntoRawMode, RawTerminal}; use termion::input::TermRead; use termion::event::Key; +use termion::raw::{RawTerminal}; -use std::io::{Write, stdin, stdout}; +use std::io::{Write, stdin}; use std::fmt; -fn error_string>(e: &StringT) -> String { - format!("error: exception thrown: {}", e.as_ref()) -} - impl fmt::Display for LocalCodePtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -34,6 +28,17 @@ impl fmt::Display for LocalCodePtr { } } +impl fmt::Display for REPLCodePtr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + REPLCodePtr::CompileBatch => + write!(f, "REPLCodePtr::CompileBatch"), + REPLCodePtr::SubmitQueryAndPrintResults => + write!(f, "REPLCodePtr::SubmitQueryAndPrintResults") + } + } +} + impl fmt::Display for IndexPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -262,10 +267,6 @@ impl fmt::Display for SessionError { &SessionError::ModuleNotFound => write!(f, "module not found."), &SessionError::ModuleDoesNotContainExport => write!(f, "module does not contain claimed export."), - &SessionError::QueryFailure => - write!(f, "false."), - &SessionError::QueryFailureWithException(ref e) => - write!(f, "{}", error_string(e)), &SessionError::OpIsInfixAndPostFix(_) => write!(f, "cannot define an op to be both postfix and infix."), &SessionError::NamelessEntry => @@ -302,7 +303,7 @@ impl fmt::Display for ArithmeticInstruction { &ArithmeticInstruction::Pow(ref a1, ref a2, ref t) => write!(f, "** {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::IntPow(ref a1, ref a2, ref t) => - write!(f, "^ {}, {}, @{}", a1, a2, t), + write!(f, "^ {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::Div(ref a1, ref a2, ref t) => write!(f, "div {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::IDiv(ref a1, ref a2, ref t) => @@ -357,12 +358,13 @@ impl fmt::Display for Level { } } -enum ContinueResult { +pub enum ContinueResult { ContinueQuery, Conclude } -fn next_step(mut stdout: RawTerminal) -> ContinueResult +pub +fn next_keypress(mut stdout: RawTerminal) -> ContinueResult { let stdin = stdin(); @@ -382,81 +384,3 @@ fn next_step(mut stdout: RawTerminal) -> ContinueResult ContinueResult::Conclude } - -pub fn print(wam: &mut Machine, result: EvalSession) { - match result { - EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => - loop { - let bindings = { - let mut output = PrinterOutputter::new(); - wam.toplevel_heap_view(&heap_locs, output).result() - }; - - let attr_goals = wam.attribute_goals(&heap_locs); - - if wam.or_stack_is_empty() { - if bindings.is_empty() { - if !attr_goals.is_empty() { - println!("{}.", attr_goals); - } else { - println!("true."); - } - - return; - } - } else if bindings.is_empty() && attr_goals.is_empty() { - print!("true"); - stdout().flush().unwrap(); - } - - let mut raw_stdout = stdout().into_raw_mode().unwrap(); - - if !attr_goals.is_empty() { - if bindings.is_empty() { - write!(raw_stdout, "{}", attr_goals).unwrap(); - } else { - write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap(); - } - } else if !bindings.is_empty() { - write!(raw_stdout, "{}", bindings).unwrap(); - } - - if !wam.or_stack_is_empty() { - raw_stdout.flush().unwrap(); - - let result = match next_step(raw_stdout) { - ContinueResult::ContinueQuery => - wam.continue_query(&alloc_locs, &mut heap_locs), - ContinueResult::Conclude => - return - }; - - let mut raw_stdout = stdout().into_raw_mode().unwrap(); - - if let &EvalSession::Error(SessionError::QueryFailure) = &result - { - write!(raw_stdout, "false.\r\n").unwrap(); - raw_stdout.flush().unwrap(); - return; - } - - if let &EvalSession::Error(SessionError::QueryFailureWithException(ref e)) = &result - { - write!(raw_stdout, "{}\r\n", error_string(e)).unwrap(); - raw_stdout.flush().unwrap(); - return; - } - } else { - if bindings.is_empty() && attr_goals.is_empty() { - write!(raw_stdout, "true.\r\n").unwrap(); - } else { - write!(raw_stdout, ".\r\n").unwrap(); - } - - break; - } - }, - EvalSession::Error(e) => println!("{}", e), - _ => {} - }; -} diff --git a/src/tests.rs b/src/tests.rs index 9f3a2eca..f6d788ff 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,9 +1,12 @@ +use prolog_parser::ast::parsing_stream; + use prolog::heap_print::*; use prolog::machine::*; use prolog::machine::compile::*; use prolog::machine::machine_errors::*; use prolog::machine::machine_indices::*; use prolog::machine::toplevel::*; +use prolog::read::readline; use std::collections::HashSet; use std::mem::swap; @@ -133,7 +136,7 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool { wam.reset(); - match compile_user_module(wam, buffer.as_bytes()) { + match submit_code(wam, buffer) { EvalSession::InitialQuerySuccess(_, _) | EvalSession::EntrySuccess | EvalSession::SubsequentQuerySuccess => @@ -147,7 +150,7 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec { wam.reset(); - match string_to_toplevel(buffer.as_bytes(), wam) { + match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => @@ -164,7 +167,7 @@ pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool { wam.reset(); - match string_to_toplevel(buffer.as_bytes(), wam) { + match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(..) @@ -182,7 +185,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str, { wam.reset(); - match string_to_toplevel(buffer.as_bytes(), wam) { + match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) { Ok(term) => match compile_term(wam, term) { EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => @@ -195,6 +198,11 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str, } } +#[allow(dead_code)] +pub fn submit_code(wam: &mut Machine, buf: &str) -> EvalSession { + compile_user_module(wam, parsing_stream(buf.as_bytes())) +} + #[allow(unused_macros)] macro_rules! expand_strs { ($arr:expr) => ( @@ -229,154 +237,154 @@ macro_rules! assert_prolog_success { #[test] fn test_queries_on_facts() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "p(Z, Z)."); submit(&mut wam, "clouds(are, nice)."); - assert_prolog_success!(&mut wam, "?- p(Z, Z).", [["Z = _0"]]); - assert_prolog_success!(&mut wam, "?- p(Z, z).", [["Z = z"]]); - assert_prolog_success!(&mut wam, "?- p(Z, w).", [["Z = w"]]); + assert_prolog_success!(&mut wam, "p(Z, Z).", [["Z = _0"]]); + assert_prolog_success!(&mut wam, "p(Z, z).", [["Z = z"]]); + assert_prolog_success!(&mut wam, "p(Z, w).", [["Z = w"]]); - assert_prolog_failure!(&mut wam, "?- p(z, w)."); + assert_prolog_failure!(&mut wam, "p(z, w)."); - assert_prolog_success!(&mut wam, "?- p(w, w)."); + assert_prolog_success!(&mut wam, "p(w, w)."); - assert_prolog_failure!(&mut wam, "?- clouds(Z, Z)."); + assert_prolog_failure!(&mut wam, "clouds(Z, Z)."); - assert_prolog_success!(&mut wam, "?- clouds(are, Z).", [["Z = nice"]]); - assert_prolog_success!(&mut wam, "?- clouds(Z, nice).", [["Z = are"]]); + assert_prolog_success!(&mut wam, "clouds(are, Z).", [["Z = nice"]]); + assert_prolog_success!(&mut wam, "clouds(Z, nice).", [["Z = are"]]); submit(&mut wam, "p(Z, h(Z, W), f(W))."); - assert_prolog_failure!(&mut wam, "?- p(z, h(z, z), f(w))."); - assert_prolog_success!(&mut wam, "?- p(z, h(z, w), f(w))."); - assert_prolog_success!(&mut wam, "?- p(z, h(z, W), f(w)).", [["W = w"]]); - assert_prolog_success!(&mut wam, "?- p(Z, h(Z, w), f(Z)).", [["Z = w"]]); - assert_prolog_failure!(&mut wam, "?- p(z, h(Z, w), f(Z))."); + assert_prolog_failure!(&mut wam, "p(z, h(z, z), f(w))."); + assert_prolog_success!(&mut wam, "p(z, h(z, w), f(w))."); + assert_prolog_success!(&mut wam, "p(z, h(z, W), f(w)).", [["W = w"]]); + assert_prolog_success!(&mut wam, "p(Z, h(Z, w), f(Z)).", [["Z = w"]]); + assert_prolog_failure!(&mut wam, "p(z, h(Z, w), f(Z))."); submit(&mut wam, "p(f(X), h(Y, f(a)), Y)."); - assert_prolog_success!(&mut wam, "?- p(Z, h(Z, W), f(W)).", [["W = f(a)", "Z = f(f(a))"]]); + assert_prolog_success!(&mut wam, "p(Z, h(Z, W), f(W)).", [["W = f(a)", "Z = f(f(a))"]]); } #[test] fn test_queries_on_rules() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "p(X, Y) :- q(X, Z), r(Z, Y)."); submit(&mut wam, "q(q, s)."); submit(&mut wam, "r(s, t)."); - assert_prolog_success!(&mut wam, "?- p(X, Y).", [["Y = t", "X = q"]]); - assert_prolog_success!(&mut wam, "?- p(q, t)."); - assert_prolog_failure!(&mut wam, "?- p(t, q)."); - assert_prolog_success!(&mut wam, "?- p(q, T).", [["T = t"]]); - assert_prolog_failure!(&mut wam, "?- p(t, t)."); + assert_prolog_success!(&mut wam, "p(X, Y).", [["Y = t", "X = q"]]); + assert_prolog_success!(&mut wam, "p(q, t)."); + assert_prolog_failure!(&mut wam, "p(t, q)."); + assert_prolog_success!(&mut wam, "p(q, T).", [["T = t"]]); + assert_prolog_failure!(&mut wam, "p(t, t)."); submit(&mut wam, "p(X, Y) :- q(f(f(X)), R), r(S, T)."); submit(&mut wam, "q(f(f(X)), r)."); - assert_prolog_success!(&mut wam, "?- p(X, Y).", [["X = _0", "Y = _1"]]); + assert_prolog_success!(&mut wam, "p(X, Y).", [["X = _0", "Y = _1"]]); submit(&mut wam, "q(f(f(x)), r)."); - assert_prolog_success!(&mut wam, "?- p(X, Y).", [["X = x", "Y = _1"]]); + assert_prolog_success!(&mut wam, "p(X, Y).", [["X = x", "Y = _1"]]); submit(&mut wam, "p(X, Y) :- q(X, Y), r(X, Y)."); submit(&mut wam, "q(s, t)."); submit(&mut wam, "r(X, Y) :- r(a)."); submit(&mut wam, "r(a)."); - assert_prolog_success!(&mut wam, "?- p(X, Y).", [["X = s", "Y = t"]]); - assert_prolog_failure!(&mut wam, "?- p(t, S)."); - assert_prolog_success!(&mut wam, "?- p(s, T).", [["T = t"]]); - assert_prolog_success!(&mut wam, "?- p(S, t).", [["S = s"]]); + assert_prolog_success!(&mut wam, "p(X, Y).", [["X = s", "Y = t"]]); + assert_prolog_failure!(&mut wam, "p(t, S)."); + assert_prolog_success!(&mut wam, "p(s, T).", [["T = t"]]); + assert_prolog_success!(&mut wam, "p(S, t).", [["S = s"]]); submit(&mut wam, "p(f(f(a), g(b), X), g(b), h) :- q(X, Y)."); submit(&mut wam, "q(X, Y)."); - assert_prolog_success!(&mut wam, "?- p(f(X, Y, Z), g(b), h).", + assert_prolog_success!(&mut wam, "p(f(X, Y, Z), g(b), h).", [["Z = _3", "Y = g(b)", "X = f(a)"]]); - assert_prolog_failure!(&mut wam, "?- p(f(X, g(Y), Z), g(Z), X)."); - assert_prolog_success!(&mut wam, "?- p(f(X, g(Y), Z), g(Z), h).", + assert_prolog_failure!(&mut wam, "p(f(X, g(Y), Z), g(Z), X)."); + assert_prolog_success!(&mut wam, "p(f(X, g(Y), Z), g(Z), h).", [["Z = b", "Y = b", "X = f(a)"]]); - assert_prolog_success!(&mut wam, "?- p(Z, Y, X).", + assert_prolog_success!(&mut wam, "p(Z, Y, X).", [["X = h", "Y = g(b)", "Z = f(f(a), g(b), _7)"]]); - assert_prolog_success!(&mut wam, "?- p(f(X, Y, Z), Y, h).", + assert_prolog_success!(&mut wam, "p(f(X, Y, Z), Y, h).", [["Y = g(b)", "Z = _3", "X = f(a)"]]); submit(&mut wam, "p(_, f(_, Y, _)) :- h(Y)."); submit(&mut wam, "h(y)."); - assert_prolog_success!(&mut wam, "?- p(_, f(_, Y, _)).", [["Y = y"]]); - assert_prolog_success!(&mut wam, "?- p(_, f(_, y, _))."); - assert_prolog_failure!(&mut wam, "?- p(_, f(_, z, _))."); + assert_prolog_success!(&mut wam, "p(_, f(_, Y, _)).", [["Y = y"]]); + assert_prolog_success!(&mut wam, "p(_, f(_, y, _))."); + assert_prolog_failure!(&mut wam, "p(_, f(_, z, _))."); } #[test] fn test_queries_on_predicates() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "p(X, a). p(b, X)."); - assert_prolog_success!(&mut wam, "?- p(x, Y).", [["Y = a"]]); - assert_prolog_success!(&mut wam, "?- p(X, a).", [["X = _0"], // 1st case + assert_prolog_success!(&mut wam, "p(x, Y).", [["Y = a"]]); + assert_prolog_success!(&mut wam, "p(X, a).", [["X = _0"], // 1st case ["X = b"]]); // 2nd case. - assert_prolog_success!(&mut wam, "?- p(b, X).", [["X = a"], // 1st case + assert_prolog_success!(&mut wam, "p(b, X).", [["X = a"], // 1st case ["X = _0"]]); // 2nd case. - assert_prolog_success!(&mut wam, "?- p(X, X).", [["X = a"], + assert_prolog_success!(&mut wam, "p(X, X).", [["X = a"], ["X = b"]]); - assert_prolog_success!(&mut wam, "?- p(b, a)."); - assert_prolog_failure!(&mut wam, "?- p(a, b)."); + assert_prolog_success!(&mut wam, "p(b, a)."); + assert_prolog_failure!(&mut wam, "p(a, b)."); submit(&mut wam, "p(X, Y, a). p(X, a, Y). p(X, Y, a)."); - assert_prolog_success!(&mut wam, "?- p(c, d, X).", [["X = a"], + assert_prolog_success!(&mut wam, "p(c, d, X).", [["X = a"], ["X = a"]]); - assert_prolog_success!(&mut wam, "?- p(a, a, a)."); - assert_prolog_failure!(&mut wam, "?- p(b, c, d)."); + assert_prolog_success!(&mut wam, "p(a, a, a)."); + assert_prolog_failure!(&mut wam, "p(b, c, d)."); submit(&mut wam, "p(X, a). p(X, Y) :- q(Z), p(X, X)."); - assert_prolog_success!(&mut wam, "?- p(X, Y).", [["X = _0", "Y = a"]]); - assert_prolog_success!(&mut wam, "?- p(x, a)."); - assert_prolog_success!(&mut wam, "?- p(X, a).", [["X = _0"]]); - assert_prolog_failure!(&mut wam, "?- p(X, b)."); + assert_prolog_success!(&mut wam, "p(X, Y).", [["X = _0", "Y = a"]]); + assert_prolog_success!(&mut wam, "p(x, a)."); + assert_prolog_success!(&mut wam, "p(X, a).", [["X = _0"]]); + assert_prolog_failure!(&mut wam, "p(X, b)."); submit(&mut wam, "q(z)."); - assert_prolog_success_with_limit!(&mut wam, "?- p(X, b).", [["X = a"], + assert_prolog_success_with_limit!(&mut wam, "p(X, b).", [["X = a"], ["X = a"], ["X = a"]], 3); - assert_prolog_success!(&mut wam, "?- p(x, a)."); - assert_prolog_success_with_limit!(&mut wam, "?- p(X, Y).", [["X = _0", "Y = a"], + assert_prolog_success!(&mut wam, "p(x, a)."); + assert_prolog_success_with_limit!(&mut wam, "p(X, Y).", [["X = _0", "Y = a"], ["Y = _1", "X = a"], ["Y = _1", "X = a"]], 3); submit(&mut wam, "p(X, a). p(X, Y) :- q(Y), p(X, X)."); - assert_prolog_success_with_limit!(&mut wam, "?- p(X, Y).", [["X = _0", "Y = a"], + assert_prolog_success_with_limit!(&mut wam, "p(X, Y).", [["X = _0", "Y = a"], ["Y = z", "X = a"]], 2); - assert_prolog_failure!(&mut wam, "?- p(X, b)."); + assert_prolog_failure!(&mut wam, "p(X, b)."); submit(&mut wam, "p(a, z). p(X, Y) :- q(Y), p(X, Y)."); - assert_prolog_success_with_limit!(&mut wam, "?- p(X, Y).", [["X = a", "Y = z"], + assert_prolog_success_with_limit!(&mut wam, "p(X, Y).", [["X = a", "Y = z"], ["X = a", "Y = z"]], 2); - assert_prolog_success_with_limit!(&mut wam, "?- p(X, z).", [["X = a"], + assert_prolog_success_with_limit!(&mut wam, "p(X, z).", [["X = a"], ["X = a"]], 2); - assert_prolog_success!(&mut wam, "?- p(a, z)."); - assert_prolog_success_with_limit!(&mut wam, "?- p(a, X).", [["X = z"], + assert_prolog_success!(&mut wam, "p(a, z)."); + assert_prolog_success_with_limit!(&mut wam, "p(a, X).", [["X = z"], ["X = z"]], 2); - assert_prolog_failure!(&mut wam, "?- p(b, a)."); + assert_prolog_failure!(&mut wam, "p(b, a)."); submit(&mut wam, "p(X, Y, Z) :- q(X), r(Y), s(Z). p(a, b, Z) :- q(Z)."); @@ -385,10 +393,10 @@ fn test_queries_on_predicates() { submit(&mut wam, "r(y)."); submit(&mut wam, "s(z)."); - assert_prolog_success!(&mut wam, "?- p(X, Y, Z).", [["Y = y", "X = x", "Z = z"], + assert_prolog_success!(&mut wam, "p(X, Y, Z).", [["Y = y", "X = x", "Z = z"], ["Y = b", "X = a", "Z = x"]]); - assert_prolog_failure!(&mut wam, "?- p(a, b, c)."); - assert_prolog_success!(&mut wam, "?- p(a, b, C).", [["C = x"]]); + assert_prolog_failure!(&mut wam, "p(a, b, c)."); + assert_prolog_success!(&mut wam, "p(a, b, C).", [["C = x"]]); submit(&mut wam, "p(X) :- r(X)."); submit(&mut wam, "r(X) :- s(X, t). r(X) :- t(X, u)."); @@ -396,11 +404,11 @@ fn test_queries_on_predicates() { submit(&mut wam, "s(x, t)."); submit(&mut wam, "t(y, u)."); - assert_prolog_success!(&mut wam, "?- p(X).", [["X = x"], + assert_prolog_success!(&mut wam, "p(X).", [["X = x"], ["X = y"]]); - assert_prolog_success!(&mut wam, "?- p(x)."); - assert_prolog_success!(&mut wam, "?- p(y)."); - assert_prolog_failure!(&mut wam, "?- p(z)."); + assert_prolog_success!(&mut wam, "p(x)."); + assert_prolog_success!(&mut wam, "p(y)."); + assert_prolog_failure!(&mut wam, "p(z)."); submit(&mut wam, "p(f(f(X)), h(W), Y) :- g(W), h(W), f(X). p(X, Y, Z) :- h(Y), g(W), z(Z)."); @@ -409,7 +417,7 @@ fn test_queries_on_predicates() { submit(&mut wam, "f(s)."); submit(&mut wam, "z(Z)."); - assert_prolog_success!(&mut wam, "?- p(X, Y, Z).", [["Y = h(w)", "X = f(f(s))", "Z = _2"], + assert_prolog_success!(&mut wam, "p(X, Y, Z).", [["Y = h(w)", "X = f(f(s))", "Z = _2"], ["Y = h(x)", "X = f(f(s))", "Z = _2"], ["Y = h(z)", "X = f(f(s))", "Z = _2"], ["Y = w", "Z = _2", "X = _0"], @@ -424,7 +432,7 @@ fn test_queries_on_predicates() { ["Y = z", "Z = _2", "X = _0"], ["Y = z", "Z = _2", "X = _0"], ["Y = z", "Z = _2", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- p(X, X, Z).", [["Z = _1", "X = w"], + assert_prolog_success!(&mut wam, "p(X, X, Z).", [["Z = _1", "X = w"], ["Z = _1", "X = w"], ["Z = _1", "X = w"], ["Z = _1", "X = w"], @@ -436,7 +444,7 @@ fn test_queries_on_predicates() { ["Z = _1", "X = z"], ["Z = _1", "X = z"], ["Z = _1", "X = z"]]); - assert_prolog_success!(&mut wam, "?- p(f(f(Z)), Y, Z).", [["Y = h(w)", "Z = s"], + assert_prolog_success!(&mut wam, "p(f(f(Z)), Y, Z).", [["Y = h(w)", "Z = s"], ["Y = h(x)", "Z = s"], ["Y = h(z)", "Z = s"], ["Y = w", "Z = _1"], @@ -451,7 +459,7 @@ fn test_queries_on_predicates() { ["Y = z", "Z = _1"], ["Y = z", "Z = _1"], ["Y = z", "Z = _1"]]); - assert_prolog_success!(&mut wam, "?- p(X, X, X).", [["X = w"], + assert_prolog_success!(&mut wam, "p(X, X, X).", [["X = w"], ["X = w"], ["X = w"], ["X = w"], @@ -463,7 +471,7 @@ fn test_queries_on_predicates() { ["X = z"], ["X = z"], ["X = z"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y, X).", [["Y = h(w)", "X = f(f(s))"], + assert_prolog_success!(&mut wam, "p(X, Y, X).", [["Y = h(w)", "X = f(f(s))"], ["Y = h(x)", "X = f(f(s))"], ["Y = h(z)", "X = f(f(s))"], ["Y = w", "X = _0"], @@ -478,178 +486,178 @@ fn test_queries_on_predicates() { ["Y = z", "X = _0"], ["Y = z", "X = _0"], ["Y = z", "X = _0"]]); - assert_prolog_failure!(&mut wam, "?- p(f(f(X)), h(f(X)), Y)."); + assert_prolog_failure!(&mut wam, "p(f(f(X)), h(f(X)), Y)."); submit(&mut wam, "p(X) :- f(Y), g(Y), i(X, Y)."); submit(&mut wam, "g(f(a)). g(f(b)). g(f(c))."); submit(&mut wam, "f(f(a)). f(f(b)). f(f(c))."); submit(&mut wam, "i(X, X)."); - assert_prolog_success!(&mut wam, "?- p(X).", [["X = f(a)"], + assert_prolog_success!(&mut wam, "p(X).", [["X = f(a)"], ["X = f(b)"], ["X = f(c)"]]); submit(&mut wam, "p(X) :- f(f(Y)), g(Y, f(Y)), i(X, f(Y))."); submit(&mut wam, "g(Y, f(Y)) :- g(f(Y))."); - assert_prolog_success!(&mut wam, "?- p(X).", [["X = f(a)"], + assert_prolog_success!(&mut wam, "p(X).", [["X = f(a)"], ["X = f(b)"], ["X = f(c)"]]); } #[test] fn test_queries_on_cuts() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); // test shallow cuts. submit(&mut wam, "memberchk(X, [X|_]) :- !. memberchk(X, [_|Xs]) :- memberchk(X, Xs)."); - assert_prolog_success!(&mut wam, "?- memberchk(X, [a,b,c]).", [["X = a"]]); - assert_prolog_success!(&mut wam, "?- memberchk([X,X], [a,b,c,[d,e],[d,d]]).", [["X = d"]]); - assert_prolog_success!(&mut wam, "?- memberchk([X,X], [a,b,c,[D,d],[e,e]]).", [["X = d", "D = d"]]); - assert_prolog_failure!(&mut wam, "?- memberchk([X,X], [a,b,c,[e,d],[f,e]])."); - assert_prolog_failure!(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,d],[f,e]])."); - assert_prolog_success!(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,e,d],[f,e]]).", [["X = e", "Y = d"]]); + assert_prolog_success!(&mut wam, "memberchk(X, [a,b,c]).", [["X = a"]]); + assert_prolog_success!(&mut wam, "memberchk([X,X], [a,b,c,[d,e],[d,d]]).", [["X = d"]]); + assert_prolog_success!(&mut wam, "memberchk([X,X], [a,b,c,[D,d],[e,e]]).", [["X = d", "D = d"]]); + assert_prolog_failure!(&mut wam, "memberchk([X,X], [a,b,c,[e,d],[f,e]])."); + assert_prolog_failure!(&mut wam, "memberchk([X,X,Y], [a,b,c,[e,d],[f,e]])."); + assert_prolog_success!(&mut wam, "memberchk([X,X,Y], [a,b,c,[e,e,d],[f,e]]).", [["X = e", "Y = d"]]); // test deep cuts. submit(&mut wam, "commit :- a, !."); - assert_prolog_failure!(&mut wam, "?- commit."); + assert_prolog_failure!(&mut wam, "commit."); submit(&mut wam, "a."); - assert_prolog_success!(&mut wam, "?- commit."); + assert_prolog_success!(&mut wam, "commit."); submit(&mut wam, "commit(X) :- a(X), !."); - assert_prolog_failure!(&mut wam, "?- commit(X)."); + assert_prolog_failure!(&mut wam, "commit(X)."); submit(&mut wam, "a(x)."); - assert_prolog_success!(&mut wam, "?- commit(X).", [["X = x"]]); + assert_prolog_success!(&mut wam, "commit(X).", [["X = x"]]); submit(&mut wam, "a :- b, !, c. a :- d."); - assert_prolog_failure!(&mut wam, "?- a."); + assert_prolog_failure!(&mut wam, "a."); submit(&mut wam, "b."); - assert_prolog_failure!(&mut wam, "?- a."); + assert_prolog_failure!(&mut wam, "a."); submit(&mut wam, "d."); // we've committed to the first clause since the query on b // succeeds, so we expect failure here. - assert_prolog_failure!(&mut wam, "?- a."); + assert_prolog_failure!(&mut wam, "a."); submit(&mut wam, "c."); - assert_prolog_success!(&mut wam, "?- a."); + assert_prolog_success!(&mut wam, "a."); submit(&mut wam, "a(X) :- b, !, c(X). a(X) :- d(X)."); - assert_prolog_failure!(&mut wam, "?- a(X)."); + assert_prolog_failure!(&mut wam, "a(X)."); submit(&mut wam, "c(c)."); submit(&mut wam, "d(d)."); - assert_prolog_success!(&mut wam, "?- a(X).", [["X = c"]]); + assert_prolog_success!(&mut wam, "a(X).", [["X = c"]]); submit(&mut wam, "b."); - assert_prolog_success!(&mut wam, "?- a(X).", [["X = c"]]); + assert_prolog_success!(&mut wam, "a(X).", [["X = c"]]); } #[test] fn test_queries_on_lists() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "p([Z, W])."); - assert_prolog_success!(&mut wam, "?- p([Z, Z]).", [["Z = _0"]]); - assert_prolog_failure!(&mut wam, "?- p([Z, W, Y])."); - assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["Z = _0", "W = [_3]"]]); - assert_prolog_success!(&mut wam, "?- p([Z | [Z]]).", [["Z = _0"]]); - assert_prolog_success!(&mut wam, "?- p([Z | [W]]).", [["Z = _2", "W = _0"]]); - assert_prolog_failure!(&mut wam, "?- p([Z | []])."); + assert_prolog_success!(&mut wam, "p([Z, Z]).", [["Z = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z, W, Y])."); + assert_prolog_success!(&mut wam, "p([Z | W]).", [["Z = _0", "W = [_3]"]]); + assert_prolog_success!(&mut wam, "p([Z | [Z]]).", [["Z = _0"]]); + assert_prolog_success!(&mut wam, "p([Z | [W]]).", [["Z = _2", "W = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z | []])."); submit(&mut wam, "p([Z, Z])."); - assert_prolog_success!(&mut wam, "?- p([Z, Z]).", [["Z = _0"]]); - assert_prolog_failure!(&mut wam, "?- p([Z, W, Y])."); - assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["Z = _0", "W = [_0]"]]); - assert_prolog_success!(&mut wam, "?- p([Z | [Z]]).", [["Z = _0"]]); - assert_prolog_success!(&mut wam, "?- p([Z | [W]]).", [["Z = _0", "W = _0"]]); - assert_prolog_failure!(&mut wam, "?- p([Z | []])."); + assert_prolog_success!(&mut wam, "p([Z, Z]).", [["Z = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z, W, Y])."); + assert_prolog_success!(&mut wam, "p([Z | W]).", [["Z = _0", "W = [_0]"]]); + assert_prolog_success!(&mut wam, "p([Z | [Z]]).", [["Z = _0"]]); + assert_prolog_success!(&mut wam, "p([Z | [W]]).", [["Z = _0", "W = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z | []])."); submit(&mut wam, "p([Z])."); - assert_prolog_failure!(&mut wam, "?- p([Z, Z])."); - assert_prolog_failure!(&mut wam, "?- p([Z, W, Y])."); - assert_prolog_success!(&mut wam, "?- p([Z | W]).", [["W = []", "Z = _0"]]); - assert_prolog_failure!(&mut wam, "?- p([Z | [Z]])."); - assert_prolog_failure!(&mut wam, "?- p([Z | [W]])."); - assert_prolog_success!(&mut wam, "?- p([Z | []]).", [["Z = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z, Z])."); + assert_prolog_failure!(&mut wam, "p([Z, W, Y])."); + assert_prolog_success!(&mut wam, "p([Z | W]).", [["W = []", "Z = _0"]]); + assert_prolog_failure!(&mut wam, "p([Z | [Z]])."); + assert_prolog_failure!(&mut wam, "p([Z | [W]])."); + assert_prolog_success!(&mut wam, "p([Z | []]).", [["Z = _0"]]); submit(&mut wam, "member(X, [X|_]). member(X, [_|Xs]) :- member(X, Xs)."); - assert_prolog_failure!(&mut wam, "?- member(a, [c, [X, Y]])."); - assert_prolog_failure!(&mut wam, "?- member(c, [a, [X, Y]])."); - assert_prolog_success!(&mut wam, "?- member(a, [a, [X, Y]]).", [["X = _2", "Y = _0"]]); + assert_prolog_failure!(&mut wam, "member(a, [c, [X, Y]])."); + assert_prolog_failure!(&mut wam, "member(c, [a, [X, Y]])."); + assert_prolog_success!(&mut wam, "member(a, [a, [X, Y]]).", [["X = _2", "Y = _0"]]); - assert_prolog_success!(&mut wam, "?- member(a, [X, Y, Z]).", [["Y = _2", "X = a", "Z = _0"], + assert_prolog_success!(&mut wam, "member(a, [X, Y, Z]).", [["Y = _2", "X = a", "Z = _0"], ["Y = a", "X = _4", "Z = _0"], ["Y = _2", "X = _4", "Z = a"]]); - assert_prolog_success!(&mut wam, "?- member([X, X], [a, [X, Y]]).", [["X = _0", "Y = _0"]]); - assert_prolog_success!(&mut wam, "?- member([X, X], [a, [b, c], [b, b], [Z, x], [d, f]]).", + assert_prolog_success!(&mut wam, "member([X, X], [a, [X, Y]]).", [["X = _0", "Y = _0"]]); + assert_prolog_success!(&mut wam, "member([X, X], [a, [b, c], [b, b], [Z, x], [d, f]]).", [["Z = _14", "X = b"], ["Z = x", "X = x"]]); - assert_prolog_failure!(&mut wam, "?- member([X, X], [a, [b, c], [b, d], [foo, x], [d, f]])."); - assert_prolog_success!(&mut wam, "?- member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).", + assert_prolog_failure!(&mut wam, "member([X, X], [a, [b, c], [b, d], [foo, x], [d, f]])."); + assert_prolog_success!(&mut wam, "member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).", [["X = b", "Y = c", "Z = _14"], ["X = b", "Y = b", "Z = _14"], ["X = _2", "Y = x", "Z = _2"], ["X = d", "Y = f", "Z = _14"]]); - assert_prolog_failure!(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]])."); - assert_prolog_failure!(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]])."); + assert_prolog_failure!(&mut wam, "member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]])."); + assert_prolog_failure!(&mut wam, "member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]])."); } #[test] fn test_queries_on_conjuctive_queries() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "p(a, b)."); submit(&mut wam, "q(b, c)."); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", [["X = a", "Z = c", "Y = b"]]); - assert_prolog_failure!(&mut wam, "?- p(X, Y), q(Y, X)."); + assert_prolog_success!(&mut wam, "p(X, Y), q(Y, Z).", [["X = a", "Z = c", "Y = b"]]); + assert_prolog_failure!(&mut wam, "p(X, Y), q(Y, X)."); submit(&mut wam, "p(a, [f(g(X))])."); submit(&mut wam, "q(Y, c)."); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", [["Y = [f(g(_9))]", "X = a", "Z = c"]]); - assert_prolog_failure!(&mut wam, "?- p(X, Y), q(Y, X)."); + assert_prolog_success!(&mut wam, "p(X, Y), q(Y, Z).", [["Y = [f(g(_9))]", "X = a", "Z = c"]]); + assert_prolog_failure!(&mut wam, "p(X, Y), q(Y, X)."); submit(&mut wam, "member(X, [X|_]). member(X, [_|Xs]) :- member(X, Xs)."); - assert_prolog_success!(&mut wam, "?- member(X, [a,b,c]), member(X, [a,b,c]).", + assert_prolog_success!(&mut wam, "member(X, [a,b,c]), member(X, [a,b,c]).", [["X = a"], ["X = b"], ["X = c"]]); - assert_prolog_success!(&mut wam, "?- member(X, [a,b,c]), member(X, [b,c]).", + assert_prolog_success!(&mut wam, "member(X, [a,b,c]), member(X, [b,c]).", [["X = b"], ["X = c"]]); - assert_prolog_success!(&mut wam, "?- member(X, [a,c]), member(X, [b,c]).", + assert_prolog_success!(&mut wam, "member(X, [a,c]), member(X, [b,c]).", [["X = c"]]); - assert_prolog_success!(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [a,d]).", + assert_prolog_success!(&mut wam, "member(X, [a,b,c,d]), !, member(X, [a,d]).", [["X = a"]]); - assert_prolog_failure!(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [e])."); - assert_prolog_success!(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]), + assert_prolog_failure!(&mut wam, "member(X, [a,b,c,d]), !, member(X, [e])."); + assert_prolog_success!(&mut wam, "member([X,X],[a,b,c,[d,d],[e,d]]), member(X, [a,b,c,d,e,f,g]), member(Y, [X, a, b, c, d]).", [["X = d", "Y = d"], @@ -662,49 +670,49 @@ fn test_queries_on_conjuctive_queries() { submit(&mut wam, "c."); submit(&mut wam, "q(Y, c)."); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", + assert_prolog_success!(&mut wam, "p(X, Y), q(Y, Z).", [["X = a", "Z = c", "Y = [f(g(_9))]"], ["X = _0", "Z = c", "Y = c"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).", + assert_prolog_success!(&mut wam, "p(X, Y), !, q(Y, Z).", [["Z = c", "Y = [f(g(_9))]", "X = a"]]); submit(&mut wam, "q([f(g(x))], Z). q([f(g(y))], Y). q([f(g(z))], a)."); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", + assert_prolog_success!(&mut wam, "p(X, Y), q(Y, Z).", [["Z = _11", "X = a", "Y = [f(g(x))]"], ["Z = _11", "X = a", "Y = [f(g(y))]"], ["Z = a", "X = a", "Y = [f(g(z))]"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).", + assert_prolog_success!(&mut wam, "p(X, Y), !, q(Y, Z).", [["X = a", "Y = [f(g(x))]", "Z = _11"], ["X = a", "Y = [f(g(y))]", "Z = _11"], ["X = a", "Y = [f(g(z))]", "Z = a"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, X).", + assert_prolog_success!(&mut wam, "p(X, Y), !, q(Y, X).", [["X = a", "Y = [f(g(x))]"], ["X = a", "Y = [f(g(y))]"], ["X = a", "Y = [f(g(z))]"]]); submit(&mut wam, "p(X, [f(g(x))]). p(X, [f(g(y))]). p(X, [f(g(z))])."); - assert_prolog_failure!(&mut wam, "?- q(f(X), Y), p(X, Y)."); - assert_prolog_success!(&mut wam, "?- q(X, Y), p(X, Y).", + assert_prolog_failure!(&mut wam, "q(f(X), Y), p(X, Y)."); + assert_prolog_success!(&mut wam, "q(X, Y), p(X, Y).", [["Y = [f(g(x))]", "X = [f(g(x))]"], ["Y = [f(g(y))]", "X = [f(g(x))]"], ["Y = [f(g(z))]", "X = [f(g(x))]"], ["Y = [f(g(x))]", "X = [f(g(y))]"], ["Y = [f(g(y))]", "X = [f(g(y))]"], ["Y = [f(g(z))]", "X = [f(g(y))]"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(X, Y).", + assert_prolog_success!(&mut wam, "p(X, Y), q(X, Y).", [["Y = [f(g(x))]", "X = [f(g(x))]"], ["Y = [f(g(x))]", "X = [f(g(y))]"], ["Y = [f(g(y))]", "X = [f(g(x))]"], ["Y = [f(g(y))]", "X = [f(g(y))]"], ["Y = [f(g(z))]", "X = [f(g(x))]"], ["Y = [f(g(z))]", "X = [f(g(y))]"]]); - assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, X).", + assert_prolog_success!(&mut wam, "p(X, Y), q(Y, X).", [["Y = [f(g(x))]", "X = _10"], ["Y = [f(g(y))]", "X = _10"], ["Y = [f(g(z))]", "X = a"]]); - assert_prolog_success!(&mut wam, "?- q(X, Y), p(Y, X).", + assert_prolog_success!(&mut wam, "q(X, Y), p(Y, X).", [["Y = _9", "X = [f(g(x))]"], ["Y = _9", "X = [f(g(y))]"], ["Y = a" , "X = [f(g(z))]"]]); @@ -713,13 +721,13 @@ fn test_queries_on_conjuctive_queries() { #[test] fn test_queries_on_call_n() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "maplist(_, []). maplist(P, [X|Xs]) :- call(P, X), maplist(P, Xs)."); submit(&mut wam, "f(a). f(b). f(c)."); - assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).", + assert_prolog_success!(&mut wam, "maplist(f, [X,Y,Z]).", [["X = a", "Y = a", "Z = a"], ["X = a", "Y = a", "Z = b"], ["X = a", "Y = a", "Z = c"], @@ -748,7 +756,7 @@ fn test_queries_on_call_n() ["X = c", "Y = c", "Z = b"], ["X = c", "Y = c", "Z = c"]]); - assert_prolog_success!(&mut wam, "?- maplist(f, [a,Y,Z]).", + assert_prolog_success!(&mut wam, "maplist(f, [a,Y,Z]).", [["Y = a", "Z = a"], ["Y = a", "Z = b"], ["Y = a", "Z = c"], @@ -759,53 +767,53 @@ fn test_queries_on_call_n() ["Y = c", "Z = b"], ["Y = c", "Z = c"]]); - assert_prolog_success!(&mut wam, "?- maplist(f, [X,a,b]).", + assert_prolog_success!(&mut wam, "maplist(f, [X,a,b]).", [["X = a"], ["X = b"], ["X = c"]]); - assert_prolog_success!(&mut wam, "?- maplist(f, [c,a,b])."); - assert_prolog_failure!(&mut wam, "?- maplist(f, [d,e,f])."); - assert_prolog_success!(&mut wam, "?- maplist(f, [])."); - assert_prolog_failure!(&mut wam, "?- maplist(f(X), [a,b,c])."); + assert_prolog_success!(&mut wam, "maplist(f, [c,a,b])."); + assert_prolog_failure!(&mut wam, "maplist(f, [d,e,f])."); + assert_prolog_success!(&mut wam, "maplist(f, [])."); + assert_prolog_failure!(&mut wam, "maplist(f(X), [a,b,c])."); submit(&mut wam, "f(X) :- call(X), call(X)."); submit(&mut wam, "p(x). p(y)."); - assert_prolog_failure!(&mut wam, "?- f(p)."); - assert_prolog_success!(&mut wam, "?- f(p(X)).", [["X = x"], + assert_prolog_failure!(&mut wam, "f(p)."); + assert_prolog_success!(&mut wam, "f(p(X)).", [["X = x"], ["X = y"]]); - assert_prolog_success!(&mut wam, "?- f(p(x))."); - assert_prolog_failure!(&mut wam, "?- f(p(w))."); - assert_prolog_failure!(&mut wam, "?- f(p(X, Y))."); + assert_prolog_success!(&mut wam, "f(p(x))."); + assert_prolog_failure!(&mut wam, "f(p(w))."); + assert_prolog_failure!(&mut wam, "f(p(X, Y))."); submit(&mut wam, "f(P) :- call(P, X), call(P, Y)."); - assert_prolog_success!(&mut wam, "?- f(p)."); - assert_prolog_failure!(&mut wam, "?- f(non_existent)."); + assert_prolog_success!(&mut wam, "f(p)."); + assert_prolog_failure!(&mut wam, "f(non_existent)."); submit(&mut wam, "f(P, X, Y) :- call(P, X), call(P, Y)."); - assert_prolog_success!(&mut wam, "?- f(p, X, Y).", [["Y = x", "X = x"], + assert_prolog_success!(&mut wam, "f(p, X, Y).", [["Y = x", "X = x"], ["Y = y", "X = x"], ["Y = x", "X = y"], ["Y = y", "X = y"]]); - assert_prolog_success!(&mut wam, "?- f(p, x, Y).", [["Y = x"], + assert_prolog_success!(&mut wam, "f(p, x, Y).", [["Y = x"], ["Y = y"]]); - assert_prolog_success!(&mut wam, "?- f(p, X, y).", [["X = x"], + assert_prolog_success!(&mut wam, "f(p, X, y).", [["X = x"], ["X = y"]]); - assert_prolog_success!(&mut wam, "?- f(p, x, y)."); - assert_prolog_failure!(&mut wam, "?- f(p, X, z)."); - assert_prolog_failure!(&mut wam, "?- f(p, z, Y)."); + assert_prolog_success!(&mut wam, "f(p, x, y)."); + assert_prolog_failure!(&mut wam, "f(p, X, z)."); + assert_prolog_failure!(&mut wam, "f(p, z, Y)."); - assert_prolog_success!(&mut wam, "?- call(p, X).", [["X = x"], + assert_prolog_success!(&mut wam, "call(p, X).", [["X = x"], ["X = y"]]); - assert_prolog_success!(&mut wam, "?- call(p, x)."); - assert_prolog_success!(&mut wam, "?- call(p, y)."); - assert_prolog_failure!(&mut wam, "?- call(p, z)."); + assert_prolog_success!(&mut wam, "call(p, x)."); + assert_prolog_success!(&mut wam, "call(p, y)."); + assert_prolog_failure!(&mut wam, "call(p, z)."); submit(&mut wam, "r(f(X)) :- p(X). r(g(Y)) :- p(Y)."); - assert_prolog_success!(&mut wam, "?- f(r, X, Y).", + assert_prolog_success!(&mut wam, "f(r, X, Y).", [["X = f(x)", "Y = f(x)"], ["X = f(x)", "Y = f(y)"], ["X = f(x)", "Y = g(x)"], @@ -822,57 +830,57 @@ fn test_queries_on_call_n() ["X = g(y)", "Y = f(y)"], ["X = g(y)", "Y = g(x)"], ["X = g(y)", "Y = g(y)"]]); - assert_prolog_success!(&mut wam, "?- f(r, X, X).", + assert_prolog_success!(&mut wam, "f(r, X, X).", [["X = f(x)"], ["X = f(y)"], ["X = g(x)"], ["X = g(y)"]]); - assert_prolog_success!(&mut wam, "?- f(r, f(X), g(Y)).", + assert_prolog_success!(&mut wam, "f(r, f(X), g(Y)).", [["X = x", "Y = x"], ["X = x", "Y = y"], ["X = y", "Y = x"], ["X = y", "Y = y"]]); - assert_prolog_failure!(&mut wam, "?- f(r, j(X), h(Y))."); + assert_prolog_failure!(&mut wam, "f(r, j(X), h(Y))."); submit(&mut wam, "p(one, one). p(one, two). p(two, two)."); - assert_prolog_success!(&mut wam, "?- f(p(one), X, Y).", + assert_prolog_success!(&mut wam, "f(p(one), X, Y).", [["X = one", "Y = one"], ["X = one", "Y = two"], ["X = two", "Y = one"], ["X = two", "Y = two"]]); - assert_prolog_success!(&mut wam, "?- f(p(one), X, X).", + assert_prolog_success!(&mut wam, "f(p(one), X, X).", [["X = one"], ["X = two"]]); - assert_prolog_success!(&mut wam, "?- f(p(one), one, Y).", + assert_prolog_success!(&mut wam, "f(p(one), one, Y).", [["Y = one"], ["Y = two"]]); - assert_prolog_success!(&mut wam, "?- f(p(one), one, two)."); - assert_prolog_failure!(&mut wam, "?- f(p(one), one, three)."); + assert_prolog_success!(&mut wam, "f(p(one), one, two)."); + assert_prolog_failure!(&mut wam, "f(p(one), one, three)."); - assert_prolog_failure!(&mut wam, "?- f(p(two), one, two)."); - assert_prolog_failure!(&mut wam, "?- f(p(two), two, one)."); - assert_prolog_success!(&mut wam, "?- f(p(two), two, two)."); - assert_prolog_failure!(&mut wam, "?- f(p(two), two, three)."); + assert_prolog_failure!(&mut wam, "f(p(two), one, two)."); + assert_prolog_failure!(&mut wam, "f(p(two), two, one)."); + assert_prolog_success!(&mut wam, "f(p(two), two, two)."); + assert_prolog_failure!(&mut wam, "f(p(two), two, three)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), X, Y)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), X, X)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), one, Y)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), one, two)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), one, three)."); + assert_prolog_failure!(&mut wam, "f(p(three), X, Y)."); + assert_prolog_failure!(&mut wam, "f(p(three), X, X)."); + assert_prolog_failure!(&mut wam, "f(p(three), one, Y)."); + assert_prolog_failure!(&mut wam, "f(p(three), one, two)."); + assert_prolog_failure!(&mut wam, "f(p(three), one, three)."); submit(&mut wam, "f(P, X) :- call(P, X)."); - assert_prolog_success!(&mut wam, "?- f(p(one), one)."); - assert_prolog_success!(&mut wam, "?- f(p(two), two)."); - assert_prolog_failure!(&mut wam, "?- f(p(two), one)."); - assert_prolog_failure!(&mut wam, "?- f(p(three), one)."); - assert_prolog_failure!(&mut wam, "?- f(p(one), three)."); - assert_prolog_failure!(&mut wam, "?- f(p(two), three)."); + assert_prolog_success!(&mut wam, "f(p(one), one)."); + assert_prolog_success!(&mut wam, "f(p(two), two)."); + assert_prolog_failure!(&mut wam, "f(p(two), one)."); + assert_prolog_failure!(&mut wam, "f(p(three), one)."); + assert_prolog_failure!(&mut wam, "f(p(one), three)."); + assert_prolog_failure!(&mut wam, "f(p(two), three)."); submit(&mut wam, "p(f(g(X)), compound, [lists,are,good])."); - assert_prolog_success!(&mut wam, "?- call(p(f(g(X))), Y, Z).", + assert_prolog_success!(&mut wam, "call(p(f(g(X))), Y, Z).", [["Y = compound", "Z = [lists, are, good]", "X = _3"]]); submit(&mut wam, "david_lynch(coffee). @@ -884,63 +892,63 @@ fn test_queries_on_call_n() kyle(showgirls). kyle(flintstones)."); - assert_prolog_success!(&mut wam, "?- call(david_lynch, X).", + assert_prolog_success!(&mut wam, "call(david_lynch, X).", [["X = coffee"], ["X = pie"], ["X = kyle(dune)"], ["X = kyle(blue_velvet)"], ["X = kyle(showgirls)"], ["X = kyle(flintstones)"]]); - assert_prolog_success!(&mut wam, "?- call(david_lynch, kyle(Film)).", + assert_prolog_success!(&mut wam, "call(david_lynch, kyle(Film)).", [["Film = dune"], ["Film = blue_velvet"], ["Film = showgirls"], ["Film = flintstones"]]); - assert_prolog_failure!(&mut wam, "?- call(david_lynch, kyle(Film), _)."); + assert_prolog_failure!(&mut wam, "call(david_lynch, kyle(Film), _)."); submit(&mut wam, "call_mult(P, X) :- call(call(P), X)."); - assert_prolog_success!(&mut wam, "?- call_mult(p(X), Y).", + assert_prolog_success!(&mut wam, "call_mult(p(X), Y).", [["Y = one", "X = one"], ["Y = two", "X = one"], ["Y = two", "X = two"]]); - assert_prolog_success!(&mut wam, "?- call_mult(p(X), X).", + assert_prolog_success!(&mut wam, "call_mult(p(X), X).", [["X = one"], ["X = two"]]); - assert_prolog_success!(&mut wam, "?- call_mult(p(one), X).", + assert_prolog_success!(&mut wam, "call_mult(p(one), X).", [["X = one"], ["X = two"]]); - assert_prolog_success!(&mut wam, "?- call_mult(p(X), one).", + assert_prolog_success!(&mut wam, "call_mult(p(X), one).", [["X = one"]]); - assert_prolog_failure!(&mut wam, "?- call_mult(p(two), one)."); - assert_prolog_success!(&mut wam, "?- call_mult(p(two), two)."); + assert_prolog_failure!(&mut wam, "call_mult(p(two), one)."); + assert_prolog_success!(&mut wam, "call_mult(p(two), two)."); - assert_prolog_success!(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), two).", + assert_prolog_success!(&mut wam, "call(call(p(one)), X), call(call(p(two)), two).", [["X = one"], ["X = two"]]); - assert_prolog_success!(&mut wam, "?- call(call(p(one, X))), call(call(p(two, two))).", + assert_prolog_success!(&mut wam, "call(call(p(one, X))), call(call(p(two, two))).", [["X = one"], ["X = two"]]); - assert_prolog_failure!(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), one)."); - assert_prolog_success!(&mut wam, "?- call(call(p(X)), X), call(call(p(Y)), Y).", + assert_prolog_failure!(&mut wam, "call(call(p(one)), X), call(call(p(two)), one)."); + assert_prolog_success!(&mut wam, "call(call(p(X)), X), call(call(p(Y)), Y).", [["X = one", "Y = one"], ["X = one", "Y = two"], ["X = two", "Y = one"], ["X = two", "Y = two"]]); - assert_prolog_success!(&mut wam, "?- call(call(p(X)), Y), call(call(p(Y)), X).", + assert_prolog_success!(&mut wam, "call(call(p(X)), Y), call(call(p(Y)), X).", [["X = one", "Y = one"], ["X = two", "Y = two"]]); - assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p)), X, Y).", + assert_prolog_success!(&mut wam, "call(call(p), X, Y), call(call(call(p)), X, Y).", [["X = one", "Y = one"], ["Y = two", "X = one"], ["Y = two", "X = two"]]); - assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), Y).", + assert_prolog_success!(&mut wam, "call(call(p), X, Y), call(call(call(p(X))), Y).", [["X = one", "Y = one"], ["Y = two", "X = one"], ["Y = two", "X = two"]]); - assert_prolog_failure!(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X, Y)."); - assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X).", + assert_prolog_failure!(&mut wam, "call(call(p), X, Y), call(call(call(p(X))), X, Y)."); + assert_prolog_success!(&mut wam, "call(call(p), X, Y), call(call(call(p(X))), X).", [["X = one", "Y = one"], ["Y = two", "X = one"], ["Y = two", "X = two"]]); @@ -948,18 +956,18 @@ fn test_queries_on_call_n() submit(&mut wam, "f(call(f, undefined)). f(undefined)."); submit(&mut wam, "call_var(P) :- P."); - assert_prolog_success!(&mut wam, "?- f(X), call_var(X).", + assert_prolog_success!(&mut wam, "f(X), call_var(X).", [["X = call(f, undefined)"]]); - assert_prolog_success!(&mut wam, "?- f(call(f, Q)), call_var(call(f, Q)).", + assert_prolog_success!(&mut wam, "f(call(f, Q)), call_var(call(f, Q)).", [["Q = undefined"]]); - assert_prolog_failure!(&mut wam, "?- call_var(call(undefined, Q))."); - - assert_prolog_failure!(&mut wam, "?- call(call)."); - assert_prolog_failure!(&mut wam, "?- call(call(call))."); - assert_prolog_failure!(&mut wam, "?- call(call(call(call)))."); - assert_prolog_failure!(&mut wam, "?- call(call(call(call(call))))."); - assert_prolog_failure!(&mut wam, "?- call(call(call(call(call(call)))))."); - assert_prolog_success!(&mut wam, "?- call(call(call(call(call(call(p(X))))))).", + assert_prolog_failure!(&mut wam, "call_var(call(undefined, Q))."); + + assert_prolog_failure!(&mut wam, "call(call)."); + assert_prolog_failure!(&mut wam, "call(call(call))."); + assert_prolog_failure!(&mut wam, "call(call(call(call)))."); + assert_prolog_failure!(&mut wam, "call(call(call(call(call))))."); + assert_prolog_failure!(&mut wam, "call(call(call(call(call(call)))))."); + assert_prolog_success!(&mut wam, "call(call(call(call(call(call(p(X))))))).", [["X = x"], ["X = y"]]); } @@ -967,85 +975,85 @@ fn test_queries_on_call_n() #[test] fn test_queries_on_arithmetic() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); - assert_prolog_success!(&mut wam, "?- X is 1, X is X.", [["X = 1"]]); - assert_prolog_failure!(&mut wam, "?- X is 1, X is X + 1."); - assert_prolog_success!(&mut wam, "?- X is 1, X is X + 0.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is 1, X is X * 1.", [["X = 1"]]); - assert_prolog_failure!(&mut wam, "?- X is 1, X is X * 2."); + assert_prolog_success!(&mut wam, "X is 1, X is X.", [["X = 1"]]); + assert_prolog_failure!(&mut wam, "X is 1, X is X + 1."); + assert_prolog_success!(&mut wam, "X is 1, X is X + 0.", [["X = 1"]]); + assert_prolog_success!(&mut wam, "X is 1, X is X * 1.", [["X = 1"]]); + assert_prolog_failure!(&mut wam, "X is 1, X is X * 2."); - // assert_prolog_failure!(&mut wam, "?- X is 1 + a."); - // assert_prolog_failure!(&mut wam, "?- X is 1 + Y."); - assert_prolog_success!(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 3.", + // assert_prolog_failure!(&mut wam, "X is 1 + a."); + // assert_prolog_failure!(&mut wam, "X is 1 + Y."); + assert_prolog_success!(&mut wam, "Y is 2 + 2 - 2, X is 1 + Y, X = 3.", [["X = 3", "Y = 2"]]); - assert_prolog_failure!(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 2."); - - assert_prolog_success!(&mut wam, "?- 6 is 6."); - assert_prolog_success!(&mut wam, "?- 6 is 3 + 3."); - assert_prolog_success!(&mut wam, "?- 6 is 3 * 2."); - assert_prolog_failure!(&mut wam, "?- 7 is 3 * 2."); - assert_prolog_failure!(&mut wam, "?- 7 is 3.5 * 2."); - assert_prolog_success!(&mut wam, "?- 7.0 is 3.5 * 2."); - assert_prolog_success!(&mut wam, "?- 7.0 is 14 / 2."); - assert_prolog_failure!(&mut wam, "?- 4.666 is 14.0 / 3."); - assert_prolog_success!(&mut wam, "?- 4.0 is 8.0 / 2."); + assert_prolog_failure!(&mut wam, "Y is 2 + 2 - 2, X is 1 + Y, X = 2."); + + assert_prolog_success!(&mut wam, "6 is 6."); + assert_prolog_success!(&mut wam, "6 is 3 + 3."); + assert_prolog_success!(&mut wam, "6 is 3 * 2."); + assert_prolog_failure!(&mut wam, "7 is 3 * 2."); + assert_prolog_failure!(&mut wam, "7 is 3.5 * 2."); + assert_prolog_success!(&mut wam, "7.0 is 3.5 * 2."); + assert_prolog_success!(&mut wam, "7.0 is 14 / 2."); + assert_prolog_failure!(&mut wam, "4.666 is 14.0 / 3."); + assert_prolog_success!(&mut wam, "4.0 is 8.0 / 2."); submit(&mut wam, "f(X) :- X is 5 // 0."); - assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", + assert_prolog_success!(&mut wam, "catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", [["E = zero_divisor", "X = _1"]]); submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0."); - assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", + assert_prolog_success!(&mut wam, "catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", [["E = zero_divisor", "X = _1"]]); submit(&mut wam, "f(X) :- X is 5.0 / 0."); - assert_prolog_success!(&mut wam, "?- catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", + assert_prolog_success!(&mut wam, "catch(f(X), error(evaluation_error(E), _), true), E = zero_divisor.", [["E = zero_divisor", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y.", + assert_prolog_success!(&mut wam, "X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y.", [["Y = 4", "X = 4", "Z = 8"]]); - assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z = 8, Y is 4.", + assert_prolog_success!(&mut wam, "X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z = 8, Y is 4.", [["Y = 4", "X = 4", "Z = 8"]]); - assert_prolog_success!(&mut wam, "?- X is (3 rdiv 4) / 2, Y is 3 rdiv 8, X = Y.", + assert_prolog_success!(&mut wam, "X is (3 rdiv 4) / 2, Y is 3 rdiv 8, X = Y.", [["X = 3/8", "Y = 3/8"]]); - assert_prolog_success!(&mut wam, "?- X is 10 xor -4, X is -10.", [["X = -10"]]); - assert_prolog_success!(&mut wam, "?- X is 4 xor -7, X is -3.", [["X = -3"]]); - assert_prolog_success!(&mut wam, "?- X is 10 xor 5 + 55, X = 70.", [["X = 70"]]); + assert_prolog_success!(&mut wam, "X is 10 xor -4, X is -10.", [["X = -10"]]); + assert_prolog_success!(&mut wam, "X is 4 xor -7, X is -3.", [["X = -3"]]); + assert_prolog_success!(&mut wam, "X is 10 xor 5 + 55, X = 70.", [["X = 70"]]); - assert_prolog_success!(&mut wam, "?- X is 10 rem -3, X = 1.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is 10 mod -3, X is -2.", [["X = -2"]]); + assert_prolog_success!(&mut wam, "X is 10 rem -3, X = 1.", [["X = 1"]]); + assert_prolog_success!(&mut wam, "X is 10 mod -3, X is -2.", [["X = -2"]]); - assert_prolog_success!(&mut wam, "?- call(is, X, 3 + 4).", [["X = 7"]]); + assert_prolog_success!(&mut wam, "call(is, X, 3 + 4).", [["X = 7"]]); - assert_prolog_success!(&mut wam, "?- Y is 3 + 3, call(is, X, Y + 4).", [["Y = 6", "X = 10"]]); - assert_prolog_success!(&mut wam, "?- call(is, X, 3 + 4.5).", [["X = 7.5"]]); - assert_prolog_success!(&mut wam, "?- X is 2 rdiv 3, call(is, Y, X*X).", [["X = 2/3", "Y = 4/9"]]); + assert_prolog_success!(&mut wam, "Y is 3 + 3, call(is, X, Y + 4).", [["Y = 6", "X = 10"]]); + assert_prolog_success!(&mut wam, "call(is, X, 3 + 4.5).", [["X = 7.5"]]); + assert_prolog_success!(&mut wam, "X is 2 rdiv 3, call(is, Y, X*X).", [["X = 2/3", "Y = 4/9"]]); - assert_prolog_failure!(&mut wam, "?- call(>, 3, 3 + 3)."); - assert_prolog_failure!(&mut wam, "?- X is 3 + 3, call(>, 3, X)."); + assert_prolog_failure!(&mut wam, "call(>, 3, 3 + 3)."); + assert_prolog_failure!(&mut wam, "X is 3 + 3, call(>, 3, X)."); - assert_prolog_success!(&mut wam, "?- X is 3 + 3, call(<, 3, X).", [["X = 6"]]); - assert_prolog_success!(&mut wam, "?- X is 3 + 3, X =:= 3 + 3.", [["X = 6"]]); + assert_prolog_success!(&mut wam, "X is 3 + 3, call(<, 3, X).", [["X = 6"]]); + assert_prolog_success!(&mut wam, "X is 3 + 3, X =:= 3 + 3.", [["X = 6"]]); - assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 0), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(call(is, X, 3 // 0), error(E, _), true).", [["X = _5", "E = evaluation_error(zero_divisor)"]]); - assert_prolog_success!(&mut wam, "?- catch(call(is, X, 3 // 3), _, true).", [["X = 1"]]); + assert_prolog_success!(&mut wam, "catch(call(is, X, 3 // 3), _, true).", [["X = 1"]]); submit(&mut wam, "f(X, Sum) :- ( integer(X) -> Sum is X + X * X + 3 ; var(X) -> Sum = 1, X = 1 )."); - assert_prolog_success!(&mut wam, "?- f(X, Sum).", [["X = 1", "Sum = 1"]]); - assert_prolog_success!(&mut wam, "?- f(5, Sum).", [["Sum = 33"]]); - assert_prolog_success!(&mut wam, "?- f(5, 33)."); - assert_prolog_failure!(&mut wam, "?- f(5, 32)."); + assert_prolog_success!(&mut wam, "f(X, Sum).", [["X = 1", "Sum = 1"]]); + assert_prolog_success!(&mut wam, "f(5, Sum).", [["Sum = 33"]]); + assert_prolog_success!(&mut wam, "f(5, 33)."); + assert_prolog_failure!(&mut wam, "f(5, 32)."); // exponentiation. @@ -1054,78 +1062,78 @@ fn test_queries_on_arithmetic() submit(&mut wam, ":- op(900, xfx, ~)."); submit(&mut wam, "X ~ Y :- abs(X - Y) =< 1 rdiv 10000."); - assert_prolog_success!(&mut wam, "?- X is 3 ** 3.", + assert_prolog_success!(&mut wam, "X is 3 ** 3.", [["X = 27"]]); - assert_prolog_success!(&mut wam, "?- X is 3 ** 0.", + assert_prolog_success!(&mut wam, "X is 3 ** 0.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is 3 ** -0.", + assert_prolog_success!(&mut wam, "X is 3 ** -0.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is 3 ** 1.", + assert_prolog_success!(&mut wam, "X is 3 ** 1.", [["X = 3"]]); - assert_prolog_success!(&mut wam, "?- X is 3 ** -3.", + assert_prolog_success!(&mut wam, "X is 3 ** -3.", [["X = 1/27"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** 3.", + assert_prolog_success!(&mut wam, "X is (-3) ** 3.", [["X = -27"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** 3.", + assert_prolog_success!(&mut wam, "X is (-3) ** 3.", [["X = -27"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** 0.", + assert_prolog_success!(&mut wam, "X is (-3) ** 0.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** -0.", + assert_prolog_success!(&mut wam, "X is (-3) ** -0.", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** 1.", + assert_prolog_success!(&mut wam, "X is (-3) ** 1.", [["X = -3"]]); - assert_prolog_success!(&mut wam, "?- X is (-3) ** -3.", + assert_prolog_success!(&mut wam, "X is (-3) ** -3.", [["X = -1/27"]]); - assert_prolog_success!(&mut wam, "?- X is (1 rdiv 27) ** -3, X ~ 19683."); - assert_prolog_success!(&mut wam, "?- X is (-1 rdiv 27) ** -3, X ~ -19683."); + assert_prolog_success!(&mut wam, "X is (1 rdiv 27) ** -3, X ~ 19683."); + assert_prolog_success!(&mut wam, "X is (-1 rdiv 27) ** -3, X ~ -19683."); - assert_prolog_success!(&mut wam, "?- X is 0.0 ** 0.", + assert_prolog_success!(&mut wam, "X is 0.0 ** 0.", [["X = 1.0"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is 0.0 ** -2342, error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is 0.0 ** -2342, error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- X is 0.0 ** 2342.", + assert_prolog_success!(&mut wam, "X is 0.0 ** 2342.", [["X = 0"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is (-3) ** (1 rdiv 2), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is (-3) ** (1 rdiv 2), error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is (-3/2) ** (1 rdiv 2), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is (-3/2) ** (1 rdiv 2), error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ** (1 rdiv 4), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is (-3 rdiv 2) ** (1 rdiv 4), error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is (-3 rdiv 2) ** (-1 rdiv 4), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is (-3 rdiv 2) ** (-1 rdiv 4), error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is 0 ** (-5 rdiv 4), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is 0 ** (-5 rdiv 4), error(E, _), true).", [["E = evaluation_error(no_roots)"]]); - assert_prolog_success!(&mut wam, "?- X is 3 ** (1 rdiv 3), Y is X ** 3, Y ~ 3."); - assert_prolog_success!(&mut wam, "?- X is (-3) ** (1 rdiv 3), Y is X ** 3, Y ~ -3."); - assert_prolog_failure!(&mut wam, "?- X is (-5) ** (1 rdiv 3), Y is X ** 3, Y ~ -3."); - assert_prolog_failure!(&mut wam, "?- X is 5 ** (1 rdiv 3), Y is X ** 3, Y ~ 3."); - assert_prolog_failure!(&mut wam, "?- X is (1 rdiv 3) ** 0.5, Y is X ** 2, X ~ Y."); - assert_prolog_success!(&mut wam, "?- X is (1 rdiv 3) ** 0.5, Y is X ** 2, 1 rdiv 3 ~ Y."); + assert_prolog_success!(&mut wam, "X is 3 ** (1 rdiv 3), Y is X ** 3, Y ~ 3."); + assert_prolog_success!(&mut wam, "X is (-3) ** (1 rdiv 3), Y is X ** 3, Y ~ -3."); + assert_prolog_failure!(&mut wam, "X is (-5) ** (1 rdiv 3), Y is X ** 3, Y ~ -3."); + assert_prolog_failure!(&mut wam, "X is 5 ** (1 rdiv 3), Y is X ** 3, Y ~ 3."); + assert_prolog_failure!(&mut wam, "X is (1 rdiv 3) ** 0.5, Y is X ** 2, X ~ Y."); + assert_prolog_success!(&mut wam, "X is (1 rdiv 3) ** 0.5, Y is X ** 2, 1 rdiv 3 ~ Y."); - assert_prolog_success!(&mut wam, "?- X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ -1 rdiv 5."); - assert_prolog_failure!(&mut wam, "?- X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ 1 rdiv 5."); + assert_prolog_success!(&mut wam, "X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ -1 rdiv 5."); + assert_prolog_failure!(&mut wam, "X is (-5) ** (-1 rdiv 3), Y is X ** 3, Y ~ 1 rdiv 5."); - assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ** 5.", + assert_prolog_success!(&mut wam, "X is (0 rdiv 5) ** 5.", [["X = 0"]]); - assert_prolog_success!(&mut wam, "?- X is (-0 rdiv 5) ** 5.", + assert_prolog_success!(&mut wam, "X is (-0 rdiv 5) ** 5.", [["X = 0"]]); - assert_prolog_success!(&mut wam, "?- X is (0 rdiv 5) ** 0.", + assert_prolog_success!(&mut wam, "X is (0 rdiv 5) ** 0.", [["X = 1.0"]]); - assert_prolog_success!(&mut wam, "?- catch(_ is (0 rdiv 0) ** 5, error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(_ is (0 rdiv 0) ** 5, error(E, _), true).", [["E = evaluation_error(zero_divisor)"]]); } #[test] fn test_queries_on_exceptions() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "f(a). f(_) :- throw(stuff)."); submit(&mut wam, "handle(stuff)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(E)).", + assert_prolog_success!(&mut wam, "catch(f(X), E, handle(E)).", [["E = _2", "X = a"], ["E = stuff", "X = _1"]]); @@ -1133,62 +1141,62 @@ fn test_queries_on_exceptions() submit(&mut wam, "g(x). g(y). g(z)."); submit(&mut wam, "handle(x). handle(y)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), X, handle(X)).", + assert_prolog_success!(&mut wam, "catch(f(X), X, handle(X)).", [["X = a"], ["X = x"], ["X = y"], ["X = z"]]); - assert_prolog_success!(&mut wam, "?- catch(f(a), _, handle(X)).", + assert_prolog_success!(&mut wam, "catch(f(a), _, handle(X)).", [["X = _4"]]); - assert_prolog_failure!(&mut wam, "?- catch(f(b), _, handle(X))."); + assert_prolog_failure!(&mut wam, "catch(f(b), _, handle(X))."); submit(&mut wam, "g(x). g(X) :- throw(x)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), x, handle(X)).", + assert_prolog_success!(&mut wam, "catch(f(X), x, handle(X)).", [["X = a"], ["X = x"], ["X = x"], ["X = y"]]); - assert_prolog_success!(&mut wam, "?- catch(f(X), x, handle(z)).", + assert_prolog_success!(&mut wam, "catch(f(X), x, handle(z)).", [["X = a"], ["X = x"]]); - assert_prolog_success!(&mut wam, "?- catch(f(z), x, handle(x))."); - assert_prolog_success!(&mut wam, "?- catch(f(z), x, handle(y))."); - assert_prolog_failure!(&mut wam, "?- catch(f(z), x, handle(z))."); + assert_prolog_success!(&mut wam, "catch(f(z), x, handle(x))."); + assert_prolog_success!(&mut wam, "catch(f(z), x, handle(y))."); + assert_prolog_failure!(&mut wam, "catch(f(z), x, handle(z))."); submit(&mut wam, "f(X) :- throw(stuff)."); submit(&mut wam, "handle(stuff). handle(other_stuff)."); // the first 3 cases should deterministically succeed. - assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(E)).", + assert_prolog_success!(&mut wam, "catch(f(X), E, handle(E)).", [["X = _1", "E = stuff"]]); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(stuff)).", + assert_prolog_success!(&mut wam, "catch(f(X), E, handle(stuff)).", [["X = _1", "E = stuff"]]); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(other_stuff)).", + assert_prolog_success!(&mut wam, "catch(f(X), E, handle(other_stuff)).", [["X = _1", "E = stuff"]]); - assert_prolog_failure!(&mut wam, "?- catch(f(X), E, handle(not_stuff))."); + assert_prolog_failure!(&mut wam, "catch(f(X), E, handle(not_stuff))."); submit(&mut wam, "f(success). f(X) :- catch(g(X), E, handle(E))."); submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X)."); submit(&mut wam, "handle(x). handle(y). handle(z)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).", + assert_prolog_success!(&mut wam, "catch(f(X), E, E).", [["X = success", "E = _2"], ["X = g_success", "E = _2"], ["X = g_success_2", "E = _2"], ["X = _1", "E = _2"], ["X = _1", "E = _2"], ["X = _1", "E = _2"]]); - assert_prolog_failure!(&mut wam, "?- catch(f(fail), _, _)."); - assert_prolog_success!(&mut wam, "?- catch(f(x), _, _)."); - assert_prolog_success!(&mut wam, "?- catch(f(y), _, _)."); - assert_prolog_success!(&mut wam, "?- catch(f(z), _, _)."); + assert_prolog_failure!(&mut wam, "catch(f(fail), _, _)."); + assert_prolog_success!(&mut wam, "catch(f(x), _, _)."); + assert_prolog_success!(&mut wam, "catch(f(y), _, _)."); + assert_prolog_success!(&mut wam, "catch(f(z), _, _)."); submit(&mut wam, "f(success). f(E) :- catch(g(E), E, handle(E))."); submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X)."); submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).", + assert_prolog_success!(&mut wam, "catch(f(X), E, E).", [["X = success", "E = _2"], ["X = g_success", "E = _2"], ["X = g_success_2", "E = _2"], @@ -1199,7 +1207,7 @@ fn test_queries_on_exceptions() submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(handle_top(X))."); submit(&mut wam, "handle_top(an_error_1). handle_top(an_error_2)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).", + assert_prolog_success!(&mut wam, "catch(f(X), E, E).", [["X = success", "E = _2"], ["X = g_success", "E = _2"], ["X = g_success_2", "E = _2"], @@ -1211,7 +1219,7 @@ fn test_queries_on_exceptions() submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X)."); - assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle_top(E)).", + assert_prolog_success!(&mut wam, "catch(f(X), E, handle_top(E)).", [["X = success", "E = _2"], ["X = g_success", "E = _2"], ["X = g_success_2", "E = _2"], @@ -1224,93 +1232,93 @@ fn test_queries_on_exceptions() #[test] fn test_queries_on_skip_max_list() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); // test on proper and empty lists. - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 5, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 5, [], Xs).", [["Xs = []", "N = 0"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 5, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 5, [a,b,c], Xs).", [["Xs = []", "N = 3"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 2, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 2, [a,b,c], Xs).", [["Xs = [c]", "N = 2"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 3, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 3, [a,b,c], Xs).", [["Xs = []", "N = 3"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 0, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 0, [], Xs).", [["Xs = []", "N = 0"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 0, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 0, [a,b,c], Xs).", [["Xs = [a, b, c]", "N = 0"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 0, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 0, [a,b,c], Xs).", [["Xs = [a, b, c]", "N = 0"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 0, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 0, [a,b,c], Xs).", [["Xs = [a, b, c]", "N = 0"]]); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(4, 0, [], Xs)."); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(3, 0, [a,b,c], Xs)."); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(2, 0, [a,b,c], Xs)."); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(1, 0, [a,b,c], Xs)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(4, 0, [], Xs)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(3, 0, [a,b,c], Xs)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(2, 0, [a,b,c], Xs)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(1, 0, [a,b,c], Xs)."); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(0, 5, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(0, 5, [], Xs).", [["Xs = []"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, 5, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, 5, [a,b,c], Xs).", [["Xs = []"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(2, 2, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(2, 2, [a,b,c], Xs).", [["Xs = [c]"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, 3, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, 3, [a,b,c], Xs).", [["Xs = []"]]); // tests on proper and empty lists with no max. // test on proper and empty lists. - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, -1, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, -1, [], Xs).", [["Xs = []", "N = 0"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, -1, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, -1, [a,b,c], Xs).", [["Xs = []", "N = 3"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, -1, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, -1, [], Xs).", [["Xs = []", "N = 0"]]); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(4, -1, [], Xs)."); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, -1, [a,b,c], Xs).", + assert_prolog_failure!(&mut wam, "'$skip_max_list'(4, -1, [], Xs)."); + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, -1, [a,b,c], Xs).", [["Xs = []"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(0, -1, [], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(0, -1, [], Xs).", [["Xs = []"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, -1, [a,b,c], Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, -1, [a,b,c], Xs).", [["Xs = []"]]); // tests on partial lists. - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, 4, [a,b,c|X], Xs0).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, 4, [a,b,c|X], Xs0).", [["X = _1", "Xs0 = _1"]]); - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(3, 3, [a,b,c|X], Xs0).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(3, 3, [a,b,c|X], Xs0).", [["X = _1", "Xs0 = _1"]]); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(3, 2, [a,b,c|X], Xs0)."); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(3, 1, [a,b,c|X], Xs0)."); - assert_prolog_failure!(&mut wam, "?- '$skip_max_list'(3, 0, [a,b,c|X], Xs0)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(3, 2, [a,b,c|X], Xs0)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(3, 1, [a,b,c|X], Xs0)."); + assert_prolog_failure!(&mut wam, "'$skip_max_list'(3, 0, [a,b,c|X], Xs0)."); // tests on cyclic lists. - assert_prolog_failure!(&mut wam, "?- Xs = [a,b|Xs], '$skip_max_list'(3, 5, X, Xs0)."); - assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 5, X, Xs0)."); - assert_prolog_failure!(&mut wam, "?- X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 3, X, Xs0)."); + assert_prolog_failure!(&mut wam, "Xs = [a,b|Xs], '$skip_max_list'(3, 5, X, Xs0)."); + assert_prolog_failure!(&mut wam, "X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 5, X, Xs0)."); + assert_prolog_failure!(&mut wam, "X = [a,b|Y], Y = [c,d|X], '$skip_max_list'(4, 3, X, Xs0)."); // tests on non lists. - assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 9, non_list, Xs).", + assert_prolog_success!(&mut wam, "'$skip_max_list'(N, 9, non_list, Xs).", [["Xs = non_list", "N = 0"]]); } #[test] fn test_queries_on_conditionals() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, "test(A) :- ( A =:= 2 -> writeq(\"A is 2\") ; A =:= 3 -> writeq(\"A is 3\") ; A = \"not 2 or 3\" )."); - assert_prolog_success!(&mut wam, "?- catch(test(A), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- A = 2, test(A).", [["A = 2"]]); - assert_prolog_success!(&mut wam, "?- A = 3, test(A), B = 3, test(B).", [["A = 3", "B = 3"]]); + assert_prolog_success!(&mut wam, "catch(test(A), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "A = 2, test(A).", [["A = 2"]]); + assert_prolog_success!(&mut wam, "A = 3, test(A), B = 3, test(B).", [["A = 3", "B = 3"]]); submit(&mut wam, "f(a). f(b)."); submit(&mut wam, "g(1). g(2). g(3)."); @@ -1319,174 +1327,172 @@ fn test_queries_on_conditionals() ; integer(X) -> g(X) ; atomic(X))."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(X).", [["X = a"], ["X = b"]]); - assert_prolog_success!(&mut wam, "?- typed_dispatch(a)."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(b)."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(c)."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(1)."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(2)."); - assert_prolog_success!(&mut wam, "?- typed_dispatch(3)."); - assert_prolog_failure!(&mut wam, "?- typed_dispatch(4)."); - assert_prolog_failure!(&mut wam, "?- typed_dispatch(5)."); - assert_prolog_failure!(&mut wam, "?- typed_dispatch(compound(term))."); + assert_prolog_success!(&mut wam, "typed_dispatch(X).", [["X = a"], ["X = b"]]); + assert_prolog_success!(&mut wam, "typed_dispatch(a)."); + assert_prolog_success!(&mut wam, "typed_dispatch(b)."); + assert_prolog_success!(&mut wam, "typed_dispatch(c)."); + assert_prolog_success!(&mut wam, "typed_dispatch(1)."); + assert_prolog_success!(&mut wam, "typed_dispatch(2)."); + assert_prolog_success!(&mut wam, "typed_dispatch(3)."); + assert_prolog_failure!(&mut wam, "typed_dispatch(4)."); + assert_prolog_failure!(&mut wam, "typed_dispatch(5)."); + assert_prolog_failure!(&mut wam, "typed_dispatch(compound(term))."); submit(&mut wam, "f(a). f(b). f(compound(term))."); submit(&mut wam, "g(X, Y) :- f(X), (atomic(X) -> X = a ; X = a ; X = compound(Y))."); - assert_prolog_success!(&mut wam, "?- g(X, Y).", + assert_prolog_success!(&mut wam, "g(X, Y).", [["Y = _1", "X = a"], ["Y = term", "X = compound(term)"]]); - assert_prolog_success!(&mut wam, "?- g(X, X).", [["X = a"]]); - assert_prolog_success!(&mut wam, "?- g(compound(X), X).", [["X = term"]]); - assert_prolog_success!(&mut wam, "?- g(X, term).", [["X = a"], ["X = compound(term)"]]); - assert_prolog_success!(&mut wam, "?- g(a, _)."); - assert_prolog_success!(&mut wam, "?- g(X, _), X = a.", [["X = a"]]); + assert_prolog_success!(&mut wam, "g(X, X).", [["X = a"]]); + assert_prolog_success!(&mut wam, "g(compound(X), X).", [["X = term"]]); + assert_prolog_success!(&mut wam, "g(X, term).", [["X = a"], ["X = compound(term)"]]); + assert_prolog_success!(&mut wam, "g(a, _)."); + assert_prolog_success!(&mut wam, "g(X, _), X = a.", [["X = a"]]); submit(&mut wam, "g(X) :- var(X) -> (var(X) -> X is 3 + 3 ; X = not_6)."); - assert_prolog_success!(&mut wam, "?- g(X).", [["X = 6"]]); - assert_prolog_failure!(&mut wam, "?- g(1)."); - assert_prolog_failure!(&mut wam, "?- g(6)."); - assert_prolog_failure!(&mut wam, "?- g(not_6)."); + assert_prolog_success!(&mut wam, "g(X).", [["X = 6"]]); + assert_prolog_failure!(&mut wam, "g(1)."); + assert_prolog_failure!(&mut wam, "g(6)."); + assert_prolog_failure!(&mut wam, "g(not_6)."); - assert_prolog_success!(&mut wam, "?- f(X), (g(Y), !).", [["X = a", "Y = 6"]]); + assert_prolog_success!(&mut wam, "f(X), (g(Y), !).", [["X = a", "Y = 6"]]); submit(&mut wam, "test(X, [X]) :- (atomic(X) -> true ; throw(type_error(atomic_expected, X))). test(_, _)."); - assert_prolog_success!(&mut wam, "?- catch(test(a, [a]), type_error(E), true).", + assert_prolog_success!(&mut wam, "catch(test(a, [a]), type_error(E), true).", [["E = _6"], ["E = _6"]]); - assert_prolog_success!(&mut wam, "?- f(X), call(->, atomic(X), true).", + assert_prolog_success!(&mut wam, "f(X), call(->, atomic(X), true).", [["X = a"], ["X = b"]]); } #[test] fn test_queries_on_modules() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, ":- use_module(library(lists))."); - compile_user_module(&mut wam, " + submit_code(&mut wam, " :- module(my_lists, [local_member/2, reverse/2]). :- use_module(library(lists), [member/2]). local_member(X, Xs) :- member(X, Xs). -reverse(Xs, Ys) :- lists:reverse(Xs, Ys). -".as_bytes()); +reverse(Xs, Ys) :- lists:reverse(Xs, Ys)."); - 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])."); + 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])."); - compile_user_module(&mut wam, " + submit_code(&mut wam, " :- module(my_lists_2, [local_member/2]). -:- use_module(library(my_lists), [local_member/2]). -".as_bytes()); +:- use_module(library(my_lists), [local_member/2])."); - 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).", + 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"]]); submit(&mut wam, ":- use_module(library(lists), [reverse/2])."); - assert_prolog_success!(&mut wam, "?- catch(member(_, _), error(existence_error(procedure, P), _), true).", + assert_prolog_success!(&mut wam, "catch(member(_, _), error(existence_error(procedure, P), _), true).", [["P = member/2"]]); - assert_prolog_success!(&mut wam, "?- reverse(_, _)."); + assert_prolog_success!(&mut wam, "reverse(_, _)."); submit(&mut wam, ":- use_module(library(lists), [])."); - assert_prolog_success!(&mut wam, "?- catch(reverse(_, _), error(existence_error(procedure, P), _), true).", + assert_prolog_success!(&mut wam, "catch(reverse(_, _), error(existence_error(procedure, P), _), true).", [["P = reverse/2"]]); } #[test] fn test_queries_on_builtins() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, ":- use_module(library(lists))."); submit(&mut wam, ":- use_module(library(control))."); - assert_prolog_failure!(&mut wam, "?- atom(X)."); - assert_prolog_success!(&mut wam, "?- atom(a)."); - assert_prolog_failure!(&mut wam, "?- atom(\"string\")."); - assert_prolog_success!(&mut wam, "?- atom([])."); - assert_prolog_failure!(&mut wam, "?- atom(1)."); - assert_prolog_failure!(&mut wam, "?- atom(0)."); - assert_prolog_failure!(&mut wam, "?- atom(0.0)."); - assert_prolog_failure!(&mut wam, "?- atom([a,b,c])."); - assert_prolog_failure!(&mut wam, "?- atom(atop(the_trees))."); - - assert_prolog_failure!(&mut wam, "?- atomic(X)."); - assert_prolog_success!(&mut wam, "?- atomic(a)."); - assert_prolog_success!(&mut wam, "?- atomic(\"string\")."); - assert_prolog_success!(&mut wam, "?- atomic([])."); - assert_prolog_success!(&mut wam, "?- atomic(1)."); - assert_prolog_success!(&mut wam, "?- atomic(0)."); - assert_prolog_success!(&mut wam, "?- atomic(0.0)."); - assert_prolog_failure!(&mut wam, "?- atomic([a,b,c])."); - assert_prolog_failure!(&mut wam, "?- atomic(atop(the_trees))."); - - assert_prolog_success!(&mut wam, "?- var(X), X = 3, atomic(X).", [["X = 3"]]); - assert_prolog_failure!(&mut wam, "?- var(X), X = 3, var(X)."); - - assert_prolog_success!(&mut wam, "?- arg(1, f(a,b,c,d), Arg).", [["Arg = a"]]); - assert_prolog_success!(&mut wam, "?- arg(2, f(a,b,c,d), Arg).", [["Arg = b"]]); - assert_prolog_success!(&mut wam, "?- arg(3, f(a,b,c,d), Arg).", [["Arg = c"]]); - assert_prolog_success!(&mut wam, "?- arg(4, f(a,b,c,d), Arg).", [["Arg = d"]]); - - assert_prolog_success!(&mut wam, "?- catch(arg(N, f, Arg), error(E, _), true).", + assert_prolog_failure!(&mut wam, "atom(X)."); + assert_prolog_success!(&mut wam, "atom(a)."); + assert_prolog_failure!(&mut wam, "atom(\"string\")."); + assert_prolog_success!(&mut wam, "atom([])."); + assert_prolog_failure!(&mut wam, "atom(1)."); + assert_prolog_failure!(&mut wam, "atom(0)."); + assert_prolog_failure!(&mut wam, "atom(0.0)."); + assert_prolog_failure!(&mut wam, "atom([a,b,c])."); + assert_prolog_failure!(&mut wam, "atom(atop(the_trees))."); + + assert_prolog_failure!(&mut wam, "atomic(X)."); + assert_prolog_success!(&mut wam, "atomic(a)."); + assert_prolog_success!(&mut wam, "atomic(\"string\")."); + assert_prolog_success!(&mut wam, "atomic([])."); + assert_prolog_success!(&mut wam, "atomic(1)."); + assert_prolog_success!(&mut wam, "atomic(0)."); + assert_prolog_success!(&mut wam, "atomic(0.0)."); + assert_prolog_failure!(&mut wam, "atomic([a,b,c])."); + assert_prolog_failure!(&mut wam, "atomic(atop(the_trees))."); + + assert_prolog_success!(&mut wam, "var(X), X = 3, atomic(X).", [["X = 3"]]); + assert_prolog_failure!(&mut wam, "var(X), X = 3, var(X)."); + + assert_prolog_success!(&mut wam, "arg(1, f(a,b,c,d), Arg).", [["Arg = a"]]); + assert_prolog_success!(&mut wam, "arg(2, f(a,b,c,d), Arg).", [["Arg = b"]]); + assert_prolog_success!(&mut wam, "arg(3, f(a,b,c,d), Arg).", [["Arg = c"]]); + assert_prolog_success!(&mut wam, "arg(4, f(a,b,c,d), Arg).", [["Arg = d"]]); + + assert_prolog_success!(&mut wam, "catch(arg(N, f, Arg), error(E, _), true).", [["E = instantiation_error", "Arg = _3", "N = _1"]]); - assert_prolog_failure!(&mut wam, "?- arg(N, f(arg, arg, arg), not_arg)."); - assert_prolog_failure!(&mut wam, "?- arg(1, f(arg, not_arg, not_arg), not_arg)."); - assert_prolog_success!(&mut wam, "?- arg(2, f(arg, not_arg, not_arg), not_arg)."); - assert_prolog_success!(&mut wam, "?- arg(3, f(arg, not_arg, not_arg), not_arg)."); + assert_prolog_failure!(&mut wam, "arg(N, f(arg, arg, arg), not_arg)."); + assert_prolog_failure!(&mut wam, "arg(1, f(arg, not_arg, not_arg), not_arg)."); + assert_prolog_success!(&mut wam, "arg(2, f(arg, not_arg, not_arg), not_arg)."); + assert_prolog_success!(&mut wam, "arg(3, f(arg, not_arg, not_arg), not_arg)."); - assert_prolog_success!(&mut wam, "?- functor(f(a,b,c), F, Arity).", + assert_prolog_success!(&mut wam, "functor(f(a,b,c), F, Arity).", [["F = f", "Arity = 3"]]); - assert_prolog_success!(&mut wam, "?- functor(f(a,b,c), F, N).", + assert_prolog_success!(&mut wam, "functor(f(a,b,c), F, N).", [["F = f", "N = 3"]]); - assert_prolog_failure!(&mut wam, "?- functor(f(a,b,c), g, N)."); - assert_prolog_success!(&mut wam, "?- functor(f(a,b,c), F, 3).", [["F = f"]]); - assert_prolog_failure!(&mut wam, "?- functor(f(a,b,c), F, 4)."); - assert_prolog_failure!(&mut wam, "?- functor(f(a,b,c), g, 3)."); + assert_prolog_failure!(&mut wam, "functor(f(a,b,c), g, N)."); + assert_prolog_success!(&mut wam, "functor(f(a,b,c), F, 3).", [["F = f"]]); + assert_prolog_failure!(&mut wam, "functor(f(a,b,c), F, 4)."); + assert_prolog_failure!(&mut wam, "functor(f(a,b,c), g, 3)."); - assert_prolog_success!(&mut wam, "?- functor(F, f, 0).", [["F = f"]]); + assert_prolog_success!(&mut wam, "functor(F, f, 0).", [["F = f"]]); - assert_prolog_success!(&mut wam, "?- functor(Func, f, 3).", [["Func = f(_2, _3, _4)"]]); - assert_prolog_success!(&mut wam, "?- functor(Func, f, 4).", [["Func = f(_2, _3, _4, _5)"]]); + assert_prolog_success!(&mut wam, "functor(Func, f, 3).", [["Func = f(_2, _3, _4)"]]); + assert_prolog_success!(&mut wam, "functor(Func, f, 4).", [["Func = f(_2, _3, _4, _5)"]]); - assert_prolog_success!(&mut wam, "?- catch(functor(F, \"sdf\", 3), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(functor(F, \"sdf\", 3), error(E, _), true).", [["E = type_error(atom, [s, d, f])", "F = _1"]]); - assert_prolog_success!(&mut wam, "?- catch(functor(Func, F, 3), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(functor(Func, F, 3), error(E, _), true).", [["E = instantiation_error", "Func = _1", "F = _2"]]); - assert_prolog_success!(&mut wam, "?- catch(functor(Func, f, N), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(functor(Func, f, N), error(E, _), true).", [["E = instantiation_error", "Func = _1", "N = _3"]]); - assert_prolog_failure!(&mut wam, "?- catch(functor(Func, f, N), error(E, _), false)."); - - assert_prolog_success!(&mut wam, "?- X is 3, call(integer, X)."); - assert_prolog_failure!(&mut wam, "?- X is 3 + 3.5, call(integer, X)."); - assert_prolog_success!(&mut wam, "?- X is 3 + 3.5, \\+ call(integer, X)."); - assert_prolog_success!(&mut wam, "?- X is 3 + 3.5, \\+ integer(X)."); - - assert_prolog_success!(&mut wam, "?- Func =.. [atom].", [["Func = atom"]]); - assert_prolog_success!(&mut wam, "?- Func =.. [\"sdf\"].", [["Func = [s, d, f]"]]); - assert_prolog_success!(&mut wam, "?- Func =.. [1].", [["Func = 1"]]); - assert_prolog_success!(&mut wam, "?- catch(Func =.. [1,2], error(type_error(atom, 1), _), true)."); - assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. List.", [["List = [f, 1, 2, 3]"]]); - assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. [f,1,2,3]."); - assert_prolog_failure!(&mut wam, "?- f(1,2,3) =.. [f,1]."); - assert_prolog_failure!(&mut wam, "?- f(1,2,3) =.. [g,1,2,3]."); - assert_prolog_success!(&mut wam, "?- f(1,2,3) =.. [f,X,Y,Z].", + assert_prolog_failure!(&mut wam, "catch(functor(Func, f, N), error(E, _), false)."); + + assert_prolog_success!(&mut wam, "X is 3, call(integer, X)."); + assert_prolog_failure!(&mut wam, "X is 3 + 3.5, call(integer, X)."); + assert_prolog_success!(&mut wam, "X is 3 + 3.5, \\+ call(integer, X)."); + assert_prolog_success!(&mut wam, "X is 3 + 3.5, \\+ integer(X)."); + + assert_prolog_success!(&mut wam, "Func =.. [atom].", [["Func = atom"]]); + assert_prolog_success!(&mut wam, "Func =.. [\"sdf\"].", [["Func = [s, d, f]"]]); + assert_prolog_success!(&mut wam, "Func =.. [1].", [["Func = 1"]]); + assert_prolog_success!(&mut wam, "catch(Func =.. [1,2], error(type_error(atom, 1), _), true)."); + assert_prolog_success!(&mut wam, "f(1,2,3) =.. List.", [["List = [f, 1, 2, 3]"]]); + assert_prolog_success!(&mut wam, "f(1,2,3) =.. [f,1,2,3]."); + assert_prolog_failure!(&mut wam, "f(1,2,3) =.. [f,1]."); + assert_prolog_failure!(&mut wam, "f(1,2,3) =.. [g,1,2,3]."); + assert_prolog_success!(&mut wam, "f(1,2,3) =.. [f,X,Y,Z].", [["X = 1", "Y = 2", "Z = 3"]]); - assert_prolog_success!(&mut wam, "?- length([a,b,c], N).", [["N = 3"]]); - assert_prolog_success_with_limit!(&mut wam, "?- length(Xs, N).", + assert_prolog_success!(&mut wam, "length([a,b,c], N).", [["N = 3"]]); + assert_prolog_success_with_limit!(&mut wam, "length(Xs, N).", [["N = 0", "Xs = []"], ["N = 1", "Xs = [_4]"], ["N = 2", "Xs = [_4, _8]"], @@ -1495,321 +1501,320 @@ fn test_queries_on_builtins() ["N = 5", "Xs = [_4, _8, _12, _16, _20]"]], 6); - assert_prolog_success!(&mut wam, "?- length(Xs, 3).", [["Xs = [_5, _9, _13]"]]); - assert_prolog_success!(&mut wam, "?- length([], N).", [["N = 0"]]); - assert_prolog_success!(&mut wam, "?- length(Xs, 0).", [["Xs = []"]]); - assert_prolog_success!(&mut wam, "?- length([a,b,[a,b,c]], 3)."); - assert_prolog_failure!(&mut wam, "?- length([a,b,[a,b,c]], 2)."); - assert_prolog_success!(&mut wam, "?- catch(length(a, []), error(E, _), true).", + assert_prolog_success!(&mut wam, "length(Xs, 3).", [["Xs = [_5, _9, _13]"]]); + assert_prolog_success!(&mut wam, "length([], N).", [["N = 0"]]); + assert_prolog_success!(&mut wam, "length(Xs, 0).", [["Xs = []"]]); + assert_prolog_success!(&mut wam, "length([a,b,[a,b,c]], 3)."); + assert_prolog_failure!(&mut wam, "length([a,b,[a,b,c]], 2)."); + assert_prolog_success!(&mut wam, "catch(length(a, []), error(E, _), true).", [["E = type_error(integer, [])"]]); - assert_prolog_success!(&mut wam, "?- copy_term([1,2,3], [X,Y,Z]).", + assert_prolog_success!(&mut wam, "copy_term([1,2,3], [X,Y,Z]).", [["Z = 3", "Y = 2", "X = 1"]]); - assert_prolog_success!(&mut wam, "?- copy_term(f(X, [a], Z), f(X, Y, Z)).", + assert_prolog_success!(&mut wam, "copy_term(f(X, [a], Z), f(X, Y, Z)).", [["X = _3", "Y = [a]", "Z = _5"]]); - assert_prolog_failure!(&mut wam, "?- copy_term(g(X), f(X))."); - assert_prolog_success!(&mut wam, "?- copy_term(f(X), f(X)).", + assert_prolog_failure!(&mut wam, "copy_term(g(X), f(X))."); + assert_prolog_success!(&mut wam, "copy_term(f(X), f(X)).", [["X = _1"]]); - assert_prolog_success!(&mut wam, "?- copy_term([[[[X, Y], Y], X]], Term).", + assert_prolog_success!(&mut wam, "copy_term([[[[X, Y], Y], X]], Term).", [["Term = [[[[_22, _26], _26], _22]]", "X = _2", "Y = _0"]]); - assert_prolog_success!(&mut wam, "?- copy_term([X, [Y, [X]]], Term).", + assert_prolog_success!(&mut wam, "copy_term([X, [Y, [X]]], Term).", [["Term = [_12, [_16, [_12]]]", "X = _0", "Y = _4"]]); // test copy_term on cyclic terms. - assert_prolog_failure!(&mut wam, "?- X = g(X, Y), Y = f(X), copy_term(Y, g(Z))."); - assert_prolog_success!(&mut wam, "?- X = g(X, Y), Y = f(X), copy_term(Y, f(Z)).", + assert_prolog_failure!(&mut wam, "X = g(X, Y), Y = f(X), copy_term(Y, g(Z))."); + assert_prolog_success!(&mut wam, "X = g(X, Y), Y = f(X), copy_term(Y, f(Z)).", [["Y = f(g(X, Y))", "X = g(X, f(X))", "Z = g(Z, f(Z))"]]); - assert_prolog_success!(&mut wam, "?- X = g(X, Y), Y = f(X), copy_term(Y, V).", + assert_prolog_success!(&mut wam, "X = g(X, Y), Y = f(X), copy_term(Y, V).", [["Y = f(g(X, Y))", "X = g(X, f(X))", "V = f(g(_9, V))"]]); - assert_prolog_success!(&mut wam, "?- f(Y,Y,[X,a,[],Y]) = Term, copy_term(Term, NewTerm).", + assert_prolog_success!(&mut wam, "f(Y,Y,[X,a,[],Y]) = Term, copy_term(Term, NewTerm).", [["NewTerm = f(_16, _16, [_19, a, [], _16])", "Term = f(_0, Y, [_6, a, [], Y])", "X = _6", "Y = _0"]]); - assert_prolog_success!(&mut wam, "?- float(3.14159269)."); - assert_prolog_failure!(&mut wam, "?- float(3)."); - assert_prolog_failure!(&mut wam, "?- float(\"sdfsa\")."); - assert_prolog_failure!(&mut wam, "?- float(atom)."); - assert_prolog_failure!(&mut wam, "?- float(structure(functor))."); - assert_prolog_failure!(&mut wam, "?- float([1,2,3])."); - assert_prolog_failure!(&mut wam, "?- float([1,2,X])."); - assert_prolog_failure!(&mut wam, "?- X is 3 rdiv 4, float(X)."); - - assert_prolog_success!(&mut wam, "?- X is 3 rdiv 4, rational(X)."); - assert_prolog_failure!(&mut wam, "?- rational(3)."); - assert_prolog_failure!(&mut wam, "?- rational(f(X))."); - assert_prolog_failure!(&mut wam, "?- rational(\"sdfsa\")."); - assert_prolog_failure!(&mut wam, "?- rational(atom)."); - assert_prolog_failure!(&mut wam, "?- rational(structure(functor))."); - assert_prolog_failure!(&mut wam, "?- rational([1,2,3])."); - assert_prolog_failure!(&mut wam, "?- rational([1,2,X])."); - - assert_prolog_success!(&mut wam, "?- compound(functor(compound))."); - assert_prolog_success!(&mut wam, "?- compound(f(X))."); - assert_prolog_success!(&mut wam, "?- compound([1,2,3])."); - assert_prolog_failure!(&mut wam, "?- compound([])."); - assert_prolog_failure!(&mut wam, "?- compound(3.14159269)."); - assert_prolog_failure!(&mut wam, "?- compound(3)."); - assert_prolog_failure!(&mut wam, "?- compound(\"sdfsa\")."); - assert_prolog_failure!(&mut wam, "?- compound(atom)."); - - assert_prolog_failure!(&mut wam, "?- string(functor(string))."); - assert_prolog_failure!(&mut wam, "?- string(3.14159269)."); - assert_prolog_failure!(&mut wam, "?- string(3)."); - assert_prolog_failure!(&mut wam, "?- string(f(X))."); - assert_prolog_success!(&mut wam, "?- string(\"sdfsa\")."); - assert_prolog_failure!(&mut wam, "?- string(atom)."); - assert_prolog_failure!(&mut wam, "?- string([1,2,3])."); - assert_prolog_failure!(&mut wam, "?- string([1,2,X])."); - - assert_prolog_success!(&mut wam, "?- X = nonvar, nonvar(X)."); - assert_prolog_failure!(&mut wam, "?- nonvar(X)."); - assert_prolog_success!(&mut wam, "?- nonvar(f(X))."); - assert_prolog_success!(&mut wam, "?- nonvar(functor(nonvar))."); - assert_prolog_success!(&mut wam, "?- nonvar(3.14159269)."); - assert_prolog_success!(&mut wam, "?- nonvar(3)."); - assert_prolog_success!(&mut wam, "?- nonvar(\"sdfsa\")."); - assert_prolog_success!(&mut wam, "?- nonvar(atom)."); - assert_prolog_success!(&mut wam, "?- nonvar([1,2,3])."); - assert_prolog_success!(&mut wam, "?- nonvar([1,2,X])."); - - assert_prolog_success!(&mut wam, "?- A = f(A), ground(f(f(A))), ground(f(A)), ground(A)."); - assert_prolog_failure!(&mut wam, "?- B = f(A), ground(B)."); - assert_prolog_failure!(&mut wam, "?- B = f(A), ground(A)."); - - assert_prolog_success!(&mut wam, "?- ground(x), ground(f(x)), X = f(x), ground(g(f(X), [a,b]))."); - - assert_prolog_success!(&mut wam, "?- A = f(A), g(A, B) == g(f(A), B)."); - assert_prolog_failure!(&mut wam, "?- A = f(A), g(A, B) == g(f(A), b)."); - assert_prolog_failure!(&mut wam, "?- A == B."); - assert_prolog_failure!(&mut wam, "?- A == 12.1."); - assert_prolog_success!(&mut wam, "?- X = x, f(X, x) == f(x, X)."); - - assert_prolog_failure!(&mut wam, "?- A = f(A), g(A, B) \\== g(f(A), B)."); - assert_prolog_success!(&mut wam, "?- A = f(A), g(A, B) \\== g(f(A), b)."); - assert_prolog_success!(&mut wam, "?- A \\== B."); - assert_prolog_success!(&mut wam, "?- A \\== 12.1."); - assert_prolog_failure!(&mut wam, "?- X = x, f(X, x) \\== f(x, X)."); - - assert_prolog_success!(&mut wam, "?- X @=< Y."); - assert_prolog_failure!(&mut wam, "?- X @>= Y."); - assert_prolog_failure!(&mut wam, "?- X @> Y."); - assert_prolog_success!(&mut wam, "?- X @>= X."); - assert_prolog_failure!(&mut wam, "?- atom @=< \"string\"."); - assert_prolog_success!(&mut wam, "?- atom @=< atom."); - assert_prolog_failure!(&mut wam, "?- atom @=< aaa."); - assert_prolog_success!(&mut wam, "?- atom @>= \"string\"."); - assert_prolog_success!(&mut wam, "?- X is 3 + 3, X @>= Y."); - assert_prolog_success!(&mut wam, "?- f(X) @>= f(X)."); - assert_prolog_success!(&mut wam, "?- f(X) @>= a."); - assert_prolog_failure!(&mut wam, "?- f(X) @=< a."); - assert_prolog_success!(&mut wam, "?- [1,2] @=< [1,2]."); - assert_prolog_failure!(&mut wam, "?- [1,2,3] @=< [1,2]."); - assert_prolog_success!(&mut wam, "?- [] @=< [1,2]."); - assert_prolog_failure!(&mut wam, "?- [] @< 1."); - assert_prolog_failure!(&mut wam, "?- [] @< \"string\"."); - assert_prolog_failure!(&mut wam, "?- [] @< atom."); - assert_prolog_success!(&mut wam, "?- atom @< []."); - assert_prolog_failure!(&mut wam, "?- 1.1 @< 1."); - assert_prolog_success!(&mut wam, "?- 1.0 @=< 1."); - assert_prolog_success!(&mut wam, "?- 1 @=< 1.0."); //TODO: currently this succeeds. make it fail. - - assert_prolog_success!(&mut wam, "?- X =@= Y."); - assert_prolog_failure!(&mut wam, "?- f(X) =@= f(x)."); - assert_prolog_failure!(&mut wam, "?- X \\=@= X."); - assert_prolog_success!(&mut wam, "?- f(x) =@= f(x)."); - assert_prolog_failure!(&mut wam, "?- [X,Y,Z] =@= [V,W,V]."); - assert_prolog_success!(&mut wam, "?- [X,Y,Z] =@= [V,W,Z]."); - assert_prolog_success!(&mut wam, "?- [X,Y,X] =@= [V,W,V]."); - assert_prolog_success!(&mut wam, "?- g(B) = B, g(A) = A, A =@= B."); - - assert_prolog_success!(&mut wam, "?- keysort([1-1, 1-1], Sorted).", + assert_prolog_success!(&mut wam, "float(3.14159269)."); + assert_prolog_failure!(&mut wam, "float(3)."); + assert_prolog_failure!(&mut wam, "float(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "float(atom)."); + assert_prolog_failure!(&mut wam, "float(structure(functor))."); + assert_prolog_failure!(&mut wam, "float([1,2,3])."); + assert_prolog_failure!(&mut wam, "float([1,2,X])."); + assert_prolog_failure!(&mut wam, "X is 3 rdiv 4, float(X)."); + + assert_prolog_success!(&mut wam, "X is 3 rdiv 4, rational(X)."); + assert_prolog_failure!(&mut wam, "rational(3)."); + assert_prolog_failure!(&mut wam, "rational(f(X))."); + assert_prolog_failure!(&mut wam, "rational(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "rational(atom)."); + assert_prolog_failure!(&mut wam, "rational(structure(functor))."); + assert_prolog_failure!(&mut wam, "rational([1,2,3])."); + assert_prolog_failure!(&mut wam, "rational([1,2,X])."); + + assert_prolog_success!(&mut wam, "compound(functor(compound))."); + assert_prolog_success!(&mut wam, "compound(f(X))."); + assert_prolog_success!(&mut wam, "compound([1,2,3])."); + assert_prolog_failure!(&mut wam, "compound([])."); + assert_prolog_failure!(&mut wam, "compound(3.14159269)."); + assert_prolog_failure!(&mut wam, "compound(3)."); + assert_prolog_failure!(&mut wam, "compound(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "compound(atom)."); + + assert_prolog_failure!(&mut wam, "string(functor(string))."); + assert_prolog_failure!(&mut wam, "string(3.14159269)."); + assert_prolog_failure!(&mut wam, "string(3)."); + assert_prolog_failure!(&mut wam, "string(f(X))."); + assert_prolog_success!(&mut wam, "string(\"sdfsa\")."); + assert_prolog_failure!(&mut wam, "string(atom)."); + assert_prolog_failure!(&mut wam, "string([1,2,3])."); + assert_prolog_failure!(&mut wam, "string([1,2,X])."); + + assert_prolog_success!(&mut wam, "X = nonvar, nonvar(X)."); + assert_prolog_failure!(&mut wam, "nonvar(X)."); + assert_prolog_success!(&mut wam, "nonvar(f(X))."); + assert_prolog_success!(&mut wam, "nonvar(functor(nonvar))."); + assert_prolog_success!(&mut wam, "nonvar(3.14159269)."); + assert_prolog_success!(&mut wam, "nonvar(3)."); + assert_prolog_success!(&mut wam, "nonvar(\"sdfsa\")."); + assert_prolog_success!(&mut wam, "nonvar(atom)."); + assert_prolog_success!(&mut wam, "nonvar([1,2,3])."); + assert_prolog_success!(&mut wam, "nonvar([1,2,X])."); + + assert_prolog_success!(&mut wam, "A = f(A), ground(f(f(A))), ground(f(A)), ground(A)."); + assert_prolog_failure!(&mut wam, "B = f(A), ground(B)."); + assert_prolog_failure!(&mut wam, "B = f(A), ground(A)."); + + assert_prolog_success!(&mut wam, "ground(x), ground(f(x)), X = f(x), ground(g(f(X), [a,b]))."); + + assert_prolog_success!(&mut wam, "A = f(A), g(A, B) == g(f(A), B)."); + assert_prolog_failure!(&mut wam, "A = f(A), g(A, B) == g(f(A), b)."); + assert_prolog_failure!(&mut wam, "A == B."); + assert_prolog_failure!(&mut wam, "A == 12.1."); + assert_prolog_success!(&mut wam, "X = x, f(X, x) == f(x, X)."); + + assert_prolog_failure!(&mut wam, "A = f(A), g(A, B) \\== g(f(A), B)."); + assert_prolog_success!(&mut wam, "A = f(A), g(A, B) \\== g(f(A), b)."); + assert_prolog_success!(&mut wam, "A \\== B."); + assert_prolog_success!(&mut wam, "A \\== 12.1."); + assert_prolog_failure!(&mut wam, "X = x, f(X, x) \\== f(x, X)."); + + assert_prolog_success!(&mut wam, "X @=< Y."); + assert_prolog_failure!(&mut wam, "X @>= Y."); + assert_prolog_failure!(&mut wam, "X @> Y."); + assert_prolog_success!(&mut wam, "X @>= X."); + assert_prolog_failure!(&mut wam, "atom @=< \"string\"."); + assert_prolog_success!(&mut wam, "atom @=< atom."); + assert_prolog_failure!(&mut wam, "atom @=< aaa."); + assert_prolog_success!(&mut wam, "atom @>= \"string\"."); + assert_prolog_success!(&mut wam, "X is 3 + 3, X @>= Y."); + assert_prolog_success!(&mut wam, "f(X) @>= f(X)."); + assert_prolog_success!(&mut wam, "f(X) @>= a."); + assert_prolog_failure!(&mut wam, "f(X) @=< a."); + assert_prolog_success!(&mut wam, "[1,2] @=< [1,2]."); + assert_prolog_failure!(&mut wam, "[1,2,3] @=< [1,2]."); + assert_prolog_success!(&mut wam, "[] @=< [1,2]."); + assert_prolog_failure!(&mut wam, "[] @< 1."); + assert_prolog_failure!(&mut wam, "[] @< \"string\"."); + assert_prolog_failure!(&mut wam, "[] @< atom."); + assert_prolog_success!(&mut wam, "atom @< []."); + assert_prolog_failure!(&mut wam, "1.1 @< 1."); + assert_prolog_success!(&mut wam, "1.0 @=< 1."); + assert_prolog_success!(&mut wam, "1 @=< 1.0."); //TODO: currently this succeeds. make it fail. + + assert_prolog_success!(&mut wam, "X =@= Y."); + assert_prolog_failure!(&mut wam, "f(X) =@= f(x)."); + assert_prolog_failure!(&mut wam, "X \\=@= X."); + assert_prolog_success!(&mut wam, "f(x) =@= f(x)."); + assert_prolog_failure!(&mut wam, "[X,Y,Z] =@= [V,W,V]."); + assert_prolog_success!(&mut wam, "[X,Y,Z] =@= [V,W,Z]."); + assert_prolog_success!(&mut wam, "[X,Y,X] =@= [V,W,V]."); + assert_prolog_success!(&mut wam, "g(B) = B, g(A) = A, A =@= B."); + + assert_prolog_success!(&mut wam, "keysort([1-1, 1-1], Sorted).", [["Sorted = [1-1, 1-1]"]]); - assert_prolog_success!(&mut wam, "?- keysort([2-99, 1-a, 3-f(_), 1-z, 1-a, 2-44], Sorted).", + assert_prolog_success!(&mut wam, "keysort([2-99, 1-a, 3-f(_), 1-z, 1-a, 2-44], Sorted).", [["Sorted = [1-a, 1-z, 1-a, 2-99, 2-44, 3-f(_7)]"]]); - assert_prolog_success!(&mut wam, "?- keysort([X-1,1-1],[2-1,1-1]).", + assert_prolog_success!(&mut wam, "keysort([X-1,1-1],[2-1,1-1]).", [["X = 2"]]); - assert_prolog_failure!(&mut wam, "?- Pairs = [a-a|Pairs], keysort(Pairs, _)."); - assert_prolog_success!(&mut wam, "?- Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).", + assert_prolog_failure!(&mut wam, "Pairs = [a-a|Pairs], keysort(Pairs, _)."); + assert_prolog_success!(&mut wam, "Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).", [["E = type_error(list, [a-a | _25])", "Pairs = [a-a | Pairs]"]]); - assert_prolog_success!(&mut wam, "?- keysort([], L).", + assert_prolog_success!(&mut wam, "keysort([], L).", [["L = []"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort([a|_], _), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(keysort([a|_], _), error(E, _), true).", [["E = instantiation_error"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort([],[a|a]),error(Pat, _),true).", + assert_prolog_success!(&mut wam, "catch(keysort([],[a|a]),error(Pat, _),true).", [["Pat = type_error(list, [a | a])"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort(_, _), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(keysort(_, _), error(E, _), true).", [["E = type_error(list, _16)"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [_|b]), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(keysort([a-1], [_|b]), error(E, _), true).", [["E = type_error(list, [_27 | b])"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [a-b,c-d,a]), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(keysort([a-1], [a-b,c-d,a]), error(E, _), true).", [["E = type_error(pair, a)"]]); - assert_prolog_success!(&mut wam, "?- catch(keysort([a], [a-b]), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(keysort([a], [a-b]), error(E, _), true).", [["E = type_error(pair, a)"]]); - assert_prolog_success!(&mut wam, "?- catch(sort([a|_], _), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(sort([a|_], _), error(E, _), true).", [["E = instantiation_error"]]); - assert_prolog_success!(&mut wam, "?- catch(sort([],[a|a]),error(Pat, _),true).", + assert_prolog_success!(&mut wam, "catch(sort([],[a|a]),error(Pat, _),true).", [["Pat = type_error(list, [a | a])"]]); - assert_prolog_success!(&mut wam, "?- sort([], L).", + assert_prolog_success!(&mut wam, "sort([], L).", [["L = []"]]); - assert_prolog_success!(&mut wam, "?- catch(sort(_, []), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(sort(_, []), error(E, _), true).", [["E = type_error(list, _16)"]]); - assert_prolog_success!(&mut wam, "?- catch(sort([a,b,c], not_a_list), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(sort([a,b,c], not_a_list), error(E, _), true).", [["E = type_error(list, not_a_list)"]]); - assert_prolog_success!(&mut wam, "?- call(((G = 2 ; fail), B=3, !)).", + assert_prolog_success!(&mut wam, "call(((G = 2 ; fail), B=3, !)).", [["G = 2", "B = 3"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 100, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 100, R).", [["G = 2", "B = 3", "R = !", "S = 1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 10, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 10, R).", [["S = _1", "G = _4", "B = _14", "R = inference_limit_exceeded"]]); - assert_prolog_success!(&mut wam, "?- X = '\\033\\'.", + assert_prolog_success!(&mut wam, "X = '\\033\\'.", [["X = '\\x1b\\'"]]); - - assert_prolog_success!(&mut wam, "?- X = '\\n'.", + + assert_prolog_success!(&mut wam, "X = '\\n'.", [["X = '\\n'"]]); - assert_prolog_success!(&mut wam, "?- X = '\\b'.", + assert_prolog_success!(&mut wam, "X = '\\b'.", [["X = '\\b'"]]); - assert_prolog_success!(&mut wam, "?- X = '\\v'.", + assert_prolog_success!(&mut wam, "X = '\\v'.", [["X = '\\v'"]]); - assert_prolog_success!(&mut wam, "?- X = '\\a'.", + assert_prolog_success!(&mut wam, "X = '\\a'.", [["X = '\\a'"]]); - assert_prolog_success!(&mut wam, "?- X = '\\f'.", + assert_prolog_success!(&mut wam, "X = '\\f'.", [["X = '\\f'"]]); - assert_prolog_success!(&mut wam, "?- X = '\\b\\r\\f\\t\\n'.", + assert_prolog_success!(&mut wam, "X = '\\b\\r\\f\\t\\n'.", [["X = '\\b\\r\\f\\t\\n'"]]); - assert_prolog_success!(&mut wam, "?- (- (1)) = -(1)."); - assert_prolog_success!(&mut wam, "?- (- -1) = -(-1)."); - - assert_prolog_success!(&mut wam, "?- X = ((*)=(*)).", + assert_prolog_success!(&mut wam, "(- (1)) = -(1)."); + assert_prolog_success!(&mut wam, "(- -1) = -(-1)."); + + assert_prolog_success!(&mut wam, "X = ((*)=(*)).", [["X = ((*)=(*))"]]); - assert_prolog_success!(&mut wam, "?- X = [.,.(.,.,.)].", + assert_prolog_success!(&mut wam, "X = [.,.(.,.,.)].", [["X = ['.', '.'('.', '.', '.')]"]]); - assert_prolog_success!(&mut wam, "?- X = a+(b*c).", + assert_prolog_success!(&mut wam, "X = a+(b*c).", [["X = a+b*c"]]); - assert_prolog_success!(&mut wam, "?- X = a*(b+c).", + assert_prolog_success!(&mut wam, "X = a*(b+c).", [["X = a*(b+c)"]]); - assert_prolog_success!(&mut wam, "?- X = [:-,-].", + assert_prolog_success!(&mut wam, "X = [:-,-].", [["X = [:-, -]"]]); - assert_prolog_success!(&mut wam, "?- X = a*(b+c).", + assert_prolog_success!(&mut wam, "X = a*(b+c).", [["X = a*(b+c)"]]); - assert_prolog_success!(&mut wam, "?- X = (-)-(-).", + assert_prolog_success!(&mut wam, "X = (-)-(-).", [["X = (-)-(-)"]]); - assert_prolog_success!(&mut wam, "?- X = ((:-):-(:-)).", + assert_prolog_success!(&mut wam, "X = ((:-):-(:-)).", [["X = ((:-):-(:-))"]]); - assert_prolog_success!(&mut wam, "?- X = (a:-b,c).", + assert_prolog_success!(&mut wam, "X = (a:-b,c).", [["X = (a:-b,c)"]]); - assert_prolog_success!(&mut wam, "?- X = f((f:-a,b,c)).", + assert_prolog_success!(&mut wam, "X = f((f:-a,b,c)).", [["X = f((f:-a,b,c))"]]); - assert_prolog_success!(&mut wam, "?- X = f((f:-a,(b,c))).", + assert_prolog_success!(&mut wam, "X = f((f:-a,(b,c))).", [["X = f((f:-a,b,c))"]]); - assert_prolog_success!(&mut wam, "?- X = f((a,b,c)).", + assert_prolog_success!(&mut wam, "X = f((a,b,c)).", [["X = f((a,b,c))"]]); - assert_prolog_success!(&mut wam, "?- X = f((a,(b,c))).", + assert_prolog_success!(&mut wam, "X = f((a,(b,c))).", [["X = f((a,b,c))"]]); - assert_prolog_success!(&mut wam, "?- X = f(((a,b),c)).", + assert_prolog_success!(&mut wam, "X = f(((a,b),c)).", [["X = f(((a,b),c))"]]); - assert_prolog_success!(&mut wam, "?- X = f(((a,b),(c, d))).", + assert_prolog_success!(&mut wam, "X = f(((a,b),(c, d))).", [["X = f(((a,b),c,d))"]]); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), S).", + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 2), S).", [["S = [1, 2]", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- findall(X+Y, (X = 1), S).", + assert_prolog_success!(&mut wam, "findall(X+Y, (X = 1), S).", [["S = [1+_36]", "X = _1", "Y = _2"]]); - assert_prolog_success!(&mut wam, "?- findall(X, false, S).", + assert_prolog_success!(&mut wam, "findall(X, false, S).", [["S = []", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 1), S).", + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 1), S).", [["S = [1, 1]", "X = _0"]]); - assert_prolog_failure!(&mut wam, "?- findall(X, (X = 2 ; X = 1), [1, 2])."); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), [X, Y]).", + assert_prolog_failure!(&mut wam, "findall(X, (X = 2 ; X = 1), [1, 2])."); + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 2), [X, Y]).", [["X = 1", "Y = 2"]]); - assert_prolog_success!(&mut wam, "?- catch(findall(X, 4, S), error(type_error(callable, 4), _), true).", + assert_prolog_success!(&mut wam, "catch(findall(X, 4, S), error(type_error(callable, 4), _), true).", [["S = _3", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- bagof(X, (X=Y; X=Z), S).", + assert_prolog_success!(&mut wam, "bagof(X, (X=Y; X=Z), S).", [["S = [_3, _6]", "X = _0", "Y = _3", "Z = _6"]]); - assert_prolog_success!(&mut wam, "?- bagof(X, (X=1 ; X = 2), X).", + assert_prolog_success!(&mut wam, "bagof(X, (X=1 ; X = 2), X).", [["X = [1, 2]"]]); - assert_prolog_success!(&mut wam, "?- bagof(X, (X=1 ; X = 2), S).", + assert_prolog_success!(&mut wam, "bagof(X, (X=1 ; X = 2), S).", [["S = [1, 2]", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- bagof(1, (Y=1 ; Y=2), L).", + assert_prolog_success!(&mut wam, "bagof(1, (Y=1 ; Y=2), L).", [["L = [1]", "Y = 1"], ["L = [1]", "Y = 2"]]); submit(&mut wam, "b(1, 1). b(1, 1). b(1, 2). b(2, 1). b(2, 2). b(2, 2)."); - assert_prolog_success!(&mut wam, "?- bagof(X, b(X, Y), L).", + assert_prolog_success!(&mut wam, "bagof(X, b(X, Y), L).", [["L = [1, Y, 2]", "X = _0", "Y = 1"], ["L = [1, 2, Y]", "X = _0", "Y = 2"]]); - assert_prolog_success!(&mut wam, "?- bagof(X, (X=Y; X=Z; Y=1), L).", + assert_prolog_success!(&mut wam, "bagof(X, (X=Y; X=Z; Y=1), L).", [["L = [_3, _6]", "X = _0", "Y = _3", "Z = _6"], ["L = [_112]", "X = _0", "Y = 1", "Z = _6"]]); submit(&mut wam, "a(1, f(_)). a(2, f(_))."); - assert_prolog_success!(&mut wam, "?- bagof(X, a(X, Y), L).", + assert_prolog_success!(&mut wam, "bagof(X, a(X, Y), L).", [["L = [1, 2]", "X = _0", "Y = f(_78)"]]); - assert_prolog_success!(&mut wam, "?- setof(X, (X = 1 ; X = 2), S).", + assert_prolog_success!(&mut wam, "setof(X, (X = 1 ; X = 2), S).", [["S = [1, 2]", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- setof(X, (X=Y ; X=Z), S).", + assert_prolog_success!(&mut wam, "setof(X, (X=Y ; X=Z), S).", [["S = [_3, _6]", "X = _0", "Y = _3", "Z = _6"]]); - assert_prolog_failure!(&mut wam, "?- setof(X, false, S)."); - assert_prolog_success!(&mut wam, "?- setof(1, (Y=1 ; Y=2), L).", + assert_prolog_failure!(&mut wam, "setof(X, false, S)."); + assert_prolog_success!(&mut wam, "setof(1, (Y=1 ; Y=2), L).", [["L = [1]", "Y = 1"], ["L = [1]", "Y = 2"]]); - assert_prolog_success!(&mut wam, "?- setof(X, (X=Y; X=Z; Y=1), L).", + assert_prolog_success!(&mut wam, "setof(X, (X=Y; X=Z; Y=1), L).", [["L = [_3, _6]", "X = _0", "Y = _3", "Z = _6"], ["L = [_112]", "Y = 1", "X = _0", "Y = 1", "Z = _6"]]); - assert_prolog_failure!(&mut wam, "?- setof(X, member(X, [f(U,b),f(V,c)]), [f(a,c),f(a,b)])."); - assert_prolog_success!(&mut wam, "?- setof(X, member(X, [f(U,b),f(V,c)]), [f(a,b),f(a,c)]).", + assert_prolog_failure!(&mut wam, "setof(X, member(X, [f(U,b),f(V,c)]), [f(a,c),f(a,b)])."); + assert_prolog_success!(&mut wam, "setof(X, member(X, [f(U,b),f(V,c)]), [f(a,b),f(a,c)]).", [["U = a", "V = a", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- setof(X, member(X, [V,U,f(U),f(V)]), L).", + assert_prolog_success!(&mut wam, "setof(X, member(X, [V,U,f(U),f(V)]), L).", [["L = [_2, _4, f(U), f(V)]", "U = _2", "V = _4", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- setof(X, member(X, [V,U,f(U),f(V)]), [a,b,f(a),f(b)]).", + assert_prolog_success!(&mut wam, "setof(X, member(X, [V,U,f(U),f(V)]), [a,b,f(a),f(b)]).", [["U = a", "V = b", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), S0, S1).", + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 2), S0, S1).", [["S0 = [1, 2 | _11]", "S1 = _11", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- findall(X+Y, (X = 1), S0, S1).", + assert_prolog_success!(&mut wam, "findall(X+Y, (X = 1), S0, S1).", [["S0 = [1+_44 | _7]", "S1 = _7", "X = _1", "Y = _2"]]); - assert_prolog_success!(&mut wam, "?- findall(X, false, S, _).", + assert_prolog_success!(&mut wam, "findall(X, false, S, _).", [["S = []", "X = _0"]]); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 1), S0, S1).", + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 1), S0, S1).", [["S0 = [1, 1 | _11]", "S1 = _11", "X = _0"]]); - assert_prolog_failure!(&mut wam, "?- findall(X, (X = 2 ; X = 1), [1, 2 | S], S)."); - assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), [X, Y | S], S).", + assert_prolog_failure!(&mut wam, "findall(X, (X = 2 ; X = 1), [1, 2 | S], S)."); + assert_prolog_success!(&mut wam, "findall(X, (X = 1 ; X = 2), [X, Y | S], S).", [["S = _11", "X = 1", "Y = 2"]]); - assert_prolog_success!(&mut wam, "?- catch(findall(X, 4, S0, S1), error(type_error(callable, 4), _), true).", + assert_prolog_success!(&mut wam, "catch(findall(X, 4, S0, S1), error(type_error(callable, 4), _), true).", [["S0 = _3", "S1 = _4", "X = _1"]]); // bagof & setof with existential variables. - assert_prolog_success!(&mut wam, "?- bagof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", + assert_prolog_success!(&mut wam, "bagof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", [["S = [1, 2]", "X = _0", "Y = _5"]]); - assert_prolog_success!(&mut wam, "?- bagof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", + assert_prolog_success!(&mut wam, "bagof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", [["S = [1, _126, 2]", "X = _0", "Y = _5"]]); - assert_prolog_success!(&mut wam, "?- setof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", + assert_prolog_success!(&mut wam, "setof(X, Y^((X = 1, Y = 1; (X = 2, Y = 2))), S).", [["S = [1, 2]", "X = _0", "Y = _5"]]); - assert_prolog_success!(&mut wam, "?- setof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", + assert_prolog_success!(&mut wam, "setof(X, Y^((X = 1 ; Y = 1) ; (X = 2, Y = 2)), S).", [["S = [_126, 1, 2]", "X = _0", "Y = _5"]]); - assert_prolog_success!(&mut wam, "?- setof(X, (exists(U,V) ^ member(X, [V,U,f(U),f(V)])), [a,b,f(b),f(a)])."); submit(&mut wam, ":- use_module(library(non_iso))."); - - assert_prolog_failure!(&mut wam, "?- forall(true, false)."); - assert_prolog_success!(&mut wam, "?- forall(false, true)."); - assert_prolog_success!(&mut wam, "?- catch(forall(_, true), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- catch(forall(true, _), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- catch(forall(1, true), error(type_error(callable, 1), _), true)."); - assert_prolog_success!(&mut wam, "?- catch(forall(true, 1), error(type_error(callable, 1), _), true)."); + + assert_prolog_failure!(&mut wam, "forall(true, false)."); + assert_prolog_success!(&mut wam, "forall(false, true)."); + assert_prolog_success!(&mut wam, "catch(forall(_, true), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "catch(forall(true, _), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "catch(forall(1, true), error(type_error(callable, 1), _), true)."); + assert_prolog_success!(&mut wam, "catch(forall(true, 1), error(type_error(callable, 1), _), true)."); submit(&mut wam, " :- dynamic(cat/0). @@ -1828,32 +1833,32 @@ legs(A, 7) :- A, call(A). insect(ant). insect(bee)."); - assert_prolog_success!(&mut wam, "?- clause(cat, true)."); - assert_prolog_success!(&mut wam, "?- clause(dog, true)."); - assert_prolog_success!(&mut wam, "?- clause(legs(I, 6), Body).", + assert_prolog_success!(&mut wam, "clause(cat, true)."); + assert_prolog_success!(&mut wam, "clause(dog, true)."); + assert_prolog_success!(&mut wam, "clause(legs(I, 6), Body).", [["I = _1", "Body = insect(_1)"]]); - assert_prolog_success!(&mut wam, "?- clause(legs(C, 7), Body).", + assert_prolog_success!(&mut wam, "clause(legs(C, 7), Body).", [["C = _1", "Body = ','(_1, call(C))"]]); - assert_prolog_success!(&mut wam, "?- clause(insect(I), T).", + assert_prolog_success!(&mut wam, "clause(insect(I), T).", [["I = ant", "T = true"], ["I = bee", "T = true"]]); - assert_prolog_failure!(&mut wam, "?- clause(x, Body)."); - assert_prolog_success!(&mut wam, "?- catch(clause(_, _), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- catch(clause(4, _), error(type_error(callable, 4), _), true)."); - assert_prolog_success!(&mut wam, "?- catch(clause(elk(N), _), error(permission_error(access, private_procedure, elk/1), _), true)."); - assert_prolog_success!(&mut wam, "?- catch(clause(atom(N), _), error(permission_error(access, private_procedure, atom/1), _), true)."); - - assert_prolog_success!(&mut wam, "?- asserta(legs(octopus, 8))."); - assert_prolog_success!(&mut wam, "?- asserta( (legs(A, 4) :- animal(A)) )."); - assert_prolog_success!(&mut wam, "?- asserta( (foo(X) :- X, call(X)) )."); - assert_prolog_success!(&mut wam, "?- catch(asserta(_), error(instantiation_error, _), true)."); - assert_prolog_failure!(&mut wam, "?- asserta(_)."); - assert_prolog_success!(&mut wam, "?- catch(asserta(4), error(type_error(callable, 4), _), true)."); - assert_prolog_failure!(&mut wam, "?- asserta(4)."); - assert_prolog_success!(&mut wam, "?- catch(asserta( (foo :- 4) ), error(type_error(callable, 4), _), true)."); - assert_prolog_failure!(&mut wam, "?- asserta( (foo :- 4) )."); - assert_prolog_success!(&mut wam, "?- catch(asserta( (atom(_) :- true) ), error(permission_error(modify, static_procedure, atom/1), _), true)."); - assert_prolog_failure!(&mut wam, "?- asserta( (atom(_) :- true) )."); + assert_prolog_failure!(&mut wam, "clause(x, Body)."); + assert_prolog_success!(&mut wam, "catch(clause(_, _), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "catch(clause(4, _), error(type_error(callable, 4), _), true)."); + assert_prolog_success!(&mut wam, "catch(clause(elk(N), _), error(permission_error(access, private_procedure, elk/1), _), true)."); + assert_prolog_success!(&mut wam, "catch(clause(atom(N), _), error(permission_error(access, private_procedure, atom/1), _), true)."); + + assert_prolog_success!(&mut wam, "asserta(legs(octopus, 8))."); + assert_prolog_success!(&mut wam, "asserta( (legs(A, 4) :- animal(A)) )."); + assert_prolog_success!(&mut wam, "asserta( (foo(X) :- X, call(X)) )."); + assert_prolog_success!(&mut wam, "catch(asserta(_), error(instantiation_error, _), true)."); + assert_prolog_failure!(&mut wam, "asserta(_)."); + assert_prolog_success!(&mut wam, "catch(asserta(4), error(type_error(callable, 4), _), true)."); + assert_prolog_failure!(&mut wam, "asserta(4)."); + assert_prolog_success!(&mut wam, "catch(asserta( (foo :- 4) ), error(type_error(callable, 4), _), true)."); + assert_prolog_failure!(&mut wam, "asserta( (foo :- 4) )."); + assert_prolog_success!(&mut wam, "catch(asserta( (atom(_) :- true) ), error(permission_error(modify, static_procedure, atom/1), _), true)."); + assert_prolog_failure!(&mut wam, "asserta( (atom(_) :- true) )."); submit(&mut wam, " :- dynamic(cat/0). @@ -1872,17 +1877,17 @@ legs(A, 7) :- A, call(A). insect(ant). insect(bee)."); - assert_prolog_success!(&mut wam, "?- assertz(legs(octopus, 8))."); - assert_prolog_success!(&mut wam, "?- assertz( (legs(A, 4) :- animal(A)) )."); - assert_prolog_success!(&mut wam, "?- assertz( (foo(X) :- X, call(X)) )."); - assert_prolog_success!(&mut wam, "?- catch(assertz(_), error(instantiation_error, _), true)."); - assert_prolog_failure!(&mut wam, "?- assertz(_)."); - assert_prolog_success!(&mut wam, "?- catch(assertz(4), error(type_error(callable, 4), _), true)."); - assert_prolog_failure!(&mut wam, "?- assertz(4)."); - assert_prolog_success!(&mut wam, "?- catch(assertz( (foo :- 4) ), error(type_error(callable, 4), _), true)."); - assert_prolog_failure!(&mut wam, "?- assertz( (foo :- 4) )."); - assert_prolog_success!(&mut wam, "?- catch(assertz( (atom(_) :- true) ), error(permission_error(modify, static_procedure, atom/1), _), true)."); - assert_prolog_failure!(&mut wam, "?- assertz( (atom(_) :- true) )."); + assert_prolog_success!(&mut wam, "assertz(legs(octopus, 8))."); + assert_prolog_success!(&mut wam, "assertz( (legs(A, 4) :- animal(A)) )."); + assert_prolog_success!(&mut wam, "assertz( (foo(X) :- X, call(X)) )."); + assert_prolog_success!(&mut wam, "catch(assertz(_), error(instantiation_error, _), true)."); + assert_prolog_failure!(&mut wam, "assertz(_)."); + assert_prolog_success!(&mut wam, "catch(assertz(4), error(type_error(callable, 4), _), true)."); + assert_prolog_failure!(&mut wam, "assertz(4)."); + assert_prolog_success!(&mut wam, "catch(assertz( (foo :- 4) ), error(type_error(callable, 4), _), true)."); + assert_prolog_failure!(&mut wam, "assertz( (foo :- 4) )."); + assert_prolog_success!(&mut wam, "catch(assertz( (atom(_) :- true) ), error(permission_error(modify, static_procedure, atom/1), _), true)."); + assert_prolog_failure!(&mut wam, "assertz( (atom(_) :- true) )."); submit(&mut wam, " :- dynamic(legs/2). @@ -1900,29 +1905,29 @@ insect(bee). foo(X) :- call(X), call(X). foo(X) :- call(X) -> call(X)."); - assert_prolog_success!(&mut wam, "?- retract(legs(octopus, 8))."); - assert_prolog_failure!(&mut wam, "?- retract(legs(spider, 6))."); - assert_prolog_success!(&mut wam, "?- retract( (legs(X, 2) :- T) ).", + assert_prolog_success!(&mut wam, "retract(legs(octopus, 8))."); + assert_prolog_failure!(&mut wam, "retract(legs(spider, 6))."); + assert_prolog_success!(&mut wam, "retract( (legs(X, 2) :- T) ).", [["X = _1", "T = bird(_1)"]]); - assert_prolog_success!(&mut wam, "?- retract( (legs(X, Y) :- Z) ).", + assert_prolog_success!(&mut wam, "retract( (legs(X, Y) :- Z) ).", [["X = _1", "Y = 4", "Z = animal(_1)"], ["X = _1", "Y = 6", "Z = insect(_1)"], ["X = spider", "Y = 8", "Z = true"]]); - assert_prolog_failure!(&mut wam, "?- retract( (legs(X, Y) :- Z) )."); - assert_prolog_success!(&mut wam, "?- retract(insect(I)).", + assert_prolog_failure!(&mut wam, "retract( (legs(X, Y) :- Z) )."); + assert_prolog_success!(&mut wam, "retract(insect(I)).", [["I = ant"], ["I = bee"]]); - assert_prolog_success!(&mut wam, "?- retract(( foo(A) :- A, call(A) )).", + assert_prolog_success!(&mut wam, "retract(( foo(A) :- A, call(A) )).", [["A = call(A)"]]); - assert_prolog_success!(&mut wam, "?- foo(atom(atom))."); - assert_prolog_success!(&mut wam, "?- retract(( foo(C) :- A -> B )).", + assert_prolog_success!(&mut wam, "foo(atom(atom))."); + assert_prolog_success!(&mut wam, "retract(( foo(C) :- A -> B )).", [["A = call(_1)", "B = call(_1)", "C = _1"]]); - assert_prolog_failure!(&mut wam, "?- retract( (X :- in_eec(Y)) )."); - assert_prolog_success!(&mut wam, "?- catch(retract( (X :- in_eec(Y)) ), error(instantiation_error, _), true)."); - assert_prolog_failure!(&mut wam, "?- retract( (4 :- X) )."); - assert_prolog_success!(&mut wam, "?- catch(retract( (4 :- X) ), error(type_error(callable, 4), _), true)."); - assert_prolog_failure!(&mut wam, "?- retract( (atom(X) :- X == '[]') )."); - assert_prolog_success!(&mut wam, "?- catch(retract( (atom(X) :- X == '[]') ), error(permission_error(modify, static_procedure, atom/1), _), true)."); + assert_prolog_failure!(&mut wam, "retract( (X :- in_eec(Y)) )."); + assert_prolog_success!(&mut wam, "catch(retract( (X :- in_eec(Y)) ), error(instantiation_error, _), true)."); + assert_prolog_failure!(&mut wam, "retract( (4 :- X) )."); + assert_prolog_success!(&mut wam, "catch(retract( (4 :- X) ), error(type_error(callable, 4), _), true)."); + assert_prolog_failure!(&mut wam, "retract( (atom(X) :- X == '[]') )."); + assert_prolog_success!(&mut wam, "catch(retract( (atom(X) :- X == '[]') ), error(permission_error(modify, static_procedure, atom/1), _), true)."); /* This example shows why machine::compile::localize_self_calls is necessary. */ submit(&mut wam, " @@ -1933,37 +1938,37 @@ p(b). p(c) :- p(d). p(d)."); - assert_prolog_success!(&mut wam, "?- p(X), retract(p(_)).", + assert_prolog_success!(&mut wam, "p(X), retract(p(_)).", [["X = a"], ["X = a"], ["X = a"]]); - + submit(&mut wam, " :- dynamic(foo/1). foo(X) :- call(X), call(X). foo(X) :- call(X) -> call(X)."); - assert_prolog_success!(&mut wam, "?- abolish(foo/2)."); - assert_prolog_failure!(&mut wam, "?- abolish(foo/_)."); - assert_prolog_success!(&mut wam, "?- catch(abolish(foo/_), error(instantiation_error, abolish/1), true)."); - assert_prolog_failure!(&mut wam, "?- abolish(foo)."); - assert_prolog_success!(&mut wam, "?- catch(abolish(foo), error(type_error(predicate_indicator, foo), abolish/1), true)."); - assert_prolog_failure!(&mut wam, "?- abolish(foo(_))."); - assert_prolog_success!(&mut wam, "?- catch(abolish(foo(_)), error(type_error(predicate_indicator, foo(_)), abolish/1), true)."); - assert_prolog_failure!(&mut wam, "?- abolish(abolish/1)."); - assert_prolog_success!(&mut wam, "?- catch(abolish(abolish/1), error(permission_error(modify, static_procedure, abolish/1), abolish/1), true)."); - - assert_prolog_success!(&mut wam, "?- atom_length('enchanted evening', N).", + assert_prolog_success!(&mut wam, "abolish(foo/2)."); + assert_prolog_failure!(&mut wam, "abolish(foo/_)."); + assert_prolog_success!(&mut wam, "catch(abolish(foo/_), error(instantiation_error, abolish/1), true)."); + assert_prolog_failure!(&mut wam, "abolish(foo)."); + assert_prolog_success!(&mut wam, "catch(abolish(foo), error(type_error(predicate_indicator, foo), abolish/1), true)."); + assert_prolog_failure!(&mut wam, "abolish(foo(_))."); + assert_prolog_success!(&mut wam, "catch(abolish(foo(_)), error(type_error(predicate_indicator, foo(_)), abolish/1), true)."); + assert_prolog_failure!(&mut wam, "abolish(abolish/1)."); + assert_prolog_success!(&mut wam, "catch(abolish(abolish/1), error(permission_error(modify, static_procedure, abolish/1), abolish/1), true)."); + + assert_prolog_success!(&mut wam, "atom_length('enchanted evening', N).", [["N = 17"]]); - assert_prolog_success!(&mut wam, r"?- atom_length('enchanted\ + assert_prolog_success!(&mut wam, r"atom_length('enchanted\ evening', N).", [["N = 17"]]); - assert_prolog_success!(&mut wam, "?- atom_length('', N).", + assert_prolog_success!(&mut wam, "atom_length('', N).", [["N = 0"]]); - assert_prolog_failure!(&mut wam, "?- atom_length('scarlet', 5)."); - assert_prolog_success!(&mut wam, "?- catch((atom_length(Atom, 4), false), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- catch((atom_length(1.23, 4), false), error(type_error(atom, 1.23), _), true)."); - assert_prolog_success!(&mut wam, "?- catch((atom_length(atom, '4'), false), error(type_error(integer, '4'), _), true)."); + assert_prolog_failure!(&mut wam, "atom_length('scarlet', 5)."); + assert_prolog_success!(&mut wam, "catch((atom_length(Atom, 4), false), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "catch((atom_length(1.23, 4), false), error(type_error(atom, 1.23), _), true)."); + assert_prolog_success!(&mut wam, "catch((atom_length(atom, '4'), false), error(type_error(integer, '4'), _), true)."); } @@ -1971,93 +1976,93 @@ foo(X) :- call(X) -> call(X)."); #[test] fn test_queries_on_setup_call_cleanup() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); // Test examples from the ISO Prolog page for setup_call_catch. - assert_prolog_failure!(&mut wam, "?- setup_call_cleanup(false, _, _)."); - assert_prolog_success!(&mut wam, "?- catch(setup_call_cleanup(true, throw(unthrown), _), error(instantiation_error, _), true)."); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(true, true, (true ; throw(x)))."); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(true, X = 1, X = 2).", + assert_prolog_failure!(&mut wam, "setup_call_cleanup(false, _, _)."); + assert_prolog_success!(&mut wam, "catch(setup_call_cleanup(true, throw(unthrown), _), error(instantiation_error, _), true)."); + assert_prolog_success!(&mut wam, "setup_call_cleanup(true, true, (true ; throw(x)))."); + assert_prolog_success!(&mut wam, "setup_call_cleanup(true, X = 1, X = 2).", [["X = 1"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(true, true, X = 2).", + assert_prolog_success!(&mut wam, "setup_call_cleanup(true, true, X = 2).", [["X = 2"]]); - assert_prolog_success!(&mut wam, "?- catch(setup_call_cleanup(true, X=true, X), error(E, _), true).", + assert_prolog_success!(&mut wam, "catch(setup_call_cleanup(true, X=true, X), error(E, _), true).", [["E = instantiation_error", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- catch(setup_call_cleanup(X=throw(ex), true, X), E, true).", + assert_prolog_success!(&mut wam, "catch(setup_call_cleanup(X=throw(ex), true, X), E, true).", [["E = ex", "X = _3"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(true, true, false)."); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(S = 1, G = 2, C = 3).", + assert_prolog_success!(&mut wam, "setup_call_cleanup(true, true, false)."); + assert_prolog_success!(&mut wam, "setup_call_cleanup(S = 1, G = 2, C = 3).", [["S = 1", "G = 2", "C = 3"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup((S=1;S=2), G=3, C=4).", + assert_prolog_success!(&mut wam, "setup_call_cleanup((S=1;S=2), G=3, C=4).", [["S = 1", "G = 3", "C = 4"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(S=1, G=2, writeq(S+G)).", + assert_prolog_success!(&mut wam, "setup_call_cleanup(S=1, G=2, writeq(S+G)).", [["S = 1", "G = 2"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(S=1, (G=2;G=3), writeq(S+G)).", + assert_prolog_success!(&mut wam, "setup_call_cleanup(S=1, (G=2;G=3), writeq(S+G)).", [["S = 1", "G = 2"], ["S = 1", "G = 3"]]); - assert_prolog_success!(&mut wam, "?- setup_call_cleanup(S=1, G=2, writeq(S+G>A+B)), A=3, B=4.", + assert_prolog_success!(&mut wam, "setup_call_cleanup(S=1, G=2, writeq(S+G>A+B)), A=3, B=4.", [["S = 1", "G = 2", "A = 3", "B = 4"]]); assert_prolog_success!(&mut wam, - "?- catch(setup_call_cleanup(S=1, (G=2;G=3,throw(x)), writeq(S+G)), E, true).", + "catch(setup_call_cleanup(S=1, (G=2;G=3,throw(x)), writeq(S+G)), E, true).", [["S = 1", "G = 2", "E = _26"], ["G = _4", "E = x", "S = _1"]]); assert_prolog_success!(&mut wam, - "?- setup_call_cleanup(S=1, (G=2;G=3),writeq(S+G>B)), B=4, !.", + "setup_call_cleanup(S=1, (G=2;G=3),writeq(S+G>B)), B=4, !.", [["S = 1", "B = 4", "G = 2"]]); assert_prolog_success!(&mut wam, - "?- setup_call_cleanup(S=1,G=2,writeq(S+G>B)),B=3,!.", + "setup_call_cleanup(S=1,G=2,writeq(S+G>B)),B=3,!.", [["S = 1", "G = 2", "B = 3"]]); assert_prolog_success!(&mut wam, - "?- setup_call_cleanup(S=1,(G=2;false),writeq(S+G>B)),B=3,!.", + "setup_call_cleanup(S=1,(G=2;false),writeq(S+G>B)),B=3,!.", [["S = 1", "G = 2", "B = 3"]]); assert_prolog_success!(&mut wam, - "?- setup_call_cleanup(S=1,(G=2;S=2),writeq(S+G>B)), B=3, !.", + "setup_call_cleanup(S=1,(G=2;S=2),writeq(S+G>B)), B=3, !.", [["S = 1", "B = 3", "G = 2"]]); assert_prolog_failure!(&mut wam, - "?- setup_call_cleanup(S=1,(G=2;G=3), writeq(S+G>B)), B=4, !, throw(x)."); + "setup_call_cleanup(S=1,(G=2;G=3), writeq(S+G>B)), B=4, !, throw(x)."); assert_prolog_success!(&mut wam, - "?- catch(setup_call_cleanup(true,throw(goal),throw(cl)), Pat, true).", + "catch(setup_call_cleanup(true,throw(goal),throw(cl)), Pat, true).", [["Pat = goal"]]); assert_prolog_success!(&mut wam, - "?- catch(( setup_call_cleanup(true,(G=1;G=2),throw(cl)), throw(cont)), Pat, true).", + "catch(( setup_call_cleanup(true,(G=1;G=2),throw(cl)), throw(cont)), Pat, true).", [["Pat = cont", "G = _1"]]); // fails here. assert_prolog_success!(&mut wam, -"?- setup_call_cleanup(true, (X=1;X=2), writeq(a)), setup_call_cleanup(true,(Y=1;Y=2),writeq(b)), !.", +"setup_call_cleanup(true, (X=1;X=2), writeq(a)), setup_call_cleanup(true,(Y=1;Y=2),writeq(b)), !.", [["Y = 1", "X = 1"]]); } #[test] fn test_queries_on_call_with_inference_limit() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(throw(error), 0, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(throw(error), 0, R).", [["R = inference_limit_exceeded"]]); - assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R), error, true)."); + assert_prolog_success!(&mut wam, "catch(call_with_inference_limit(throw(error), 1, R), error, true)."); - assert_prolog_failure!(&mut wam, "?- call_with_inference_limit(g(X), 5, R)."); + assert_prolog_failure!(&mut wam, "call_with_inference_limit(g(X), 5, R)."); submit(&mut wam, "g(1). g(2). g(3). g(4). g(5)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 5, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 5, R), call(true).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 5, R), call(true).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 2, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 2, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 3, R1), + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 3, R1), call_with_inference_limit(g(X), 5, R2).", [["X = 1", "R1 = true", "R2 = !"], ["X = 2", "R1 = true", "R2 = !"], @@ -2067,59 +2072,59 @@ fn test_queries_on_call_with_inference_limit() submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 7, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X), 7, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 6, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X), 6, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 4, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X), 4, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 3, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X), 3, R).", [["R = true", "X = 1"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 2, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X), 2, R).", [["R = inference_limit_exceeded", "X = _1"]]); submit(&mut wam, "e(X) :- call_with_inference_limit(f(X), 10, _)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 10, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(e(X), 10, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 8, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(e(X), 8, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 6, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(e(X), 6, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 5, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(e(X), 5, R).", [["R = true", "X = 1"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 4, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(e(X), 4, R).", [["R = inference_limit_exceeded", "X = _1"]]); submit(&mut wam, "f(X, R) :- call_with_inference_limit(g(X), 5, R)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 4, S).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X, R), 4, S).", [["S = true", "X = 1", "R = true"], ["S = true", "X = 2", "R = true"], ["S = inference_limit_exceeded", "X = _1", "R = _2"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 8, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X, R), 8, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], @@ -2128,35 +2133,35 @@ fn test_queries_on_call_with_inference_limit() submit(&mut wam, "g(1). g(2). g(3). g(4). g(5). g(6)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 8, S).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(f(X, R), 8, S).", [["R = true", "X = 1", "S = true"], ["R = true", "X = 2", "S = true"], ["R = true", "X = 3", "S = true"], ["R = true", "X = 4", "S = true"], ["R = true", "X = 5", "S = true"], ["R = inference_limit_exceeded", "S = !", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 2, R), call_with_inference_limit(g(X), 1, S).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 2, R), call_with_inference_limit(g(X), 1, S).", [["R = true", "X = 1", "S = !"], ["R = true", "X = 2", "S = !"], ["R = true", "X = 3", "S = !"], ["R = true", "X = 4", "S = !"], ["R = true", "X = 5", "S = !"], ["R = !", "X = 6", "S = !"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 2, R), call_with_inference_limit(g(X), 1, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 2, R), call_with_inference_limit(g(X), 1, R).", [["R = !", "X = 6"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 1, R), call_with_inference_limit(g(X), 1, R).", + assert_prolog_success!(&mut wam, "call_with_inference_limit(g(X), 1, R), call_with_inference_limit(g(X), 1, R).", [["R = inference_limit_exceeded", "X = _1"]]); } #[test] fn test_queries_on_dcgs() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, ":- use_module(library(dcgs))."); // test case by YeGoblynQueene from hacker news. - compile_user_module(&mut wam, + submit_code(&mut wam, " ability(destroy, X) --> destroy(X). destroy(X) --> [destroy], target(X). target(X) --> [target], permanent(X). @@ -2171,9 +2176,9 @@ fn test_queries_on_dcgs() land('Mountain') --> []. % etc permanents sorcery('Duress') --> []. - instant('Lightning Bolt') --> [].".as_bytes()); + instant('Lightning Bolt') --> []."); - assert_prolog_success!(&mut wam, "?- phrase(ability(destroy, X), P).", + assert_prolog_success!(&mut wam, "phrase(ability(destroy, X), P).", [["P = [destroy, target, creature]", "X = 'Llanowar Elves'"], ["P = [destroy, target, artifact]", "X = 'Ankh of Mishra'"], ["P = [destroy, target, land]", "X = 'Mountain'"]]); @@ -2182,150 +2187,150 @@ fn test_queries_on_dcgs() #[test] fn test_queries_on_string_lists() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); // double_quotes is chars by default. - assert_prolog_success!(&mut wam, "?- \"\" =@= []."); - assert_prolog_failure!(&mut wam, "?- \"\" == []."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == []."); - assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', 'b', 'c']."); - assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', 'b', c]."); - assert_prolog_success!(&mut wam, "?- \"abc\" =@= ['a', b, 'c']."); - assert_prolog_success!(&mut wam, "?- \"abc\" =@= [a, 'b', 'c']."); - assert_prolog_success!(&mut wam, "?- \"abc\" =@= [a, 'b', c]."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', 'b', 'c']."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', 'b', c]."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == ['a', b, 'c']."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == [a, 'b', 'c']."); - assert_prolog_failure!(&mut wam, "?- \"abc\" == [a, 'b', c]."); - assert_prolog_failure!(&mut wam, "?- \"koen\" == [k, o, e, n]."); - assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o, e, n]."); - assert_prolog_success!(&mut wam, "?- \"koen\" =@= [k, o, e, n]."); - assert_prolog_success!(&mut wam, "?- \"koen\" =@= \"koen\"."); - assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X].", + assert_prolog_success!(&mut wam, "\"\" =@= []."); + assert_prolog_failure!(&mut wam, "\"\" == []."); + assert_prolog_failure!(&mut wam, "\"abc\" == []."); + assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', 'b', 'c']."); + assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', 'b', c]."); + assert_prolog_success!(&mut wam, "\"abc\" =@= ['a', b, 'c']."); + assert_prolog_success!(&mut wam, "\"abc\" =@= [a, 'b', 'c']."); + assert_prolog_success!(&mut wam, "\"abc\" =@= [a, 'b', c]."); + assert_prolog_failure!(&mut wam, "\"abc\" == ['a', 'b', 'c']."); + assert_prolog_failure!(&mut wam, "\"abc\" == ['a', 'b', c]."); + assert_prolog_failure!(&mut wam, "\"abc\" == ['a', b, 'c']."); + assert_prolog_failure!(&mut wam, "\"abc\" == [a, 'b', 'c']."); + assert_prolog_failure!(&mut wam, "\"abc\" == [a, 'b', c]."); + assert_prolog_failure!(&mut wam, "\"koen\" == [k, o, e, n]."); + assert_prolog_success!(&mut wam, "\"koen\" = [k, o, e, n]."); + assert_prolog_success!(&mut wam, "\"koen\" =@= [k, o, e, n]."); + assert_prolog_success!(&mut wam, "\"koen\" =@= \"koen\"."); + assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X].", [["X = [e, n]"]]); - assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X], X = \"en\".", + assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X], X = \"en\".", [["X = [e, n]"]]); - assert_prolog_failure!(&mut wam, "?- \"koen\" = [k, o | X], X == \"en\"."); - assert_prolog_success!(&mut wam, "?- \"koen\" = [k, o | X], X =@= \"en\".", + assert_prolog_failure!(&mut wam, "\"koen\" = [k, o | X], X == \"en\"."); + assert_prolog_success!(&mut wam, "\"koen\" = [k, o | X], X =@= \"en\".", [["X = [e, n]"]]); - assert_prolog_failure!(&mut wam, "?- X = \"abc\", Y = \"abc\", X == Y."); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abc\", Y), X == Y."); + assert_prolog_failure!(&mut wam, "X = \"abc\", Y = \"abc\", X == Y."); + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), X == Y."); - assert_prolog_success!(&mut wam, "?- X = \"abc\", Y = \"abc\", X =@= Y."); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abc\", Y), X =@= Y."); + assert_prolog_success!(&mut wam, "X = \"abc\", Y = \"abc\", X =@= Y."); + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), X =@= Y."); submit(&mut wam, "matcher([a,b,c|X], ['d','e','f'|X])."); - assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", \"defdef\")."); - assert_prolog_failure!(&mut wam, "?- matcher(\"abcdef\", \"defdff\")."); + assert_prolog_success!(&mut wam, "matcher(\"abcdef\", \"defdef\")."); + assert_prolog_failure!(&mut wam, "matcher(\"abcdef\", \"defdff\")."); - assert_prolog_success!(&mut wam, "?- matcher([X, Y, Z | W], [A, B, C | W]).", + assert_prolog_success!(&mut wam, "matcher([X, Y, Z | W], [A, B, C | W]).", [["A = d", "B = e", "C = f", "W = _1", "X = a", "Y = b", "Z = c"]]); - assert_prolog_failure!(&mut wam, "?- matcher([X, Y, Z | W], [X, B, C | W])."); + assert_prolog_failure!(&mut wam, "matcher([X, Y, Z | W], [X, B, C | W])."); submit(&mut wam, "matcher([a,b,c|X], X)."); - assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X = \"def\".", + assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X = \"def\".", [["X = [d, e, f]", "Y = []"]]); - assert_prolog_success!(&mut wam, "?- matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X =@= \"def\".", + assert_prolog_success!(&mut wam, "matcher(\"abcdef\", X), X = [d,e,f|Y], Y =@= [], X =@= \"def\".", [["X = [d, e, f]", "Y = []"]]); - assert_prolog_success!(&mut wam, "?- X = ['a', 'b', 'c' | \"def\"].", + assert_prolog_success!(&mut wam, "X = ['a', 'b', 'c' | \"def\"].", [["X = [a, b, c, d, e, f]"]]); - assert_prolog_success!(&mut wam, "?- X = [a,b,c|\"abc\"].", + assert_prolog_success!(&mut wam, "X = [a,b,c|\"abc\"].", [["X = [a, b, c, a, b, c]"]]); - assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, atom)."); + assert_prolog_success!(&mut wam, "set_prolog_flag(double_quotes, atom)."); - assert_prolog_success!(&mut wam, "?- matcher(X, Y).", + assert_prolog_success!(&mut wam, "matcher(X, Y).", [["X = [a, b, c | _1]", "Y = _1"]]); - assert_prolog_failure!(&mut wam, "?- matcher(\"abcdef\", Y)."); + assert_prolog_failure!(&mut wam, "matcher(\"abcdef\", Y)."); - assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, chars)."); + assert_prolog_success!(&mut wam, "set_prolog_flag(double_quotes, chars)."); - assert_prolog_success!(&mut wam, "?- X = \"abc\", X = ['a' | Y], set_prolog_flag(double_quotes, atom).", + assert_prolog_success!(&mut wam, "X = \"abc\", X = ['a' | Y], set_prolog_flag(double_quotes, atom).", [["X = \"abc\"", "Y = \"bc\""]]); // partial strings. - assert_prolog_success!(&mut wam, "?- set_prolog_flag(double_quotes, chars)."); + assert_prolog_success!(&mut wam, "set_prolog_flag(double_quotes, chars)."); - assert_prolog_failure!(&mut wam, "?- Y = 5, partial_string(\"abc\", Y)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X).", + assert_prolog_failure!(&mut wam, "Y = 5, partial_string(\"abc\", Y)."); + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X).", [["X = [a, b, c | _]"]]); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abc\", Y), matcher(X, V), + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abc\", Y), matcher(X, V), matcher(Y, Z), V = Z."); submit(&mut wam, "matcher([a, b, c | X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y).", [["X = [a, b, c | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = \"def\".", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = \"def\".", [["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), \"def\" = Y.", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), \"def\" = Y.", [["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y).", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y).", [["X = [a, b, c, d, e, f | _]", "Y = [d, e, f | _]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), Y = \"defghijkl\".", [["X = [a, b, c, d, e, f, g, h, i, j, k, l]", "Y = [d, e, f, g, h, i, j, k, l]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), partial_string(\"def\", Y), \"defghijkl\" = Y.", [["X = [a, b, c, d, e, f, g, h, i, j, k, l]", "Y = [d, e, f, g, h, i, j, k, l]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G].", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G].", [["X = [a, b, c, d, e, f | _]", "Y = [d, e, f | _]", "G = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), [d, e, f | G] = Y.", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), [d, e, f | G] = Y.", [["X = [a, b, c, d, e, f | _]", "Y = [d, e, f | _]", "G = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], G = \"ghi\".", [["X = [a, b, c, d, e, f, g, h, i]", "Y = [d, e, f, g, h, i]", "G = [g, h, i]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], is_partial_string(Y), G = \"ghi\".", [["X = [a, b, c, d, e, f, g, h, i]", "Y = [d, e, f, g, h, i]", "G = [g, h, i]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y), Y = [d, e, f | G], is_partial_string(Y), is_partial_string(G), G = \"ghi\".", [["X = [a, b, c, d, e, f, g, h, i]", "Y = [d, e, f, g, h, i]", "G = [g, h, i]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"ababc\", Y), Y = [a,b|Z], + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"ababc\", Y), Y = [a,b|Z], X =@= Z.", [["X = [a, b, c | _]", "Y = [a, b, a, b, c | _]", "Z = [a, b, c | _]"]]); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"ababc\", Y), Y = [a,b|Z], + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), partial_string(\"ababc\", Y), Y = [a,b|Z], X == Z."); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), X @> \"abc\"."); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), X \\=@= \"abc\"."); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), X @< \"abc\"."); + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), X @> \"abc\"."); + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), X \\=@= \"abc\"."); + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), X @< \"abc\"."); - assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y), Y = [a,b|V], + assert_prolog_success!(&mut wam, "partial_string(\"ab\", X), matcher(X, Y), Y = [a,b|V], matcher(Y, Z), is_partial_string(Y).", [["V = [c | _]", "X = [a, b, c, a, b, c | _]", "Y = [a, b, c | _]", "Z = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y).", [["X = [a, b, c | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), is_partial_string(Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y), is_partial_string(Y).", [["X = [a, b, c | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), Y = \"def\".", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y), Y = \"def\".", [["X = [a, b, c, d, e, f]", "Y = [d, e, f]"]]); submit(&mut wam, "matcher([a,b,c|X], X). matcher([a,b,d|X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"ab\", X), matcher(X, Y).", [["X = [a, b, c | _]", "Y = _"], ["X = [a, b, d | _]", "Y = _"]]); submit(&mut wam, "matcher([a,b,c,d|X], X). matcher([a,c,d|X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"ab\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"ab\", X), matcher(X, Y).", [["X = [a, b, c, d | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y).", [["X = [a, b, c, d | _]", "Y = _"], ["X = [a, c, d | _]", "Y = _"]]); @@ -2333,11 +2338,11 @@ fn test_queries_on_string_lists() matcher([a,c,d|X], X). matcher([a,e,f|X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y).", [["X = [a, b, c, d | _]", "Y = _"], ["X = [a, c, d | _]", "Y = _"], ["X = [a, e, f | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y), Y = \" t\".", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y), Y = \" t\".", [["X = [a, b, c, d, ' ', t]", "Y = [' ', t]"], ["X = [a, c, d, ' ', t]", "Y = [' ', t]"], ["X = [a, e, f, ' ', t]", "Y = [' ', t]"]]); @@ -2345,14 +2350,14 @@ fn test_queries_on_string_lists() submit(&mut wam, "matcher([a,b,c|X], X) :- X = []. matcher([a,b,c|X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), matcher(X, Y).", [["X = [a, b, c]", "Y = []"], ["X = [a, b, c | _]", "Y = _"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y).", [["X = [a, b, c]", "Y = []"], ["X = [a, b, c | _]", "Y = _"]]); - assert_prolog_failure!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"bc\", Y), X = [a | Y]."); + assert_prolog_failure!(&mut wam, "partial_string(\"abc\", X), partial_string(\"bc\", Y), X = [a | Y]."); submit(&mut wam, "matcher([a|X], X) :- matcher2(X, _). matcher([b|X], X) :- matcher2(X, _). @@ -2360,39 +2365,39 @@ fn test_queries_on_string_lists() matcher2([c|X], X). matcher2([d|X], X)."); - assert_prolog_success!(&mut wam, "?- partial_string(\"\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"\", X), matcher(X, Y).", [["X = [a, c | _]", "Y = [c | _]"], ["X = [a, d | _]", "Y = [d | _]"], ["X = [b, c | _]", "Y = [c | _]"], ["X = [b, d | _]", "Y = [d | _]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"a\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"a\", X), matcher(X, Y).", [["X = [a, c | _]", "Y = [c | _]"], ["X = [a, d | _]", "Y = [d | _]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"b\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"b\", X), matcher(X, Y).", [["X = [b, c | _]", "Y = [c | _]"], ["X = [b, d | _]", "Y = [d | _]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"bc\", X), matcher(X, Y).", + assert_prolog_success!(&mut wam, "partial_string(\"bc\", X), matcher(X, Y).", [["X = [b, c | _]", "Y = [c | _]"]]); submit(&mut wam, "f(\"appendy jones\"). f(\"appendy smithers jones\"). f(\"appendy o'toole\")."); - assert_prolog_success!(&mut wam, "?- partial_string(\"appendy\", X), f(X).", + assert_prolog_success!(&mut wam, "partial_string(\"appendy\", X), f(X).", [["X = [a, p, p, e, n, d, y, ' ', j, o, n, e, s]"], ["X = [a, p, p, e, n, d, y, ' ', s, m, i, t, h, e, r, s, ' ', j, o, n, e, s]"], ["X = [a, p, p, e, n, d, y, ' ', o, ''', t, o, o, l, e]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abcdef\", X).", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abcdef\", X).", [["X = [a, b, c, d, e, f | _]"]]); - assert_prolog_success!(&mut wam, "?- partial_string(\"abc\", X), partial_string(\"abcdef\", X), X = \"abcdef\".", + assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abcdef\", X), X = \"abcdef\".", [["X = [a, b, c, d, e, f]"]]); } #[test] fn test_queries_on_attributed_variables() { - let mut wam = Machine::new(); + let mut wam = Machine::new(readline::input_stream()); submit(&mut wam, " :- module(my_mod, []). @@ -2400,12 +2405,12 @@ fn test_queries_on_attributed_variables() :- attribute dif/1, frozen/1."); - assert_prolog_success!(&mut wam, "?- ( put_atts(V, my_mod, dif(1)) ; put_atts(V, my_mod, dif(2)) ), - get_atts(V, my_mod, L).", + assert_prolog_success!(&mut wam, "( put_atts(V, my_mod, dif(1)) ; put_atts(V, my_mod, dif(2)) ), + get_atts(V, my_mod, L).", [["L = [dif(1)]", "V = _10"], ["L = [dif(2)]", "V = _10"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, frozen(a)), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, frozen(a)), ( put_atts(V, my_mod, dif(1)) ; put_atts(V, my_mod, -frozen(a)), put_atts(V, my_mod, dif(2)) ; put_atts(V, my_mod, dif(different)) ), @@ -2414,43 +2419,43 @@ fn test_queries_on_attributed_variables() ["Ls = [dif(2)]", "V = _10"], ["Ls = [frozen(a), dif(different)]", "V = _10"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a)]), ( put_atts(V, my_mod, -dif(2)); put_atts(V, my_mod, -frozen(A)) ), get_atts(V, my_mod, L).", [["A = _71", "L = [frozen(a)]", "V = _25"], ["A = _71", "L = [dif(2)]", "V = _25"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), ( put_atts(V, my_mod, -dif(2)) ; put_atts(V, my_mod, -frozen(A)) ), get_atts(V, my_mod, L).", [["A = _111", "L = [frozen(b)]", "V = _29"], ["A = _111", "L = [dif(2)]", "V = _29"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), get_atts(V, my_mod, -dif(1))."); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), get_atts(V, my_mod, -dif(3))."); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), get_atts(V, my_mod, dif(X)).", [["X = 2", "V = _29"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), dif(2), frozen(a), frozen(b)]), put_atts(V, my_mod, -dif(A)), get_atts(V, my_mod, Ls).", [["A = _112", "Ls = [frozen(b)]", "V = _29"]]); - assert_prolog_success!(&mut wam, "?- put_atts(V, my_mod, [dif(1), frozen(a), dif(2), frozen(b)]), + assert_prolog_success!(&mut wam, "put_atts(V, my_mod, [dif(1), frozen(a), dif(2), frozen(b)]), put_atts(V, my_mod, -dif(A)), get_atts(V, my_mod, Ls).", [["A = _114", "Ls = [frozen(b)]", "V = _29"]]); submit(&mut wam, include_str!("./prolog/examples/minatotask.pl")); submit(&mut wam, ":- use_module(library(zdd))."); - assert_prolog_failure!(&mut wam, "?- ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), + assert_prolog_failure!(&mut wam, "ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), Vs = [X,Y], variables_set_zdd(Vs, ZDD), Vs = [1,1]."); - assert_prolog_success!(&mut wam, "?- ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), + assert_prolog_success!(&mut wam, "ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), Vs = [X,Y], variables_set_zdd(Vs, ZDD), X = 1.", [["X = 1", "Y = 0", "Vs = [1, 0]", "ZDD = (1->b(true);0->b(true);b(false))"]]); - assert_prolog_success!(&mut wam, "?- ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), + assert_prolog_success!(&mut wam, "ZDD = ( X -> b(true) ; ( Y -> b(true) ; b(false) ) ), Vs = [X,Y], variables_set_zdd(Vs, ZDD), X = 0.", -- 2.54.0