From: Mark Thom Date: Thu, 10 May 2018 07:43:36 +0000 (-0600) Subject: add catch/throw support, make exceptions and arithmetic tests pass. X-Git-Tag: v0.8.110~465^2~14 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=954c29b103787b2db750b334111a8d5a75d11e19;p=scryer-prolog.git add catch/throw support, make exceptions and arithmetic tests pass. --- diff --git a/src/main.rs b/src/main.rs index 1e4a7e29..a220f41a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,6 @@ use prolog::machine::*; #[cfg(test)] mod tests; -pub static BUILTINS: &str = include_str!("./prolog/lib/builtins.pl"); pub static LISTS: &str = include_str!("./prolog/lib/lists.pl"); pub static CONTROL: &str = include_str!("./prolog/lib/control.pl"); pub static QUEUES: &str = include_str!("./prolog/lib/queues.pl"); @@ -27,20 +26,6 @@ fn parse_and_compile_line(wam: &mut Machine, buffer: &str) } } -fn load_init_str(wam: &mut Machine, src_str: &str) -{ - match compile_listing(wam, src_str) { - EvalSession::Error(_) => panic!("failed to parse batch from string."), - _ => {} - } -} - -fn load_init_str_and_include(wam: &mut Machine, src_str: &str, module: &'static str) -{ - load_init_str(wam, src_str); - wam.use_module_in_toplevel(clause_name!(module)); -} - fn prolog_repl() { let mut wam = Machine::new(); diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 34623fee..f4d47303 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -711,13 +711,31 @@ pub struct Rule { #[derive(Copy, Clone, PartialEq)] pub enum SystemClauseType { - SkipMaxList + CleanUpBlock, + EraseBall, + Fail, + GetBall, + GetCurrentBlock, + InstallNewBlock, + ResetBlock, + SetBall, + SkipMaxList, + UnwindStack } impl SystemClauseType { pub fn arity(&self) -> usize { match self { - &SystemClauseType::SkipMaxList => 4 + &SystemClauseType::CleanUpBlock => 1, + &SystemClauseType::EraseBall => 0, + &SystemClauseType::Fail => 0, + &SystemClauseType::GetBall => 1, + &SystemClauseType::GetCurrentBlock => 1, + &SystemClauseType::InstallNewBlock => 1, + &SystemClauseType::ResetBlock => 1, + &SystemClauseType::SetBall => 1, + &SystemClauseType::SkipMaxList => 4, + &SystemClauseType::UnwindStack => 0 } } @@ -727,13 +745,31 @@ impl SystemClauseType { pub fn name(&self) -> ClauseName { match self { + &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), + &SystemClauseType::EraseBall => clause_name!("$erase_ball"), + &SystemClauseType::Fail => clause_name!("$fail"), + &SystemClauseType::GetBall => clause_name!("$get_ball"), + &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), + &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), + &SystemClauseType::ResetBlock => clause_name!("$reset_block"), + &SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), + &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), } } pub fn from(name: &str, arity: usize) -> Option { match (name, arity) { + ("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock), + ("$erase_ball", 0) => Some(SystemClauseType::EraseBall), + ("$fail", 0) => Some(SystemClauseType::Fail), + ("$get_ball", 1) => Some(SystemClauseType::GetBall), + ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), + ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), + ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), + ("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), + ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), _ => None } } diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 52876615..974876a8 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -601,6 +601,22 @@ pub fn compile_packet(wam: &mut Machine, tl: TopLevelPacket) -> EvalSession } } +pub static BUILTINS: &str = include_str!("./lib/builtins.pl"); + +pub fn load_init_str(wam: &mut Machine, src_str: &str) +{ + match compile_listing(wam, src_str) { + EvalSession::Error(_) => panic!("failed to parse batch from string."), + _ => {} + } +} + +pub fn load_init_str_and_include(wam: &mut Machine, src_str: &str, module: &'static str) +{ + load_init_str(wam, src_str); + wam.use_module_in_toplevel(clause_name!(module)); +} + pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession { fn get_module_name(module: &Option) -> ClauseName { diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 7a46bf8d..2d1856e8 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -1,8 +1,9 @@ :- op(400, yfx, /). -:- module(builtins, [(+)/2, (*)/2, (-)/2, (/)/2, (/\)/2, (\/)/2, (is)/2, - (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2, (>>)/2, (mod)/2, - (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (>=)/2, (=<)/2]). +:- module(builtins, [(=)/2, (+)/2, (*)/2, (-)/2, (/)/2, (/\)/2, + (\/)/2, (is)/2, (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2, + (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (-)/1, + (>=)/2, (=<)/2, (->)/2, (;)/2, catch/3, throw/1, true/0, false/0]). % arithmetic operators. :- op(700, xfx, is). @@ -19,6 +20,7 @@ :- op(400, yfx, >>). :- op(400, yfx, mod). :- op(400, yfx, rem). +:- op(200, fy, -). % arithmetic comparison operators. :- op(700, xfx, >). @@ -27,3 +29,57 @@ :- op(700, xfx, =:=). :- op(700, xfx, >=). :- op(700, xfx, =<). + +% conditional operators. +:- op(1050, xfy, ->). +:- op(1100, xfy, ;). + +% unify. +:- op(700, xfx, =). + +% unify. +X = X. + +true. + +false :- '$fail'. + +% conditions. +/* +','(G1, G2) :- get_cp(B), ','(G1, G2, B). + +','(!, ','(G1, G2), B) :- set_cp(B), ','(G1, G2, B). +','(!, !, B) :- set_cp(B). +','(!, G, B) :- set_cp(B), G. +','(G, ','(G2, G3), B) :- !, G, ','(G2, G3, B). +','(G, !, B) :- !, G, set_cp(B). +','(G1, G2, _) :- G1, G2. + +;(G1, G2) :- get_cp(B), ;(G1, G2, B). + +;(G1 -> G2, _, B) :- ->(G1, G2, B). +;(_ -> _ , G, B) :- set_cp(B), G. +;(!, _, B) :- set_cp(B). +;(_, !, B) :- set_cp(B). +;(G, _, _) :- G. +;(_, G, _) :- G. + +G1 -> G2 :- get_cp(B), ->(G1, G2, B). + +->(G1, !, B) :- call(G1), set_cp(B). +->(G1, G2, B) :- call(G1), set_cp(B), call(G2). +*/ + +% exceptions. +catch(G,C,R) :- '$get_current_block'(Bb), catch(G,C,R,Bb). + +catch(G,C,R,Bb) :- '$install_new_block'(NBb), call(G), end_block(Bb, NBb). +catch(G,C,R,Bb) :- '$reset_block'(Bb), '$get_ball'(Ball), handle_ball(Ball, C, R). + +end_block(Bb, NBb) :- '$clean_up_block'(NBb), '$reset_block'(Bb). +end_block(Bb, NBb) :- '$reset_block'(NBb), '$fail'. + +handle_ball(Ball, C, R) :- Ball = C, !, '$erase_ball', call(R). +handle_ball(_, _, _) :- '$unwind_stack'. + +throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 7913137a..55d22ed9 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -400,37 +400,35 @@ pub(crate) trait CallPolicy: Any { Ok(()) } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, + fn call_n<'a>(&mut self, machine_st: &mut MachineState, mut arity: usize, code_dirs: CodeDirs<'a>, lco: bool) -> CallResult { - loop { - if let Some((name, mut arity)) = machine_st.setup_call_n(arity) { - let user = clause_name!("user"); - - if machine_st.fail { - return Ok(()); - } - - match ClauseType::from(name.clone(), arity, None) { - ClauseType::CallN => { - machine_st.num_of_args = arity; - machine_st.handle_internal_call_n(); - - continue; - }, - ClauseType::BuiltIn(built_in) => - machine_st.setup_built_in_call(built_in, lco), - ClauseType::Inlined(inlined) => - machine_st.execute_inlined(&inlined), - ClauseType::Op(..) | ClauseType::Named(..) => - if let Some(idx) = code_dirs.get(name.clone(), arity, user) { - self.context_call(machine_st, name, arity, idx, lco)?; - } else { - return Err(machine_st.existence_error(name, arity)); - } - }; - } + while let Some((name, inner_arity)) = machine_st.setup_call_n(arity) { + let user = clause_name!("user"); + + match ClauseType::from(name.clone(), inner_arity, None) { + ClauseType::CallN => { + machine_st.handle_internal_call_n(inner_arity); + + if machine_st.fail { + return Ok(()); + } + + arity = inner_arity; + continue; + }, + ClauseType::BuiltIn(built_in) => + machine_st.setup_built_in_call(built_in, lco), + ClauseType::Inlined(inlined) => + machine_st.execute_inlined(&inlined), + ClauseType::Op(..) | ClauseType::Named(..) => + if let Some(idx) = code_dirs.get(name.clone(), inner_arity, user) { + self.context_call(machine_st, name, inner_arity, idx, lco)?; + } else { + return Err(machine_st.existence_error(name, inner_arity)); + } + }; break; } @@ -441,10 +439,82 @@ pub(crate) trait CallPolicy: Any { fn system_call(&mut self, machine_st: &mut MachineState, ct: &SystemClauseType) -> CallResult { match ct { + &SystemClauseType::CleanUpBlock => { + let nb = machine_st.store(machine_st.deref(machine_st[temp_v!(1)].clone())); + + match nb { + Addr::Con(Constant::Usize(nb)) => { + let b = machine_st.b - 1; + + if nb > 0 && machine_st.or_stack[b].b == nb { + machine_st.b = machine_st.or_stack[nb - 1].b; + machine_st.or_stack.truncate(machine_st.b); + } + }, + _ => machine_st.fail = true + }; + + Ok(()) + }, + &SystemClauseType::EraseBall => { + machine_st.ball.reset(); + Ok(()) + }, + &SystemClauseType::Fail => { + machine_st.fail = true; + Ok(()) + }, + &SystemClauseType::GetBall => { + let addr = machine_st.store(machine_st.deref(machine_st[temp_v!(1)].clone())); + let h = machine_st.heap.h; + + if machine_st.ball.stub.len() > 0 { + machine_st.copy_and_align_ball_to_heap(); + } else { + machine_st.fail = true; + return Ok(()); + } + + let ball = machine_st.heap[h].as_addr(h); + + match addr.as_var() { + Some(r) => machine_st.bind(r, ball), + _ => machine_st.fail = true + }; + + Ok(()) + }, + &SystemClauseType::GetCurrentBlock => { + let c = Constant::Usize(machine_st.block); + let addr = machine_st[temp_v!(1)].clone(); + + machine_st.write_constant_to_var(addr, c); + Ok(()) + }, + &SystemClauseType::InstallNewBlock => { + machine_st.block = machine_st.b; + + let c = Constant::Usize(machine_st.block); + let addr = machine_st[temp_v!(1)].clone(); + + machine_st.write_constant_to_var(addr, c); + Ok(()) + }, + &SystemClauseType::ResetBlock => { + let addr = machine_st.deref(machine_st[temp_v!(1)].clone()); + machine_st.reset_block(addr); + Ok(()) + }, + &SystemClauseType::SetBall => { + machine_st.set_ball(); + Ok(()) + }, &SystemClauseType::SkipMaxList => { machine_st.skip_max_list()?; - machine_st.p += 1; - + Ok(()) + }, + &SystemClauseType::UnwindStack => { + machine_st.unwind_stack(); Ok(()) } } @@ -549,7 +619,7 @@ pub(crate) trait CallPolicy: Any { let key_pairs = key_pairs.into_iter().map(|kp| kp.1); let heap_addr = Addr::HeapCell(machine_st.to_list(key_pairs)); - + let r2 = machine_st[temp_v!(2)].clone(); machine_st.unify(r2, heap_addr); @@ -564,8 +634,10 @@ pub(crate) trait CallPolicy: Any { Ok(()) }, - &BuiltInClauseType::System(ref ct) => - self.system_call(machine_st, ct), + &BuiltInClauseType::System(ref ct) => { + self.system_call(machine_st, ct)?; + return_from_clause!(lco, machine_st) + } } } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index bc12c399..1e368c5f 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -80,7 +80,7 @@ impl MachineState { }; } - fn bind(&mut self, r1: Ref, a2: Addr) { + pub(super) fn bind(&mut self, r1: Ref, a2: Addr) { let t2 = self.store(a2); match r1 { @@ -273,7 +273,7 @@ impl MachineState { } } - fn write_constant_to_var(&mut self, addr: Addr, c: Constant) { + pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) { let addr = self.deref(addr); match self.store(addr) { @@ -1011,9 +1011,9 @@ impl MachineState { } } - pub(super) fn handle_internal_call_n(&mut self) + pub(super) fn handle_internal_call_n(&mut self, arity: usize) { - let arity = self.num_of_args + 1; + let arity = arity + 1; let pred = self.registers[1].clone(); for i in 2 .. arity { @@ -1310,12 +1310,9 @@ impl MachineState { Ordering::Equal } - fn reset_block(&mut self, addr: Addr) { + pub(super) fn reset_block(&mut self, addr: Addr) { match self.store(addr) { - Addr::Con(Constant::Usize(b)) => { - self.block = b; - self.p += 1; - }, + Addr::Con(Constant::Usize(b)) => self.block = b, _ => self.fail = true }; } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 7f0238b2..1d1c55b1 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -152,11 +152,5 @@ impl MachineState { }; Ok(()) - } - - pub(super) fn execute_system(&mut self, ct: &SystemClauseType) -> Result<(), MachineError> { - match ct { - &SystemClauseType::SkipMaxList => self.skip_max_list() - } - } + } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index addb26e9..27986de4 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -393,7 +393,7 @@ impl RelationWorker { if name.as_str() == "!" || name.as_str() == "blocked_!" { Ok(QueryTerm::BlockedCut) } else { - Ok(QueryTerm::Clause(r, ClauseType::Named(name, CodeIndex::default()), vec![])) + Ok(QueryTerm::Clause(r, ClauseType::from(name, 0, None), vec![])) }, Term::Var(_, ref v) if v.as_str() == "!" => Ok(QueryTerm::UnblockedCut(Cell::default())), diff --git a/src/tests.rs b/src/tests.rs index df7cbae2..f965a388 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -934,10 +934,96 @@ fn test_queries_on_call_n() } #[test] -fn test_queries_on_exceptions() +fn test_queries_on_arithmetic() { let mut wam = Machine::new(); + load_init_str_and_include(&mut wam, BUILTINS, "builtins"); + + 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.", + [["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."); + + 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.", + [["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.", + [["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.", + [["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.", + [["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.", + [["Y = 4", "X = 4", "Z = 8"]]); + + 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 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, "?- 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_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).", + [["X = _5", "E = evaluation_error(zero_divisor)"]]); + + 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)."); +} + +#[test] +fn test_queries_on_exceptions() +{ + let mut wam = Machine::new(); + load_init_str_and_include(&mut wam, BUILTINS, "builtins"); + submit(&mut wam, "f(a). f(_) :- throw(stuff)."); submit(&mut wam, "handle(stuff)."); @@ -1037,91 +1123,7 @@ fn test_queries_on_exceptions() ["E = an_error_1", "X = _1"], ["E = an_error_2", "X = _1"]]); } - -#[test] -fn test_queries_on_arithmetic() -{ - let mut wam = Machine::new(); - - 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.", - [["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."); - - 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.", - [["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.", - [["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.", - [["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.", - [["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.", - [["Y = 4", "X = 4", "Z = 8"]]); - - 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 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, "?- 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_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).", - [["X = _5", "E = evaluation_error(zero_divisor)"]]); - - 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)."); -} - +/* #[test] fn test_queries_on_conditionals() { @@ -1714,3 +1716,4 @@ fn test_queries_on_skip_max_list() { assert_prolog_success!(&mut wam, "?- '$skip_max_list'(N, 9, non_list, Xs).", [["Xs = non_list", "N = 0"]]); } +*/