From: Mark Thom Date: Fri, 27 Sep 2019 05:10:04 +0000 (-0600) Subject: make *.pl files in src/prolog/lib available from libraries.rs X-Git-Tag: v0.8.110~39 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=9a83ccbdbcbdb6dd8792bddcecdf245184fd143e;p=scryer-prolog.git make *.pl files in src/prolog/lib available from libraries.rs --- diff --git a/Cargo.toml b/Cargo.toml index 93ab3852..4f3145fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,15 @@ [package] name = "scryer-prolog" -version = "0.8.94" +version = "0.8.95" authors = ["Mark Thom "] +build = "build.rs" repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." license = "BSD-3-Clause" +[build-dependencies] +indexmap = "1.0.2" + [dependencies] cfg-if = "0.1.7" dirs = "2.0.2" diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..bee74697 --- /dev/null +++ b/build.rs @@ -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(); +} diff --git a/src/prolog/examples/domain.pl b/src/prolog/examples/domain.pl index f1fadad9..cfada79f 100644 --- a/src/prolog/examples/domain.pl +++ b/src/prolog/examples/domain.pl @@ -4,8 +4,8 @@ https://sicstus.sics.se/sicstus/docs/3.7.1/html/sicstus_17.html :- module(domain, [domain/2]). -:- use_module('src/prolog/lib/atts'). -:- use_module('src/prolog/lib/ordsets', [ +:- use_module(library(atts)). +:- use_module(library(ordsets), [ ord_intersection/3, ord_intersect/2, list_to_ord_set/2 diff --git a/src/prolog/examples/expert_system.pl b/src/prolog/examples/expert_system.pl index 55b5d287..43ba9bd7 100644 --- a/src/prolog/examples/expert_system.pl +++ b/src/prolog/examples/expert_system.pl @@ -1,5 +1,5 @@ -:- use_module('src/prolog/lib/dcgs'). -:- use_module('src/prolog/lib/reif'). +:- use_module(library(dcgs)). +:- use_module(library(reif)). animals([animal(dog, [is_true('has fur'), is_true('says woof')]), animal(cat, [is_true('has fur'), is_true('says meow')]), diff --git a/src/prolog/examples/minatotask.pl b/src/prolog/examples/minatotask.pl index 2d0d4ff9..fd1a4233 100644 --- a/src/prolog/examples/minatotask.pl +++ b/src/prolog/examples/minatotask.pl @@ -60,9 +60,9 @@ :- module(zdd, [variables_set_zdd/2]). -:- use_module('src/prolog/lib/atts'). -:- use_module('src/prolog/lib/dcgs'). -:- use_module('src/prolog/lib/lists'). +:- use_module(library(atts)). +:- use_module(library(dcgs)). +:- use_module(library(lists)). :- attribute zdd_vs/2. diff --git a/src/prolog/examples/plres.pl b/src/prolog/examples/plres.pl index 3ccfc409..a19ca5a7 100644 --- a/src/prolog/examples/plres.pl +++ b/src/prolog/examples/plres.pl @@ -29,9 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -:- use_module('src/prolog/lib/dcgs'). -:- use_module('src/prolog/lib/dif'). -:- use_module('src/prolog/lib/lists'). +:- use_module(library(dcgs)). +:- use_module(library(dif)). +:- use_module(library(lists)). pl_resolution(Clauses0, Chain) :- maplist(sort, Clauses0, Clauses), % remove duplicates diff --git a/src/prolog/lib/assoc.pl b/src/prolog/lib/assoc.pl index 7880a9e6..b99b1c4b 100644 --- a/src/prolog/lib/assoc.pl +++ b/src/prolog/lib/assoc.pl @@ -52,7 +52,7 @@ del_max_assoc/4 % +Assoc0, ?Key, ?Value, ?Assoc ]). -:- use_module('src/prolog/lib/lists.pl'). +:- use_module(library(lists)). /** Binary associations diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index 1ea94277..6f3b109b 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -4,8 +4,8 @@ '$add_to_list'/3, '$del_attr'/3, '$del_attr_step'/3, '$del_attr_buried'/4]). -:- use_module('src/prolog/lib/dcgs.pl'). -:- use_module('src/prolog/lib/terms.pl'). +:- use_module(library(dcgs)). +:- use_module(library(terms)). :- op(1199, fx, attribute). diff --git a/src/prolog/lib/between.pl b/src/prolog/lib/between.pl index 90090986..16c73145 100644 --- a/src/prolog/lib/between.pl +++ b/src/prolog/lib/between.pl @@ -2,8 +2,8 @@ %% TODO: numlist/5. -:- use_module('src/prolog/lib/lists.pl', [length/2]). -:- use_module('src/prolog/lib/error.pl'). +:- use_module(library(lists), [length/2]). +:- use_module(library(error)). between(Lower, Upper, X) :- must_be(integer, Lower), diff --git a/src/prolog/lib/dcgs.pl b/src/prolog/lib/dcgs.pl index fabd67b0..60fe7126 100644 --- a/src/prolog/lib/dcgs.pl +++ b/src/prolog/lib/dcgs.pl @@ -2,8 +2,8 @@ :- module(dcgs, [phrase/2, phrase/3]). -:- use_module('src/prolog/lib/lists.pl', [append/3]). -:- use_module('src/prolog/lib/terms.pl'). +:- use_module(library(lists), [append/3]). +:- use_module(library(terms)). phrase(G, G) :- nonvar(G), G = [_|_], !. diff --git a/src/prolog/lib/diag.pl b/src/prolog/lib/diag.pl index 8e4799ed..d135238b 100644 --- a/src/prolog/lib/diag.pl +++ b/src/prolog/lib/diag.pl @@ -1,6 +1,6 @@ :- module(diag, [wam_instructions/2]). -:- use_module('src/prolog/lib/error'). +:- use_module(library(error)). wam_instructions(Clause, Listing) :- ( nonvar(Clause) -> diff --git a/src/prolog/lib/dif.pl b/src/prolog/lib/dif.pl index cd779375..991db075 100644 --- a/src/prolog/lib/dif.pl +++ b/src/prolog/lib/dif.pl @@ -1,7 +1,7 @@ :- module(dif, [dif/2]). -:- use_module('src/prolog/lib/atts.pl'). -:- use_module('src/prolog/lib/lists.pl', [append/3]). +:- use_module(library(atts)). +:- use_module(library(lists), [append/3]). :- attribute dif/1. diff --git a/src/prolog/lib/freeze.pl b/src/prolog/lib/freeze.pl index 3fa4ef91..d3a92eaf 100644 --- a/src/prolog/lib/freeze.pl +++ b/src/prolog/lib/freeze.pl @@ -1,6 +1,6 @@ :- module(freeze, [freeze/2]). -:- use_module('src/prolog/lib/atts.pl'). +:- use_module(library(atts)). :- attribute frozen/1. diff --git a/src/prolog/lib/ordsets.pl b/src/prolog/lib/ordsets.pl index a97c609b..ff080962 100644 --- a/src/prolog/lib/ordsets.pl +++ b/src/prolog/lib/ordsets.pl @@ -52,7 +52,7 @@ ord_intersection/2 % +PowerSet, -Intersection ]). -:- use_module('src/prolog/lib/lists.pl'). +:- use_module(library(lists)). /** Ordered set manipulation Ordered sets are lists with unique elements sorted to the standard order diff --git a/src/prolog/lib/reif.pl b/src/prolog/lib/reif.pl index 603d1188..0e958356 100644 --- a/src/prolog/lib/reif.pl +++ b/src/prolog/lib/reif.pl @@ -2,7 +2,7 @@ memberd_t/3, tfilter/3, tmember/2, tmember_t/3, tpartition/4]). -:- use_module('src/prolog/lib/dif.pl'). +:- use_module(library(dif)). if_(If_1, Then_0, Else_0) :- call(If_1, T), diff --git a/src/prolog/lib/terms.pl b/src/prolog/lib/terms.pl index 9b394460..8391457b 100644 --- a/src/prolog/lib/terms.pl +++ b/src/prolog/lib/terms.pl @@ -1,6 +1,6 @@ :- module(terms, [numbervars/3]). -:- use_module('src/prolog/lib/error.pl'). +:- use_module(library(error)). numbervars(Term, N0, N) :- catch(internal_numbervars(Term, N0, N), error(E,Ctx), diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 071d8f49..c6818c39 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -14,6 +14,8 @@ use prolog::machine::*; use indexmap::{IndexMap, IndexSet}; +use ref_thread_local::RefThreadLocal; + use std::cell::Cell; use std::collections::VecDeque; use std::fs::File; @@ -54,16 +56,9 @@ fn fix_filename(atom_tbl: TabledData, filename: &str) -> Result Result { - 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_src = parsing_stream(file_handle); - +fn load_module(wam: &mut Machine, name: &str, stream: ParsingStream) + -> Result +{ // follow the operation of compile_user_module, but before // compiling, check that a module is declared in the file. if not, // throw an exception. @@ -71,21 +66,32 @@ fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result Err(e), _ => Ok(module_name), - } + } +} + +fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result +{ + 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); @@ -459,6 +465,13 @@ fn add_non_module_code( Ok(()) } +fn load_library(wam: &mut Machine, name: ClauseName) -> Result { + 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 { #[inline] 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) } 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) } - Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => self - .use_qualified_module( + Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => { + let name = if !wam.indices.modules.contains_key(&name) { + load_library(wam, name)? + } else { + name + }; + + self.use_qualified_module( name, &mut wam.code_repo, flags, &exports, &mut wam.indices, - indices, - ), + indices + ) + }, Declaration::Module(module_decl) => { if self.module.is_none() { let module_name = module_decl.name.clone(); diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 73159f38..2ed98032 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -163,10 +163,8 @@ impl SubModuleUser for IndexStore { } } -static BUILTINS: &str = include_str!("../lib/builtins.pl"); -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"); +include!("libraries.rs"); + static TOPLEVEL: &str = include_str!("../toplevel.pl"); impl Machine { @@ -538,14 +536,13 @@ impl Machine { self.throw_session_error(err, (clause_name!("repl"), 0)); return; } - EvalSession::QueryFailure => { + EvalSession::QueryFailure => if self.machine_st.ball.stub.len() > 0 { return self.propagate_exception_to_toplevel(snapshot); } else { println!("false."); - } - } - _ => {} + }, + _ => println!("true.") } self.machine_st.absorb_snapshot(snapshot); diff --git a/src/prolog/read.rs b/src/prolog/read.rs index a56e957a..b003bdda 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -45,7 +45,7 @@ pub mod readline { if PROMPT { "?- " } else { "" } } } - + pub struct ReadlineStream { rl: Editor<()>, pending_input: String, @@ -54,9 +54,7 @@ pub mod readline { impl ReadlineStream { fn input_stream(pending_input: String) -> Self { let mut rl = Editor::<()>::new(); - rl.bind_sequence(KeyPress::Tab, Cmd::Insert(1, "\t".to_string())); - 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)) } Err(ReadlineError::Eof) => - Ok(self.write_to_buf(buf)), + Ok(self.write_to_buf(buf)), Err(e) => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, e)) }