Merge pull request #396 from notoria/phrase_from_file
Implemented phrase_from_file/2 and /2
This commit is contained in:
@@ -178,6 +178,7 @@ pub enum SystemClauseType {
|
|||||||
ExpandTerm,
|
ExpandTerm,
|
||||||
FetchGlobalVar,
|
FetchGlobalVar,
|
||||||
FetchGlobalVarWithOffset,
|
FetchGlobalVarWithOffset,
|
||||||
|
FileToChars,
|
||||||
GetChar,
|
GetChar,
|
||||||
GetSingleChar,
|
GetSingleChar,
|
||||||
ResetAttrVarState,
|
ResetAttrVarState,
|
||||||
@@ -312,6 +313,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::FetchGlobalVarWithOffset => {
|
&SystemClauseType::FetchGlobalVarWithOffset => {
|
||||||
clause_name!("$fetch_global_var_with_offset")
|
clause_name!("$fetch_global_var_with_offset")
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::FileToChars => clause_name!("$file_to_chars"),
|
||||||
&SystemClauseType::GetChar => clause_name!("$get_char"),
|
&SystemClauseType::GetChar => clause_name!("$get_char"),
|
||||||
&SystemClauseType::GetSingleChar => clause_name!("$get_single_char"),
|
&SystemClauseType::GetSingleChar => clause_name!("$get_single_char"),
|
||||||
&SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"),
|
&SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"),
|
||||||
@@ -461,6 +463,7 @@ impl SystemClauseType {
|
|||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
||||||
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
|
||||||
|
("$file_to_chars", 2) => Some(SystemClauseType::FileToChars),
|
||||||
("$get_char", 1) => Some(SystemClauseType::GetChar),
|
("$get_char", 1) => Some(SystemClauseType::GetChar),
|
||||||
("$get_single_char", 1) => Some(SystemClauseType::GetSingleChar),
|
("$get_single_char", 1) => Some(SystemClauseType::GetSingleChar),
|
||||||
("$points_to_cont_reset_marker", 1) => {
|
("$points_to_cont_reset_marker", 1) => {
|
||||||
|
|||||||
7
src/prolog/lib/pio.pl
Normal file
7
src/prolog/lib/pio.pl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
:- module(pio, [phrase_from_file/2]).
|
||||||
|
|
||||||
|
:- use_module(library(dcgs)).
|
||||||
|
|
||||||
|
phrase_from_file(NT, File) :-
|
||||||
|
'$file_to_chars'(File, Chars),
|
||||||
|
phrase(NT, Chars).
|
||||||
@@ -24,8 +24,9 @@ use indexmap::IndexSet;
|
|||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Read, Write};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
use std::fs::File;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -1519,6 +1520,74 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::FileToChars => {
|
||||||
|
let a1 = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
let a2 = self.store(self.deref(self[temp_v!(2)]));
|
||||||
|
|
||||||
|
let file_name = match a1 {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(name, _) = &self.heap[h] {
|
||||||
|
name.as_str().to_string()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Char(c) => {
|
||||||
|
c.to_string()
|
||||||
|
}
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
let name = clause_name!("$file_to_chars");
|
||||||
|
let mut file = match File::open(&file_name) {
|
||||||
|
Ok(f) => f,
|
||||||
|
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 = 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 chars = buffer.chars().map(|c| Addr::Char(c));
|
||||||
|
let char_list = Addr::HeapCell(self.heap.to_list(chars));
|
||||||
|
|
||||||
|
self.unify(char_list, a2);
|
||||||
|
}
|
||||||
&SystemClauseType::GetChar => {
|
&SystemClauseType::GetChar => {
|
||||||
let mut iter = parsing_stream(current_input_stream.clone());
|
let mut iter = parsing_stream(current_input_stream.clone());
|
||||||
let result = iter.next();
|
let result = iter.next();
|
||||||
|
|||||||
Reference in New Issue
Block a user