From 0bd9831eecf92bb5429301918f37273c5eb86488 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Tue, 19 May 2020 18:44:28 +0200 Subject: [PATCH] ADDED: phrase_from_file/3 in library(pio) This allows us to specify type(binary), and read from binary files with DCGs. --- src/prolog/clause_types.rs | 2 +- src/prolog/lib/pio.pl | 19 +++++++--- src/prolog/machine/system_calls.rs | 58 ++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index cf4e1aa6..78ca09de 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -533,7 +533,7 @@ impl SystemClauseType { ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), - ("$file_to_chars", 2) => Some(SystemClauseType::FileToChars), + ("$file_to_chars", 3) => Some(SystemClauseType::FileToChars), ("$get_byte", 2) => Some(SystemClauseType::GetByte), ("$get_char", 2) => Some(SystemClauseType::GetChar), ("$get_code", 2) => Some(SystemClauseType::GetCode), diff --git a/src/prolog/lib/pio.pl b/src/prolog/lib/pio.pl index 4f387625..8467dacb 100644 --- a/src/prolog/lib/pio.pl +++ b/src/prolog/lib/pio.pl @@ -1,12 +1,23 @@ -:- module(pio, [phrase_from_file/2]). +:- module(pio, [phrase_from_file/2, + phrase_from_file/3]). :- use_module(library(dcgs)). :- use_module(library(error)). phrase_from_file(NT, File) :- - ( var(File) -> instantiation_error(phrase_from_file/2) + phrase_from_file(NT, File, []). + +phrase_from_file(NT, File, Options) :- + ( var(File) -> instantiation_error(phrase_from_file/3) ; (\+ atom(File) ; File = []) -> - domain_error(source_sink, File, phrase_from_file/2) - ; '$file_to_chars'(File, Chars), + domain_error(source_sink, File, phrase_from_file/3) + ; must_be(list, Options), + ( member(Var, Options), var(Var) -> instantiation_error(phrase_from_file/3) + ; member(type(Type), Options) -> + must_be(atom, Type), + member(Type, [text,binary]) + ; Type = text + ), + '$file_to_chars'(File, Chars, Type), phrase(NT, Chars) ). diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 6160e7dd..927fa028 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1905,29 +1905,51 @@ impl MachineState { } }; - let complete_string = { - let mut buffer = String::new(); - match file.read_to_string(&mut buffer) { - Ok(_size) => { - self.heap.put_complete_string(&buffer) - } - Err(_e) => { - // This case if the data isn't UTF-8 valid. - let mut buffer = Vec::new(); - let _ = match file.read_to_end(&mut buffer) { - Ok(size) => size, - Err(_e) => unreachable!() - }; - - let buffer = String::from_iter( - buffer.into_iter().map(|b| b as char) - ); - self.heap.put_complete_string(&buffer) + let type_str = match self.store(self.deref(self[temp_v!(3)])) { + Addr::Con(h) if self.heap.atom_at(h) => { + if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] { + atom.as_str() + } else { + unreachable!() } } + _ => { + unreachable!() + } }; + let complete_string = { + let mut buffer = String::new(); + match type_str { + "text" => { match file.read_to_string(&mut buffer) { + Ok(_size) => { + self.heap.put_complete_string(&buffer) + } + Err(_e) => { + // the data isn't valid UTF-8, so we fail. + self.fail = true; + return Ok(()); + + } + } + } + "binary" => { let mut buffer = Vec::new(); + let _ = match file.read_to_end(&mut buffer) { + Ok(size) => size, + Err(_e) => unreachable!() + }; + + let buffer = String::from_iter( + buffer.into_iter().map(|b| b as char) + ); + + self.heap.put_complete_string(&buffer) + } + _ => { unreachable!() } + } + }; + self.unify(complete_string, a2); } &SystemClauseType::PutCode => { -- 2.54.0