merge latest commit

This commit is contained in:
Mark Thom
2019-11-28 21:22:59 -04:00
26 changed files with 1343 additions and 354 deletions

View File

@@ -170,7 +170,7 @@ pub enum SystemClauseType {
CopyToLiftedHeap,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution,
DynamicModuleResolution(usize),
EnqueueAttributeGoal,
EnqueueAttributedVar,
ExpandGoal,
@@ -179,6 +179,7 @@ pub enum SystemClauseType {
FetchGlobalVar,
FetchGlobalVarWithOffset,
GetChar,
ResetAttrVarState,
TruncateIfNoLiftedHeapGrowthDiff,
TruncateIfNoLiftedHeapGrowth,
GetAttributedVariableList,
@@ -278,7 +279,7 @@ impl SystemClauseType {
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
&SystemClauseType::DynamicModuleResolution(_) => clause_name!("$module_call"),
&SystemClauseType::EnqueueAttributeGoal => clause_name!("$enqueue_attribute_goal"),
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
@@ -289,6 +290,7 @@ impl SystemClauseType {
clause_name!("$fetch_global_var_with_offset")
}
&SystemClauseType::GetChar => clause_name!("$get_char"),
&SystemClauseType::ResetAttrVarState => clause_name!("$reset_attr_var_state"),
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
clause_name!("$truncate_if_no_lh_growth")
}
@@ -399,7 +401,7 @@ impl SystemClauseType {
("$get_next_op_db_ref", 2) => Some(SystemClauseType::GetNextOpDBRef),
("$lookup_db_ref", 3) => Some(SystemClauseType::LookupDBRef),
("$lookup_op_db_ref", 4) => Some(SystemClauseType::LookupOpDBRef),
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
("$module_call", _) => Some(SystemClauseType::DynamicModuleResolution(arity - 2)),
("$enqueue_attribute_goal", 1) => Some(SystemClauseType::EnqueueAttributeGoal),
("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
@@ -408,6 +410,7 @@ impl SystemClauseType {
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar),
("$reset_attr_var_state", 0) => Some(SystemClauseType::ResetAttrVarState),
("$truncate_if_no_lh_growth", 1) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
}

View File

@@ -179,7 +179,7 @@ pub enum Declaration {
NonCountedBacktracking(ClauseName, usize), // name, arity
Op(OpDecl),
UseModule(ModuleSource),
UseQualifiedModule(ModuleSource, Vec<PredicateKey>),
UseQualifiedModule(ModuleSource, Vec<ModuleExport>),
}
impl Declaration {
@@ -216,15 +216,20 @@ impl OpDecl {
self.insert_into_op_dir(clause_name!(""), op_dir, 0);
}
fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) {
let (spec, name) = (self.1, self.2.clone());
let fixity = match spec {
#[inline]
pub fn fixity(&self) -> Fixity {
match self.1 {
XFY | XFX | YFX => Fixity::In,
XF | YF => Fixity::Post,
FX | FY => Fixity::Pre,
_ => return,
};
_ => unreachable!()
}
}
pub fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) {
let (spec, name) = (self.1, self.2.clone());
let fixity = self.fixity();
match op_dir.get(&(name.clone(), fixity)) {
Some(cell) => {
@@ -322,10 +327,16 @@ pub fn fetch_op_spec(
pub type ModuleDir = IndexMap<ClauseName, Module>;
#[derive(Clone, PartialEq)]
pub enum ModuleExport {
OpDecl(OpDecl),
PredicateKey(PredicateKey),
}
#[derive(Clone)]
pub struct ModuleDecl {
pub name: ClauseName,
pub exports: Vec<PredicateKey>,
pub exports: Vec<ModuleExport>,
}
pub struct Module {
@@ -337,6 +348,8 @@ pub struct Module {
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions.
pub local_term_expansions: (Predicate, VecDeque<TopLevel>), // expansions local to the module.
pub local_goal_expansions: (Predicate, VecDeque<TopLevel>),
pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
pub is_impromptu_module: bool,
}

View File

@@ -1,14 +1,13 @@
:- module(atts, [attribute/1, call_residue_vars/2, '$absent_attr'/2,
'$copy_attr_list'/2, '$get_attr'/2, '$put_attr'/2,
'$absent_from_list'/2, '$get_from_list'/3,
'$add_to_list'/3, '$del_attr'/3, '$del_attr_step'/3,
'$del_attr_buried'/4, '$default_attr_list'/4]).
:- module(atts, [op(1199, fx, attribute), call_residue_vars/2,
'$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2,
'$put_attr'/2, '$absent_from_list'/2,
'$get_from_list'/3, '$add_to_list'/3, '$del_attr'/3,
'$del_attr_step'/3, '$del_attr_buried'/4,
'$default_attr_list'/4]).
:- use_module(library(dcgs)).
:- use_module(library(terms)).
:- op(1199, fx, attribute).
/* represent the list of attributes belonging to a variable,
of a particular module, as a list of terms of the form
Module:put_atts(V, ListOfAtts). */

View File

@@ -1,35 +1,19 @@
:- op(400, yfx, /).
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
instructions are unchanged. */
:- op(700, fx, non_counted_backtracking).
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, (^)/2, (\)/1, (+)/1,
(+)/2, (**)/2, (*)/2, (-)/1, (-)/2, (/)/2, (/\)/2, (\/)/2,
(is)/2, (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2, (>>)/2,
(mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (>=)/2,
(=<)/2, (',')/2, (->)/2, (;)/2, (=..)/2, (==)/2, (\==)/2,
(@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (:)/2, abolish/1, asserta/1,
assertz/1, atom_chars/2, atom_codes/2, atom_concat/3,
atom_length/2, bagof/3, catch/3, char_code/2, clause/2,
current_op/3, current_predicate/1, current_prolog_flag/2,
expand_goal/2, expand_term/2, fail/0, false/0, findall/3,
findall/4, get_char/1, halt/0, number_chars/2, number_codes/2,
once/1, op/3, read_term/2, repeat/0, retract/1,
set_prolog_flag/2, setof/3, sub_atom/5, subsumes_term/2,
term_variables/2, throw/1, true/0, unify_with_occurs_check/2,
write/1, write_canonical/1, write_term/2, writeq/1]).
% module resolution operator.
:- op(600, xfy, :).
user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
expand_op_list([Op | OtherOps], Pred, Spec, OpResults).
'$expand_op_list'([Op | OtherOps], Pred, Spec, OpResults).
expand_op_list([], _, _, []).
expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResults]) :-
expand_op_list(OtherOps, Pred, Spec, OtherResults).
'$expand_op_list'([], _, _, []).
'$expand_op_list'([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResults]) :-
'$expand_op_list'(OtherOps, Pred, Spec, OtherResults).
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
instructions are unchanged. */
:- op(700, fx, non_counted_backtracking).
% arithmetic operators.
:- op(700, xfx, is).
@@ -37,8 +21,7 @@ expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResu
:- op(400, yfx, *).
:- op(200, xfy, [**, ^]).
:- op(500, yfx, [/\, \/, xor]).
:- op(400, yfx, [div, //, rdiv]).
:- op(400, yfx, [<<, >>, mod, rem]).
:- op(400, yfx, [div, //, rdiv, <<, >>, mod, rem]).
:- op(200, fy, [+, -, \]).
% arithmetic comparison operators.
@@ -47,9 +30,6 @@ expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResu
% term comparison.
:- op(700, xfx, [==, \==, @=<, @>=, @<, @>]).
% the maximum arity flag. needs to be replaced with current_prolog_flag(max_arity, MAX_ARITY).
max_arity(255).
% conditional operators.
:- op(1050, xfy, ->).
:- op(1100, xfy, ;).
@@ -58,6 +38,27 @@ max_arity(255).
:- op(700, xfx, [=, =.., \=]).
:- op(900, fy, \+).
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, (',')/2, (->)/2, (;)/2,
(=..)/2, (:)/2, (:)/3, (:)/4, (:)/5, (:)/6,
(:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12,
abolish/1, asserta/1, assertz/1, atom_chars/2,
atom_codes/2, atom_concat/3, atom_length/2,
bagof/3, catch/3, char_code/2, clause/2,
current_op/3, current_predicate/1,
current_prolog_flag/2, expand_goal/2,
expand_term/2, fail/0, false/0, findall/3,
findall/4, get_char/1, halt/0, max_arity/1,
number_chars/2, number_codes/2, once/1, op/3,
read_term/2, repeat/0, retract/1,
set_prolog_flag/2, setof/3, sub_atom/5,
subsumes_term/2, term_variables/2, throw/1,
true/0, unify_with_occurs_check/2, write/1,
write_canonical/1, write_term/2, writeq/1]).
% the maximum arity flag. needs to be replaced with
% current_prolog_flag(max_arity, MAX_ARITY).
max_arity(255).
% unify.
X = X.
@@ -72,6 +73,57 @@ Module : Predicate :-
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1) :-
( atom(Module) -> '$module_call'(A1, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2) :-
( atom(Module) -> '$module_call'(A1, A2, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3) :-
( atom(Module) -> '$module_call'(A1, A2, A3, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5, A6) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, A9, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
:(Module, Predicate, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) :-
( atom(Module) -> '$module_call'(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
% flags.
current_prolog_flag(Flag, false) :- Flag == bounded, !.

View File

@@ -16,11 +16,9 @@
Public operators.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
:- op(300, fy, ~).
:- op(500, yfx, #).
:- module(clpb, [
sat/1,
:- module(clpb, [op(300, fy, ~),
op(500, yfx, #),
sat/1,
taut/2,
labeling/1,
sat_count/2,

View File

@@ -1,7 +1,6 @@
:- op(1200, xfx, -->).
% :- op(1105, xfy, ('|')).
:- module(dcgs, [phrase/2, phrase/3]).
:- module(dcgs, [op(1200, xfx, -->), phrase/2, phrase/3]).
:- use_module(library(lists), [append/3]).

View File

@@ -32,9 +32,9 @@ impl AttrVarInitializer {
#[inline]
pub(super) fn reset(&mut self) {
self.attribute_goals.clear();
self.attr_var_queue.clear();
self.bindings.clear();
self.attribute_goals.clear();
}
}

View File

@@ -448,7 +448,8 @@ fn add_toplevel_code(wam: &mut Machine, code: Code, indices: IndexStore) {
}
#[inline]
fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, indices: IndexStore) {
fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, indices: IndexStore)
{
module.code_dir.extend(indices.code_dir);
module.op_dir.extend(indices.op_dir.into_iter());
@@ -573,7 +574,7 @@ impl ListingCompiler {
submodule: ClauseName,
code_repo: &mut CodeRepo,
flags: MachineFlags,
exports: &Vec<PredicateKey>,
exports: &Vec<ModuleExport>,
wam_indices: &mut IndexStore,
indices: &mut IndexStore,
) -> Result<(), SessionError> {
@@ -683,7 +684,8 @@ impl ListingCompiler {
.or_insert((Predicate::new(), VecDeque::from(vec![])));
if let Some(ref mut module) = &mut self.module {
module.add_module_expansion_record(hook, clause.clone(), queue.clone());
module.add_expansion_record(hook, clause.clone(), queue.clone());
module.add_local_expansion(hook, clause.clone(), queue.clone());
}
(module_preds.0).0.push(clause);
@@ -710,6 +712,24 @@ impl ListingCompiler {
(len, queue_len)
}
fn submit_op(
&mut self,
wam: &Machine,
indices: &mut IndexStore,
op_decl: &OpDecl,
) -> Result<(), SessionError> {
let spec = get_desc(
op_decl.name(),
composite_op!(
self.module.is_some(),
&wam.indices.op_dir,
&mut indices.op_dir
),
);
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
}
fn process_decl(
&mut self,
decl: Declaration,
@@ -728,6 +748,7 @@ impl ListingCompiler {
.code_repo
.compile_hook(hook, flags)
.map_err(SessionError::from);
wam.code_repo.truncate_terms(key, len, queue_len);
result
@@ -736,16 +757,7 @@ impl ListingCompiler {
Ok(self.add_non_counted_bt_flag(name, arity))
}
Declaration::Op(op_decl) => {
let spec = get_desc(
op_decl.name(),
composite_op!(
self.module.is_some(),
&wam.indices.op_dir,
&mut indices.op_dir
),
);
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
self.submit_op(wam, indices, &op_decl)
}
Declaration::UseModule(ModuleSource::Library(name)) => {
let name = if !wam.indices.modules.contains_key(&name) {
@@ -777,6 +789,12 @@ impl ListingCompiler {
let module_name = module_decl.name.clone();
let atom_tbl = TabledData::new(module_name.to_rc());
for export in module_decl.exports.iter() {
if let ModuleExport::OpDecl(ref op_decl) = export {
self.submit_op(wam, indices, op_decl)?;
}
}
Ok(self.module = Some(Module::new(module_decl, atom_tbl)))
} else {
Err(SessionError::from(ParserError::InvalidModuleDecl))
@@ -824,8 +842,9 @@ impl ListingCompiler {
.entry((name.clone(), arity))
.or_insert(vec![]);
indices.code_dir.insert((name.clone(), arity),
CodeIndex::dynamic_undefined(self.get_module_name()));
indices.code_dir
.entry((name.clone(), arity))
.or_insert(CodeIndex::dynamic_undefined(self.get_module_name()));
}
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
.term_stream
@@ -917,6 +936,16 @@ fn compile_work_impl(
mut indices: IndexStore,
mut results: GatherResult,
) -> Result<(), SessionError> {
if let Some(ref mut module) = &mut compiler.module {
// compile the module-level goal and term expansions and store
// their locations to the module's code_dir.
let decls = module.take_local_expansions();
if !decls.is_empty() {
results.worker_results.extend(decls.into_iter());
}
}
let module_code = compiler.generate_code(
results.worker_results,
wam,
@@ -946,8 +975,9 @@ fn compile_work_impl(
if let Some(mut module) = compiler.module.take() {
if module.is_impromptu_module {
module.module_decl.exports = indices.code_dir.keys().cloned()
.filter(|(name, _)| name.owning_module().as_str() != "builtins")
.collect();
.filter(|(name, _)| name.owning_module().as_str() != "builtins")
.map(ModuleExport::PredicateKey)
.collect();
}
let mut clause_code_generator =
@@ -968,7 +998,7 @@ fn compile_work_impl(
wam.indices.use_module(&mut wam.code_repo, wam.machine_st.flags, &module)?;
wam.indices.insert_module(module);
} else {
} else {
add_module_code(wam, module, module_code, indices);
}

View File

@@ -863,13 +863,7 @@ pub(crate) trait CallPolicy: Any {
if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
self.context_call(machine_st, name, arity, idx, indices)?;
} else {
let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
let key = ExistenceError::Procedure(name, arity);
return Err(
machine_st.error_form(MachineError::existence_error(h, key), stub)
);
try_in_situ(machine_st, name, arity, indices, machine_st.last_call)?;
}
}
ClauseType::Hook(_) | ClauseType::System(_) => {

View File

@@ -3051,14 +3051,15 @@ impl MachineState {
| (
HeapCellValue::Addr(v1 @ Addr::StackCell(..)),
HeapCellValue::Addr(v2 @ Addr::HeapCell(_)),
) => match (var_pairs.get(&v1).cloned(), var_pairs.get(&v2).cloned()) {
(Some(ref v2_p), Some(ref v1_p)) if *v1_p == v1 && *v2_p == v2 => continue,
(Some(_), _) | (_, Some(_)) => return true,
(None, None) => {
var_pairs.insert(v1.clone(), v2.clone());
var_pairs.insert(v2, v1);
}
},
) =>
match (var_pairs.get(&v1).cloned(), var_pairs.get(&v2).cloned()) {
(Some(ref v2_p), Some(ref v1_p)) if *v1_p == v1 && *v2_p == v2 => continue,
(Some(_), _) | (_, Some(_)) => return true,
(None, None) => {
var_pairs.insert(v1.clone(), v2.clone());
var_pairs.insert(v2, v1);
}
},
(HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) => {
if a1 != a2 {
return true;
@@ -3079,6 +3080,7 @@ impl MachineState {
match v {
HeapCellValue::Addr(Addr::HeapCell(..)) => return true,
HeapCellValue::Addr(Addr::StackCell(..)) => return true,
HeapCellValue::Addr(Addr::AttrVar(..)) => return true,
_ => {}
}
}

View File

@@ -33,6 +33,7 @@ use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
use crate::prolog::machine::modules::*;
use crate::prolog::machine::toplevel::*;
use crate::prolog::read::PrologStream;
use indexmap::IndexMap;
@@ -105,13 +106,13 @@ impl SubModuleUser for IndexStore {
&mut self.op_dir
}
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
match module.as_str() {
fn get_code_index(&self, key: PredicateKey, module_name: ClauseName) -> Option<CodeIndex> {
match module_name.as_str() {
"user" | "builtin" => self.code_dir.get(&key).cloned(),
_ => self
.modules
.get(&module)
.and_then(|ref module| module.code_dir.get(&key).cloned().map(CodeIndex::from)),
.modules
.get(&module_name)
.and_then(|ref module| module.code_dir.get(&key).cloned().map(CodeIndex::from))
}
}
@@ -130,7 +131,7 @@ impl SubModuleUser for IndexStore {
return;
}
self.code_dir.insert((name, arity), idx);
self.code_dir.insert((name.clone(), arity), idx.clone());
}
fn use_qualified_module(
@@ -138,7 +139,7 @@ impl SubModuleUser for IndexStore {
code_repo: &mut CodeRepo,
flags: MachineFlags,
submodule: &Module,
exports: &Vec<PredicateKey>,
exports: &Vec<ModuleExport>,
) -> Result<(), SessionError> {
use_qualified_module(self, submodule, exports)?;
submodule
@@ -239,7 +240,7 @@ impl Machine {
pub fn run_init_code(&mut self, code: Code) -> bool {
let old_machine_st = self.sink_to_snapshot();
self.machine_st.reset();
self.machine_st.reset();
self.code_repo.cached_query = code;
self.run_query();
@@ -399,30 +400,64 @@ impl Machine {
return;
}
fn extract_predicate_indicator_list(&mut self) -> Vec<PredicateKey>
fn extract_module_export_list(&mut self) -> Result<Vec<ModuleExport>, ParserError>
{
let export_list = self.machine_st[temp_v!(2)].clone();
let mut export_list = self.machine_st.store(self.machine_st.deref(export_list));
let mut export_list = self.machine_st[temp_v!(2)].clone();
let mut exports = vec![];
while let Addr::Lis(l) = export_list {
while let Addr::Lis(l) = self.machine_st.store(self.machine_st.deref(export_list)) {
match &self.machine_st.heap[l] {
&HeapCellValue::Addr(Addr::Str(s)) => {
let name = match &self.machine_st.heap[s+1] {
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
name.clone(),
_ =>
unreachable!()
};
match &self.machine_st.heap[s] {
HeapCellValue::NamedStr(arity, ref name, _)
if *arity == 2 && name.as_str() == "/" => {
let name = match &self.machine_st.heap[s+1] {
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
name.clone(),
_ =>
unreachable!()
};
let arity = match &self.machine_st.heap[s+2] {
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
arity.to_usize().unwrap(),
_ =>
unreachable!()
};
let arity = match &self.machine_st.heap[s+2] {
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
arity.to_usize().unwrap(),
_ =>
unreachable!()
};
exports.push((name, arity));
exports.push(ModuleExport::PredicateKey((name, arity)));
}
HeapCellValue::NamedStr(arity, ref name, _)
if *arity == 3 && name.as_str() == "op" => {
let name = match &self.machine_st.heap[s+3] {
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
name.clone(),
_ =>
unreachable!()
};
let spec = match &self.machine_st.heap[s+2] {
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
name.clone(),
_ =>
unreachable!()
};
let prec = match &self.machine_st.heap[s+1] {
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
arity.to_usize().unwrap(),
_ =>
unreachable!()
};
exports.push(ModuleExport::OpDecl(to_op_decl(
prec,
spec.as_str(),
name,
)?));
}
_ => unreachable!()
}
}
_ => unreachable!()
}
@@ -430,7 +465,7 @@ impl Machine {
export_list = self.machine_st.heap[l+1].as_addr(l+1);
}
exports
Ok(exports)
}
fn use_module<ToSource>(&mut self, to_src: ToSource)
@@ -488,7 +523,13 @@ impl Machine {
_ => unreachable!()
};
let exports = self.extract_predicate_indicator_list();
let exports = match self.extract_module_export_list() {
Ok(exports) => exports,
Err(e) => {
self.throw_session_error(SessionError::from(e), (clause_name!("use_module"), 2));
return;
}
};
let load_result = match to_src(name) {
ModuleSource::Library(name) =>
@@ -520,7 +561,7 @@ impl Machine {
self.code_repo.cached_query = cached_query;
if let Err(e) = result {
self.throw_session_error(e, (clause_name!("use_module"), 1));
self.throw_session_error(e, (clause_name!("use_module"), 2));
}
}
@@ -551,7 +592,7 @@ impl Machine {
fn sink_to_snapshot(&mut self) -> MachineState {
let mut snapshot = MachineState::with_capacity(0);
snapshot.hb = self.machine_st.hb;
snapshot.e = self.machine_st.e;
snapshot.b = self.machine_st.b;
@@ -576,7 +617,7 @@ impl Machine {
snapshot
}
fn absorb_snapshot(&mut self, mut snapshot: MachineState) {
fn absorb_snapshot(&mut self, mut snapshot: MachineState) {
self.machine_st.hb = snapshot.hb;
self.machine_st.e = snapshot.e;
self.machine_st.b = snapshot.b;
@@ -623,37 +664,19 @@ impl Machine {
// so hold onto it locally and restore it after the compiler has finished.
self.machine_st.fail = false;
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
self.dynamic_transaction(trans_type, p);
self.code_repo.cached_query = cached_query;
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
self.code_repo.cached_query = cached_query;
break;
}
self.code_repo.cached_query = cached_query;
}
_ =>
break
};
}
}
#[cfg(test)]
pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where
Outputter: HCValueOutputter,
{
for (var, addr) in self.machine_st.heap_locs.iter() {
output = self.machine_st.print_var_eq(
var.clone(),
addr.clone(),
&self.indices.op_dir,
output,
);
}
output
}
}
impl MachineState {

View File

@@ -7,6 +7,7 @@ use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*;
use std::collections::VecDeque;
use std::mem;
// Module's and related types are defined in forms.
impl Module {
@@ -19,6 +20,8 @@ impl Module {
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
local_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
local_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
code_dir: CodeDir::new(),
op_dir: default_op_dir(),
inserted_expansions: false,
@@ -61,7 +64,7 @@ impl Module {
Ok(())
}
pub fn add_module_expansion_record(
pub fn add_expansion_record(
&mut self,
hook: CompileTimeHook,
clause: PredicateClause,
@@ -78,6 +81,45 @@ impl Module {
}
}
}
pub fn add_local_expansion(
&mut self,
hook: CompileTimeHook,
clause: PredicateClause,
queue: VecDeque<TopLevel>,
) {
match hook {
CompileTimeHook::TermExpansion => {
(self.local_term_expansions.0).0.push(clause);
self.local_term_expansions.1.extend(queue.into_iter());
}
CompileTimeHook::GoalExpansion => {
(self.local_goal_expansions.0).0.push(clause);
self.local_goal_expansions.1.extend(queue.into_iter());
}
_ => {}
}
}
pub fn take_local_expansions(&mut self) -> Vec<(Predicate, VecDeque<TopLevel>)>
{
let term_expansions =
mem::replace(&mut self.local_term_expansions, (Predicate::new(), VecDeque::new()));
let goal_expansions =
mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
let mut result = vec![];
if !(term_expansions.0).0.is_empty() {
result.push(term_expansions);
}
if !(goal_expansions.0).0.is_empty() {
result.push(goal_expansions);
}
result
}
}
pub trait SubModuleUser {
@@ -95,64 +137,55 @@ pub trait SubModuleUser {
}
fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
for (name, arity) in module.module_decl.exports.iter().cloned() {
let name = name.defrock_brackets();
for export in module.module_decl.exports.iter().cloned() {
match export {
ModuleExport::PredicateKey((name, arity)) => {
let name = name.defrock_brackets();
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
Some(CodeIndex(ref code_idx)) => {
if &code_idx.borrow().1 != &module.module_decl.name {
continue;
}
self.remove_code_index((name.clone(), arity));
// remove or respecify ops.
if arity == 2 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::In));
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
Some(CodeIndex(ref code_idx)) => {
if &code_idx.borrow().1 != &module.module_decl.name {
continue;
}
}
} else if arity == 1 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::Pre));
}
}
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Post)
{
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::Post));
self.remove_code_index((name.clone(), arity));
// remove or respecify ops.
if arity == 2 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::In));
}
}
} else if arity == 1 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::Pre));
}
}
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Post)
{
if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::Post));
}
}
}
}
}
}
_ => {}
};
},
ModuleExport::OpDecl(op_decl) => {
let op_dir = self.op_dir();
op_dir.remove(&(op_decl.name(), op_decl.fixity()));
}
_ => {}
};
}
}
}
// returns true on successful import.
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
let name = name.defrock_brackets();
let mut found_op = false;
{
let mut insert_op_dir = |fix| {
if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) {
self.op_dir().insert((name.clone(), fix), op_data.clone());
found_op = true;
}
};
if arity == 1 {
insert_op_dir(Fixity::Pre);
insert_op_dir(Fixity::Post);
} else if arity == 2 {
insert_op_dir(Fixity::In);
}
}
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
let name = name.with_table(submodule.atom_tbl.clone());
@@ -163,7 +196,7 @@ pub trait SubModuleUser {
self.insert_dir_entry(name, arity, code_data.clone());
true
} else {
found_op || submodule.is_impromptu_module
submodule.is_impromptu_module
}
}
@@ -172,30 +205,58 @@ pub trait SubModuleUser {
_: &mut CodeRepo,
_: MachineFlags,
_: &Module,
_: &Vec<PredicateKey>,
_: &Vec<ModuleExport>,
) -> Result<(), SessionError>;
fn use_module(
&mut self,
_: &mut CodeRepo,
_: MachineFlags,
_: &Module
) -> Result<(), SessionError>;
fn use_module(&mut self, _: &mut CodeRepo, _: MachineFlags, _: &Module) -> Result<(), SessionError>;
}
pub fn use_qualified_module<User>(
user: &mut User,
submodule: &Module,
exports: &Vec<PredicateKey>,
exports: &Vec<ModuleExport>,
) -> Result<(), SessionError>
where
User: SubModuleUser,
{
for (name, arity) in exports.iter().cloned() {
if !submodule
.module_decl
.exports
.contains(&(name.clone(), arity))
{
continue;
}
for export in exports.iter().cloned() {
match export {
ModuleExport::PredicateKey((name, arity)) => {
if !submodule
.module_decl
.exports
.contains(&ModuleExport::PredicateKey((name.clone(), arity)))
{
continue;
}
if !user.import_decl(name, arity, submodule) {
return Err(SessionError::ModuleDoesNotContainExport);
if !user.import_decl(name, arity, submodule) {
return Err(SessionError::ModuleDoesNotContainExport);
}
},
ModuleExport::OpDecl(op_decl) => {
if !submodule
.module_decl
.exports
.contains(&ModuleExport::OpDecl(op_decl.clone()))
{
continue;
}
let op_dir = user.op_dir();
let prec = op_decl.0;
op_decl.insert_into_op_dir(
submodule.module_decl.name.clone(),
op_dir,
prec,
);
}
}
}
@@ -206,9 +267,23 @@ pub fn use_module<User: SubModuleUser>(
user: &mut User,
submodule: &Module,
) -> Result<(), SessionError> {
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
if !user.import_decl(name, arity, submodule) {
return Err(SessionError::ModuleDoesNotContainExport);
for export in submodule.module_decl.exports.iter().cloned() {
match export {
ModuleExport::PredicateKey((name, arity)) => {
if !user.import_decl(name, arity, submodule) {
return Err(SessionError::ModuleDoesNotContainExport);
}
}
ModuleExport::OpDecl(op_decl) => {
let op_dir = user.op_dir();
let prec = op_decl.0;
op_decl.insert_into_op_dir(
submodule.module_decl.name.clone(),
op_dir,
prec,
);
}
}
}
@@ -241,7 +316,7 @@ impl SubModuleUser for Module {
_: &mut CodeRepo,
_: MachineFlags,
submodule: &Module,
exports: &Vec<PredicateKey>,
exports: &Vec<ModuleExport>,
) -> Result<(), SessionError> {
use_qualified_module(self, submodule, exports)?;
@@ -283,7 +358,7 @@ impl SubModuleUser for Module {
self.user_goal_expansions
.1
.extend(submodule.goal_expansions.1.iter().cloned());
Ok(())
}
}

View File

@@ -1099,27 +1099,31 @@ impl MachineState {
_ => unreachable!(),
}
}
&SystemClauseType::DynamicModuleResolution => {
let module_name = self.store(self.deref(self[temp_v!(1)].clone()));
&SystemClauseType::DynamicModuleResolution(narity) => {
let module_name = self.store(self.deref(self[temp_v!(1 + narity)].clone()));
if let Addr::Con(Constant::Atom(module_name, _)) = module_name {
match self.store(self.deref(self[temp_v!(2)].clone())) {
match self.store(self.deref(self[temp_v!(2 + narity)].clone())) {
Addr::Str(a) => {
if let HeapCellValue::NamedStr(arity, name, _) = self.heap[a].clone() {
for i in 1..arity + 1 {
for i in (arity + 1 .. arity + narity + 1).rev() {
self.registers[i] = self.registers[i - arity].clone();
}
for i in 1 .. arity + 1 {
self.registers[i] = self.heap[a + i].as_addr(a + i);
}
return self.module_lookup(
indices,
(name, arity),
(name, arity + narity),
module_name,
true,
);
}
}
Addr::Con(Constant::Atom(name, _)) => {
return self.module_lookup(indices, (name, 0), module_name, true)
Addr::Con(Constant::Atom(name, _)) => {
return self.module_lookup(indices, (name, narity), module_name, true)
}
addr => {
let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
@@ -1309,11 +1313,7 @@ impl MachineState {
let result = {
let mut rand = RANDOM_STATE.borrow_mut();
if rand.bits(1) == 0 {
true
} else {
false
}
rand.bits(1) == 0
};
self.fail = result;
@@ -1689,6 +1689,9 @@ impl MachineState {
}
};
},
&SystemClauseType::ResetAttrVarState => {
self.attr_var_init.reset();
}
&SystemClauseType::RemoveCallPolicyCheck => {
let restore_default = match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
Some(call_policy) => {

View File

@@ -161,7 +161,7 @@ impl<'a, R: Read> TermStream<'a, R> {
pub fn col_num(&self) -> usize {
self.parser.col_num()
}
#[inline]
pub fn update_expansion_lens(&mut self) {
let te_key = (clause_name!("term_expansion"), 2);
@@ -257,7 +257,6 @@ impl<'a, R: Read> TermStream<'a, R> {
self.enqueue_term(term)?
}
None => {
let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?;
return Ok(term);
}
};
@@ -267,7 +266,7 @@ impl<'a, R: Read> TermStream<'a, R> {
let line_num = self.line_num();
let col_num = self.col_num();
let term = self.parser.read_term(composite_op!(
self.in_module,
&self.wam.indices.op_dir,
@@ -281,40 +280,6 @@ impl<'a, R: Read> TermStream<'a, R> {
}
}
pub(crate) fn run_goal_expanders(
&mut self,
machine_st: &mut MachineState,
op_dir: &OpDir,
term: Term,
) -> Result<Term, ParserError> {
match term {
Term::Clause(cell, name, mut terms, arity) => {
let mut new_terms = {
let old_terms = match (name.as_str(), terms.len()) {
(":-", 2) => {
let comma_term = *terms.pop().unwrap();
unfold_by_str(comma_term, ",")
}
("?-", 1) => unfold_by_str(*terms.pop().unwrap(), ","),
_ => return Ok(Term::Clause(cell, name, terms, arity)),
};
self.expand_goals(machine_st, op_dir, VecDeque::from(old_terms))?
};
let initial_term = new_terms.pop().unwrap();
terms.push(Box::new(fold_by_str(
new_terms.into_iter(),
initial_term,
clause_name!(","),
)));
Ok(Term::Clause(cell, name, terms, arity))
}
_ => Ok(term),
}
}
pub(super)
fn expand_goals(
&mut self,
@@ -324,7 +289,7 @@ impl<'a, R: Read> TermStream<'a, R> {
) -> Result<Vec<Term>, ParserError> {
let mut results = vec![];
while let Some(term) = terms.pop_front() {
while let Some(term) = terms.pop_front() {
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) {
Some(term_string) => {
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
@@ -374,6 +339,15 @@ impl MachineState {
output
}
// reset the machine, but keep the heap contents as they were.
// this prevents clashes between underscored variable names
// in the same query.
fn reset_with_heap_preservation(&mut self) {
let heap = self.heap.take();
self.reset();
self.heap = heap;
}
fn try_expand_term(
&mut self,
wam: &mut Machine,
@@ -382,14 +356,14 @@ impl MachineState {
) -> Option<String> {
let term_write_result = write_term_to_heap(term, self);
let h = self.heap.h;
self[temp_v!(1)] = Addr::HeapCell(term_write_result.heap_loc);
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self[temp_v!(2)] = Addr::HeapCell(h);
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
wam.code_repo.cached_query = code;
self.query_stepper(
&mut wam.indices,
&mut wam.policies,
@@ -398,7 +372,7 @@ impl MachineState {
);
if self.fail {
self.reset();
self.reset_with_heap_preservation();
None
} else {
let TermWriteResult { var_dict, .. } = term_write_result;
@@ -406,7 +380,7 @@ impl MachineState {
self.heap_locs = var_dict;
let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
self.reset();
self.reset_with_heap_preservation();
Some(output.result())
}
}

View File

@@ -81,11 +81,11 @@ impl<'a, 'b, 'c, R: Read> CompositeIndices<'a, 'b, 'c, R> {
};
if let Some(idx) = idx_opt {
self.local_code_dir().insert((name, arity), idx.clone());
self.local_code_dir().insert((name.clone(), arity), idx.clone());
idx
} else {
let idx = CodeIndex::default();
self.local_code_dir().insert((name, arity), idx.clone());
self.local_code_dir().insert((name.clone(), arity), idx.clone());
idx
}
}
@@ -196,13 +196,13 @@ fn setup_op_decl(
to_op_decl(prec, spec.as_str(), name)
}
fn setup_predicate_indicator(mut term: Term) -> Result<PredicateKey, ParserError> {
fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, ParserError> {
match term {
Term::Clause(_, ref name, ref mut terms, Some(_))
if name.as_str() == "/" && terms.len() == 2 =>
{
let arity = *terms.pop().unwrap();
let name = *terms.pop().unwrap();
let name = *terms.pop().unwrap();
let arity = arity
.to_constant()
@@ -210,7 +210,7 @@ fn setup_predicate_indicator(mut term: Term) -> Result<PredicateKey, ParserError
.and_then(|n| n.to_usize())
.ok_or(ParserError::InvalidModuleExport)?;
let name = name
let name = name
.to_constant()
.and_then(|c| c.to_atom())
.ok_or(ParserError::InvalidModuleExport)?;
@@ -221,7 +221,32 @@ fn setup_predicate_indicator(mut term: Term) -> Result<PredicateKey, ParserError
}
}
fn setup_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleDecl, ParserError> {
fn setup_module_export(
mut term: Term,
atom_tbl: TabledData<Atom>,
) -> Result<ModuleExport, ParserError> {
setup_predicate_indicator(&mut term)
.map(ModuleExport::PredicateKey)
.or_else(|_| {
if let Term::Clause(_, name, terms, _) = term {
if terms.len() == 3 && name.as_str() == "op" {
Ok(ModuleExport::OpDecl(setup_op_decl(
terms,
atom_tbl
)?))
} else {
Err(ParserError::InvalidModuleDecl)
}
} else {
Err(ParserError::InvalidModuleDecl)
}
})
}
fn setup_module_decl(
mut terms: Vec<Box<Term>>,
atom_tbl: TabledData<Atom>,
) -> Result<ModuleDecl, ParserError> {
let mut export_list = *terms.pop().unwrap();
let name = terms
.pop()
@@ -230,10 +255,12 @@ fn setup_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleDecl, ParserErro
.and_then(|c| c.to_atom())
.ok_or(ParserError::InvalidModuleDecl)?;
let mut exports = Vec::new();
let mut exports = vec![];
while let Term::Cons(_, t1, t2) = export_list {
exports.push(setup_predicate_indicator(*t1)?);
let module_export = setup_module_export(*t1, atom_tbl.clone())?;
exports.push(module_export);
export_list = *t2;
}
@@ -257,14 +284,18 @@ fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, Pars
.map(|c| ModuleSource::Library(c))
.ok_or(ParserError::InvalidUseModuleDecl)
}
Term::Constant(_, Constant::Atom(ref name, _)) => Ok(ModuleSource::File(name.clone())),
Term::Constant(_, Constant::Atom(ref name, _)) =>
Ok(ModuleSource::File(name.clone())),
_ => Err(ParserError::InvalidUseModuleDecl),
}
}
type UseModuleExport = (ModuleSource, Vec<PredicateKey>);
type UseModuleExport = (ModuleSource, Vec<ModuleExport>);
fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport, ParserError> {
fn setup_qualified_import(
mut terms: Vec<Box<Term>>,
atom_tbl: TabledData<Atom>,
) -> Result<UseModuleExport, ParserError> {
let mut export_list = *terms.pop().unwrap();
let module_src = match *terms.pop().unwrap() {
Term::Clause(_, ref name, ref mut terms, None)
@@ -282,10 +313,10 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
_ => Err(ParserError::InvalidUseModuleDecl),
}?;
let mut exports = Vec::new();
let mut exports = vec![];
while let Term::Cons(_, t1, t2) = export_list {
exports.push(setup_predicate_indicator(*t1)?);
exports.push(setup_module_export(*t1, atom_tbl.clone())?);
export_list = *t2;
}
@@ -296,9 +327,14 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
}
}
fn is_consistent(tl: &TopLevel, clauses: &Vec<PredicateClause>) -> bool {
fn is_consistent(
name: Option<ClauseName>,
arity: usize,
clauses: &Vec<PredicateClause>,
) -> bool
{
match clauses.first() {
Some(ref cl) => tl.name() == cl.name() && tl.arity() == cl.arity(),
Some(ref cl) => name == cl.name() && arity == cl.arity(),
None => true,
}
}
@@ -311,18 +347,18 @@ fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError>
TopLevel::Query(_) if clauses.is_empty() && tls.is_empty() => return Ok(tl),
TopLevel::Declaration(_) if clauses.is_empty() => return Ok(tl),
TopLevel::Query(_) => return Err(ParserError::InconsistentEntry),
TopLevel::Fact(..) if is_consistent(&tl, &clauses) =>
TopLevel::Fact(..) if is_consistent(tl.name(), tl.arity(), &clauses) =>
if let TopLevel::Fact(fact, line_num, col_num) = tl {
let clause = PredicateClause::Fact(fact, line_num, col_num);
clauses.push(clause);
},
TopLevel::Rule(..) if is_consistent(&tl, &clauses) => {
TopLevel::Rule(..) if is_consistent(tl.name(), tl.arity(), &clauses) => {
if let TopLevel::Rule(rule, line_num, col_num) = tl {
let clause = PredicateClause::Rule(rule, line_num, col_num);
clauses.push(clause);
}
}
TopLevel::Predicate(_) if is_consistent(&tl, &clauses) => {
TopLevel::Predicate(_) if is_consistent(tl.name(), tl.arity(), &clauses) => {
if let TopLevel::Predicate(pred) = tl {
clauses.extend(pred.clauses().into_iter())
}
@@ -460,19 +496,19 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
("op", 3) =>
Ok(Declaration::Op(setup_op_decl(terms, indices.atom_tbl())?)),
("module", 2) =>
Ok(Declaration::Module(setup_module_decl(terms)?)),
Ok(Declaration::Module(setup_module_decl(terms, indices.atom_tbl())?)),
("use_module", 1) =>
Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
("use_module", 2) => {
let (name, exports) = setup_qualified_import(terms)?;
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
("non_counted_backtracking", 1) => {
let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
Ok(Declaration::NonCountedBacktracking(name, arity))
}
("dynamic", 1) => {
let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
let (name, arity) = setup_predicate_indicator(&mut *terms.pop().unwrap())?;
Ok(Declaration::Dynamic(name, arity))
}
("initialization", 1) => {
@@ -563,7 +599,7 @@ impl RelationWorker {
fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque<Term>) {
let vars = self.compute_head(&body_term);
let clauses: Vec<_> = unfold_by_str(body_term, ";")
let results = unfold_by_str(body_term, ";")
.into_iter()
.map(|term| {
let mut subterms = unfold_by_str(term, ",");
@@ -572,13 +608,10 @@ impl RelationWorker {
check_for_internal_if_then(&mut subterms);
let term = subterms.pop().unwrap();
fold_by_str(subterms.into_iter(), term, clause_name!(","))
})
.collect();
let clause = fold_by_str(subterms.into_iter(), term, clause_name!(","));
let results = clauses
.into_iter()
.map(|clause| self.fabricate_rule_body(&vars, clause))
self.fabricate_rule_body(&vars, clause)
})
.collect();
(vars, results)
@@ -723,11 +756,11 @@ impl RelationWorker {
if name.as_str() == "," {
let term = Term::Clause(cell, name, terms, op_spec);
let mut subterms = unfold_by_str(term, ",");
while let Some(subterm) = subterms.pop() {
work_queue.push_front(Box::new(subterm));
}
continue;
} else {
term = Term::Clause(cell, name, terms, op_spec);
@@ -741,7 +774,7 @@ impl RelationWorker {
query_terms.push(self.pre_query_term(indices, term)?);
}
}
Ok(query_terms)
}
@@ -946,14 +979,14 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
&mut self,
indices: &mut IndexStore,
preds: &mut Vec<PredicateClause>,
) -> Result<(), SessionError> {
) -> Result<(), SessionError> {
let mut indices = CompositeIndices::new(
&mut self.term_stream,
IndexSource::Local(indices),
if self.in_module { None } else { Some(IndexSource::TermStream) }
);
let queue = self.rel_worker.parse_queue(&mut indices)?;
let queue = self.rel_worker.parse_queue(&mut indices)?;
let result = (append_preds(preds), queue);
let in_situ_code_dir = &mut indices.term_stream.wam.indices.in_situ_code_dir;
@@ -992,17 +1025,18 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
while !self.term_stream.eof()? {
let term = self.term_stream.read_term(&indices.op_dir)?;
// if is_consistent is false, preds is non-empty.
if !is_consistent(term.predicate_name(), term.predicate_arity(), &preds) {
self.process_result(indices, &mut preds)?;
self.take_dynamic_clauses();
}
let (mut tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
if tl.is_end_of_file_atom() {
tl = TopLevel::Declaration(Declaration::EndOfFile);
}
// if is_consistent is false, preds is non-empty.
if !is_consistent(&tl, &preds) {
self.process_result(indices, &mut preds)?;
self.take_dynamic_clauses();
}
}
self.rel_worker.absorb(new_rel_worker);

View File

@@ -1,8 +1,11 @@
extern crate dirs;
extern crate ordered_float;
extern crate prolog_parser;
#[cfg(feature = "rug")]
extern crate rug;
extern crate rustyline;
#[cfg(feature = "num-rug-adapter")]
extern crate num_rug_adapter as rug;
extern crate rustyline;
#[macro_use]
mod macros;

View File

@@ -1,8 +1,8 @@
:- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2]).
:- use_module(library(lists)).
:- use_module(library(si)).
:- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2]).
'$repl'(ListOfModules) :-
maplist('$use_list_of_modules', ListOfModules),
false.
@@ -29,8 +29,10 @@
catch('$$compile_batch', E, '$print_exception_with_check'(E))
; consult(Item)
)
; catch(throw(error(type_error(atom, Item), repl/0)),
'$print_exception_with_check'(E))
; !,
catch(throw(error(type_error(atom, Item), repl/0)),
E,
'$print_exception_with_check'(E))
).
'$instruction_match'(Term, VarList) :-
'$submit_query_and_print_results'(Term, VarList),
@@ -42,13 +44,49 @@
),
( '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList), !
; write('false.'), nl
),
'$reset_attr_var_state'.
'$needs_bracketing'(Value, Op) :-
catch((functor(Value, F, _),
current_op(EqPrec, EqSpec, Op),
current_op(FPrec, _, F)),
_,
false),
( EqPrec < FPrec -> true
; EqPrec == FPrec,
memberchk(EqSpec, [fx,xfx,yfx])
).
'$write_goal'(G, VarList) :-
( G = (Var = Value) ->
write(Var),
write(' = '),
write_term(Value, [quoted(true), variable_names(VarList)])
( '$needs_bracketing'(Value, (=)) ->
write('('),
write_term(Value, [quoted(true), variable_names(VarList)]),
write(')')
; write_term(Value, [quoted(true), variable_names(VarList)])
)
; G == [] ->
write('true')
; write_term(G, [quoted(true), variable_names(VarList)])
).
'$write_last_goal'(G, VarList) :-
( G = (Var = Value) ->
write(Var),
write(' = '),
( '$needs_bracketing'(Value, (=)) ->
write('('),
write_term(Value, [quoted(true), variable_names(VarList)]),
write(')')
; write_term(Value, [quoted(true), variable_names(VarList)]),
( '$trailing_period_is_ambiguous'(Value) ->
write(' ')
; true
)
)
; G == [] ->
write('true')
; write_term(G, [quoted(true), variable_names(VarList)])
@@ -60,7 +98,21 @@
write(', '),
'$write_eq'(G2, VarList).
'$write_eq'(G, VarList) :-
'$write_goal'(G, VarList).
'$write_last_goal'(G, VarList).
'$graphic_token_char'(C) :-
memberchk(C, ['#', '$', '&', '*', '+', '-', '.', ('/'), ':',
'<', '=', '>', '?', '@', '^', '~', ('\\')]).
'$list_last_item'([C], C) :- !.
'$list_last_item'([_|Cs], D) :-
'$list_last_item'(Cs, D).
'$trailing_period_is_ambiguous'(Value) :-
atom(Value),
atom_chars(Value, ValueChars),
'$list_last_item'(ValueChars, Char),
'$graphic_token_char'(Char).
'$write_eqs_and_read_input'(B, VarList) :-
sort(VarList, SortedVarList),
@@ -71,11 +123,10 @@
write('true.'), nl
; thread_goals(Goals, ThreadedGoals, (',')),
'$write_eq'(ThreadedGoals, VarList),
write(' .'),
write('.'),
nl
)
; repeat,
thread_goals(Goals, ThreadedGoals, (',')),
; thread_goals(Goals, ThreadedGoals, (',')),
'$write_eq'(ThreadedGoals, VarList),
'$raw_input_read_char'(C),
( C == (';'), !,
@@ -117,7 +168,7 @@
; '$print_exception'(E)
).
'$predicate_indicator'(Source, PI) :-
'$module_export'(Source, PI) :-
( nonvar(PI) ->
( PI = Name / Arity ->
( var(Name) -> throw(error(instantiation_error, Source))
@@ -128,7 +179,20 @@
)
; throw(error(type_error(integer, Arity), Source))
)
; throw(error(type_error(predicate_indicator, PI), Source))
; PI = op(Prec, Spec, Name) ->
( integer(Prec) ->
( \+ atom(Name) ->
throw(error(type_error(atom, Name), Source))
; Prec < 0 ->
throw(error(domain_error(not_less_than_zero, Prec), Source))
; Prec > 1200 ->
throw(error(domain_error(operator_precision, Prec), Source))
; memberchk(Spec, [xfy, yfx, xfx, fx, fy, yf, xf])
; throw(error(domain_error(operator_specification, Spec), Source))
)
; throw(error(type_error(integer, Prec), Source))
)
; throw(error(type_error(module_export, PI), Source))
)
; throw(error(instantiation_error, Source))
).
@@ -150,9 +214,11 @@ use_module(Module) :-
use_module(Module, QualifiedExports) :-
( nonvar(Module) ->
( list_si(QualifiedExports) ->
maplist('$predicate_indicator'(use_module/2), QualifiedExports), !,
( Module = library(Filename) -> '$use_qualified_module'(Filename, QualifiedExports)
; atom(Module) -> '$use_qualified_module_from_file'(Module, QualifiedExports)
maplist('$module_export'(use_module/2), QualifiedExports) ->
( Module = library(Filename) ->
'$use_qualified_module'(Filename, QualifiedExports)
; atom(Module) ->
'$use_qualified_module_from_file'(Module, QualifiedExports)
; throw(error(invalid_module_specifier, use_module/2))
)
; throw(error(type_error(list, QualifiedExports), use_module/2))