From: Mark Thom Date: Sun, 6 Sep 2020 00:57:03 +0000 (-0600) Subject: refactor SystemClauseType::Open in anticipation of #614 X-Git-Tag: v0.9.0~174^2~1 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=323e9c3eb3d4016991cd0da2b973747c08ab49eb;p=scryer-prolog.git refactor SystemClauseType::Open in anticipation of #614 --- diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a4933097..da31e966 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -375,6 +375,113 @@ impl MachineState { Ok(()) } + fn stream_from_file_spec( + &self, + file_spec: ClauseName, + indices: &mut IndexStore, + options: &StreamOptions, + ) -> Result { + if file_spec.as_str().is_empty() { + let stub = MachineError::functor_stub(clause_name!("open"), 4); + let err = MachineError::domain_error( + DomainErrorType::SourceSink, + self[temp_v!(1)], + ); + + return Err(self.error_form(err, stub)); + } + + // 8.11.5.3l) + if let Some(ref alias) = &options.alias { + if indices.stream_aliases.contains_key(alias) { + return Err(self.occupied_alias_permission_error( + alias.clone(), + "open", + 4, + )); + } + } + + let mode = + atom_from!(self, indices, self.store(self.deref(self[temp_v!(2)]))); + + let mut open_options = fs::OpenOptions::new(); + + let (is_input_file, in_append_mode) = + match mode.as_str() { + "read" => { + open_options.read(true).write(false).create(false); + (true, false) + } + "write" => { + open_options.read(false).write(true).truncate(true).create(true); + (false, false) + } + "append" => { + open_options.read(false).write(true).create(true).append(true); + (false, true) + } + _ => { + let stub = MachineError::functor_stub(clause_name!("open"), 4); + let err = MachineError::domain_error( + DomainErrorType::IOMode, + self[temp_v!(2)], + ); + + // 8.11.5.3h) + return Err(self.error_form(err, stub)); + } + }; + + let file = + match open_options.open(file_spec.as_str()) { + Ok(file) => { + file + } + Err(err) => { + match err.kind() { + ErrorKind::NotFound => { + // 8.11.5.3j) + let stub = MachineError::functor_stub( + clause_name!("open"), + 4, + ); + + let err = MachineError::existence_error( + self.heap.h(), + ExistenceError::SourceSink(self[temp_v!(1)]), + ); + + return Err(self.error_form(err, stub)); + } + ErrorKind::PermissionDenied => { + // 8.11.5.3k) + return Err(self.open_permission_error(self[temp_v!(1)], "open", 4)); + } + _ => { + let stub = MachineError::functor_stub( + clause_name!("open"), + 4, + ); + + let err = MachineError::syntax_error( + self.heap.h(), + ParserError::IO(err), + ); + + return Err(self.error_form(err, stub)); + } + } + } + }; + + Ok(if is_input_file { + Stream::from_file_as_input(file_spec, file) + } else { + Stream::from_file_as_output(file_spec, file, in_append_mode) + }) + } + #[inline] fn install_new_block(&mut self, r: RegType) -> usize { self.block = self.b; @@ -3368,12 +3475,12 @@ impl MachineState { let options = self.to_stream_options(alias, eof_action, reposition, stream_type); - let file_spec = + let mut stream = match self.store(self.deref(self[temp_v!(1)])) { Addr::Con(h) if self.heap.atom_at(h) => { match &self.heap[h] { &HeapCellValue::Atom(ref atom, _) => { - atom.clone() + self.stream_from_file_spec(atom.clone(), indices, &options)? } _ => { unreachable!() @@ -3386,109 +3493,24 @@ impl MachineState { let mut heap_pstr_iter = self.heap_pstr_iter(Addr::PStrLocation(h, n)); - clause_name!( - heap_pstr_iter.to_string(), - indices.atom_tbl.clone() - ) + let file_spec = + clause_name!( + heap_pstr_iter.to_string(), + indices.atom_tbl.clone() + ); + + self.stream_from_file_spec(file_spec, indices, &options)? } _ => { - clause_name!("") + self.stream_from_file_spec(clause_name!(""), indices, &options)? } } } _ => { - clause_name!("") - } - }; - - if file_spec.as_str().is_empty() { - let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::domain_error( - DomainErrorType::SourceSink, - self[temp_v!(1)], - ); - - return Err(self.error_form(err, stub)); - } - - // 8.11.5.3l) - if let Some(ref alias) = &options.alias { - if indices.stream_aliases.contains_key(alias) { - return Err(self.occupied_alias_permission_error( - alias.clone(), - "open", - 4, - )); - } - } - - let mode = - atom_from!(self, indices, self.store(self.deref(self[temp_v!(2)]))); - - let mut open_options = fs::OpenOptions::new(); - - let (is_input_file, in_append_mode) = - match mode.as_str() { - "read" => { - open_options.read(true).write(false).create(false); - (true, false) - } - "write" => { - open_options.read(false).write(true).truncate(true).create(true); - (false, false) - } - "append" => { - open_options.read(false).write(true).create(true).append(true); - (false, true) - } - _ => { - let stub = MachineError::functor_stub(clause_name!("open"), 4); - let err = MachineError::domain_error( - DomainErrorType::IOMode, - self[temp_v!(2)], - ); - - // 8.11.5.3h) - return Err(self.error_form(err, stub)); + self.stream_from_file_spec(clause_name!(""), indices, &options)? } }; - let file = - match open_options.open(file_spec.as_str()).map_err(|e| e.kind()) { - Ok(file) => { - file - } - Err(ErrorKind::NotFound) => { - // 8.11.5.3j) - let stub = MachineError::functor_stub( - clause_name!("open"), - 4, - ); - - let err = MachineError::existence_error( - self.heap.h(), - ExistenceError::SourceSink(self[temp_v!(1)]), - ); - - return Err(self.error_form(err, stub)); - } - Err(ErrorKind::PermissionDenied) => { - // 8.11.5.3k) - return Err(self.open_permission_error(self[temp_v!(1)], "open", 4)); - } - Err(_) => { - // for now, just fail. expand to meaningful error messages later. - self.fail = true; - return Ok(()); - } - }; - - let mut stream = if is_input_file { - Stream::from_file_as_input(file_spec, file) - } else { - Stream::from_file_as_output(file_spec, file, in_append_mode) - }; - stream.options = options; indices.streams.insert(stream.clone());