refactor SystemClauseType::Open in anticipation of #614
This commit is contained in:
@@ -375,6 +375,113 @@ impl MachineState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stream_from_file_spec(
|
||||||
|
&self,
|
||||||
|
file_spec: ClauseName,
|
||||||
|
indices: &mut IndexStore,
|
||||||
|
options: &StreamOptions,
|
||||||
|
) -> Result<Stream, MachineStub> {
|
||||||
|
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]
|
#[inline]
|
||||||
fn install_new_block(&mut self, r: RegType) -> usize {
|
fn install_new_block(&mut self, r: RegType) -> usize {
|
||||||
self.block = self.b;
|
self.block = self.b;
|
||||||
@@ -3368,12 +3475,12 @@ impl MachineState {
|
|||||||
let options =
|
let options =
|
||||||
self.to_stream_options(alias, eof_action, reposition, stream_type);
|
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)])) {
|
match self.store(self.deref(self[temp_v!(1)])) {
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
match &self.heap[h] {
|
match &self.heap[h] {
|
||||||
&HeapCellValue::Atom(ref atom, _) => {
|
&HeapCellValue::Atom(ref atom, _) => {
|
||||||
atom.clone()
|
self.stream_from_file_spec(atom.clone(), indices, &options)?
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -3386,109 +3493,24 @@ impl MachineState {
|
|||||||
let mut heap_pstr_iter =
|
let mut heap_pstr_iter =
|
||||||
self.heap_pstr_iter(Addr::PStrLocation(h, n));
|
self.heap_pstr_iter(Addr::PStrLocation(h, n));
|
||||||
|
|
||||||
clause_name!(
|
let file_spec =
|
||||||
heap_pstr_iter.to_string(),
|
clause_name!(
|
||||||
indices.atom_tbl.clone()
|
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!("")
|
self.stream_from_file_spec(clause_name!(""), indices, &options)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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()).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;
|
stream.options = options;
|
||||||
|
|
||||||
indices.streams.insert(stream.clone());
|
indices.streams.insert(stream.clone());
|
||||||
|
|||||||
Reference in New Issue
Block a user