]> Repositorios git - scryer-prolog.git/commitdiff
ENHANCED: open/4 to allow opening a stream by specifying stream(S).
authorMarkus Triska <[email protected]>
Thu, 4 Nov 2021 17:28:05 +0000 (18:28 +0100)
committerMarkus Triska <[email protected]>
Thu, 4 Nov 2021 17:33:40 +0000 (18:33 +0100)
This allows switching standard output to binary, using for example:

  ?- current_output(S0), open(stream(S0), write, S, [type(binary)]).

format/3 can then be used to write binary data to S. This is needed
for example when piping binary data to other programs.

This addresses #614, please read the discussion for more information.

The current implementation is very preliminary: Specifically, it works
by destructively modifiying the parameters of the underlying stream,
making it no longer usable in its original mode. Currently, if the
type of standard output is set to binary, then the toplevel no longer
works. Therefore, after writing binary output to standard output,
the program should either halt, or set the stream type back to text.

src/clause_types.rs
src/lib/builtins.pl
src/machine/system_calls.rs

index a22b542e1505a214deb03dc1a8aa6cd7336f2198..87dbbe27f4fdc722ed10d86521c2464f73c20d80 100644 (file)
@@ -221,6 +221,7 @@ pub(crate) enum SystemClauseType {
     NumberToCodes,
     OpDeclaration,
     Open,
+    SetStreamOptions,
     NextStream,
     PartialStringTail,
     PeekByte,
@@ -478,6 +479,7 @@ impl SystemClauseType {
             &SystemClauseType::Halt => clause_name!("$halt"),
             &SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
             &SystemClauseType::Open => clause_name!("$open"),
+            &SystemClauseType::SetStreamOptions => clause_name!("$set_stream_options"),
             &SystemClauseType::OpDeclaration => clause_name!("$op"),
             &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
             &SystemClauseType::InstallInferenceCounter => {
@@ -701,6 +703,7 @@ impl SystemClauseType {
             ("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
             ("$op", 3) => Some(SystemClauseType::OpDeclaration),
             ("$open", 7) => Some(SystemClauseType::Open),
+            ("$set_stream_options", 5) => Some(SystemClauseType::SetStreamOptions),
             ("$redo_attr_var_binding", 2) => Some(SystemClauseType::RedoAttrVarBinding),
             ("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
             ("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter),
index 616a2b0d25fe631d744bf6fe4e57fa6dc9ba26e5..3c9c27a18160cb72a3428ffb2930bc3335bb8f32 100644 (file)
@@ -1466,7 +1466,11 @@ open(SourceSink, Mode, Stream, StreamOptions) :-
        throw(error(uninstantiation_error(Stream), open/4)) % 8.11.5.3f)
     ;
        parse_stream_options(StreamOptions, [Alias, EOFAction, Reposition, Type], open/4),
-       '$open'(SourceSink, Mode, Stream, Alias, EOFAction, Reposition, Type)
+       (   SourceSink = stream(S0) ->
+           '$set_stream_options'(S0, Alias, EOFAction, Reposition, Type),
+           Stream = S0
+       ;   '$open'(SourceSink, Mode, Stream, Alias, EOFAction, Reposition, Type)
+       )
     ).
 
 
index 8b4d7b27b45769ebaa88d052b8a78b2a9f1c3646..3fbab138f2c69f77acda5f7ec918b458980aaf44 100644 (file)
@@ -3220,6 +3220,22 @@ impl MachineState {
 
                 self.bind(stream_var.as_var().unwrap(), stream);
             }
+            &SystemClauseType::SetStreamOptions => {
+                let mut stream = self.get_stream_or_alias(
+                    self[temp_v!(1)],
+                    &indices.stream_aliases,
+                    "open",
+                    4,
+                )?;
+
+                let alias = self[temp_v!(2)];
+                let eof_action = self[temp_v!(3)];
+                let reposition = self[temp_v!(4)];
+                let stream_type = self[temp_v!(5)];
+
+                let options = self.to_stream_options(alias, eof_action, reposition, stream_type);
+                *stream.options_mut() = options;
+            }
             &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => {
                 self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h))
             }