diff --git a/src/lib/format.pl b/src/lib/format.pl index 2e496730..811a4c33 100644 --- a/src/lib/format.pl +++ b/src/lib/format.pl @@ -375,20 +375,9 @@ format(Fs, Args) :- format(Stream, Fs, Args) :- phrase(format_(Fs, Args), Cs), ( stream_property(Stream, type(binary)) -> - % maplist(char_code, Cs, Bytes) is currently a lot slower - % than first converting Cs to an atom, and then to codes. - % In the future, we can ideally avoid creating an atom here, - % since an atom leaves traces in the system. - atom_chars(A, Cs), - atom_codes(A, Bytes), - ( member(NonByte, Bytes), NonByte > 255 -> - char_code(Char, NonByte), - throw(error(representation_error(Char), format/3)) - ; true - ), % For binary streams, we use a specialised internal predicate % that uses only a single "write" operation for efficiency. - '$put_bytes'(Stream, Bytes) + '$put_bytes'(Stream, Cs) ; maplist(put_char(Stream), Cs) ). @@ -471,7 +460,7 @@ portray_clause(Term) :- portray_clause(Stream, Term) :- phrase(portray_clause_(Term), Ls), - maplist(put_char(Stream), Ls). + format(Stream, "~s", [Ls]). portray_clause_(Term) --> { term_variables(Term, Vs), diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index e18da09b..025da98b 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -2022,8 +2022,24 @@ impl MachineState { let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_bytes", 2)?; - let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2); - let bytes = self.integers_to_bytevec(temp_v!(2), stub); + let mut iter = self.heap_pstr_iter(self[temp_v!(2)]); + let mut bytes = Vec::new(); + for c in iter.to_string().chars() { + if c as u32 > 255 { + + let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2); + + let err = MachineError::type_error( + self.heap.h(), + ValidType::Byte, + Addr::Char(c), + ); + + return Err(self.error_form(err, stub)); + } + + bytes.push(c as u8); + } match stream.write(&bytes) { Ok(_) => {