FetchGlobalVarWithOffset,
FileToChars,
FlushOutput,
+ GetByte,
GetChar,
GetSingleChar,
ResetAttrVarState,
}
&SystemClauseType::FileToChars => clause_name!("$file_to_chars"),
&SystemClauseType::FlushOutput => clause_name!("$flush_output"),
+ &SystemClauseType::GetByte => clause_name!("$get_byte"),
&SystemClauseType::GetChar => clause_name!("$get_char"),
&SystemClauseType::GetSingleChar => clause_name!("$get_single_char"),
&SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$file_to_chars", 2) => Some(SystemClauseType::FileToChars),
+ ("$get_byte", 2) => Some(SystemClauseType::GetByte),
("$get_char", 1) => Some(SystemClauseType::GetChar),
("$get_single_char", 1) => Some(SystemClauseType::GetSingleChar),
("$points_to_cont_reset_marker", 1) => {
current_prolog_flag/2, expand_goal/2,
expand_term/2, fail/0, false/0, findall/3,
findall/4, flush_output/0, flush_output/1,
- get_char/1, halt/0, max_arity/1, number_chars/2,
- number_codes/2, once/1, op/3, open/3, open/4,
- read_term/2, read_term/3, repeat/0, retract/1,
+ get_byte/1, get_byte/2, get_char/1, halt/0,
+ max_arity/1, number_chars/2, number_codes/2,
+ once/1, op/3, open/3, open/4, read_term/2,
+ read_term/3, repeat/0, retract/1,
set_prolog_flag/2, set_input/1, set_output/1,
setof/3, sub_atom/5, subsumes_term/2,
term_variables/2, throw/1, true/0,
flush_output :-
current_output(S),
'$flush_output'(S).
+
+
+get_byte(S, B) :-
+ '$get_byte'(S, B).
+
+get_byte(S) :-
+ current_input(S),
+ '$get_byte'(S, B).
Compound,
Evaluable,
Float,
- // InByte,
+ InByte,
// InCharacter,
Integer,
List,
ValidType::Compound => "compound",
ValidType::Evaluable => "evaluable",
ValidType::Float => "float",
- // ValidType::InByte => "in_byte",
+ ValidType::InByte => "in_byte",
// ValidType::InCharacter => "in_character",
ValidType::Integer => "integer",
ValidType::List => "list",
};
if let Some(err_string) = opt_err {
- let stub = MachineError::functor_stub(clause_name!("read_term"), 3);
-
- let addr = vec![
- HeapCellValue::Stream(stream)
- ];
-
- let err = MachineError::permission_error(
- self.heap.h(),
+ return Err(self.stream_permission_error(
Permission::InputStream,
err_string,
- addr,
- );
-
- return Err(self.error_form(err, stub));
+ stream,
+ clause_name!("read_term"),
+ 3,
+ ));
}
let mut orig_stream = stream.clone();
#[derive(Debug, Clone, Hash)]
pub struct Stream {
- past_end_of_stream: bool,
+ pub past_end_of_stream: bool,
pub options: StreamOptions,
stream_inst: WrappedStreamInstance,
}
match stream.options.eof_action {
EOFAction::Error => {
stream.past_end_of_stream = true;
-
- let stub = MachineError::functor_stub(caller, arity);
- let payload = vec![
- HeapCellValue::Stream(stream.clone())
- ];
-
- let err = MachineError::permission_error(
- self.heap.h(),
- Permission::InputStream,
- "past_end_of_stream",
- payload,
- );
-
- Err(self.error_form(err, stub))
+ return Err(self.open_past_eos_error(stream.clone(), caller, arity));
}
EOFAction::EOFCode => {
let end_of_stream = self.heap.to_unifiable(
}
}
+ pub(crate)
+ fn stream_permission_error(
+ &self,
+ perm: Permission,
+ err_string: &'static str,
+ stream: Stream,
+ caller: ClauseName,
+ arity: usize,
+ ) -> MachineStub {
+ let stub = MachineError::functor_stub(caller, arity);
+ let payload = vec![
+ HeapCellValue::Stream(stream)
+ ];
+
+ let err = MachineError::permission_error(
+ self.heap.h(),
+ perm,
+ err_string,
+ payload,
+ );
+
+ return self.error_form(err, stub);
+ }
+
+ #[inline]
+ pub(crate)
+ fn open_past_eos_error(
+ &self,
+ stream: Stream,
+ caller: ClauseName,
+ arity: usize,
+ ) -> MachineStub {
+ self.stream_permission_error(
+ Permission::InputStream,
+ "past_end_of_stream",
+ stream,
+ caller,
+ arity,
+ )
+ }
+
pub(crate)
fn open_permission_error<T: PermissionError>(
&self,
self.unify(complete_string, a2);
}
+ &SystemClauseType::GetByte => {
+ let mut stream =
+ self.get_stream_or_alias(self[temp_v!(1)], indices, "get_byte", 2)?;
+
+ let opt_err =
+ if !stream.is_input_stream() {
+ Some("stream") // 8.14.2.3 g)
+ } else if stream.options.stream_type == StreamType::Text {
+ Some("text_stream") // 8.14.2.3 h)
+ } else {
+ None
+ };
+
+ if let Some(err_string) = opt_err {
+ return Err(self.stream_permission_error(
+ Permission::InputStream,
+ err_string,
+ stream,
+ clause_name!("get_byte"),
+ 2,
+ ));
+ }
+
+ if stream.past_end_of_stream {
+ self.eof_action(
+ self[temp_v!(2)],
+ &mut stream,
+ clause_name!("get_byte"),
+ 2,
+ )?;
+
+ if EOFAction::Reset != stream.options.eof_action {
+ return return_from_clause!(self.last_call, self);
+ } else if self.fail {
+ return Ok(());
+ }
+ }
+
+ loop {
+ let mut b = [0u8; 1];
+
+ match stream.read(&mut b) {
+ Ok(1) => {
+ match self.store(self.deref(self[temp_v!(2)])) {
+ addr if addr.is_ref() => {
+ if let Some(var) = addr.as_var() {
+ self.bind(var, Addr::Usize(b[0] as usize));
+ return return_from_clause!(self.last_call, self);
+ } else {
+ unreachable!()
+ }
+ }
+ addr => {
+ match Number::try_from((addr, &self.heap)) {
+ Ok(Number::Integer(n)) => {
+ if let Some(nb) = n.to_u8() {
+ self.fail = b[0] != nb;
+ return return_from_clause!(self.last_call, self);
+ }
+ }
+ Ok(Number::Fixnum(n)) => {
+ if let Ok(nb) = u8::try_from(n) {
+ self.fail = b[0] != nb;
+ return return_from_clause!(self.last_call, self);
+ }
+ }
+ _ => {
+ }
+ }
+ }
+ }
+
+ let stub = MachineError::functor_stub(clause_name!("get_byte"), 2);
+ let err = MachineError::type_error(
+ self.heap.h(),
+ ValidType::InByte,
+ self[temp_v!(2)],
+ );
+
+ return Err(self.error_form(err, stub));
+ }
+ _ => {
+ self.eof_action(
+ self[temp_v!(2)],
+ &mut stream,
+ clause_name!("get_byte"),
+ 2,
+ )?;
+
+ if EOFAction::Reset != stream.options.eof_action {
+ return return_from_clause!(self.last_call, self);
+ } else if self.fail {
+ return Ok(());
+ }
+ }
+ }
+ }
+ }
&SystemClauseType::GetChar => {
let mut iter = self.open_parsing_stream(
current_input_stream.clone(),
};
if let Some(err_string) = opt_err {
- let stub = MachineError::functor_stub(clause_name!("write_term"), 3);
- let addr = vec![
- HeapCellValue::Stream(stream)
- ];
-
- let err = MachineError::permission_error(
- self.heap.h(),
+ return Err(self.stream_permission_error(
Permission::OutputStream,
err_string,
- addr,
- );
-
- return Err(self.error_form(err, stub));
+ stream,
+ clause_name!("write_term"),
+ 3,
+ ));
}
let addr = self[temp_v!(2)];