ENHANCED: open/4 to allow opening a stream by specifying stream(S).
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.
This commit is contained in:
@@ -221,6 +221,7 @@ pub(crate) enum SystemClauseType {
|
|||||||
NumberToCodes,
|
NumberToCodes,
|
||||||
OpDeclaration,
|
OpDeclaration,
|
||||||
Open,
|
Open,
|
||||||
|
SetStreamOptions,
|
||||||
NextStream,
|
NextStream,
|
||||||
PartialStringTail,
|
PartialStringTail,
|
||||||
PeekByte,
|
PeekByte,
|
||||||
@@ -478,6 +479,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::Halt => clause_name!("$halt"),
|
&SystemClauseType::Halt => clause_name!("$halt"),
|
||||||
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
||||||
&SystemClauseType::Open => clause_name!("$open"),
|
&SystemClauseType::Open => clause_name!("$open"),
|
||||||
|
&SystemClauseType::SetStreamOptions => clause_name!("$set_stream_options"),
|
||||||
&SystemClauseType::OpDeclaration => clause_name!("$op"),
|
&SystemClauseType::OpDeclaration => clause_name!("$op"),
|
||||||
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
||||||
&SystemClauseType::InstallInferenceCounter => {
|
&SystemClauseType::InstallInferenceCounter => {
|
||||||
@@ -701,6 +703,7 @@ impl SystemClauseType {
|
|||||||
("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
|
("$number_to_codes", 2) => Some(SystemClauseType::NumberToCodes),
|
||||||
("$op", 3) => Some(SystemClauseType::OpDeclaration),
|
("$op", 3) => Some(SystemClauseType::OpDeclaration),
|
||||||
("$open", 7) => Some(SystemClauseType::Open),
|
("$open", 7) => Some(SystemClauseType::Open),
|
||||||
|
("$set_stream_options", 5) => Some(SystemClauseType::SetStreamOptions),
|
||||||
("$redo_attr_var_binding", 2) => Some(SystemClauseType::RedoAttrVarBinding),
|
("$redo_attr_var_binding", 2) => Some(SystemClauseType::RedoAttrVarBinding),
|
||||||
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
||||||
("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter),
|
("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter),
|
||||||
|
|||||||
@@ -1466,7 +1466,11 @@ open(SourceSink, Mode, Stream, StreamOptions) :-
|
|||||||
throw(error(uninstantiation_error(Stream), open/4)) % 8.11.5.3f)
|
throw(error(uninstantiation_error(Stream), open/4)) % 8.11.5.3f)
|
||||||
;
|
;
|
||||||
parse_stream_options(StreamOptions, [Alias, EOFAction, Reposition, Type], open/4),
|
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)
|
||||||
|
)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3220,6 +3220,22 @@ impl MachineState {
|
|||||||
|
|
||||||
self.bind(stream_var.as_var().unwrap(), stream);
|
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 => {
|
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => {
|
||||||
self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h))
|
self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user