From f45b0bcfe8cb0bebcdcc7994f9b63661cfc7ad77 Mon Sep 17 00:00:00 2001 From: Emilie Burgun Date: Fri, 7 Feb 2025 14:59:32 +0100 Subject: [PATCH] Remove redundant alias resolution in at_end_of_stream/1, add corresponding tests for null streams Also fixed at_end_of_stream/0 leaving a choicepoint. --- src/lib/builtins.pl | 10 +++--- src/machine/mod.rs | 5 ++- src/machine/streams.rs | 75 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 745cbc48..f6df8da7 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -2188,12 +2188,10 @@ stream_property(S, P) :- %% at_end_of_stream(+Stream). % % True iff the stream Stream has ended -at_end_of_stream(S_or_a) :- - ( var(S_or_a) -> +at_end_of_stream(S) :- + ( var(S) -> throw(error(instantiation_error, at_end_of_stream/1)) - ; atom(S_or_a) -> - stream_property(S, alias(S_or_a)) - ; S = S_or_a + ; true ), stream_property(S, end_of_stream(E)), ( E = at -> true ; E = past ). @@ -2205,7 +2203,7 @@ at_end_of_stream :- current_input(S), stream_property(S, end_of_stream(E)), !, - ( E = at ; E = past ). + ( E = at -> true ; E = past ). %% set_stream_position(+Stream, +Position). % diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 10724030..e2306283 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -510,9 +510,12 @@ impl Machine { self.indices.streams.insert(self.user_error); + let mut null_options = StreamOptions::default(); + null_options.set_alias_to_atom_opt(Some(atom!("null_stream"))); + self.indices .stream_aliases - .insert(atom!("null_stream"), Stream::Null(StreamOptions::default())); + .insert(atom!("null_stream"), Stream::Null(null_options)); } #[inline(always)] diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 253bd47e..54efbd39 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1908,6 +1908,14 @@ impl MachineState { mod test { use super::*; use crate::machine::config::*; + use crate::LeafAnswer; + + fn is_successful(answer: &Result) -> bool { + matches!( + answer, + Ok(LeafAnswer::True) | Ok(LeafAnswer::LeafAnswer { .. }) + ) + } #[test] #[cfg_attr(miri, ignore)] @@ -1919,7 +1927,7 @@ mod test { let results = machine.run_query("current_input(S).").collect::>(); assert_eq!(results.len(), 1); - assert!(results[0].is_ok()); + assert!(is_successful(&results[0])); } #[test] @@ -1933,7 +1941,7 @@ mod test { assert_eq!(results.len(), 1); assert!( - results[0].is_ok(), + is_successful(&results[0]), "Expected read to succeed, got {:?}", results[0] ); @@ -1951,7 +1959,7 @@ mod test { let results = machine.run_query("current_output(S).").collect::>(); assert_eq!(results.len(), 1); - assert!(results[0].is_ok()); + assert!(is_successful(&results[0])); } #[test] @@ -1967,7 +1975,28 @@ mod test { assert_eq!(results.len(), 1); assert!( - results[0].is_ok(), + is_successful(&results[0]), + "Expected write to succeed, got {:?}", + results[0] + ); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn put_code_null_stream() { + // TODO: switch to a proper solution for configuring the machine with null streams + // once `StreamConfig` supports it. + let mut machine = MachineBuilder::new().build(); + machine.user_output = Stream::Null(StreamOptions::default()); + machine.configure_streams(); + + let results = machine + .run_query("put_code(user_output, 65).") + .collect::>(); + + assert_eq!(results.len(), 1); + assert!( + is_successful(&results[0]), "Expected write to succeed, got {:?}", results[0] ); @@ -1987,9 +2016,45 @@ mod test { assert_eq!(results.len(), 1); assert!( - results[0].is_ok(), + is_successful(&results[0]), "Expected write to succeed, got {:?}", results[0] ); } + + #[test] + #[cfg_attr(miri, ignore)] + fn at_end_of_stream_0_null_stream() { + let mut machine = MachineBuilder::new() + .with_streams(StreamConfig::in_memory()) + .build(); + + let results = machine.run_query("at_end_of_stream.").collect::>(); + + assert_eq!(results.len(), 1); + assert!( + is_successful(&results[0]), + "Expected at_end_of_stream to succeed, got {:?}", + results[0] + ); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn at_end_of_stream_1_null_stream() { + let mut machine = MachineBuilder::new() + .with_streams(StreamConfig::in_memory()) + .build(); + + let results = machine + .run_query("current_input(Stream), at_end_of_stream(Stream).") + .collect::>(); + + assert_eq!(results.len(), 1); + assert!( + is_successful(&results[0]), + "Expected at_end_of_stream to succeed, got {:?}", + results[0] + ); + } } -- 2.54.0