make *.pl files in src/prolog/lib available from libraries.rs
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.94"
|
version = "0.8.95"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
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."
|
||||||
license = "BSD-3-Clause"
|
license = "BSD-3-Clause"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
indexmap = "1.0.2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cfg-if = "0.1.7"
|
cfg-if = "0.1.7"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
|
|||||||
48
build.rs
Normal file
48
build.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
extern crate indexmap;
|
||||||
|
|
||||||
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
|
use std::fs::{File, read_dir};
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
let dest_path = Path::new("./src/prolog/machine/libraries.rs");
|
||||||
|
|
||||||
|
let mut libraries = File::create(&dest_path).unwrap();
|
||||||
|
let mut library_index = IndexSet::new();
|
||||||
|
|
||||||
|
let paths = read_dir("./src/prolog/lib").unwrap();
|
||||||
|
|
||||||
|
for item in paths {
|
||||||
|
let item = item.unwrap().path();
|
||||||
|
|
||||||
|
if item.is_file() {
|
||||||
|
if let Some(ext) = item.extension() {
|
||||||
|
if ext == "pl" {
|
||||||
|
let file_stem = item.file_stem().unwrap();
|
||||||
|
let file_str = file_stem.to_string_lossy().to_uppercase();
|
||||||
|
|
||||||
|
let include_line = format!("static {}: &str = include_str!(\"{}/{}.pl\");\n",
|
||||||
|
file_str, "../lib", file_stem.to_string_lossy());
|
||||||
|
|
||||||
|
libraries.write_all(include_line.as_bytes()).unwrap();
|
||||||
|
library_index.insert(file_stem.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libraries.write_all(b"\nref_thread_local! {
|
||||||
|
pub static managed LIBRARIES: IndexMap<&'static str, &'static str> = {
|
||||||
|
let mut m = IndexMap::new();\n").unwrap();
|
||||||
|
|
||||||
|
for item in library_index {
|
||||||
|
let line = format!("\n m.insert(\"{}\", {});", item, item.to_uppercase());
|
||||||
|
libraries.write_all(line.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
libraries.write_all(b"\n\n m\n };
|
||||||
|
}").unwrap();
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ https://sicstus.sics.se/sicstus/docs/3.7.1/html/sicstus_17.html
|
|||||||
|
|
||||||
:- module(domain, [domain/2]).
|
:- module(domain, [domain/2]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/atts').
|
:- use_module(library(atts)).
|
||||||
:- use_module('src/prolog/lib/ordsets', [
|
:- use_module(library(ordsets), [
|
||||||
ord_intersection/3,
|
ord_intersection/3,
|
||||||
ord_intersect/2,
|
ord_intersect/2,
|
||||||
list_to_ord_set/2
|
list_to_ord_set/2
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
:- use_module('src/prolog/lib/dcgs').
|
:- use_module(library(dcgs)).
|
||||||
:- use_module('src/prolog/lib/reif').
|
:- use_module(library(reif)).
|
||||||
|
|
||||||
animals([animal(dog, [is_true('has fur'), is_true('says woof')]),
|
animals([animal(dog, [is_true('has fur'), is_true('says woof')]),
|
||||||
animal(cat, [is_true('has fur'), is_true('says meow')]),
|
animal(cat, [is_true('has fur'), is_true('says meow')]),
|
||||||
|
|||||||
@@ -60,9 +60,9 @@
|
|||||||
|
|
||||||
:- module(zdd, [variables_set_zdd/2]).
|
:- module(zdd, [variables_set_zdd/2]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/atts').
|
:- use_module(library(atts)).
|
||||||
:- use_module('src/prolog/lib/dcgs').
|
:- use_module(library(dcgs)).
|
||||||
:- use_module('src/prolog/lib/lists').
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
:- attribute zdd_vs/2.
|
:- attribute zdd_vs/2.
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/dcgs').
|
:- use_module(library(dcgs)).
|
||||||
:- use_module('src/prolog/lib/dif').
|
:- use_module(library(dif)).
|
||||||
:- use_module('src/prolog/lib/lists').
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
pl_resolution(Clauses0, Chain) :-
|
pl_resolution(Clauses0, Chain) :-
|
||||||
maplist(sort, Clauses0, Clauses), % remove duplicates
|
maplist(sort, Clauses0, Clauses), % remove duplicates
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
del_max_assoc/4 % +Assoc0, ?Key, ?Value, ?Assoc
|
del_max_assoc/4 % +Assoc0, ?Key, ?Value, ?Assoc
|
||||||
]).
|
]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/lists.pl').
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
/** <module> Binary associations
|
/** <module> Binary associations
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
'$add_to_list'/3, '$del_attr'/3, '$del_attr_step'/3,
|
'$add_to_list'/3, '$del_attr'/3, '$del_attr_step'/3,
|
||||||
'$del_attr_buried'/4]).
|
'$del_attr_buried'/4]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/dcgs.pl').
|
:- use_module(library(dcgs)).
|
||||||
:- use_module('src/prolog/lib/terms.pl').
|
:- use_module(library(terms)).
|
||||||
|
|
||||||
:- op(1199, fx, attribute).
|
:- op(1199, fx, attribute).
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
%% TODO: numlist/5.
|
%% TODO: numlist/5.
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/lists.pl', [length/2]).
|
:- use_module(library(lists), [length/2]).
|
||||||
:- use_module('src/prolog/lib/error.pl').
|
:- use_module(library(error)).
|
||||||
|
|
||||||
between(Lower, Upper, X) :-
|
between(Lower, Upper, X) :-
|
||||||
must_be(integer, Lower),
|
must_be(integer, Lower),
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
:- module(dcgs, [phrase/2, phrase/3]).
|
:- module(dcgs, [phrase/2, phrase/3]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/lists.pl', [append/3]).
|
:- use_module(library(lists), [append/3]).
|
||||||
:- use_module('src/prolog/lib/terms.pl').
|
:- use_module(library(terms)).
|
||||||
|
|
||||||
phrase(G, G) :-
|
phrase(G, G) :-
|
||||||
nonvar(G), G = [_|_], !.
|
nonvar(G), G = [_|_], !.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
:- module(diag, [wam_instructions/2]).
|
:- module(diag, [wam_instructions/2]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/error').
|
:- use_module(library(error)).
|
||||||
|
|
||||||
wam_instructions(Clause, Listing) :-
|
wam_instructions(Clause, Listing) :-
|
||||||
( nonvar(Clause) ->
|
( nonvar(Clause) ->
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
:- module(dif, [dif/2]).
|
:- module(dif, [dif/2]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/atts.pl').
|
:- use_module(library(atts)).
|
||||||
:- use_module('src/prolog/lib/lists.pl', [append/3]).
|
:- use_module(library(lists), [append/3]).
|
||||||
|
|
||||||
:- attribute dif/1.
|
:- attribute dif/1.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
:- module(freeze, [freeze/2]).
|
:- module(freeze, [freeze/2]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/atts.pl').
|
:- use_module(library(atts)).
|
||||||
|
|
||||||
:- attribute frozen/1.
|
:- attribute frozen/1.
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
ord_intersection/2 % +PowerSet, -Intersection
|
ord_intersection/2 % +PowerSet, -Intersection
|
||||||
]).
|
]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/lists.pl').
|
:- use_module(library(lists)).
|
||||||
|
|
||||||
/** <module> Ordered set manipulation
|
/** <module> Ordered set manipulation
|
||||||
Ordered sets are lists with unique elements sorted to the standard order
|
Ordered sets are lists with unique elements sorted to the standard order
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
memberd_t/3, tfilter/3, tmember/2, tmember_t/3,
|
memberd_t/3, tfilter/3, tmember/2, tmember_t/3,
|
||||||
tpartition/4]).
|
tpartition/4]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/dif.pl').
|
:- use_module(library(dif)).
|
||||||
|
|
||||||
if_(If_1, Then_0, Else_0) :-
|
if_(If_1, Then_0, Else_0) :-
|
||||||
call(If_1, T),
|
call(If_1, T),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
:- module(terms, [numbervars/3]).
|
:- module(terms, [numbervars/3]).
|
||||||
|
|
||||||
:- use_module('src/prolog/lib/error.pl').
|
:- use_module(library(error)).
|
||||||
|
|
||||||
numbervars(Term, N0, N) :-
|
numbervars(Term, N0, N) :-
|
||||||
catch(internal_numbervars(Term, N0, N), error(E,Ctx),
|
catch(internal_numbervars(Term, N0, N), error(E,Ctx),
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ use prolog::machine::*;
|
|||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
|
use ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -54,16 +56,9 @@ fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, S
|
|||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName, SessionError> {
|
fn load_module<R: Read>(wam: &mut Machine, name: &str, stream: ParsingStream<R>)
|
||||||
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
|
-> Result<ClauseName, SessionError>
|
||||||
|
{
|
||||||
let file_handle = File::open(&path).or_else(|_| {
|
|
||||||
let filename = clause_name!(path.to_string_lossy().to_string(), wam.indices.atom_tbl);
|
|
||||||
Err(SessionError::InvalidFileName(filename))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let file_src = parsing_stream(file_handle);
|
|
||||||
|
|
||||||
// follow the operation of compile_user_module, but before
|
// follow the operation of compile_user_module, but before
|
||||||
// compiling, check that a module is declared in the file. if not,
|
// compiling, check that a module is declared in the file. if not,
|
||||||
// throw an exception.
|
// throw an exception.
|
||||||
@@ -71,21 +66,32 @@ fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName
|
|||||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
||||||
let results = compiler.gather_items(wam, file_src, &mut indices)?;
|
let results = compiler.gather_items(wam, stream, &mut indices)?;
|
||||||
|
|
||||||
let module_name = if let Some(ref module) = &compiler.module {
|
let module_name = if let Some(ref module) = &compiler.module {
|
||||||
module.module_decl.name.clone()
|
module.module_decl.name.clone()
|
||||||
} else {
|
} else {
|
||||||
let module_name = path.to_string_lossy().to_string();
|
let module_name = clause_name!(name.to_string(), wam.indices.atom_tbl);
|
||||||
let module_name = clause_name!(module_name, wam.indices.atom_tbl);
|
|
||||||
|
|
||||||
return Err(SessionError::NoModuleDeclaration(module_name));
|
return Err(SessionError::NoModuleDeclaration(module_name));
|
||||||
};
|
};
|
||||||
|
|
||||||
match compile_work_impl(&mut compiler, wam, indices, results) {
|
match compile_work_impl(&mut compiler, wam, indices, results) {
|
||||||
EvalSession::Error(e) => Err(e),
|
EvalSession::Error(e) => Err(e),
|
||||||
_ => Ok(module_name),
|
_ => Ok(module_name),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName, SessionError>
|
||||||
|
{
|
||||||
|
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
|
||||||
|
|
||||||
|
let file_handle = File::open(&path).or_else(|_| {
|
||||||
|
let filename = clause_name!(path.to_string_lossy().to_string(), wam.indices.atom_tbl);
|
||||||
|
Err(SessionError::InvalidFileName(filename))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let file_stem = path.file_stem().unwrap().to_string_lossy();
|
||||||
|
load_module(wam, &file_stem, parsing_stream(file_handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
|
||||||
@@ -459,6 +465,13 @@ fn add_non_module_code(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_library(wam: &mut Machine, name: ClauseName) -> Result<ClauseName, SessionError> {
|
||||||
|
match LIBRARIES.borrow().get(name.as_str()) {
|
||||||
|
Some(code) => load_module(wam, name.as_str(), parsing_stream(code.as_bytes())),
|
||||||
|
None => Err(SessionError::ModuleNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ListingCompiler {
|
impl ListingCompiler {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(code_repo: &CodeRepo) -> Self {
|
pub fn new(code_repo: &CodeRepo) -> Self {
|
||||||
@@ -702,17 +715,30 @@ impl ListingCompiler {
|
|||||||
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
|
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
|
||||||
}
|
}
|
||||||
Declaration::UseModule(ModuleSource::Library(name)) => {
|
Declaration::UseModule(ModuleSource::Library(name)) => {
|
||||||
|
let name = if !wam.indices.modules.contains_key(&name) {
|
||||||
|
load_library(wam, name)?
|
||||||
|
} else {
|
||||||
|
name
|
||||||
|
};
|
||||||
|
|
||||||
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
||||||
}
|
}
|
||||||
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => self
|
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => {
|
||||||
.use_qualified_module(
|
let name = if !wam.indices.modules.contains_key(&name) {
|
||||||
|
load_library(wam, name)?
|
||||||
|
} else {
|
||||||
|
name
|
||||||
|
};
|
||||||
|
|
||||||
|
self.use_qualified_module(
|
||||||
name,
|
name,
|
||||||
&mut wam.code_repo,
|
&mut wam.code_repo,
|
||||||
flags,
|
flags,
|
||||||
&exports,
|
&exports,
|
||||||
&mut wam.indices,
|
&mut wam.indices,
|
||||||
indices,
|
indices
|
||||||
),
|
)
|
||||||
|
},
|
||||||
Declaration::Module(module_decl) => {
|
Declaration::Module(module_decl) => {
|
||||||
if self.module.is_none() {
|
if self.module.is_none() {
|
||||||
let module_name = module_decl.name.clone();
|
let module_name = module_decl.name.clone();
|
||||||
|
|||||||
@@ -163,10 +163,8 @@ impl SubModuleUser for IndexStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
include!("libraries.rs");
|
||||||
static ERROR: &str = include_str!("../lib/error.pl");
|
|
||||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
|
||||||
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
|
||||||
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
@@ -538,14 +536,13 @@ impl Machine {
|
|||||||
self.throw_session_error(err, (clause_name!("repl"), 0));
|
self.throw_session_error(err, (clause_name!("repl"), 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EvalSession::QueryFailure => {
|
EvalSession::QueryFailure =>
|
||||||
if self.machine_st.ball.stub.len() > 0 {
|
if self.machine_st.ball.stub.len() > 0 {
|
||||||
return self.propagate_exception_to_toplevel(snapshot);
|
return self.propagate_exception_to_toplevel(snapshot);
|
||||||
} else {
|
} else {
|
||||||
println!("false.");
|
println!("false.");
|
||||||
}
|
},
|
||||||
}
|
_ => println!("true.")
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.machine_st.absorb_snapshot(snapshot);
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub mod readline {
|
|||||||
if PROMPT { "?- " } else { "" }
|
if PROMPT { "?- " } else { "" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReadlineStream {
|
pub struct ReadlineStream {
|
||||||
rl: Editor<()>,
|
rl: Editor<()>,
|
||||||
pending_input: String,
|
pending_input: String,
|
||||||
@@ -54,9 +54,7 @@ pub mod readline {
|
|||||||
impl ReadlineStream {
|
impl ReadlineStream {
|
||||||
fn input_stream(pending_input: String) -> Self {
|
fn input_stream(pending_input: String) -> Self {
|
||||||
let mut rl = Editor::<()>::new();
|
let mut rl = Editor::<()>::new();
|
||||||
|
|
||||||
rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string()));
|
rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string()));
|
||||||
|
|
||||||
ReadlineStream { rl, pending_input }
|
ReadlineStream { rl, pending_input }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,11 +70,11 @@ pub mod readline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pending_input += "\n";
|
self.pending_input += "\n";
|
||||||
Ok(self.write_to_buf(buf))
|
Ok(self.write_to_buf(buf))
|
||||||
}
|
}
|
||||||
Err(ReadlineError::Eof) =>
|
Err(ReadlineError::Eof) =>
|
||||||
Ok(self.write_to_buf(buf)),
|
Ok(self.write_to_buf(buf)),
|
||||||
Err(e) =>
|
Err(e) =>
|
||||||
Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, e))
|
Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, e))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user