add put_byte/{1,2}, put_char/{1,2}

This commit is contained in:
Mark Thom
2020-05-05 17:42:18 -06:00
parent 573df892bc
commit 47e3a5e75a
5 changed files with 157 additions and 4 deletions

View File

@@ -222,6 +222,8 @@ pub enum SystemClauseType {
Open, Open,
PartialStringTail, PartialStringTail,
PointsToContinuationResetMarker, PointsToContinuationResetMarker,
PutByte,
PutChar,
REPL(REPLCodePtr), REPL(REPLCodePtr),
ReadQueryTerm, ReadQueryTerm,
ReadTerm, ReadTerm,
@@ -385,6 +387,12 @@ impl SystemClauseType {
&SystemClauseType::PointsToContinuationResetMarker => { &SystemClauseType::PointsToContinuationResetMarker => {
clause_name!("$points_to_cont_reset_marker") clause_name!("$points_to_cont_reset_marker")
} }
&SystemClauseType::PutByte => {
clause_name!("$put_byte")
}
&SystemClauseType::PutChar => {
clause_name!("$put_char")
}
&SystemClauseType::QuotedToken => { &SystemClauseType::QuotedToken => {
clause_name!("$quoted_token") clause_name!("$quoted_token")
} }
@@ -495,6 +503,12 @@ impl SystemClauseType {
("$points_to_cont_reset_marker", 1) => { ("$points_to_cont_reset_marker", 1) => {
Some(SystemClauseType::PointsToContinuationResetMarker) Some(SystemClauseType::PointsToContinuationResetMarker)
} }
("$put_byte", 2) => {
Some(SystemClauseType::PutByte)
}
("$put_char", 2) => {
Some(SystemClauseType::PutChar)
}
("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState), ("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState),
("$truncate_if_no_lh_growth", 1) => { ("$truncate_if_no_lh_growth", 1) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth) Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)

View File

@@ -52,6 +52,7 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
get_byte/1, get_byte/2, get_char/1, get_char/2, get_byte/1, get_byte/2, get_char/1, get_char/2,
halt/0, max_arity/1, number_chars/2, halt/0, max_arity/1, number_chars/2,
number_codes/2, once/1, op/3, open/3, open/4, number_codes/2, once/1, op/3, open/3, open/4,
put_byte/1, put_byte/2, put_char/1, put_char/2,
read_term/2, read_term/3, repeat/0, retract/1, read_term/2, read_term/3, repeat/0, retract/1,
set_prolog_flag/2, set_input/1, set_output/1, set_prolog_flag/2, set_input/1, set_output/1,
setof/3, sub_atom/5, subsumes_term/2, setof/3, sub_atom/5, subsumes_term/2,
@@ -1199,3 +1200,19 @@ get_byte(S, B) :-
get_byte(S) :- get_byte(S) :-
current_input(S), current_input(S),
'$get_byte'(S, B). '$get_byte'(S, B).
put_char(C) :-
current_output(S),
'$put_char'(S, C).
put_char(S, C) :-
'$put_char'(S, C).
put_byte(C) :-
current_output(S),
'$put_byte'(S, C).
put_byte(S, C) :-
'$put_byte'(S, C).

View File

@@ -489,7 +489,7 @@ pub enum ValidType {
Atom, Atom,
Atomic, Atomic,
// Boolean, // Boolean,
// Byte, Byte,
Callable, Callable,
Character, Character,
Compound, Compound,
@@ -512,7 +512,7 @@ impl ValidType {
ValidType::Atom => "atom", ValidType::Atom => "atom",
ValidType::Atomic => "atomic", ValidType::Atomic => "atomic",
// ValidType::Boolean => "boolean", // ValidType::Boolean => "boolean",
// ValidType::Byte => "byte", ValidType::Byte => "byte",
ValidType::Callable => "callable", ValidType::Callable => "callable",
ValidType::Character => "character", ValidType::Character => "character",
ValidType::Compound => "compound", ValidType::Compound => "compound",

View File

@@ -278,6 +278,17 @@ impl Stream {
pub(crate) pub(crate)
fn close(&mut self) { fn close(&mut self) {
*self.stream_inst.0.borrow_mut() = StreamInstance::Null; *self.stream_inst.0.borrow_mut() = StreamInstance::Null;
self.past_end_of_stream = true;
}
#[inline]
pub(crate)
fn is_null_stream(&self) -> bool {
if let StreamInstance::Null = *self.stream_inst.0.borrow() {
true
} else {
false
}
} }
#[inline] #[inline]
@@ -485,7 +496,15 @@ impl MachineState {
} }
Addr::Stream(h) => { Addr::Stream(h) => {
if let HeapCellValue::Stream(ref stream) = &self.heap[h] { if let HeapCellValue::Stream(ref stream) = &self.heap[h] {
stream.clone() if stream.is_null_stream() {
return Err(self.open_permission_error(
Addr::Stream(h),
caller,
arity,
));
} else {
stream.clone()
}
} else { } else {
unreachable!() unreachable!()
} }

View File

@@ -1592,6 +1592,109 @@ impl MachineState {
self.unify(complete_string, a2); self.unify(complete_string, a2);
} }
&SystemClauseType::PutChar => {
let mut stream =
self.get_stream_or_alias(self[temp_v!(1)], indices, "put_char", 2)?;
self.check_stream_properties(
&mut stream,
StreamType::Text,
None,
clause_name!("put_char"),
2,
)?;
match self.store(self.deref(self[temp_v!(2)])) {
addr if addr.is_ref() => {
let stub = MachineError::functor_stub(clause_name!("put_char"), 2);
let err = MachineError::instantiation_error();
return Err(self.error_form(err, stub));
}
addr => {
match self.store(self.deref(self[temp_v!(2)])) {
Addr::Con(h) if self.heap.atom_at(h) => {
match &self.heap[h] {
HeapCellValue::Atom(ref atom, _) if atom.is_char() => {
if let Some(c) = atom.as_str().chars().next() {
write!(&mut stream, "{}", c).unwrap();
return return_from_clause!(self.last_call, self);
} else {
unreachable!()
}
}
_ => {
unreachable!()
}
}
}
Addr::Char(c) => {
write!(&mut stream, "{}", c).unwrap();
return return_from_clause!(self.last_call, self);
}
_ => {
}
}
let stub = MachineError::functor_stub(clause_name!("put_char"), 2);
let err = MachineError::type_error(
self.heap.h(),
ValidType::Character,
addr,
);
return Err(self.error_form(err, stub));
}
}
}
&SystemClauseType::PutByte => {
let mut stream =
self.get_stream_or_alias(self[temp_v!(1)], indices, "put_byte", 2)?;
self.check_stream_properties(
&mut stream,
StreamType::Binary,
None,
clause_name!("put_byte"),
2,
)?;
match self.store(self.deref(self[temp_v!(2)])) {
addr if addr.is_ref() => {
let stub = MachineError::functor_stub(clause_name!("put_byte"), 2);
let err = MachineError::instantiation_error();
return Err(self.error_form(err, stub));
}
addr => {
match Number::try_from((addr, &self.heap)) {
Ok(Number::Integer(n)) => {
if let Some(nb) = n.to_u8() {
stream.write(&mut [nb]).unwrap();
return return_from_clause!(self.last_call, self);
}
}
Ok(Number::Fixnum(n)) => {
if let Ok(nb) = u8::try_from(n) {
stream.write(&mut [nb]).unwrap();
return return_from_clause!(self.last_call, self);
}
}
_ => {
}
}
let stub = MachineError::functor_stub(clause_name!("put_byte"), 2);
let err = MachineError::type_error(
self.heap.h(),
ValidType::Byte,
self[temp_v!(2)],
);
return Err(self.error_form(err, stub));
}
}
}
&SystemClauseType::GetByte => { &SystemClauseType::GetByte => {
let mut stream = let mut stream =
self.get_stream_or_alias(self[temp_v!(1)], indices, "get_byte", 2)?; self.get_stream_or_alias(self[temp_v!(1)], indices, "get_byte", 2)?;
@@ -2436,7 +2539,7 @@ impl MachineState {
true true
} }
"write" => { "write" => {
open_options.read(false).write(true).create(true).append(false); open_options.read(false).write(true).truncate(true).create(true);
false false
} }
"append" => { "append" => {