Merge pull request #621 from notoria/tabling

Tabling
This commit is contained in:
Mark Thom
2020-07-03 14:40:52 -03:00
committed by GitHub
8 changed files with 145 additions and 240 deletions

103
build.rs
View File

@@ -1,74 +1,55 @@
extern crate indexmap;
use crate::indexmap::IndexSet;
use std::env;
use std::fs::{File, copy, create_dir_all, read_dir};
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main()
{
fn find_prolog_files(libraries: &mut File, prefix: &str, current_dir: &Path) {
let entries = match current_dir.read_dir() {
Ok(entries) => entries,
Err(_) => return,
};
for entry in entries.filter_map(Result::ok).map(|e| e.path()) {
if entry.is_dir() {
if let Some(file_name) = entry.file_name() {
let new_prefix =
prefix.to_owned() + file_name.to_str().unwrap() + "/";
find_prolog_files(libraries, &new_prefix, &entry);
}
} else if entry.is_file() {
let ext = std::ffi::OsStr::new("pl");
if entry.extension() == Some(ext) {
let contain =
String::from_utf8(fs::read(&entry).unwrap()).unwrap();
let name = entry.file_stem().unwrap().to_str().unwrap();
let line = format!(
" m.insert(\"{}\",\n{:?});\n",
prefix.to_owned() + name,
contain
);
libraries.write_all(line.as_bytes()).unwrap();
}
}
}
}
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("libraries.rs");
let mut libraries = File::create(&dest_path).unwrap();
let mut library_index = IndexSet::new();
let lib_path = Path::new("src/lib");
let mut paths: Vec<_> = read_dir("./src/lib").unwrap()
.map(|e| e.unwrap().path()).collect();
while let Some(item) = paths.pop() {
if item.is_file() {
let file_name = item.strip_prefix(".").unwrap();
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 dest = Path::new(&out_dir).join(file_name);
let dir_name = dest.parent().unwrap();
if !dir_name.exists() {
create_dir_all(dir_name).unwrap();
}
match copy(&item, dest) {
Ok(_) => {
}
Err(e) => {
panic!("die: {:?}", e)
}
};
let include_line = format!("static {}: &str = include_str!({:?});\n",
file_str, file_name); //file_stem.to_string_lossy());
libraries.write_all(include_line.as_bytes()).unwrap();
library_index.insert(file_stem.to_string_lossy().to_string());
}
}
} else if item.is_dir() {
for entry in read_dir(item).unwrap() {
let path = entry.unwrap().path();
paths.push(path);
}
}
}
libraries.write_all(b"\nref_thread_local! {
libraries
.write_all(
b"ref_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 };
}\n").unwrap();
libraries.write_all(b"\npub static PROJECT_DIR: &'static str = \"").unwrap();
libraries.write_all(env::var("CARGO_MANIFEST_DIR").unwrap().as_bytes()).unwrap();
libraries.write_all(b"\";\n").unwrap();
let mut m = IndexMap::new();\n",
)
.unwrap();
find_prolog_files(&mut libraries, "", &lib_path);
libraries.write_all(b"\n m\n };\n}\n").unwrap();
}

View File

@@ -8,12 +8,12 @@
op(1150, fx, table)
]).
:- use_module('tabling/double_linked_list').
:- use_module('tabling/table_data_structure').
:- use_module('tabling/batched_worklist').
:- use_module('tabling/wrapper').
:- use_module('tabling/global_worklist').
:- use_module('tabling/table_link_manager').
:- use_module(library(tabling/double_linked_list)).
:- use_module(library(tabling/table_data_structure)).
:- use_module(library(tabling/batched_worklist)).
:- use_module(library(tabling/wrapper)).
:- use_module(library(tabling/global_worklist)).
:- use_module(library(tabling/table_link_manager)).
:- use_module(library(cont)).
:- use_module(library(lists)).

View File

@@ -45,8 +45,8 @@
wkl_worklist_work_done/1 % +WorkList
]).
:- use_module(global_worklist).
:- use_module(double_linked_list).
:- use_module(library(tabling/global_worklist)).
:- use_module(library(tabling/double_linked_list)).
:- use_module(library(atts)).
:- use_module(library(lists)).

View File

@@ -15,8 +15,8 @@
get_nb_identifiers/3 % +Table, -NbWorklistID, -NbAnswerTreeID
]).
:- use_module(table_link_manager).
:- use_module(trie).
:- use_module(library(tabling/table_link_manager)).
:- use_module(library(tabling/trie)).
/* Part of SWI-Prolog
@@ -53,7 +53,7 @@
POSSIBILITY OF SUCH DAMAGE.
*/
:- use_module(batched_worklist).
:- use_module(library(tabling/batched_worklist)).
:- use_module(library(atts)).
:- use_module(library(gensym)).

View File

@@ -47,7 +47,7 @@
:- use_module(library(iso_ext)).
:- use_module(library(terms)).
:- use_module(trie).
:- use_module(library(tabling/trie)).
:- attribute trie_table_link/1.

View File

@@ -600,44 +600,25 @@ fn load_library(
name: ClauseName,
suppress_warnings: bool,
) -> Result<ClauseName, SessionError> {
let mut lib_path = current_dir();
match LIBRARIES.borrow().get(name.as_str()) {
Some(code) => {
let listing_src = ListingSource::User;
lib_path.pop();
lib_path.push("lib");
load_module(
wam,
Stream::from(*code),
suppress_warnings,
&listing_src,
)
}
None => {
let err = ExistenceError::ModuleSource(ModuleSource::Library(
name.clone()
));
let (stream, listing_src) =
match LIBRARIES.borrow().get(name.as_str()) {
Some(code) => {
let listing_src = ListingSource::from_file_and_path(name, lib_path);
(Stream::from(*code), listing_src)
}
None => {
// assume that name is a path.
lib_path.push(name.as_str());
lib_path.set_extension("pl");
let file =
match File::open(&lib_path) {
Ok(file) => {
file
}
Err(_) => {
let err = ExistenceError::ModuleSource(ModuleSource::Library(name));
return Err(SessionError::ExistenceError(err));
}
};
let listing_src = ListingSource::from_file_and_path(name.clone(), lib_path);
(Stream::from_file_as_input(name, file), listing_src)
}
};
load_module(
wam,
stream,
suppress_warnings,
&listing_src,
)
Err(SessionError::ExistenceError(err))
}
}
}
impl ListingCompiler {

View File

@@ -212,17 +212,6 @@ impl SubModuleUser for IndexStore {
}
}
#[inline]
fn current_dir() -> std::path::PathBuf {
let mut path_buf = std::path::PathBuf::from(PROJECT_DIR);
// file!() always produces a path relative to PROJECT_DIR.
path_buf = path_buf.join(std::path::PathBuf::from(file!()));
path_buf.pop();
path_buf
}
include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
static TOPLEVEL: &str = include_str!("../toplevel.pl");
@@ -230,12 +219,7 @@ static TOPLEVEL: &str = include_str!("../toplevel.pl");
impl Machine {
fn compile_special_forms(&mut self)
{
let current_dir = current_dir();
let verify_attrs_src = ListingSource::from_file_and_path(
clause_name!("attributed_variables.pl"),
current_dir.clone(),
);
let verify_attrs_src = ListingSource::User;
match compile_special_form(
self,
@@ -250,10 +234,7 @@ impl Machine {
panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
}
let project_attrs_src = ListingSource::from_file_and_path(
clause_name!("project_attributes.pl"),
current_dir,
);
let project_attrs_src = ListingSource::User;
match compile_special_form(
self,
@@ -273,13 +254,7 @@ impl Machine {
{
self.toplevel_idx = self.code_repo.code.len();
let mut current_dir = current_dir();
current_dir.pop();
let top_lvl_src = ListingSource::from_file_and_path(
clause_name!("toplevel.pl"),
current_dir,
);
let top_lvl_src = ListingSource::User;
compile_user_module(
self,
@@ -371,6 +346,8 @@ impl Machine {
pub fn new(current_input_stream: Stream, current_output_stream: Stream) -> Self
{
use crate::ref_thread_local::RefThreadLocal;
let mut wam = Machine {
machine_st: MachineState::new(),
inner_heap: Heap::new(),
@@ -383,78 +360,59 @@ impl Machine {
};
let atom_tbl = wam.indices.atom_tbl.clone();
let mut lib_path = current_dir();
lib_path.pop();
lib_path.push("lib");
wam.indices.add_term_and_goal_expansion_indices();
compile_listing(
&mut wam,
Stream::from(BUILTINS),
Stream::from(LIBRARIES.borrow()["builtins"]),
default_index_store!(atom_tbl.clone()),
true,
ListingSource::from_file_and_path(
clause_name!("builtins.pl"),
lib_path.clone(),
),
ListingSource::User,
);
wam.compile_special_forms();
compile_user_module(&mut wam,
Stream::from(ERROR),
true,
ListingSource::from_file_and_path(
clause_name!("error"),
lib_path.clone(),
)
compile_user_module(
&mut wam,
Stream::from(LIBRARIES.borrow()["error"]),
true,
ListingSource::User,
);
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,
Stream::from(LIBRARIES.borrow()["pairs"]),
true,
ListingSource::User,
);
compile_user_module(&mut wam,
Stream::from(LISTS),
true,
ListingSource::from_file_and_path(
clause_name!("lists"),
lib_path.clone(),
),
compile_user_module(
&mut wam,
Stream::from(LIBRARIES.borrow()["lists"]),
true,
ListingSource::User,
);
compile_user_module(&mut wam,
Stream::from(ISO_EXT),
true,
ListingSource::from_file_and_path(
clause_name!("iso_ext"),
lib_path.clone(),
)
compile_user_module(
&mut wam,
Stream::from(LIBRARIES.borrow()["iso_ext"]),
true,
ListingSource::User,
);
compile_user_module(&mut wam,
Stream::from(SI),
true,
ListingSource::from_file_and_path(
clause_name!("si"),
lib_path.clone(),
)
compile_user_module(
&mut wam,
Stream::from(LIBRARIES.borrow()["si"]),
true,
ListingSource::User,
);
compile_user_module(&mut wam,
Stream::from(CHARSIO),
true,
ListingSource::from_file_and_path(
clause_name!("charsio"),
lib_path.clone(),
)
compile_user_module(
&mut wam,
Stream::from(LIBRARIES.borrow()["charsio"]),
true,
ListingSource::User,
);
if wam.compile_top_level().is_err() {
@@ -666,46 +624,43 @@ impl Machine {
Ok(exports)
}
fn use_module(&mut self, to_src: impl Fn(ClauseName) -> ModuleSource)
fn use_module<ToSource>(&mut self, to_src: ToSource)
where ToSource: Fn(ClauseName) -> ModuleSource
{
// the term expander will overwrite the cached query, so save it here.
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
let module_spec = self.machine_st[temp_v!(1)].clone();
let (name, is_path) = {
let name = {
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
match self.machine_st.heap.index_addr(&addr).as_ref() {
HeapCellValue::Atom(name, _) =>
(name.clone(), name.as_str().contains('/')),
name.clone(),
HeapCellValue::Addr(Addr::Char(c)) =>
(clause_name!(c.to_string(), self.indices.atom_tbl), false),
clause_name!(c.to_string(), self.indices.atom_tbl),
HeapCellValue::Addr(addr @ Addr::PStrLocation(..)) => {
let mut heap_pstr_iter = self.machine_st.heap_pstr_iter(*addr);
let filename = heap_pstr_iter.to_string();
let is_path = filename.contains('/');
(clause_name!(filename, self.indices.atom_tbl), is_path)
let mut heap_pstr_iter =
self.machine_st.heap_pstr_iter(*addr);
clause_name!(
heap_pstr_iter.to_string(),
self.indices.atom_tbl
)
}
_ =>
unreachable!(),
_ => unreachable!(),
}
};
let load_result = match to_src(name) {
ModuleSource::Library(name) =>
if is_path {
load_library(self, name, false)
} else {
if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module);
if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module);
Ok(name)
} else {
load_library(self, name, false)
}
}
Ok(name)
} else {
load_library(self, name, false)
},
ModuleSource::File(name) =>
load_module_from_file(self, PathBuf::from(name.as_str()), false)
};
@@ -727,27 +682,21 @@ impl Machine {
}
}
fn use_qualified_module(&mut self, to_src: impl Fn(ClauseName) -> ModuleSource)
fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
where ToSource: Fn(ClauseName) -> ModuleSource
{
// the term expander will overwrite the cached query, so save it here.
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
let module_spec = self.machine_st[temp_v!(1)].clone();
let (name, is_path) = {
let name = {
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
match self.machine_st.heap.index_addr(&addr).as_ref() {
HeapCellValue::Atom(name, _) =>
(name.clone(), name.as_str().contains('/')),
name.clone(),
HeapCellValue::Addr(Addr::Char(c)) =>
(clause_name!(c.to_string(), self.indices.atom_tbl), false),
HeapCellValue::Addr(addr @ Addr::PStrLocation(..)) => {
let mut heap_pstr_iter = self.machine_st.heap_pstr_iter(*addr);
let filename = heap_pstr_iter.to_string();
let is_path = filename.contains('/');
(clause_name!(filename, self.indices.atom_tbl), is_path)
}
clause_name!(c.to_string(), self.indices.atom_tbl),
_ =>
unreachable!(),
}
@@ -763,18 +712,14 @@ impl Machine {
let load_result = match to_src(name) {
ModuleSource::Library(name) =>
if is_path {
load_library(self, name, false)
} else {
if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module);
if let Some(module) = self.indices.take_module(name.clone()) {
self.indices.remove_module(clause_name!("user"), &module);
self.indices.modules.insert(name.clone(), module);
Ok(name)
} else {
load_library(self, name, false)
}
},
Ok(name)
} else {
load_library(self, name, false)
},
ModuleSource::File(name) =>
load_module_from_file(self, PathBuf::from(name.as_str()), false)
};

View File

@@ -340,7 +340,10 @@ fn setup_module_decl(
}
}
fn read_library_path(term: Term, atom_tbl: TabledData<Atom>) -> Option<ClauseName> {
fn read_library_path(
term: Term,
atom_tbl: TabledData<Atom>,
) -> Option<ClauseName> {
match term {
Term::Constant(_, Constant::Atom(atom, _)) => {
Some(atom.defrock_brackets())
@@ -353,9 +356,7 @@ fn read_library_path(term: Term, atom_tbl: TabledData<Atom>) -> Option<ClauseNam
Term::Constant(_, Constant::Atom(atom, _)) => {
atoms.push(atom.as_str().to_owned());
}
_ => {
return None;
}
_ => return None,
}
}
@@ -364,10 +365,7 @@ fn read_library_path(term: Term, atom_tbl: TabledData<Atom>) -> Option<ClauseNam
}
}
fn setup_use_module_decl(
mut terms: Vec<Box<Term>>,
atom_tbl: TabledData<Atom>,
) -> Result<ModuleSource, ParserError> {
fn setup_use_module_decl(mut terms: Vec<Box<Term>>, atom_tbl: TabledData<Atom>) -> Result<ModuleSource, ParserError> {
match *terms.pop().unwrap() {
Term::Clause(_, ref name, ref mut terms, None)
if name.as_str() == "library" && terms.len() == 1 =>