add put_byte/{1,2}, put_char/{1,2}
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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" => {
|
||||||
|
|||||||
Reference in New Issue
Block a user