From 9b1272da5134e2673444fb1e508896a725cad324 Mon Sep 17 00:00:00 2001 From: notoria Date: Sun, 26 Apr 2020 14:54:20 +0200 Subject: [PATCH] Small patch for library pio --- src/prolog/lib/pio.pl | 8 +++- src/prolog/machine/system_calls.rs | 76 ++++++++++++++++++------------ 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/prolog/lib/pio.pl b/src/prolog/lib/pio.pl index c4ee0a27..470d13fb 100644 --- a/src/prolog/lib/pio.pl +++ b/src/prolog/lib/pio.pl @@ -3,5 +3,9 @@ :- use_module(library(dcgs)). phrase_from_file(NT, File) :- - '$file_to_chars'(File, Chars), - phrase(NT, Chars). + ( var(File) -> throw(error(instantiation_error, phrase_from_file/2)) + ; (\+ atom(File) ; File = []) -> + throw(error(domain_error(source_sink, File), phrase_from_file/2)) + ; '$file_to_chars'(File, Chars), + phrase(NT, Chars) + ). diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index f3074839..d564be97 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1522,6 +1522,8 @@ impl MachineState { }; } &SystemClauseType::FileToChars => { + // TODO: Replace this with stream. + use std::io; let a1 = self.store(self.deref(self[temp_v!(1)])); let a2 = self.store(self.deref(self[temp_v!(2)])); @@ -1542,50 +1544,64 @@ impl MachineState { let name = clause_name!("$file_to_chars"); let mut file = match File::open(&file_name) { Ok(f) => f, - Err(_e) => { + Err(e) => { let file_name_ = clause_name!(file_name.clone(), indices.atom_tbl.clone()); let arity = 2; let stub = MachineError::functor_stub(name.clone(), arity); let h = self.heap.h(); + let err = match e.kind() { + io::ErrorKind::NotFound => { + MachineError::existence_error( + h, + ExistenceError::SourceSink( + ModuleSource::File(file_name_) + ), + ) + } + io::ErrorKind::PermissionDenied => { + let stub = MachineError::functor_stub( + name.clone(), + arity + ); + let source_sink = self.store(self.deref(a1)); + MachineError::permission_error( + h, + Permission::Access, + "source_sink", + source_sink + ) + } + _ => unreachable!() // Not nice. + }; - let err = MachineError::existence_error( - h, - ExistenceError::SourceSink( - ModuleSource::File(file_name_) - ), - ); let err = self.error_form(err, stub); self.throw_exception(err); return Ok(()); } }; - let mut buffer = String::new(); - let _ = match file.read_to_string(&mut buffer) { - Ok(size) => size, - Err(_e) => { - // TODO: Distinguish the case/error. - let file_name_ = clause_name!(file_name.clone(), - indices.atom_tbl.clone()); - let arity = 2; - let stub = MachineError::functor_stub(name.clone(), arity); - let h = self.heap.h(); - - let err = MachineError::existence_error( - h, - ExistenceError::SourceSink( - ModuleSource::File(file_name_) - ), - ); - let err = self.error_form(err, stub); - - self.throw_exception(err); - return Ok(()); + let char_list = { + let mut buffer = String::new(); + match file.read_to_string(&mut buffer) { + Ok(_size) => { + let chars = buffer.chars().map(|c| Addr::Char(c)); + Addr::HeapCell(self.heap.to_list(chars)) + } + 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 chars = buffer + .into_iter() + .map(|b| Addr::Char(b as char)); + Addr::HeapCell(self.heap.to_list(chars)) + } } }; - let chars = buffer.chars().map(|c| Addr::Char(c)); - let char_list = Addr::HeapCell(self.heap.to_list(chars)); self.unify(char_list, a2); } -- 2.54.0