merge with master
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -228,6 +228,17 @@ dependencies = [
|
|||||||
"winapi 0.3.8",
|
"winapi 0.3.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hostname"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"match_cfg",
|
||||||
|
"winapi 0.3.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -310,6 +321,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "match_cfg"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maybe-uninit"
|
name = "maybe-uninit"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -627,6 +644,7 @@ dependencies = [
|
|||||||
"divrem",
|
"divrem",
|
||||||
"downcast",
|
"downcast",
|
||||||
"git-version",
|
"git-version",
|
||||||
|
"hostname",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ dirs = "2.0.2"
|
|||||||
divrem = "0.1.0"
|
divrem = "0.1.0"
|
||||||
downcast = "0.10.0"
|
downcast = "0.10.0"
|
||||||
git-version = "0.3.4"
|
git-version = "0.3.4"
|
||||||
|
hostname = "0.3.1"
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2.62"
|
libc = "0.2.62"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ extern crate divrem;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate downcast;
|
extern crate downcast;
|
||||||
extern crate git_version;
|
extern crate git_version;
|
||||||
|
extern crate hostname;
|
||||||
extern crate indexmap;
|
extern crate indexmap;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ pub enum SystemClauseType {
|
|||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
CopyToLiftedHeap,
|
CopyToLiftedHeap,
|
||||||
CreatePartialString,
|
CreatePartialString,
|
||||||
|
CurrentHostname,
|
||||||
CurrentInput,
|
CurrentInput,
|
||||||
CurrentOutput,
|
CurrentOutput,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
@@ -254,6 +255,10 @@ pub enum SystemClauseType {
|
|||||||
SetSeed,
|
SetSeed,
|
||||||
SkipMaxList,
|
SkipMaxList,
|
||||||
Sleep,
|
Sleep,
|
||||||
|
SocketClientOpen,
|
||||||
|
SocketServerOpen,
|
||||||
|
SocketServerAccept,
|
||||||
|
SocketServerClose,
|
||||||
Succeed,
|
Succeed,
|
||||||
TermAttributedVariables,
|
TermAttributedVariables,
|
||||||
TermVariables,
|
TermVariables,
|
||||||
@@ -291,6 +296,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"),
|
&SystemClauseType::CopyTermWithoutAttrVars => clause_name!("$copy_term_without_attr_vars"),
|
||||||
&SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"),
|
&SystemClauseType::CreatePartialString => clause_name!("$create_partial_string"),
|
||||||
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
|
&SystemClauseType::CurrentInput => clause_name!("$current_input"),
|
||||||
|
&SystemClauseType::CurrentHostname => clause_name!("$current_hostname"),
|
||||||
&SystemClauseType::CurrentOutput => clause_name!("$current_output"),
|
&SystemClauseType::CurrentOutput => clause_name!("$current_output"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
|
||||||
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
|
||||||
@@ -410,6 +416,10 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"),
|
&SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"),
|
||||||
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
|
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
|
||||||
&SystemClauseType::Sleep => clause_name!("$sleep"),
|
&SystemClauseType::Sleep => clause_name!("$sleep"),
|
||||||
|
&SystemClauseType::SocketClientOpen => clause_name!("$socket_client_open"),
|
||||||
|
&SystemClauseType::SocketServerOpen => clause_name!("$socket_server_open"),
|
||||||
|
&SystemClauseType::SocketServerAccept => clause_name!("$socket_server_accept"),
|
||||||
|
&SystemClauseType::SocketServerClose => clause_name!("$socket_server_close"),
|
||||||
&SystemClauseType::Succeed => clause_name!("$succeed"),
|
&SystemClauseType::Succeed => clause_name!("$succeed"),
|
||||||
&SystemClauseType::TermAttributedVariables => clause_name!("$term_attributed_variables"),
|
&SystemClauseType::TermAttributedVariables => clause_name!("$term_attributed_variables"),
|
||||||
&SystemClauseType::TermVariables => clause_name!("$term_variables"),
|
&SystemClauseType::TermVariables => clause_name!("$term_variables"),
|
||||||
@@ -450,6 +460,7 @@ impl SystemClauseType {
|
|||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
|
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
|
||||||
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
||||||
|
("$current_hostname", 1) => Some(SystemClauseType::CurrentHostname),
|
||||||
("$current_input", 1) => Some(SystemClauseType::CurrentInput),
|
("$current_input", 1) => Some(SystemClauseType::CurrentInput),
|
||||||
("$current_output", 1) => Some(SystemClauseType::CurrentOutput),
|
("$current_output", 1) => Some(SystemClauseType::CurrentOutput),
|
||||||
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
||||||
@@ -523,8 +534,8 @@ impl SystemClauseType {
|
|||||||
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
|
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
|
||||||
("$quoted_token", 1) => Some(SystemClauseType::QuotedToken),
|
("$quoted_token", 1) => Some(SystemClauseType::QuotedToken),
|
||||||
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
("$nextEP", 3) => Some(SystemClauseType::NextEP),
|
||||||
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
|
("$read_query_term", 5) => Some(SystemClauseType::ReadQueryTerm),
|
||||||
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
|
("$read_term", 5) => Some(SystemClauseType::ReadTerm),
|
||||||
("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars),
|
("$read_term_from_chars", 2) => Some(SystemClauseType::ReadTermFromChars),
|
||||||
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
|
||||||
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
("$reset_cont_marker", 0) => Some(SystemClauseType::ResetContinuationMarker),
|
||||||
@@ -538,6 +549,10 @@ impl SystemClauseType {
|
|||||||
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
|
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
|
||||||
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
|
||||||
("$sleep", 1) => Some(SystemClauseType::Sleep),
|
("$sleep", 1) => Some(SystemClauseType::Sleep),
|
||||||
|
("$socket_client_open", 7) => Some(SystemClauseType::SocketClientOpen),
|
||||||
|
("$socket_server_open", 3) => Some(SystemClauseType::SocketServerOpen),
|
||||||
|
("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept),
|
||||||
|
("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose),
|
||||||
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
|
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
|
||||||
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
|
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
|
||||||
("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables),
|
("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables),
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
HeapCellValue::Stream(_) => {
|
HeapCellValue::Stream(_) => {
|
||||||
Addr::Stream(h)
|
Addr::Stream(h)
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::TcpListener(_) => {
|
||||||
|
Addr::TcpListener(h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::prolog::heap_iter::*;
|
|||||||
use crate::prolog::machine::heap::*;
|
use crate::prolog::machine::heap::*;
|
||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
use crate::prolog::machine::machine_state::*;
|
use crate::prolog::machine::machine_state::*;
|
||||||
|
use crate::prolog::machine::streams::*;
|
||||||
use crate::prolog::ordered_float::OrderedFloat;
|
use crate::prolog::ordered_float::OrderedFloat;
|
||||||
use crate::prolog::rug::{Integer, Rational};
|
use crate::prolog::rug::{Integer, Rational};
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ use indexmap::{IndexMap, IndexSet};
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::iter::{FromIterator, once};
|
use std::iter::{FromIterator, once};
|
||||||
|
use std::net::{IpAddr, TcpListener};
|
||||||
use std::ops::{Range, RangeFrom};
|
use std::ops::{Range, RangeFrom};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -170,10 +172,12 @@ enum TokenOrRedirect {
|
|||||||
NumberedVar(String),
|
NumberedVar(String),
|
||||||
CompositeRedirect(usize, DirectedOp),
|
CompositeRedirect(usize, DirectedOp),
|
||||||
FunctorRedirect(usize),
|
FunctorRedirect(usize),
|
||||||
|
IpAddr(IpAddr),
|
||||||
Number(Number, Option<DirectedOp>),
|
Number(Number, Option<DirectedOp>),
|
||||||
Open,
|
Open,
|
||||||
Close,
|
Close,
|
||||||
Comma,
|
Comma,
|
||||||
|
RawPtr(*const u8),
|
||||||
Space,
|
Space,
|
||||||
LeftCurly,
|
LeftCurly,
|
||||||
RightCurly,
|
RightCurly,
|
||||||
@@ -643,8 +647,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.state_stack.pop();
|
self.state_stack.pop();
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(name));
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
true
|
true
|
||||||
@@ -964,6 +968,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn print_ip_addr(&mut self, ip: IpAddr) {
|
||||||
|
self.push_char('\'');
|
||||||
|
self.append_str(&format!("{}", ip));
|
||||||
|
self.push_char('\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn print_raw_ptr(&mut self, ptr: *const u8) {
|
||||||
|
self.append_str(&format!("0x{:x}", ptr as usize));
|
||||||
|
}
|
||||||
|
|
||||||
fn print_number(&mut self, n: Number, op: &Option<DirectedOp>) {
|
fn print_number(&mut self, n: Number, op: &Option<DirectedOp>) {
|
||||||
let add_brackets = if let Some(op) = op {
|
let add_brackets = if let Some(op) = op {
|
||||||
op.is_negative_sign() && n.is_positive()
|
op.is_negative_sign() && n.is_positive()
|
||||||
@@ -1330,6 +1346,66 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_tcp_listener(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
tcp_listener: &TcpListener,
|
||||||
|
max_depth: usize,
|
||||||
|
) {
|
||||||
|
let (ip, port) =
|
||||||
|
if let Some(addr) = tcp_listener.local_addr().ok() {
|
||||||
|
(addr.ip(), Number::from(addr.port() as isize))
|
||||||
|
} else {
|
||||||
|
let disconnected_atom = clause_name!("$disconnected_tcp_listener");
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(disconnected_atom));
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.format_struct(iter, max_depth, 1, clause_name!("$tcp_listener")) {
|
||||||
|
let atom = self.state_stack.pop().unwrap();
|
||||||
|
|
||||||
|
self.state_stack.pop();
|
||||||
|
self.state_stack.pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Number(port, None));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Comma);
|
||||||
|
self.state_stack.push(TokenOrRedirect::IpAddr(ip));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
self.state_stack.push(atom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_stream(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
stream: &Stream,
|
||||||
|
max_depth: usize,
|
||||||
|
) {
|
||||||
|
if let Some(alias) = &stream.options.alias {
|
||||||
|
self.print_atom(alias);
|
||||||
|
} else {
|
||||||
|
if self.format_struct(iter, max_depth, 1, clause_name!("$stream")) {
|
||||||
|
let atom =
|
||||||
|
if stream.is_stdout() || stream.is_stdin() {
|
||||||
|
TokenOrRedirect::Atom(clause_name!("user"))
|
||||||
|
} else {
|
||||||
|
TokenOrRedirect::RawPtr(stream.as_ptr())
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream_root = self.state_stack.pop().unwrap();
|
||||||
|
|
||||||
|
self.state_stack.pop();
|
||||||
|
self.state_stack.pop();
|
||||||
|
|
||||||
|
self.state_stack.push(atom);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
self.state_stack.push(stream_root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_heap_term(
|
fn handle_heap_term(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: &mut HCPreOrderIterator,
|
iter: &mut HCPreOrderIterator,
|
||||||
@@ -1440,15 +1516,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.print_number(Number::Rational(n.clone()), &op);
|
self.print_number(Number::Rational(n.clone()), &op);
|
||||||
}
|
}
|
||||||
&HeapCellValue::Stream(ref stream) => {
|
&HeapCellValue::Stream(ref stream) => {
|
||||||
if let Some(alias) = &stream.options.alias {
|
self.print_stream(iter, stream, max_depth);
|
||||||
self.print_atom(alias);
|
}
|
||||||
} else {
|
&HeapCellValue::TcpListener(ref tcp_listener) => {
|
||||||
if stream.is_stdout() || stream.is_stdin() {
|
self.print_tcp_listener(iter, tcp_listener, max_depth);
|
||||||
self.print_atom(&clause_name!("user"));
|
|
||||||
} else {
|
|
||||||
self.format_struct(iter, max_depth, 1, clause_name!("$stream"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -1486,6 +1557,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.handle_heap_term(&mut iter, None, true, max_depth)
|
self.handle_heap_term(&mut iter, None, true, max_depth)
|
||||||
}
|
}
|
||||||
TokenOrRedirect::Close => self.push_char(')'),
|
TokenOrRedirect::Close => self.push_char(')'),
|
||||||
|
TokenOrRedirect::IpAddr(ip) => self.print_ip_addr(ip),
|
||||||
|
TokenOrRedirect::RawPtr(ptr) => self.print_raw_ptr(ptr),
|
||||||
TokenOrRedirect::Open => self.push_char('('),
|
TokenOrRedirect::Open => self.push_char('('),
|
||||||
TokenOrRedirect::OpenList(delimit) => {
|
TokenOrRedirect::OpenList(delimit) => {
|
||||||
if !self.at_cdr(",") {
|
if !self.at_cdr(",") {
|
||||||
|
|||||||
@@ -420,25 +420,16 @@ parse_read_term_options(Options, OptionValues, Stub) :-
|
|||||||
parse_options_list(Options, parse_read_term_options_, DefaultOptions, OptionValues, Stub).
|
parse_options_list(Options, parse_read_term_options_, DefaultOptions, OptionValues, Stub).
|
||||||
|
|
||||||
|
|
||||||
parse_read_term_options_(singletons(Vars), singletons-Vars) :-
|
parse_read_term_options_(singletons(Vars), singletons-Vars).
|
||||||
( '$skip_max_list'(Vars, _, -1, Tail), Tail == [], !
|
parse_read_term_options_(variables(Vars), variables-Vars).
|
||||||
;
|
parse_read_term_options_(variable_names(Vars), variable_names-Vars).
|
||||||
throw(error(domain_error(read_option, singletons(Vars)), _))
|
parse_read_term_options_(E,_) :-
|
||||||
).
|
throw(error(domain_error(read_option, E), _)).
|
||||||
parse_read_term_options_(variables(Vars), variables-Vars) :-
|
|
||||||
( '$skip_max_list'(Vars, _, -1, Tail), Tail == [], !
|
|
||||||
;
|
|
||||||
throw(error(domain_error(read_option, variables(Vars)), _))
|
|
||||||
).
|
|
||||||
parse_read_term_options_(variable_names(Vars), variable_names-Vars) :-
|
|
||||||
( '$skip_max_list'(Vars, _, -1, Tail), Tail == [], !
|
|
||||||
;
|
|
||||||
throw(error(domain_error(read_option, variable_names(Vars)), _))
|
|
||||||
).
|
|
||||||
|
|
||||||
|
|
||||||
read_term(Stream, Term, Options) :-
|
read_term(Stream, Term, Options) :-
|
||||||
parse_read_term_options(Options, [Singletons, Variables, VariableNames], read_term/3),
|
parse_read_term_options(Options, [Singletons, VariableNames, Variables], read_term/3),
|
||||||
'$read_term'(Stream, Term, Singletons, Variables, VariableNames).
|
'$read_term'(Stream, Term, Singletons, Variables, VariableNames).
|
||||||
|
|
||||||
read_term(Term, Options) :-
|
read_term(Term, Options) :-
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ fn load_library(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::Library(
|
let err = ExistenceError::ModuleSource(ModuleSource::Library(
|
||||||
name.clone()
|
name.clone()
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -708,7 +708,7 @@ impl ListingCompiler {
|
|||||||
|
|
||||||
Ok(wam_indices.insert_module(submodule))
|
Ok(wam_indices.insert_module(submodule))
|
||||||
} else {
|
} else {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::File(
|
let err = ExistenceError::ModuleSource(ModuleSource::File(
|
||||||
module_name,
|
module_name,
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -746,7 +746,7 @@ impl ListingCompiler {
|
|||||||
|
|
||||||
Ok(wam_indices.insert_module(submodule))
|
Ok(wam_indices.insert_module(submodule))
|
||||||
} else {
|
} else {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::File(
|
let err = ExistenceError::ModuleSource(ModuleSource::File(
|
||||||
module_name
|
module_name
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -1080,7 +1080,7 @@ impl ListingCompiler {
|
|||||||
insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
|
insert_or_refresh_term_dir_quantum(term_dir, key, term_dirs);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::File(
|
let err = ExistenceError::ModuleSource(ModuleSource::File(
|
||||||
module_name,
|
module_name,
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -1438,7 +1438,7 @@ pub(super) fn setup_indices(
|
|||||||
wam.indices.insert_module(module);
|
wam.indices.insert_module(module);
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::Library(
|
let err = ExistenceError::ModuleSource(ModuleSource::Library(
|
||||||
module
|
module
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@@ -171,15 +171,18 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||||
}
|
}
|
||||||
&HeapCellValue::Rational(ref r) => {
|
|
||||||
HeapCellValue::Rational(r.clone())
|
|
||||||
}
|
|
||||||
&HeapCellValue::PartialString(..) => {
|
&HeapCellValue::PartialString(..) => {
|
||||||
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::Rational(ref r) => {
|
||||||
|
HeapCellValue::Rational(r.clone())
|
||||||
|
}
|
||||||
&HeapCellValue::Stream(_) => {
|
&HeapCellValue::Stream(_) => {
|
||||||
HeapCellValue::Addr(Addr::Stream(h))
|
HeapCellValue::Addr(Addr::Stream(h))
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::TcpListener(_) => {
|
||||||
|
HeapCellValue::Addr(Addr::TcpListener(h))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,9 +297,6 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
val @ HeapCellValue::NamedStr(..) => {
|
val @ HeapCellValue::NamedStr(..) => {
|
||||||
Addr::Str(self.push(val))
|
Addr::Str(self.push(val))
|
||||||
}
|
}
|
||||||
val @ HeapCellValue::Stream(..) => {
|
|
||||||
Addr::Stream(self.push(val))
|
|
||||||
}
|
|
||||||
HeapCellValue::PartialString(pstr, has_tail) => {
|
HeapCellValue::PartialString(pstr, has_tail) => {
|
||||||
let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
|
let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
|
||||||
|
|
||||||
@@ -306,6 +306,12 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
|
|
||||||
Addr::Con(h)
|
Addr::Con(h)
|
||||||
}
|
}
|
||||||
|
val @ HeapCellValue::Stream(..) => {
|
||||||
|
Addr::Stream(self.push(val))
|
||||||
|
}
|
||||||
|
val @ HeapCellValue::TcpListener(..) => {
|
||||||
|
Addr::TcpListener(self.push(val))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +523,7 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
|||||||
pub
|
pub
|
||||||
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||||
match addr {
|
match addr {
|
||||||
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) => {
|
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
|
||||||
RefOrOwned::Borrowed(&self[h])
|
RefOrOwned::Borrowed(&self[h])
|
||||||
}
|
}
|
||||||
addr => {
|
addr => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ enum ErrorProvenance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct MachineError {
|
pub(crate) struct MachineError {
|
||||||
stub: MachineStub,
|
stub: MachineStub,
|
||||||
location: Option<(usize, usize)>, // line_num, col_num
|
location: Option<(usize, usize)>, // line_num, col_num
|
||||||
from: ErrorProvenance,
|
from: ErrorProvenance,
|
||||||
@@ -74,7 +74,7 @@ impl TypeError for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(crate)
|
||||||
trait PermissionError {
|
trait PermissionError {
|
||||||
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
|
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
|
||||||
}
|
}
|
||||||
@@ -250,7 +250,7 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Constructed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExistenceError::SourceSink(source) => {
|
ExistenceError::ModuleSource(source) => {
|
||||||
let source_stub = source.as_functor_stub();
|
let source_stub = source.as_functor_stub();
|
||||||
|
|
||||||
let stub = functor!(
|
let stub = functor!(
|
||||||
@@ -265,6 +265,18 @@ impl MachineError {
|
|||||||
from: ErrorProvenance::Constructed,
|
from: ErrorProvenance::Constructed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ExistenceError::SourceSink(culprit) => {
|
||||||
|
let stub = functor!(
|
||||||
|
"existence_error",
|
||||||
|
[atom("source_sink"), addr(culprit)]
|
||||||
|
);
|
||||||
|
|
||||||
|
MachineError {
|
||||||
|
stub,
|
||||||
|
location: None,
|
||||||
|
from: ErrorProvenance::Constructed,
|
||||||
|
}
|
||||||
|
}
|
||||||
ExistenceError::Stream(culprit) => {
|
ExistenceError::Stream(culprit) => {
|
||||||
let stub = functor!(
|
let stub = functor!(
|
||||||
"existence_error",
|
"existence_error",
|
||||||
@@ -454,6 +466,7 @@ pub enum Permission {
|
|||||||
Create,
|
Create,
|
||||||
InputStream,
|
InputStream,
|
||||||
Modify,
|
Modify,
|
||||||
|
Open,
|
||||||
OutputStream,
|
OutputStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,6 +477,7 @@ impl Permission {
|
|||||||
Permission::Create => "create",
|
Permission::Create => "create",
|
||||||
Permission::InputStream => "input",
|
Permission::InputStream => "input",
|
||||||
Permission::Modify => "modify",
|
Permission::Modify => "modify",
|
||||||
|
Permission::Open => "open",
|
||||||
Permission::OutputStream => "output",
|
Permission::OutputStream => "output",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -489,6 +503,7 @@ pub enum ValidType {
|
|||||||
Pair,
|
Pair,
|
||||||
// PredicateIndicator,
|
// PredicateIndicator,
|
||||||
// Variable
|
// Variable
|
||||||
|
TcpListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidType {
|
impl ValidType {
|
||||||
@@ -511,6 +526,7 @@ impl ValidType {
|
|||||||
ValidType::Pair => "pair",
|
ValidType::Pair => "pair",
|
||||||
// ValidType::PredicateIndicator => "predicate_indicator",
|
// ValidType::PredicateIndicator => "predicate_indicator",
|
||||||
// ValidType::Variable => "variable"
|
// ValidType::Variable => "variable"
|
||||||
|
ValidType::TcpListener => "tcp_listener",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -726,8 +742,9 @@ impl MachineState {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ExistenceError {
|
pub enum ExistenceError {
|
||||||
Module(ClauseName),
|
Module(ClauseName),
|
||||||
|
ModuleSource(ModuleSource),
|
||||||
Procedure(ClauseName, usize),
|
Procedure(ClauseName, usize),
|
||||||
SourceSink(ModuleSource),
|
SourceSink(Addr),
|
||||||
Stream(Addr),
|
Stream(Addr),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use std::collections::{BTreeMap, VecDeque};
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::net::TcpListener;
|
||||||
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ pub enum Addr {
|
|||||||
StackCell(usize, usize),
|
StackCell(usize, usize),
|
||||||
Str(usize),
|
Str(usize),
|
||||||
Stream(usize),
|
Stream(usize),
|
||||||
|
TcpListener(usize),
|
||||||
Usize(usize),
|
Usize(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +232,7 @@ impl Addr {
|
|||||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||||
Some(TermOrderCategory::Compound)
|
Some(TermOrderCategory::Compound)
|
||||||
}
|
}
|
||||||
Addr::CutPoint(_) | Addr::Stream(_) => {
|
Addr::CutPoint(_) | Addr::Stream(_) | Addr::TcpListener(_) => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,6 +390,7 @@ pub enum HeapCellValue {
|
|||||||
Rational(Rc<Rational>),
|
Rational(Rc<Rational>),
|
||||||
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
|
||||||
Stream(Stream),
|
Stream(Stream),
|
||||||
|
TcpListener(TcpListener),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeapCellValue {
|
impl HeapCellValue {
|
||||||
@@ -410,6 +413,9 @@ impl HeapCellValue {
|
|||||||
HeapCellValue::Stream(_) => {
|
HeapCellValue::Stream(_) => {
|
||||||
Addr::Stream(focus)
|
Addr::Stream(focus)
|
||||||
}
|
}
|
||||||
|
HeapCellValue::TcpListener(_) => {
|
||||||
|
Addr::TcpListener(focus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,6 +446,9 @@ impl HeapCellValue {
|
|||||||
&HeapCellValue::Stream(_) => {
|
&HeapCellValue::Stream(_) => {
|
||||||
HeapCellValue::Stream(Stream::null_stream())
|
HeapCellValue::Stream(Stream::null_stream())
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::TcpListener(_) => {
|
||||||
|
HeapCellValue::Atom(clause_name!("$socket_server"), None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use crate::prolog::machine::machine_indices::*;
|
|||||||
use crate::prolog::machine::modules::*;
|
use crate::prolog::machine::modules::*;
|
||||||
use crate::prolog::machine::stack::*;
|
use crate::prolog::machine::stack::*;
|
||||||
use crate::prolog::machine::streams::*;
|
use crate::prolog::machine::streams::*;
|
||||||
use crate::prolog::read::{PrologStream, readline};
|
|
||||||
use crate::prolog::rug::Integer;
|
use crate::prolog::rug::Integer;
|
||||||
|
|
||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
@@ -614,40 +613,13 @@ pub struct MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
pub(crate)
|
|
||||||
fn open_parsing_stream(
|
|
||||||
&self,
|
|
||||||
stream: Stream,
|
|
||||||
stub_name: &'static str,
|
|
||||||
stub_arity: usize,
|
|
||||||
) -> Result<PrologStream, MachineStub> {
|
|
||||||
match parsing_stream(stream) {
|
|
||||||
Ok(stream) => {
|
|
||||||
Ok(stream)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
|
|
||||||
let err = MachineError::session_error(
|
|
||||||
self.heap.h(),
|
|
||||||
SessionError::from(e),
|
|
||||||
);
|
|
||||||
|
|
||||||
Err(self.error_form(err, stub))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn read_term(
|
fn read_term(
|
||||||
&mut self,
|
&mut self,
|
||||||
current_input_stream: &mut Stream,
|
stream: Stream,
|
||||||
indices: &mut IndexStore,
|
indices: &mut IndexStore,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
let mut stream = self.open_parsing_stream(
|
let mut stream = self.open_parsing_stream(stream, "read_term", 3)?;
|
||||||
current_input_stream.clone(),
|
|
||||||
"read_term",
|
|
||||||
2,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
match self.read(
|
match self.read(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
@@ -655,8 +627,8 @@ impl MachineState {
|
|||||||
&indices.op_dir,
|
&indices.op_dir,
|
||||||
) {
|
) {
|
||||||
Ok(term_write_result) => {
|
Ok(term_write_result) => {
|
||||||
let a1 = self[temp_v!(1)];
|
let term = self[temp_v!(2)];
|
||||||
self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
|
self.unify(Addr::HeapCell(term_write_result.heap_loc), term);
|
||||||
|
|
||||||
if self.fail {
|
if self.fail {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -677,11 +649,56 @@ impl MachineState {
|
|||||||
list_of_var_eqs.push(Addr::Str(h));
|
list_of_var_eqs.push(Addr::Str(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
let a2 = self[temp_v!(2)];
|
let mut var_set: IndexMap<Ref, bool> = IndexMap::new();
|
||||||
let list_offset =
|
|
||||||
|
for addr in self.acyclic_pre_order_iter(term) {
|
||||||
|
if let Some(var) = addr.as_var() {
|
||||||
|
if !var_set.contains_key(&var) {
|
||||||
|
var_set.insert(var, true);
|
||||||
|
} else {
|
||||||
|
var_set.insert(var, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut var_list = vec![];
|
||||||
|
let mut singleton_var_list = vec![];
|
||||||
|
|
||||||
|
for addr in self.acyclic_pre_order_iter(term) {
|
||||||
|
if let Some(var) = addr.as_var() {
|
||||||
|
if var_set.get(&var) == Some(&true) {
|
||||||
|
singleton_var_list.push(var.as_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
var_list.push(var.as_addr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let singleton_addr = self[temp_v!(3)];
|
||||||
|
let singletons_offset =
|
||||||
|
Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter()));
|
||||||
|
|
||||||
|
self.unify(singletons_offset, singleton_addr);
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let vars_addr = self[temp_v!(4)];
|
||||||
|
let vars_offset =
|
||||||
|
Addr::HeapCell(self.heap.to_list(var_list.into_iter()));
|
||||||
|
|
||||||
|
self.unify(vars_offset, vars_addr);
|
||||||
|
|
||||||
|
if self.fail {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let var_names_addr = self[temp_v!(5)];
|
||||||
|
let var_names_offset =
|
||||||
Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
|
Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
|
||||||
|
|
||||||
Ok(self.unify(list_offset, a2))
|
Ok(self.unify(var_names_offset, var_names_addr))
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let ParserError::UnexpectedEOF = err {
|
if let ParserError::UnexpectedEOF = err {
|
||||||
@@ -689,7 +706,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset the input stream after an input failure.
|
// reset the input stream after an input failure.
|
||||||
*current_input_stream = readline::input_stream();
|
//*stream = readline::input_stream();
|
||||||
|
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
let syntax_error = MachineError::syntax_error(h, err);
|
let syntax_error = MachineError::syntax_error(h, err);
|
||||||
|
|||||||
@@ -1400,9 +1400,11 @@ impl MachineState {
|
|||||||
let addr = self.store(self.deref(addr));
|
let addr = self.store(self.deref(addr));
|
||||||
|
|
||||||
let offset = match addr {
|
let offset = match addr {
|
||||||
Addr::HeapCell(_) | Addr::StackCell(..) |
|
Addr::Stream(_) | Addr::TcpListener(_) => {
|
||||||
Addr::AttrVar(..) | Addr::Stream(_) => {
|
0
|
||||||
v
|
}
|
||||||
|
Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => {
|
||||||
|
v
|
||||||
}
|
}
|
||||||
Addr::PStrLocation(..) => {
|
Addr::PStrLocation(..) => {
|
||||||
if !self.flags.double_quotes.is_atom() {
|
if !self.flags.double_quotes.is_atom() {
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ impl Machine {
|
|||||||
|
|
||||||
Ok(self.indices.insert_module(module))
|
Ok(self.indices.insert_module(module))
|
||||||
} else {
|
} else {
|
||||||
let err = ExistenceError::SourceSink(ModuleSource::File(
|
let err = ExistenceError::ModuleSource(ModuleSource::File(
|
||||||
clause_name!("$toplevel"),
|
clause_name!("$toplevel"),
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -409,6 +409,15 @@ impl Machine {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
compile_user_module(&mut wam,
|
||||||
|
Stream::from(PAIRS),
|
||||||
|
true,
|
||||||
|
ListingSource::from_file_and_path(
|
||||||
|
clause_name!("pairs"),
|
||||||
|
lib_path.clone(),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
compile_user_module(&mut wam,
|
compile_user_module(&mut wam,
|
||||||
Stream::from(LISTS),
|
Stream::from(LISTS),
|
||||||
true,
|
true,
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
use crate::prolog_parser::ast::*;
|
use crate::prolog_parser::ast::*;
|
||||||
|
|
||||||
use crate::prolog::read::readline::*;
|
use crate::prolog::read::readline::*;
|
||||||
|
use crate::prolog::machine::machine_errors::*;
|
||||||
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
use crate::prolog::machine::machine_state::*;
|
||||||
|
use crate::prolog::read::PrologStream;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{stdin, stdout, Cursor, ErrorKind, Read, Write};
|
use std::io::{stdout, Cursor, ErrorKind, Read, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -32,7 +36,7 @@ pub enum StreamInstance {
|
|||||||
File(File),
|
File(File),
|
||||||
Null,
|
Null,
|
||||||
ReadlineStream(ReadlineStream),
|
ReadlineStream(ReadlineStream),
|
||||||
Stdin,
|
// Stdin,
|
||||||
Stdout,
|
Stdout,
|
||||||
TcpStream(TcpStream),
|
TcpStream(TcpStream),
|
||||||
}
|
}
|
||||||
@@ -48,7 +52,7 @@ impl fmt::Debug for StreamInstance {
|
|||||||
&StreamInstance::Null => write!(fmt, "Null"),
|
&StreamInstance::Null => write!(fmt, "Null"),
|
||||||
&StreamInstance::ReadlineStream(ref readline_stream) =>
|
&StreamInstance::ReadlineStream(ref readline_stream) =>
|
||||||
write!(fmt, "ReadlineStream({:?})", readline_stream),
|
write!(fmt, "ReadlineStream({:?})", readline_stream),
|
||||||
&StreamInstance::Stdin => write!(fmt, "Stdin"),
|
// &StreamInstance::Stdin => write!(fmt, "Stdin"),
|
||||||
&StreamInstance::Stdout => write!(fmt, "Stdout"),
|
&StreamInstance::Stdout => write!(fmt, "Stdout"),
|
||||||
&StreamInstance::TcpStream(ref tcp_stream) =>
|
&StreamInstance::TcpStream(ref tcp_stream) =>
|
||||||
write!(fmt, "TcpStream({:?})", tcp_stream),
|
write!(fmt, "TcpStream({:?})", tcp_stream),
|
||||||
@@ -140,6 +144,17 @@ pub struct Stream {
|
|||||||
stream_inst: WrappedStreamInstance,
|
stream_inst: WrappedStreamInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TcpStream> for Stream {
|
||||||
|
fn from(tcp_stream: TcpStream) -> Self {
|
||||||
|
Stream {
|
||||||
|
options: StreamOptions::default(),
|
||||||
|
stream_inst: WrappedStreamInstance::new(
|
||||||
|
StreamInstance::TcpStream(tcp_stream)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<String> for Stream {
|
impl From<String> for Stream {
|
||||||
fn from(string: String) -> Self {
|
fn from(string: String) -> Self {
|
||||||
Stream {
|
Stream {
|
||||||
@@ -187,7 +202,7 @@ impl From<File> for Stream {
|
|||||||
impl Stream {
|
impl Stream {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn as_ptr(&self) -> *const RefCell<StreamInstance> {
|
fn as_ptr(&self) -> *const u8 {
|
||||||
let rc = self.stream_inst.0.clone();
|
let rc = self.stream_inst.0.clone();
|
||||||
let ptr = Rc::into_raw(rc);
|
let ptr = Rc::into_raw(rc);
|
||||||
|
|
||||||
@@ -196,7 +211,7 @@ impl Stream {
|
|||||||
let _ = Rc::from_raw(ptr);
|
let _ = Rc::from_raw(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr
|
ptr as *const u8
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -210,6 +225,7 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
fn stdin() -> Self {
|
fn stdin() -> Self {
|
||||||
@@ -220,6 +236,7 @@ impl Stream {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate)
|
pub(crate)
|
||||||
@@ -249,7 +266,8 @@ impl Stream {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn is_stdin(&self) -> bool {
|
fn is_stdin(&self) -> bool {
|
||||||
match *self.stream_inst.0.borrow() {
|
match *self.stream_inst.0.borrow() {
|
||||||
StreamInstance::Stdin | StreamInstance::ReadlineStream(_) => {
|
//StreamInstance::Stdin |
|
||||||
|
StreamInstance::ReadlineStream(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -262,12 +280,12 @@ impl Stream {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn is_input_stream(&self) -> bool {
|
fn is_input_stream(&self) -> bool {
|
||||||
match *self.stream_inst.0.borrow() {
|
match *self.stream_inst.0.borrow() {
|
||||||
StreamInstance::Stdin
|
// StreamInstance::Stdin |
|
||||||
| StreamInstance::TcpStream(_)
|
StreamInstance::TcpStream(_) |
|
||||||
| StreamInstance::Bytes(_)
|
StreamInstance::Bytes(_) |
|
||||||
| StreamInstance::ReadlineStream(_)
|
StreamInstance::ReadlineStream(_) |
|
||||||
| StreamInstance::DynReadSource(_)
|
StreamInstance::DynReadSource(_) |
|
||||||
| StreamInstance::File(_) => {
|
StreamInstance::File(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -293,6 +311,221 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MachineState {
|
||||||
|
pub(crate)
|
||||||
|
fn to_stream_options(
|
||||||
|
&self,
|
||||||
|
alias: Addr,
|
||||||
|
eof_action: Addr,
|
||||||
|
reposition: Addr,
|
||||||
|
stream_type: Addr,
|
||||||
|
) -> StreamOptions {
|
||||||
|
let alias =
|
||||||
|
match self.store(self.deref(alias)) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
Some(name.clone())
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let eof_action =
|
||||||
|
match self.store(self.deref(eof_action)) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
match name.as_str() {
|
||||||
|
"eof_code" => EOFAction::EOFCode,
|
||||||
|
"error" => EOFAction::Error,
|
||||||
|
"reset" => EOFAction::Reset,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let reposition =
|
||||||
|
match self.store(self.deref(reposition)) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
name.as_str() == "true"
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream_type =
|
||||||
|
match self.store(self.deref(stream_type)) {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
match name.as_str() {
|
||||||
|
"text" => StreamType::Text,
|
||||||
|
"binary" => StreamType::Binary,
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut options = StreamOptions::default();
|
||||||
|
|
||||||
|
options.stream_type = stream_type;
|
||||||
|
options.reposition = reposition;
|
||||||
|
options.alias = alias;
|
||||||
|
options.eof_action = eof_action;
|
||||||
|
|
||||||
|
options
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn get_stream_or_alias(
|
||||||
|
&mut self,
|
||||||
|
addr: Addr,
|
||||||
|
indices: &IndexStore,
|
||||||
|
caller: &'static str,
|
||||||
|
arity: usize,
|
||||||
|
) -> Result<Stream, MachineStub>
|
||||||
|
{
|
||||||
|
Ok(match addr {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) {
|
||||||
|
match indices.stream_aliases.get(atom) {
|
||||||
|
Some(stream) => {
|
||||||
|
stream.clone()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(caller), arity);
|
||||||
|
let h = self.heap.h();
|
||||||
|
|
||||||
|
let addr = self.heap.to_unifiable(
|
||||||
|
HeapCellValue::Atom(atom.clone(), spec.clone())
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(
|
||||||
|
MachineError::existence_error(h + 1, ExistenceError::Stream(addr)),
|
||||||
|
stub,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Addr::Stream(h) => {
|
||||||
|
if let HeapCellValue::Stream(ref stream) = &self.heap[h] {
|
||||||
|
stream.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(caller), arity);
|
||||||
|
|
||||||
|
return Err(self.error_form(
|
||||||
|
MachineError::domain_error(DomainErrorType::StreamOrAlias, addr),
|
||||||
|
stub,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn open_parsing_stream(
|
||||||
|
&self,
|
||||||
|
stream: Stream,
|
||||||
|
stub_name: &'static str,
|
||||||
|
stub_arity: usize,
|
||||||
|
) -> Result<PrologStream, MachineStub> {
|
||||||
|
match parsing_stream(stream) {
|
||||||
|
Ok(stream) => {
|
||||||
|
Ok(stream)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
|
||||||
|
let err = MachineError::session_error(
|
||||||
|
self.heap.h(),
|
||||||
|
SessionError::from(e),
|
||||||
|
);
|
||||||
|
|
||||||
|
Err(self.error_form(err, stub))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn open_permission_error<T: PermissionError>(
|
||||||
|
&self,
|
||||||
|
culprit: T,
|
||||||
|
stub_name: &'static str,
|
||||||
|
stub_arity: usize,
|
||||||
|
) -> MachineStub {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
|
||||||
|
let err = MachineError::permission_error(
|
||||||
|
self.heap.h(),
|
||||||
|
Permission::Open,
|
||||||
|
"source_sink",
|
||||||
|
culprit,
|
||||||
|
);
|
||||||
|
|
||||||
|
return self.error_form(err, stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn occupied_alias_permission_error(
|
||||||
|
&self,
|
||||||
|
alias: ClauseName,
|
||||||
|
stub_name: &'static str,
|
||||||
|
stub_arity: usize,
|
||||||
|
) -> MachineStub {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
|
||||||
|
let err = MachineError::permission_error(
|
||||||
|
self.heap.h(),
|
||||||
|
Permission::Open,
|
||||||
|
"source_sink",
|
||||||
|
functor!("alias", [clause_name(alias)]),
|
||||||
|
);
|
||||||
|
|
||||||
|
return self.error_form(err, stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn reposition_error(
|
||||||
|
&self,
|
||||||
|
stub_name: &'static str,
|
||||||
|
stub_arity: usize,
|
||||||
|
) -> MachineStub {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!(stub_name), stub_arity);
|
||||||
|
let rep_stub = functor!("reposition", [atom("true")]);
|
||||||
|
|
||||||
|
let err = MachineError::permission_error(
|
||||||
|
self.heap.h(),
|
||||||
|
Permission::Open,
|
||||||
|
"source_sink",
|
||||||
|
rep_stub,
|
||||||
|
);
|
||||||
|
|
||||||
|
return self.error_form(err, stub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Read for Stream {
|
impl Read for Stream {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
match *self.stream_inst.0.borrow_mut() {
|
match *self.stream_inst.0.borrow_mut() {
|
||||||
@@ -311,9 +544,11 @@ impl Read for Stream {
|
|||||||
StreamInstance::Bytes(ref mut cursor) => {
|
StreamInstance::Bytes(ref mut cursor) => {
|
||||||
cursor.read(buf)
|
cursor.read(buf)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
StreamInstance::Stdin => {
|
StreamInstance::Stdin => {
|
||||||
stdin().read(buf)
|
stdin().read(buf)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
StreamInstance::Stdout | StreamInstance::Null => {
|
StreamInstance::Stdout | StreamInstance::Null => {
|
||||||
Err(std::io::Error::new(
|
Err(std::io::Error::new(
|
||||||
ErrorKind::PermissionDenied,
|
ErrorKind::PermissionDenied,
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ use crate::ref_thread_local::RefThreadLocal;
|
|||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::{stdout, Read, Write};
|
use std::io::{stdout, ErrorKind, Read, Write};
|
||||||
use std::iter::{once, FromIterator};
|
use std::iter::{once, FromIterator};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -364,56 +365,6 @@ impl MachineState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stream_or_alias(
|
|
||||||
&mut self,
|
|
||||||
addr: Addr,
|
|
||||||
indices: &IndexStore,
|
|
||||||
caller: &'static str,
|
|
||||||
) -> Result<Stream, MachineStub>
|
|
||||||
{
|
|
||||||
Ok(match addr {
|
|
||||||
Addr::Con(h) if self.heap.atom_at(h) => {
|
|
||||||
if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) {
|
|
||||||
match indices.stream_aliases.get(atom) {
|
|
||||||
Some(stream) => {
|
|
||||||
stream.clone()
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let stub = MachineError::functor_stub(clause_name!(caller), 1);
|
|
||||||
let h = self.heap.h();
|
|
||||||
|
|
||||||
let addr = self.heap.to_unifiable(
|
|
||||||
HeapCellValue::Atom(atom.clone(), spec.clone())
|
|
||||||
);
|
|
||||||
|
|
||||||
return Err(self.error_form(
|
|
||||||
MachineError::existence_error(h + 1, ExistenceError::Stream(addr)),
|
|
||||||
stub,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Addr::Stream(h) => {
|
|
||||||
if let HeapCellValue::Stream(ref stream) = &self.heap[h] {
|
|
||||||
stream.clone()
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let stub = MachineError::functor_stub(clause_name!(caller), 1);
|
|
||||||
|
|
||||||
return Err(self.error_form(
|
|
||||||
MachineError::domain_error(DomainErrorType::StreamOrAlias, addr),
|
|
||||||
stub,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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;
|
||||||
@@ -779,6 +730,29 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::CurrentHostname => {
|
||||||
|
match hostname::get().ok() {
|
||||||
|
Some(host) => {
|
||||||
|
match host.into_string().ok() {
|
||||||
|
Some(host) => {
|
||||||
|
let hostname = self.heap.to_unifiable(
|
||||||
|
HeapCellValue::Atom(clause_name!(host, indices.atom_tbl), None)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.unify(self[temp_v!(1)], hostname);
|
||||||
|
return return_from_clause!(self.last_call, self);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
&SystemClauseType::CurrentInput => {
|
&SystemClauseType::CurrentInput => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)]));
|
let addr = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
|
||||||
@@ -1539,8 +1513,6 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
&SystemClauseType::FileToChars => {
|
&SystemClauseType::FileToChars => {
|
||||||
// TODO: Replace this with stream.
|
// TODO: Replace this with stream.
|
||||||
use std::io;
|
|
||||||
|
|
||||||
let a1 = self.store(self.deref(self[temp_v!(1)]));
|
let a1 = self.store(self.deref(self[temp_v!(1)]));
|
||||||
let a2 = self.store(self.deref(self[temp_v!(2)]));
|
let a2 = self.store(self.deref(self[temp_v!(2)]));
|
||||||
|
|
||||||
@@ -1570,15 +1542,15 @@ impl MachineState {
|
|||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
let err = match e.kind() {
|
let err = match e.kind() {
|
||||||
io::ErrorKind::NotFound => {
|
ErrorKind::NotFound => {
|
||||||
MachineError::existence_error(
|
MachineError::existence_error(
|
||||||
h,
|
h,
|
||||||
ExistenceError::SourceSink(
|
ExistenceError::ModuleSource(
|
||||||
ModuleSource::File(file_name)
|
ModuleSource::File(file_name)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
io::ErrorKind::PermissionDenied => {
|
ErrorKind::PermissionDenied => {
|
||||||
let source_sink = self.store(self.deref(a1));
|
let source_sink = self.store(self.deref(a1));
|
||||||
|
|
||||||
MachineError::permission_error(
|
MachineError::permission_error(
|
||||||
@@ -2545,17 +2517,14 @@ impl MachineState {
|
|||||||
3,
|
3,
|
||||||
);
|
);
|
||||||
|
|
||||||
let type_error = self.error_form(
|
return Err(self.error_form(
|
||||||
MachineError::type_error(
|
MachineError::type_error(
|
||||||
self.heap.h(),
|
self.heap.h(),
|
||||||
ValidType::Integer,
|
ValidType::Integer,
|
||||||
a2,
|
a2,
|
||||||
),
|
),
|
||||||
stub,
|
stub,
|
||||||
);
|
));
|
||||||
|
|
||||||
self.throw_exception(type_error);
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2868,7 +2837,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
&SystemClauseType::SetInput => {
|
&SystemClauseType::SetInput => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)]));
|
let addr = self.store(self.deref(self[temp_v!(1)]));
|
||||||
let stream = self.get_stream_or_alias(addr, indices, "set_input")?;
|
let stream = self.get_stream_or_alias(addr, indices, "set_input", 1)?;
|
||||||
|
|
||||||
if stream.is_output_stream() {
|
if stream.is_output_stream() {
|
||||||
let stub = MachineError::functor_stub(
|
let stub = MachineError::functor_stub(
|
||||||
@@ -2894,7 +2863,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
&SystemClauseType::SetOutput => {
|
&SystemClauseType::SetOutput => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)]));
|
let addr = self.store(self.deref(self[temp_v!(1)]));
|
||||||
let stream = self.get_stream_or_alias(addr, indices, "set_output")?;
|
let stream = self.get_stream_or_alias(addr, indices, "set_output", 1)?;
|
||||||
|
|
||||||
if stream.is_input_stream() {
|
if stream.is_input_stream() {
|
||||||
let stub = MachineError::functor_stub(
|
let stub = MachineError::functor_stub(
|
||||||
@@ -3182,14 +3151,29 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
&SystemClauseType::ReadQueryTerm => {
|
&SystemClauseType::ReadQueryTerm => {
|
||||||
readline::set_prompt(true);
|
readline::set_prompt(true);
|
||||||
let result = self.read_term(current_input_stream, indices);
|
let result = self.read_term(current_input_stream.clone(), indices);
|
||||||
readline::set_prompt(false);
|
readline::set_prompt(false);
|
||||||
|
|
||||||
let _ = result?;
|
match result {
|
||||||
|
Ok(()) => {
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
*current_input_stream = readline::input_stream();
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&SystemClauseType::ReadTerm => {
|
&SystemClauseType::ReadTerm => {
|
||||||
readline::set_prompt(false);
|
readline::set_prompt(false);
|
||||||
self.read_term(current_input_stream, indices)?;
|
|
||||||
|
let stream = self.get_stream_or_alias(
|
||||||
|
self[temp_v!(1)],
|
||||||
|
indices,
|
||||||
|
"read_term",
|
||||||
|
3,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
self.read_term(stream, indices)?;
|
||||||
}
|
}
|
||||||
&SystemClauseType::ReadTermFromChars => {
|
&SystemClauseType::ReadTermFromChars => {
|
||||||
let mut heap_pstr_iter = self.heap_pstr_iter(self[temp_v!(1)]);
|
let mut heap_pstr_iter = self.heap_pstr_iter(self[temp_v!(1)]);
|
||||||
@@ -3302,6 +3286,304 @@ impl MachineState {
|
|||||||
let duration = duration.mul_f64(time);
|
let duration = duration.mul_f64(time);
|
||||||
::std::thread::sleep(duration);
|
::std::thread::sleep(duration);
|
||||||
}
|
}
|
||||||
|
&SystemClauseType::SocketClientOpen => {
|
||||||
|
let addr = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
let port = self.store(self.deref(self[temp_v!(2)]));
|
||||||
|
|
||||||
|
let socket_atom =
|
||||||
|
match addr {
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||||
|
name.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let port =
|
||||||
|
match port {
|
||||||
|
Addr::Fixnum(n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
Addr::Usize(n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
Addr::Con(h) => {
|
||||||
|
match &self.heap[h] {
|
||||||
|
HeapCellValue::Atom(ref name, _) => {
|
||||||
|
name.as_str().to_string()
|
||||||
|
}
|
||||||
|
HeapCellValue::Integer(ref n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let socket_addr =
|
||||||
|
format!(
|
||||||
|
"{}:{}",
|
||||||
|
if socket_atom.as_str() == "" {
|
||||||
|
"127.0.0.1"
|
||||||
|
} else {
|
||||||
|
socket_atom.as_str()
|
||||||
|
},
|
||||||
|
port,
|
||||||
|
);
|
||||||
|
|
||||||
|
let alias = self[temp_v!(4)];
|
||||||
|
let eof_action = self[temp_v!(5)];
|
||||||
|
let reposition = self[temp_v!(6)];
|
||||||
|
let stream_type = self[temp_v!(7)];
|
||||||
|
|
||||||
|
let options =
|
||||||
|
self.to_stream_options(alias, eof_action, reposition, stream_type);
|
||||||
|
|
||||||
|
if options.reposition {
|
||||||
|
return Err(self.reposition_error("socket_client_open", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref alias) = &options.alias {
|
||||||
|
if indices.stream_aliases.contains_key(alias) {
|
||||||
|
return Err(self.occupied_alias_permission_error(
|
||||||
|
alias.clone(),
|
||||||
|
"socket_client_open",
|
||||||
|
3,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let stream =
|
||||||
|
match TcpStream::connect(socket_addr).map_err(|e| e.kind()) {
|
||||||
|
Ok(tcp_stream) => {
|
||||||
|
let mut stream = Stream::from(tcp_stream);
|
||||||
|
|
||||||
|
if let Some(ref alias) = &options.alias {
|
||||||
|
indices.stream_aliases.insert(alias.clone(), stream.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.options = options;
|
||||||
|
self.heap.to_unifiable(HeapCellValue::Stream(stream))
|
||||||
|
}
|
||||||
|
Err(ErrorKind::PermissionDenied) => {
|
||||||
|
return Err(self.open_permission_error(addr, "socket_client_open", 3));
|
||||||
|
}
|
||||||
|
Err(ErrorKind::NotFound) => {
|
||||||
|
let stub = MachineError::functor_stub(
|
||||||
|
clause_name!("socket_client_open"),
|
||||||
|
3,
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = MachineError::existence_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ExistenceError::SourceSink(addr),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// for now, just fail. expand to meaningful error messages later.
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream_addr = self.store(self.deref(self[temp_v!(3)]));
|
||||||
|
self.bind(stream_addr.as_var().unwrap(), stream);
|
||||||
|
}
|
||||||
|
&SystemClauseType::SocketServerOpen => {
|
||||||
|
let addr = self.store(self.deref(self[temp_v!(1)]));
|
||||||
|
let socket_atom =
|
||||||
|
match addr {
|
||||||
|
Addr::EmptyList => {
|
||||||
|
"127.0.0.1".to_string()
|
||||||
|
}
|
||||||
|
Addr::Con(h) if self.heap.atom_at(h) => {
|
||||||
|
match &self.heap[h] {
|
||||||
|
HeapCellValue::Atom(ref name, _) => {
|
||||||
|
name.as_str().to_string()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let port =
|
||||||
|
match self.store(self.deref(self[temp_v!(2)])) {
|
||||||
|
Addr::Fixnum(n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
Addr::Usize(n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
Addr::Con(h) => {
|
||||||
|
match &self.heap[h] {
|
||||||
|
HeapCellValue::Integer(ref n) => {
|
||||||
|
n.to_string()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addr if addr.is_ref() => {
|
||||||
|
"0".to_string()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let had_zero_port = &port == "0";
|
||||||
|
|
||||||
|
let server_addr = if socket_atom.is_empty() {
|
||||||
|
port
|
||||||
|
} else {
|
||||||
|
format!("{}:{}", socket_atom, port)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (tcp_listener, port) =
|
||||||
|
match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
|
||||||
|
Ok(tcp_listener) => {
|
||||||
|
let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
|
||||||
|
|
||||||
|
if let Some(port) = port {
|
||||||
|
(
|
||||||
|
self.heap.to_unifiable(HeapCellValue::TcpListener(tcp_listener)),
|
||||||
|
port as usize,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ErrorKind::PermissionDenied) => {
|
||||||
|
return Err(self.open_permission_error(addr, "socket_server_open", 2));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let addr = self.store(self.deref(self[temp_v!(3)]));
|
||||||
|
self.bind(addr.as_var().unwrap(), tcp_listener);
|
||||||
|
|
||||||
|
if had_zero_port {
|
||||||
|
self.unify(self[temp_v!(2)], Addr::Usize(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&SystemClauseType::SocketServerAccept => {
|
||||||
|
let alias = self[temp_v!(4)];
|
||||||
|
let eof_action = self[temp_v!(5)];
|
||||||
|
let reposition = self[temp_v!(6)];
|
||||||
|
let stream_type = self[temp_v!(7)];
|
||||||
|
|
||||||
|
let options =
|
||||||
|
self.to_stream_options(alias, eof_action, reposition, stream_type);
|
||||||
|
|
||||||
|
if options.reposition {
|
||||||
|
return Err(self.reposition_error("socket_server_accept", 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.store(self.deref(self[temp_v!(1)])) {
|
||||||
|
Addr::TcpListener(h) => {
|
||||||
|
match &mut self.heap[h] {
|
||||||
|
HeapCellValue::TcpListener(ref mut tcp_listener) => {
|
||||||
|
match tcp_listener.accept().ok() {
|
||||||
|
Some((tcp_stream, socket_addr)) => {
|
||||||
|
let mut tcp_stream = Stream::from(tcp_stream);
|
||||||
|
tcp_stream.options = options;
|
||||||
|
|
||||||
|
let tcp_stream =
|
||||||
|
self.heap.to_unifiable(HeapCellValue::Stream(tcp_stream));
|
||||||
|
|
||||||
|
let client =
|
||||||
|
clause_name!(format!("{}", socket_addr), indices.atom_tbl);
|
||||||
|
let client =
|
||||||
|
self.heap.to_unifiable(HeapCellValue::Atom(client, None));
|
||||||
|
|
||||||
|
let client_addr = self.store(self.deref(self[temp_v!(2)]));
|
||||||
|
let stream_addr = self.store(self.deref(self[temp_v!(3)]));
|
||||||
|
|
||||||
|
self.bind(client_addr.as_var().unwrap(), client);
|
||||||
|
self.bind(stream_addr.as_var().unwrap(), tcp_stream);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
culprit => {
|
||||||
|
let culprit = culprit.as_addr(h);
|
||||||
|
let stub = MachineError::functor_stub(
|
||||||
|
clause_name!("socket_server_close"),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::TcpListener,
|
||||||
|
culprit,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
culprit => {
|
||||||
|
let stub = MachineError::functor_stub(
|
||||||
|
clause_name!("socket_server_accept"),
|
||||||
|
4,
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::TcpListener,
|
||||||
|
culprit,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&SystemClauseType::SocketServerClose => {
|
||||||
|
match self.store(self.deref(self[temp_v!(1)])) {
|
||||||
|
Addr::TcpListener(h) => {
|
||||||
|
self.heap[h] = HeapCellValue::Addr(Addr::EmptyList);
|
||||||
|
}
|
||||||
|
culprit => {
|
||||||
|
let stub = MachineError::functor_stub(
|
||||||
|
clause_name!("socket_server_close"),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
let err = MachineError::type_error(
|
||||||
|
self.heap.h(),
|
||||||
|
ValidType::TcpListener,
|
||||||
|
culprit,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(self.error_form(err, stub));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
&SystemClauseType::StoreGlobalVar => {
|
&SystemClauseType::StoreGlobalVar => {
|
||||||
let key = self[temp_v!(1)];
|
let key = self[temp_v!(1)];
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ repl :-
|
|||||||
repl.
|
repl.
|
||||||
|
|
||||||
read_and_match :-
|
read_and_match :-
|
||||||
'$read_query_term'(Term, VarList),
|
'$read_query_term'(_, Term, _, _, VarList),
|
||||||
instruction_match(Term, VarList).
|
instruction_match(Term, VarList).
|
||||||
|
|
||||||
% make compile_batch, a system routine, callable.
|
% make compile_batch, a system routine, callable.
|
||||||
|
|||||||
@@ -181,6 +181,9 @@ impl fmt::Display for HeapCellValue {
|
|||||||
&HeapCellValue::Stream(ref stream) => {
|
&HeapCellValue::Stream(ref stream) => {
|
||||||
write!(f, "$stream({})", stream.as_ptr() as usize)
|
write!(f, "$stream({})", stream.as_ptr() as usize)
|
||||||
}
|
}
|
||||||
|
&HeapCellValue::TcpListener(ref tcp_listener) => {
|
||||||
|
write!(f, "$tcp_listener({})", tcp_listener.local_addr().unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,6 +216,7 @@ impl fmt::Display for Addr {
|
|||||||
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
||||||
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
||||||
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
|
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
|
||||||
|
&Addr::TcpListener(tcp_listener) => write!(f, "Addr::TcpListener({})", tcp_listener),
|
||||||
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
|
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,11 +336,14 @@ impl fmt::Display for ExistenceError {
|
|||||||
&ExistenceError::Module(ref module_name) => {
|
&ExistenceError::Module(ref module_name) => {
|
||||||
write!(f, "the module {} does not exist", module_name)
|
write!(f, "the module {} does not exist", module_name)
|
||||||
}
|
}
|
||||||
|
&ExistenceError::ModuleSource(ref module_source) => {
|
||||||
|
write!(f, "the source/sink {} does not exist", module_source)
|
||||||
|
}
|
||||||
&ExistenceError::Procedure(ref name, arity) => {
|
&ExistenceError::Procedure(ref name, arity) => {
|
||||||
write!(f, "the procedure {}/{} does not exist", name, arity)
|
write!(f, "the procedure {}/{} does not exist", name, arity)
|
||||||
}
|
}
|
||||||
&ExistenceError::SourceSink(ref module_source) => {
|
&ExistenceError::SourceSink(ref addr) => {
|
||||||
write!(f, "the source/sink {} does not exist", module_source)
|
write!(f, "the source/sink {} does not exist", addr)
|
||||||
}
|
}
|
||||||
&ExistenceError::Stream(ref addr) => {
|
&ExistenceError::Stream(ref addr) => {
|
||||||
write!(f, "the stream at {} does not exist", addr)
|
write!(f, "the stream at {} does not exist", addr)
|
||||||
|
|||||||
Reference in New Issue
Block a user