make toplevel more consistent with answers, depend on readline package without renaming.

This commit is contained in:
Mark Thom
2019-03-17 17:49:51 -06:00
parent 4cefd35eb4
commit fd703c3610
6 changed files with 80 additions and 215 deletions

170
Cargo.lock generated
View File

@@ -1,170 +0,0 @@
[[package]]
name = "downcast"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-bigint"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-complex"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-iter"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-rational"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ordered-float"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prolog_parser"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "readline-rs"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scryer-prolog"
version = "0.8.6"
dependencies = [
"downcast 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"prolog_parser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"readline-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum downcast 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c6fe31318b6ef21166c8e839e680238eb16f875849d597544eead7ec882eed3"
"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1"
"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718"
"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d"
"checksum prolog_parser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6da85e0cfa5a604edf65f753e629db37bfd04af93a09a1df5576d2197a2f7af3"
"checksum readline-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f35410ab92501753b66a269387df7a8162daeaf816f6528ba8b07b34f0d80c99"
"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"

View File

@@ -1,8 +1,6 @@
cargo-features = ["rename-dependency"]
[package] [package]
name = "scryer-prolog" name = "scryer-prolog"
version = "0.8.7" version = "0.8.8"
authors = ["Mark Thom <markjordanthom@gmail.com>"] authors = ["Mark Thom <markjordanthom@gmail.com>"]
repository = "https://github.com/mthom/scryer-prolog" repository = "https://github.com/mthom/scryer-prolog"
description = "A modern Prolog implementation written mostly in Rust." description = "A modern Prolog implementation written mostly in Rust."
@@ -13,7 +11,7 @@ downcast = "0.9.1"
num = "0.2" num = "0.2"
ordered-float = "0.5.0" ordered-float = "0.5.0"
prolog_parser = "0.8.1" prolog_parser = "0.8.1"
readline_rs = { package = "readline-rs", version = "0.1.2" } readline_rs_compat = { version = "0.1.3" }
[dependencies.termion] [dependencies.termion]
version = "1.4.0" version = "1.4.0"

View File

@@ -218,11 +218,11 @@ To enter a multi-clause predicate, the directive "[user]" is used.
For example, For example,
``` ```
prolog> [user] ?- [user].
(type Enter + Ctrl-D to terminate the stream when finished) (type Enter + Ctrl-D to terminate the stream when finished)
p(f(f(X)), h(W), Y) :- g(W), h(W), f(X). p(f(f(X)), h(W), Y) :- g(W), h(W), f(X).
p(X, Y, Z) :- h(Y), z(Z). p(X, Y, Z) :- h(Y), z(Z).
prolog> [user] ?- [user].
(type Enter + Ctrl-D to terminate the stream when finished) (type Enter + Ctrl-D to terminate the stream when finished)
h(x). h(y). h(x). h(y).
h(z). h(z).
@@ -232,7 +232,7 @@ input stream. The instructive message is always printed.
Queries are issued as Queries are issued as
``` ```
prolog> ?- p(X, Y, Z). ?- p(X, Y, Z).
``` ```
Pressing `SPACE` will backtrack through other possible answers, if any exist. Pressing `SPACE` will backtrack through other possible answers, if any exist.
@@ -241,10 +241,11 @@ Pressing `.` will abort the search and return to the prompt.
Wildcards work as well: Wildcards work as well:
``` ```
prolog> [user] ?- [user].
(type Enter + Ctrl-D to terminate the stream when finished)
member(X, [X|_]). member(X, [X|_]).
member(X, [_|Xs]) :- member(X, Xs). member(X, [_|Xs]) :- member(X, Xs).
prolog> ?- member(X, [a, b, c]). ?- member(X, [a, b, c]).
true . true .
X = a ; X = a ;
X = b ; X = b ;
@@ -253,13 +254,12 @@ false.
``` ```
and so do conjunctive queries: and so do conjunctive queries:
``` ```
prolog> [user] ?- [user].
(type Enter + Ctrl-D to terminate the stream when finished)
f(X) :- g(X). f(X) :- g(X).
prolog> [user]
g(x). g(y). g(z). g(x). g(y). g(z).
prolog> [user]
h(call(f, X)). h(call(f, X)).
prolog> ?- h(X), X. ?- h(X), X.
true . true .
X = call(f, x) ; X = call(f, x) ;
X = call(f, y) ; X = call(f, y) ;
@@ -270,13 +270,18 @@ Note that the values of variables belonging to successful queries are
printed out, on one line each. Uninstantiated variables are denoted by printed out, on one line each. Uninstantiated variables are denoted by
a number preceded by an underscore (`X = _0` in an example above). a number preceded by an underscore (`X = _0` in an example above).
To quit scryer-prolog, type
```
?- halt.
```
### Dynamic operators ### Dynamic operators
Scryper supports dynamic operators. Using the built-in Scryper supports dynamic operators. Using the built-in
arithmetic operators with the usual precedences, arithmetic operators with the usual precedences,
``` ```
prolog> ?- write_canonical(-5 + 3 - (2 * 4) // 8). ?- write_canonical(-5 + 3 - (2 * 4) // 8).
-(+(-(5), 3), //(*(2, 4), 8)) -(+(-(5), 3), //(*(2, 4), 8))
true. true.
``` ```
@@ -314,15 +319,16 @@ operators and predicates are hidden in their own modules that have not
been exported to the toplevel. To export them, write been exported to the toplevel. To export them, write
``` ```
prolog> :- use_module(library(lists)). ?- use_module(library(lists)).
prolog> :- use_module(library(control)). ?- use_module(library(control)).
``` ```
The [user] prompt can also be used to define modules inline at the The [user] prompt can also be used to define modules inline at the
REPL: REPL:
``` ```
prolog> [user] ?- [user].
(type Enter + Ctrl-D to terminate the stream when finished)
:- module(test, [local_member/2]). :- module(test, [local_member/2]).
:- use_module(library(lists)). :- use_module(library(lists)).
@@ -332,7 +338,7 @@ local_member(X, Xs) :- member(X, Xs).
`use_module` directives can be qualified by adding a list of imports: `use_module` directives can be qualified by adding a list of imports:
``` ```
prolog> :- use_module(library(lists), [member/2]). ?- use_module(library(lists), [member/2]).
``` ```
A qualified `use_module` can be used to remove imports from the A qualified `use_module` can be used to remove imports from the
@@ -342,5 +348,5 @@ The `(:)/2` operator resolves calls to predicates that might not be
imported to the current working namespace: imported to the current working namespace:
``` ```
prolog> ?- lists:member(X, Xs). ?- lists:member(X, Xs).
``` ```

View File

@@ -1,7 +1,7 @@
#[macro_use] extern crate downcast; #[macro_use] extern crate downcast;
#[macro_use] extern crate prolog_parser; #[macro_use] extern crate prolog_parser;
extern crate readline_rs; extern crate readline_rs_compat;
extern crate termion; extern crate termion;
mod prolog; mod prolog;
@@ -34,7 +34,7 @@ fn prolog_repl() {
Ok(Input::Batch) => { Ok(Input::Batch) => {
set_line_mode(LineMode::Multi); set_line_mode(LineMode::Multi);
let src = match read_line("") { let src = match read_batch("") {
Ok(src) => src, Ok(src) => src,
Err(e) => { Err(e) => {
println!("{}", e); println!("{}", e);
@@ -45,7 +45,6 @@ fn prolog_repl() {
let result = compile_user_module(&mut wam, src.as_bytes()); let result = compile_user_module(&mut wam, src.as_bytes());
print(&mut wam, result); print(&mut wam, result);
}, },
Ok(Input::Quit) => break,
Ok(Input::Clear) => { Ok(Input::Clear) => {
wam.clear(); wam.clear();
continue; continue;

View File

@@ -231,8 +231,10 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
} }
} }
fn setup_declaration(term: Term) -> Result<Declaration, ParserError> fn setup_declaration(mut terms: Vec<Box<Term>>) -> Result<Declaration, ParserError>
{ {
let term = *terms.pop().unwrap();
match term { match term {
Term::Clause(_, name, mut terms, _) => Term::Clause(_, name, mut terms, _) =>
if name.as_str() == "op" && terms.len() == 3 { if name.as_str() == "op" && terms.len() == 3 {
@@ -592,11 +594,12 @@ impl RelationWorker {
} }
} }
fn setup_query(&mut self, indices: &mut CompositeIndices, terms: Vec<Box<Term>>, blocks_cuts: bool) fn setup_query(&mut self, indices: &mut CompositeIndices, terms: Vec<Box<Term>>,
blocks_cuts: bool)
-> Result<Vec<QueryTerm>, ParserError> -> Result<Vec<QueryTerm>, ParserError>
{ {
let mut query_terms = vec![]; let mut query_terms = vec![];
let mut work_queue = VecDeque::from(terms); let mut work_queue = VecDeque::from(terms);
while let Some(term) = work_queue.pop_front() { while let Some(term) = work_queue.pop_front() {
let mut term = *term; let mut term = *term;
@@ -651,9 +654,9 @@ impl RelationWorker {
blocks_cuts: bool, assume_dyn: bool) blocks_cuts: bool, assume_dyn: bool)
-> Result<Rule, ParserError> -> Result<Rule, ParserError>
{ {
let post_head_terms: Vec<_> = terms.drain(1 ..).collect();
let head = *terms.first().cloned().unwrap(); let head = *terms.first().cloned().unwrap();
let post_head_terms: Vec<_> = terms.drain(1 .. ).collect();
let tail = *post_head_terms.first().cloned().unwrap(); let tail = *post_head_terms.first().cloned().unwrap();
if assume_dyn { if assume_dyn {
@@ -677,19 +680,23 @@ impl RelationWorker {
-> Result<TopLevel, ParserError> -> Result<TopLevel, ParserError>
{ {
match term { match term {
Term::Clause(r, name, mut terms, fixity) => Term::Clause(r, name, terms, fixity) =>
if let Some(hook) = is_compile_time_hook(&name, &terms) { if let Some(hook) = is_compile_time_hook(&name, &terms) {
let term = Term::Clause(r, name, terms, fixity); let term = Term::Clause(r, name, terms, fixity);
let (hook, clause, queue) = self.setup_hook(hook, indices, term)?; let (hook, clause, queue) = self.setup_hook(hook, indices, term)?;
Ok(TopLevel::Declaration(Declaration::Hook(hook, clause, queue))) Ok(TopLevel::Declaration(Declaration::Hook(hook, clause, queue)))
} else if name.as_str() == "?-" { } else if name.as_str() == "?-" {
Ok(TopLevel::Query(try!(self.setup_query(indices, terms, blocks_cuts)))) match setup_declaration(terms.iter().cloned().collect()) {
} else if name.as_str() == ":-" && terms.len() > 1 { Ok(decl) => return Ok(TopLevel::Declaration(decl)),
Ok(TopLevel::Rule(try!(self.setup_rule(indices, terms, blocks_cuts, true)))) _ => {}
};
Ok(TopLevel::Query(self.setup_query(indices, terms, blocks_cuts)?))
} else if name.as_str() == ":-" && terms.len() == 2 {
Ok(TopLevel::Rule(self.setup_rule(indices, terms, blocks_cuts, true)?))
} else if name.as_str() == ":-" && terms.len() == 1 { } else if name.as_str() == ":-" && terms.len() == 1 {
let term = *terms.pop().unwrap(); Ok(TopLevel::Declaration(setup_declaration(terms)?))
Ok(TopLevel::Declaration(try!(setup_declaration(term))))
} else { } else {
let term = Term::Clause(r, name, terms, fixity); let term = Term::Clause(r, name, terms, fixity);
Ok(TopLevel::Fact(try!(self.setup_fact(term, true)))) Ok(TopLevel::Fact(try!(self.setup_fact(term, true))))

View File

@@ -11,7 +11,7 @@ use prolog::machine::machine_state::MachineState;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::Read; use std::io::Read;
use readline_rs::readline::*; use readline_rs_compat::readline::*;
type SubtermDeque = VecDeque<(usize, usize)>; type SubtermDeque = VecDeque<(usize, usize)>;
@@ -27,7 +27,6 @@ impl<'a> TermRef<'a> {
} }
pub enum Input { pub enum Input {
Quit,
Clear, Clear,
Batch, Batch,
TermString(&'static str) TermString(&'static str)
@@ -52,7 +51,7 @@ pub fn set_line_mode(mode: LineMode) {
fn is_directive(buf: &str) -> bool { fn is_directive(buf: &str) -> bool {
match buf { match buf {
"[user]" | "quit" | "clear" => true, "?- [user]." | "?- [clear]." => true,
_ => false _ => false
} }
} }
@@ -77,9 +76,6 @@ unsafe extern "C" fn bind_end_key(_: i32, _: i32) -> i32 {
unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 { unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 {
if END_OF_LINE { if END_OF_LINE {
println!("");
rl_done = 1;
} else {
if let Some(buf) = rl_line_buffer_as_str() { if let Some(buf) = rl_line_buffer_as_str() {
if is_directive(buf) { if is_directive(buf) {
println!(""); println!("");
@@ -88,6 +84,9 @@ unsafe extern "C" fn bind_cr(_: i32, _: i32) -> i32 {
} }
} }
println!("");
rl_done = 1;
} else {
insert_text_rl("\n"); insert_text_rl("\n");
} }
@@ -107,20 +106,46 @@ pub fn readline_initialize() {
bind_keyseq_rl("\\C-d", bind_end_chord); bind_keyseq_rl("\\C-d", bind_end_chord);
} }
pub fn read_line(prompt: &str) -> Result<&'static str, SessionError> { pub fn read_batch(prompt: &str) -> Result<&'static str, SessionError> {
unsafe {
use std::ptr::null;
use std::mem;
// deactivate the startup hook that emits a "?- " to the
// beginning of the readline buffer.
let p: *const i8 = null();
rl_startup_hook = mem::transmute(p);
}
match readline_rl(prompt) { match readline_rl(prompt) {
Some(input) => Ok(input), Some(input) => Ok(input),
None => Err(SessionError::UserPrompt) None => Err(SessionError::UserPrompt)
} }
} }
pub fn toplevel_read_line() -> Result<Input, SessionError> { fn read_line(prompt: &str) -> Result<&'static str, SessionError> {
let buffer = read_line("prolog> ")?; match readline_rl(prompt) {
Some(input) => Ok(input),
None => Err(SessionError::UserPrompt)
}
}
unsafe extern "C" fn insert_query_prompt() -> i32 {
insert_text_rl("?- ");
0
}
pub fn toplevel_read_line() -> Result<Input, SessionError>
{
unsafe {
rl_startup_hook = insert_query_prompt;
}
let buffer = read_line("")?;
Ok(match &*buffer.trim() { Ok(match &*buffer.trim() {
"quit" => Input::Quit, "?- [clear]." => Input::Clear,
"clear" => Input::Clear, "?- [user]." => {
"[user]" => {
println!("(type Enter + Ctrl-D to terminate the stream when finished)"); println!("(type Enter + Ctrl-D to terminate the stream when finished)");
Input::Batch Input::Batch
}, },