This commit is contained in:
Mark Thom
2019-11-16 19:53:29 -04:00
25 changed files with 448 additions and 4190 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "scryer-prolog" name = "scryer-prolog"
version = "0.8.115" version = "0.8.116"
authors = ["Mark Thom <markjordanthom@gmail.com>"] authors = ["Mark Thom <markjordanthom@gmail.com>"]
build = "build.rs" build = "build.rs"
repository = "https://github.com/mthom/scryer-prolog" repository = "https://github.com/mthom/scryer-prolog"

View File

@@ -162,8 +162,7 @@ pub enum SystemClauseType {
AtomChars, AtomChars,
AtomCodes, AtomCodes,
AtomLength, AtomLength,
ModuleAssertDynamicPredicateToFront, CallAttributeGoals,
ModuleAssertDynamicPredicateToBack,
CharCode, CharCode,
CharsToNumber, CharsToNumber,
CodesToNumber, CodesToNumber,
@@ -176,6 +175,7 @@ pub enum SystemClauseType {
EnqueueAttributedVar, EnqueueAttributedVar,
ExpandGoal, ExpandGoal,
ExpandTerm, ExpandTerm,
FetchAttributeGoals,
FetchGlobalVar, FetchGlobalVar,
FetchGlobalVarWithOffset, FetchGlobalVarWithOffset,
GetChar, GetChar,
@@ -200,6 +200,8 @@ pub enum SystemClauseType {
InstallSCCCleaner, InstallSCCCleaner,
InstallInferenceCounter, InstallInferenceCounter,
LiftedHeapLength, LiftedHeapLength,
ModuleAssertDynamicPredicateToFront,
ModuleAssertDynamicPredicateToBack,
ModuleOf, ModuleOf,
ModuleRetractClause, ModuleRetractClause,
NoSuchPredicate, NoSuchPredicate,
@@ -229,8 +231,8 @@ pub enum SystemClauseType {
GetDoubleQuotes, GetDoubleQuotes,
InstallNewBlock, InstallNewBlock,
Maybe, Maybe,
RawInputReadChar,
ResetBlock, ResetBlock,
ReturnFromAttributeGoals,
ReturnFromVerifyAttr, ReturnFromVerifyAttr,
SetBall, SetBall,
SetCutPointByDefault(RegType), SetCutPointByDefault(RegType),
@@ -257,20 +259,12 @@ impl SystemClauseType {
&SystemClauseType::AtomChars => clause_name!("$atom_chars"), &SystemClauseType::AtomChars => clause_name!("$atom_chars"),
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"), &SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
&SystemClauseType::AtomLength => clause_name!("$atom_length"), &SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::ModuleAssertDynamicPredicateToFront => { &SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
clause_name!("$module_asserta")
}
&SystemClauseType::ModuleAssertDynamicPredicateToBack => {
clause_name!("$module_assertz")
}
&SystemClauseType::CharCode => clause_name!("$char_code"), &SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"), &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
&SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"), &SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"), &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
&SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults) => {
clause_name!("$submit_query_and_print_results")
}
&SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"), &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => { &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
clause_name!("$use_qualified_module") clause_name!("$use_qualified_module")
@@ -289,6 +283,7 @@ impl SystemClauseType {
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"), &SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"), &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"), &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::FetchAttributeGoals => clause_name!("$fetch_attribute_goals"),
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"), &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
&SystemClauseType::FetchGlobalVarWithOffset => { &SystemClauseType::FetchGlobalVarWithOffset => {
clause_name!("$fetch_global_var_with_offset") clause_name!("$fetch_global_var_with_offset")
@@ -327,11 +322,18 @@ impl SystemClauseType {
} }
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"), &SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
&SystemClauseType::Maybe => clause_name!("maybe"), &SystemClauseType::Maybe => clause_name!("maybe"),
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
clause_name!("$module_asserta")
}
&SystemClauseType::ModuleAssertDynamicPredicateToBack => {
clause_name!("$module_assertz")
}
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"), &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleOf => clause_name!("$module_of"), &SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"), &SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
&SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"), &SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"),
&SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"),
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"), &SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"), &SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
@@ -357,9 +359,6 @@ impl SystemClauseType {
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"), &SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
&SystemClauseType::RetractClause => clause_name!("$retract_clause"), &SystemClauseType::RetractClause => clause_name!("$retract_clause"),
&SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetBlock => clause_name!("$reset_block"),
&SystemClauseType::ReturnFromAttributeGoals => {
clause_name!("$return_from_attribute_goals")
}
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
&SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SetBall => clause_name!("$set_ball"),
&SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"), &SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"),
@@ -387,6 +386,7 @@ impl SystemClauseType {
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack), ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront), ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack), ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
("$char_code", 2) => Some(SystemClauseType::CharCode), ("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber), ("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber), ("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber),
@@ -404,6 +404,7 @@ impl SystemClauseType {
("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar), ("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm), ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$fetch_attribute_goals", 1) => Some(SystemClauseType::FetchAttributeGoals),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset), ("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar), ("$get_char", 1) => Some(SystemClauseType::GetChar),
@@ -449,13 +450,13 @@ impl SystemClauseType {
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm), ("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
("$read_term", 2) => Some(SystemClauseType::ReadTerm), ("$read_term", 2) => Some(SystemClauseType::ReadTerm),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey), ("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset), ("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
("$retract_clause", 4) => Some(SystemClauseType::RetractClause), ("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
("$return_from_attribute_goals", 0) => Some(SystemClauseType::ReturnFromAttributeGoals),
("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr), ("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$set_ball", 1) => Some(SystemClauseType::SetBall),
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
@@ -464,9 +465,6 @@ impl SystemClauseType {
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset), ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
("$submit_query_and_print_results", 2) => Some(SystemClauseType::REPL(
REPLCodePtr::SubmitQueryAndPrintResults,
)),
("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),

View File

@@ -625,6 +625,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
iter.stack().last().cloned().and_then(|addr| { iter.stack().last().cloned().and_then(|addr| {
let addr = self.machine_st.store(self.machine_st.deref(addr)); let addr = self.machine_st.store(self.machine_st.deref(addr));
if let Some(var) = self.var_names.get(&addr) {
self.heap_locs.insert(addr.clone(), Rc::new(var.clone()));
}
match self.heap_locs.get(&addr).cloned() { match self.heap_locs.get(&addr).cloned() {
Some(var) => { Some(var) => {
if !self.printed_vars.contains(&addr) { if !self.printed_vars.contains(&addr) {

View File

@@ -364,14 +364,6 @@ pub enum ControlInstruction {
} }
impl ControlInstruction { impl ControlInstruction {
pub fn is_jump_instr(&self) -> bool {
match self {
&ControlInstruction::CallClause(..) => true,
&ControlInstruction::JmpBy(..) => true,
_ => false,
}
}
pub fn to_functor(&self) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&ControlInstruction::Allocate(num_frames) => { &ControlInstruction::Allocate(num_frames) => {

View File

@@ -150,7 +150,8 @@ comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)).
','(!, Atom, B) :- Atom == !, '$set_cp'(B). ','(!, Atom, B) :- Atom == !, '$set_cp'(B).
','(!, G, B) :- '$set_cp'(B), G. ','(!, G, B) :- '$set_cp'(B), G.
','(G, CF, B) :- compound(CF), ','(G, CF, B) :- compound(CF),
'$call_with_default_policy'(CF = ','(G1, G2)), !, G, '$call_with_default_policy'(CF = ','(G1, G2)),
!, G,
'$call_with_default_policy'(comma_errors(G1, G2, B)). '$call_with_default_policy'(comma_errors(G1, G2, B)).
','(G, Atom, B) :- Atom == !, !, G, '$set_cp'(B). ','(G, Atom, B) :- Atom == !, !, G, '$set_cp'(B).
','(G1, G2, _) :- G1, G2. ','(G1, G2, _) :- G1, G2.
@@ -567,7 +568,7 @@ first_match_index([Clause0 | Clauses], Clause1, N0, N) :-
; N0 = N, Clause0 = Clause1 ; N0 = N, Clause0 = Clause1
). ).
retract_clauses([Clause|Clauses0], Head, Body, Name, Arity) :- retract_clauses([Clause | Clauses0], Head, Body, Name, Arity) :-
functor(VarHead, Name, Arity), functor(VarHead, Name, Arity),
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses1), findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses1),
first_match_index(Clauses1, (Head :- Body), 0, N), first_match_index(Clauses1, (Head :- Body), 0, N),
@@ -575,7 +576,7 @@ retract_clauses([Clause|Clauses0], Head, Body, Name, Arity) :-
; true ; true
), ),
'$retract_clause'(Name, Arity, N, Clauses1). '$retract_clause'(Name, Arity, N, Clauses1).
retract_clauses([_|Clauses0], Head, Body, Name, Arity) :- retract_clauses([_ | Clauses0], Head, Body, Name, Arity) :-
retract_clauses(Clauses0, Head, Body, Name, Arity). retract_clauses(Clauses0, Head, Body, Name, Arity).
call_retract(Head, Body, Name, Arity) :- call_retract(Head, Body, Name, Arity) :-

View File

@@ -1,7 +1,5 @@
use crate::prolog::machine::*; use crate::prolog::machine::*;
use indexmap::IndexSet;
use std::vec::IntoIter; use std::vec::IntoIter;
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl"); pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
@@ -101,35 +99,6 @@ impl MachineState {
attr_vars.into_iter() attr_vars.into_iter()
} }
fn populate_project_attr_lists(&mut self) -> (Addr, Addr) {
let mut query_vars = IndexSet::new();
let attr_vars = self.gather_attr_vars_created_since(0);
for (_, addr) in self.heap_locs.iter() {
let iter = self.acyclic_pre_order_iter(addr.clone());
for value in iter {
match value {
HeapCellValue::Addr(Addr::HeapCell(h)) => {
query_vars.insert(Addr::HeapCell(h));
}
HeapCellValue::Addr(Addr::StackCell(fr, sc)) => {
query_vars.insert(Addr::StackCell(fr, sc));
}
HeapCellValue::Addr(Addr::AttrVar(h)) => {
query_vars.insert(Addr::AttrVar(h));
}
_ => {}
};
}
}
let query_var_list = Addr::HeapCell(self.heap.to_list(query_vars.into_iter()));
let attr_var_list = Addr::HeapCell(self.heap.to_list(attr_vars));
(query_var_list, attr_var_list)
}
pub(super) fn verify_attr_interrupt(&mut self, p: usize) { pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
self.allocate(self.num_of_args + 2); self.allocate(self.num_of_args + 2);
@@ -149,57 +118,4 @@ impl MachineState {
self.b0 = self.b; self.b0 = self.b;
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
} }
fn print_attribute_goals_string(&mut self, op_dir: &OpDir) -> String {
let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
if attr_goals.is_empty() {
return String::from("");
}
attr_goals.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
self.term_dedup(&mut attr_goals);
let mut output = PrinterOutputter::new();
for goal_addr in attr_goals {
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.see_all_locs();
printer.numbervars = false;
printer.quoted = true;
output = printer.print(goal_addr);
output.append(", ");
}
// cut trailing ", "
let output_len = output.len();
output.truncate(output_len - 2);
output.result()
}
}
impl Machine {
pub fn attribute_goals(&mut self) -> String {
let p = self.machine_st.attr_var_init.project_attrs_loc;
let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists();
self.machine_st.allocate(0);
self.machine_st[temp_v!(1)] = query_vars;
self.machine_st[temp_v!(2)] = attr_vars;
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
self.machine_st.query_stepper(
&mut self.indices,
&mut self.policies,
&mut self.code_repo,
&mut readline::input_stream(),
);
self.machine_st
.print_attribute_goals_string(&self.indices.op_dir)
}
} }

View File

@@ -243,40 +243,6 @@ fn compile_query(
Ok((code, cg.take_vars())) Ok((code, cg.take_vars()))
} }
fn compile_decl(
wam: &mut Machine,
compiler: &mut ListingCompiler,
decl: Declaration,
) -> Result<IndexStore, SessionError> {
let flags = wam.machine_flags();
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
compiler.process_decl(decl, wam, &mut indices, flags)?;
Ok(indices)
}
pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession {
match packet {
TopLevelPacket::Query(terms, queue) => {
match compile_query(terms, queue, wam.machine_flags()) {
Ok((code, vars)) => wam.submit_query(code, vars),
Err(e) => EvalSession::from(e),
}
}
TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
let mut compiler = ListingCompiler::new(&wam.code_repo, false, clause_name!("user"));
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
try_eval_session!(wam.check_toplevel_code(&indices));
add_toplevel_code(wam, vec![], indices);
EvalSession::EntrySuccess
}
_ => EvalSession::from(SessionError::UserPrompt),
}
}
fn add_hooks_to_mockup( fn add_hooks_to_mockup(
code_repo: &mut CodeRepo, code_repo: &mut CodeRepo,
hook: CompileTimeHook, hook: CompileTimeHook,

View File

@@ -76,16 +76,27 @@ impl Machine {
output.result() output.result()
} }
fn make_undefined(&mut self, name: ClauseName, arity: usize) {
if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
}
}
fn make_undefined_in_module(&mut self, module_name: ClauseName, name: ClauseName, arity: usize) {
if let Some(idx) = self.indices.code_dir.get(&(name, arity)) {
if idx.module_name() == module_name {
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
}
}
}
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) { fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
let (name, arity) = self.get_predicate_key(name, arity); let (name, arity) = self.get_predicate_key(name, arity);
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { self.make_undefined(name.clone(), arity);
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
}
self.indices.remove_code_index((name.clone(), arity)); self.indices.remove_code_index((name.clone(), arity));
self.indices self.indices.remove_clause_subsection(name.owning_module(), name, arity);
.remove_clause_subsection(name.owning_module(), name, arity);
} }
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) { fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) {
@@ -106,15 +117,10 @@ impl Machine {
_ => unreachable!(), _ => unreachable!(),
}; };
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { self.make_undefined_in_module(module_name.clone(), name.clone(), arity);
if idx.module_name() == module_name {
set_code_index!(idx, IndexPtr::DynamicUndefined, clause_name!("user"));
}
}
self.indices.remove_code_index((name.clone(), arity)); self.indices.remove_code_index((name.clone(), arity));
self.indices self.indices.remove_clause_subsection(module_name, name, arity);
.remove_clause_subsection(module_name, name, arity);
} }
fn handle_eval_result_from_dynamic_compile( fn handle_eval_result_from_dynamic_compile(
@@ -210,6 +216,10 @@ impl Machine {
let mut addrs = VecDeque::from(addrs); let mut addrs = VecDeque::from(addrs);
addrs.remove(index); addrs.remove(index);
if addrs.is_empty() {
self.make_undefined(name.clone(), arity);
}
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
} }
Err(err) => return self.machine_st.throw_exception(err), Err(err) => return self.machine_st.throw_exception(err),
@@ -239,6 +249,10 @@ impl Machine {
let mut addrs = VecDeque::from(addrs); let mut addrs = VecDeque::from(addrs);
addrs.remove(index); addrs.remove(index);
if addrs.is_empty() {
self.make_undefined(name.clone(), arity);
}
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
} }
Err(err) => return self.machine_st.throw_exception(err), Err(err) => return self.machine_st.throw_exception(err),

View File

@@ -537,15 +537,11 @@ pub enum SessionError {
NamelessEntry, NamelessEntry,
OpIsInfixAndPostFix(ClauseName), OpIsInfixAndPostFix(ClauseName),
ParserError(ParserError), ParserError(ParserError),
UserPrompt,
} }
pub enum EvalSession { pub enum EvalSession {
EntrySuccess, EntrySuccess,
Error(SessionError), Error(SessionError),
InitialQuerySuccess(AllocVarDict),
QueryFailure,
SubsequentQuerySuccess,
} }
impl From<SessionError> for EvalSession { impl From<SessionError> for EvalSession {

View File

@@ -300,7 +300,6 @@ pub enum DynamicTransactionType {
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr { pub enum REPLCodePtr {
CompileBatch, CompileBatch,
SubmitQueryAndPrintResults,
UseModule, UseModule,
UseQualifiedModule, UseQualifiedModule,
UseModuleFromFile, UseModuleFromFile,
@@ -469,12 +468,6 @@ pub struct IndexStore {
} }
impl IndexStore { impl IndexStore {
pub fn reset_global_variable_offsets(&mut self) {
for (_, ref mut offset) in self.global_variables.values_mut() {
*offset = None;
}
}
pub fn predicate_exists( pub fn predicate_exists(
&self, &self,
name: ClauseName, name: ClauseName,

View File

@@ -316,7 +316,7 @@ impl MachineState {
Ok(codes) Ok(codes)
} }
fn call_at_index(&mut self, arity: usize, p: usize) { pub(super) fn call_at_index(&mut self, arity: usize, p: usize) {
self.cp.assign_if_local(self.p.clone() + 1); self.cp.assign_if_local(self.p.clone() + 1);
self.num_of_args = arity; self.num_of_args = arity;
self.b0 = self.b; self.b0 = self.b;

View File

@@ -6,7 +6,6 @@ use crate::prolog::arithmetic::*;
use crate::prolog::clause_types::*; use crate::prolog::clause_types::*;
use crate::prolog::forms::*; use crate::prolog::forms::*;
use crate::prolog::heap_iter::*; use crate::prolog::heap_iter::*;
use crate::prolog::heap_print::*;
use crate::prolog::instructions::*; use crate::prolog::instructions::*;
use crate::prolog::machine::INTERRUPT; use crate::prolog::machine::INTERRUPT;
use crate::prolog::machine::attributed_variables::*; use crate::prolog::machine::attributed_variables::*;
@@ -26,7 +25,6 @@ use indexmap::{IndexMap, IndexSet};
use std::cmp::{max, min, Ordering}; use std::cmp::{max, min, Ordering};
use std::f64; use std::f64;
use std::mem; use std::mem;
use std::rc::Rc;
macro_rules! try_numeric_result { macro_rules! try_numeric_result {
($s: ident, $e: expr, $caller: expr) => {{ ($s: ident, $e: expr, $caller: expr) => {{
@@ -190,39 +188,6 @@ impl MachineState {
} }
} }
pub(super) fn print_var_eq<Outputter>(
&self,
var: Rc<Var>,
addr: Addr,
op_dir: &OpDir,
mut output: Outputter,
) -> Outputter
where
Outputter: HCValueOutputter,
{
let orig_len = output.len();
output.begin_new_var();
output.append(var.as_str());
output.append(" = ");
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.numbervars = false;
printer.quoted = true;
let mut output = printer.print(addr);
let bad_ending = format!("= {}", &var);
if output.ends_with(&bad_ending) {
output.truncate(orig_len);
}
output
}
pub(super) fn unify_strings( pub(super) fn unify_strings(
&mut self, &mut self,
pdl: &mut Vec<Addr>, pdl: &mut Vec<Addr>,

View File

@@ -2,13 +2,11 @@ use prolog_parser::ast::*;
use prolog_parser::tabled_rc::*; use prolog_parser::tabled_rc::*;
use crate::prolog::clause_types::*; use crate::prolog::clause_types::*;
use crate::prolog::fixtures::*;
use crate::prolog::forms::*; use crate::prolog::forms::*;
use crate::prolog::heap_print::*; use crate::prolog::heap_print::*;
use crate::prolog::instructions::*; use crate::prolog::instructions::*;
use crate::prolog::machine::heap::Heap; use crate::prolog::machine::heap::Heap;
use crate::prolog::read::*; use crate::prolog::read::*;
use crate::prolog::write::{next_keypress, ContinueResult};
mod attributed_variables; mod attributed_variables;
pub(super) mod code_repo; pub(super) mod code_repo;
@@ -35,21 +33,18 @@ use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*; use crate::prolog::machine::machine_state::*;
use crate::prolog::machine::modules::*; use crate::prolog::machine::modules::*;
use crate::prolog::machine::toplevel::stream_to_toplevel;
use crate::prolog::read::PrologStream; use crate::prolog::read::PrologStream;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::io::{stdout, Read, Write}; use std::io::Read;
use std::mem; use std::mem;
use std::ops::Index; use std::ops::Index;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use termion::raw::IntoRawMode;
pub struct MachinePolicies { pub struct MachinePolicies {
call_policy: Box<dyn CallPolicy>, call_policy: Box<dyn CallPolicy>,
cut_policy: Box<dyn CutPolicy>, cut_policy: Box<dyn CutPolicy>,
@@ -197,10 +192,23 @@ impl Machine {
} }
} }
fn compile_top_level(&mut self) { fn compile_top_level(&mut self) -> Result<(), SessionError>
{
self.toplevel_idx = self.code_repo.code.len(); self.toplevel_idx = self.code_repo.code.len();
compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()), compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()),
true, clause_name!("toplevel.pl")); true, clause_name!("toplevel.pl"));
if let Some(module) = self.indices.take_module(clause_name!("$toplevel")) {
self.indices.use_module(
&mut self.code_repo,
self.machine_st.flags,
&module,
)?;
Ok(self.indices.insert_module(module))
} else {
Err(SessionError::ModuleNotFound)
}
} }
fn compile_scryerrc(&mut self) { fn compile_scryerrc(&mut self) {
@@ -234,7 +242,7 @@ impl Machine {
self.machine_st.reset(); self.machine_st.reset();
self.code_repo.cached_query = code; self.code_repo.cached_query = code;
self.run_query(&AllocVarDict::new()); self.run_query();
let result = self.machine_st.fail; let result = self.machine_st.fail;
self.absorb_snapshot(old_machine_st); self.absorb_snapshot(old_machine_st);
@@ -260,7 +268,7 @@ impl Machine {
self.machine_st[temp_v!(1)] = list_addr; self.machine_st[temp_v!(1)] = list_addr;
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx)); self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
self.run_query(&AllocVarDict::new()); self.run_query();
} }
pub fn new(prolog_stream: PrologStream) -> Self { pub fn new(prolog_stream: PrologStream) -> Self {
@@ -295,7 +303,10 @@ impl Machine {
compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true, compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true,
clause_name!("si")); clause_name!("si"));
wam.compile_top_level(); if wam.compile_top_level().is_err() {
panic!("Loading '$toplevel' module failed");
}
wam.compile_scryerrc(); wam.compile_scryerrc();
wam wam
@@ -377,17 +388,6 @@ impl Machine {
self.code_repo.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
} }
pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession {
self.code_repo.cached_query = code;
self.run_query(&alloc_locs);
if self.machine_st.fail {
EvalSession::QueryFailure
} else {
EvalSession::InitialQuerySuccess(alloc_locs)
}
}
fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) { fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
let h = self.machine_st.heap.h; let h = self.machine_st.heap.h;
@@ -536,62 +536,6 @@ impl Machine {
self.throw_session_error(e, (clause_name!("repl"), 0)); self.throw_session_error(e, (clause_name!("repl"), 0));
} }
} }
REPLCodePtr::SubmitQueryAndPrintResults => {
let term = self.machine_st[temp_v!(1)].clone();
let stub = MachineError::functor_stub(clause_name!("repl"), 0);
let s = match self.machine_st.try_from_list(temp_v!(2), stub) {
Ok(addrs) => {
let mut var_dict = HeapVarDict::new();
for addr in addrs {
match addr {
Addr::Str(s) => {
let var_atom = match self.machine_st.heap[s + 1].as_addr(s + 1)
{
Addr::Con(Constant::Atom(var_atom, _)) => {
Rc::new(var_atom.to_string())
}
_ => unreachable!(),
};
let var_addr = self.machine_st.heap[s + 2].as_addr(s + 2);
var_dict.insert(var_atom, var_addr);
}
_ => unreachable!(),
};
}
self.machine_st.heap_locs = var_dict;
let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
term_output.result()
}
Err(err_stub) => {
self.machine_st.throw_exception(err_stub);
return;
}
};
let stream = parsing_stream(s.as_bytes());
let snapshot = self.sink_to_snapshot();
let policies = mem::replace(&mut self.policies, MachinePolicies::new());
self.machine_st.reset();
self.machine_st.heap = mem::replace(
&mut self.inner_heap,
Heap::with_capacity(0),
);
let result = match stream_to_toplevel(stream, self) {
Ok(packet) => compile_term(self, packet),
Err(e) => EvalSession::from(e),
};
self.handle_eval_session(result, snapshot);
self.indices.reset_global_variable_offsets();
self.policies = policies;
}
REPLCodePtr::UseModule => REPLCodePtr::UseModule =>
self.use_module(ModuleSource::Library), self.use_module(ModuleSource::Library),
REPLCodePtr::UseModuleFromFile => REPLCodePtr::UseModuleFromFile =>
@@ -615,6 +559,12 @@ impl Machine {
snapshot.s = self.machine_st.s; snapshot.s = self.machine_st.s;
snapshot.tr = self.machine_st.tr; snapshot.tr = self.machine_st.tr;
snapshot.pstr_tr = self.machine_st.pstr_tr; snapshot.pstr_tr = self.machine_st.pstr_tr;
snapshot.p = self.machine_st.p.clone();
snapshot.cp = self.machine_st.cp;
snapshot.attr_var_init = mem::replace(
&mut self.machine_st.attr_var_init,
AttrVarInitializer::new(0, 0)
);
snapshot.num_of_args = self.machine_st.num_of_args; snapshot.num_of_args = self.machine_st.num_of_args;
snapshot.fail = self.machine_st.fail; snapshot.fail = self.machine_st.fail;
@@ -627,6 +577,7 @@ impl Machine {
snapshot.block = self.machine_st.block; snapshot.block = self.machine_st.block;
snapshot.ball = self.machine_st.ball.take(); snapshot.ball = self.machine_st.ball.take();
snapshot.heap_locs = mem::replace(&mut self.machine_st.heap_locs, IndexMap::new());
snapshot.lifted_heap = mem::replace(&mut self.machine_st.lifted_heap, vec![]); snapshot.lifted_heap = mem::replace(&mut self.machine_st.lifted_heap, vec![]);
snapshot snapshot
@@ -640,6 +591,9 @@ impl Machine {
self.machine_st.s = snapshot.s; self.machine_st.s = snapshot.s;
self.machine_st.tr = snapshot.tr; self.machine_st.tr = snapshot.tr;
self.machine_st.pstr_tr = snapshot.pstr_tr; self.machine_st.pstr_tr = snapshot.pstr_tr;
self.machine_st.p = snapshot.p;
self.machine_st.cp = snapshot.cp;
self.machine_st.attr_var_init = snapshot.attr_var_init;
self.machine_st.num_of_args = snapshot.num_of_args; self.machine_st.num_of_args = snapshot.num_of_args;
self.machine_st.fail = snapshot.fail; self.machine_st.fail = snapshot.fail;
@@ -656,160 +610,15 @@ impl Machine {
self.machine_st.block = snapshot.block; self.machine_st.block = snapshot.block;
self.machine_st.ball = snapshot.ball.take(); self.machine_st.ball = snapshot.ball.take();
self.machine_st.heap_locs = mem::replace(&mut snapshot.heap_locs, IndexMap::new());
self.machine_st.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]); self.machine_st.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]);
} }
fn propagate_exception_to_toplevel(&mut self, snapshot: MachineState) { pub(super) fn run_query(&mut self) {
let ball = self.machine_st.ball.take();
self.absorb_snapshot(snapshot);
self.machine_st.ball = ball;
let h = self.machine_st.heap.h;
let stub = self.machine_st.ball.copy_and_align(h);
self.machine_st.throw_exception(stub);
return;
}
fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) {
match result {
EvalSession::InitialQuerySuccess(alloc_locs) => loop {
let bindings = {
let output = PrinterOutputter::new();
self.toplevel_heap_view(output).result()
};
let attr_goals = self.attribute_goals();
if !(self.machine_st.b > 0) {
if bindings.is_empty() {
let space = if requires_space(&attr_goals, ".") {
" "
} else {
""
};
if !attr_goals.is_empty() {
println!("{}{}.", attr_goals, space);
} else {
println!("true.");
}
self.absorb_snapshot(snapshot);
return;
}
} else if bindings.is_empty() && attr_goals.is_empty() {
print!("true");
stdout().flush().unwrap();
}
if !attr_goals.is_empty() {
if bindings.is_empty() {
print!("{}", attr_goals);
} else {
print!("{}, {}", bindings, attr_goals);
}
} else if !bindings.is_empty() {
print!("{}", bindings);
}
if self.machine_st.b > 0 {
let keypress = {
let mut raw_stdout = stdout().into_raw_mode().unwrap();
raw_stdout.flush().unwrap();
next_keypress()
};
let result = match keypress {
ContinueResult::ContinueQuery => {
print!(" ;\n");
self.continue_query(&alloc_locs)
}
ContinueResult::Conclude => {
print!(" ...\n");
self.absorb_snapshot(snapshot);
return;
}
};
match result {
EvalSession::QueryFailure => {
if self.machine_st.ball.stub.len() > 0 {
self.propagate_exception_to_toplevel(snapshot);
return;
} else {
print!("false.\n");
self.absorb_snapshot(snapshot);
return;
}
}
EvalSession::Error(err) => {
self.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0));
return;
}
_ => {}
}
} else {
if bindings.is_empty() && attr_goals.is_empty() {
print!("true.\n");
} else {
let space = if !attr_goals.is_empty() {
if requires_space(&attr_goals, ".") {
" "
} else {
""
}
} else {
if requires_space(&bindings, ".") {
" "
} else {
""
}
};
print!("{}.\n", space);
}
break;
}
},
EvalSession::Error(err) => {
self.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0));
return;
}
EvalSession::QueryFailure =>
if self.machine_st.ball.stub.len() > 0 {
return self.propagate_exception_to_toplevel(snapshot);
} else {
println!("false.");
},
_ => println!("true.")
}
self.absorb_snapshot(snapshot);
}
pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) {
self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query()); self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
let end_ptr = CodePtr::Local(self.machine_st.cp); let end_ptr = CodePtr::Local(self.machine_st.cp);
while self.machine_st.p < end_ptr { while self.machine_st.p < end_ptr {
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.machine_st.p {
match &self.code_repo[LocalCodePtr::TopLevel(cn, p)] {
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
self.machine_st.record_var_places(cn, alloc_locs);
cn += 1;
}
_ => {}
}
self.machine_st.p = top_level_code_ptr!(cn, p);
}
self.machine_st.query_stepper( self.machine_st.query_stepper(
&mut self.indices, &mut self.indices,
&mut self.policies, &mut self.policies,
@@ -828,63 +637,18 @@ impl Machine {
self.dynamic_transaction(trans_type, p); self.dynamic_transaction(trans_type, p);
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p { if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
if self.machine_st.heap_locs.is_empty() {
self.machine_st.record_var_places(0, alloc_locs);
}
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
break; break;
} }
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
} }
_ => { _ =>
if self.machine_st.heap_locs.is_empty() { break
self.machine_st.record_var_places(0, alloc_locs);
}
break;
}
}; };
} }
} }
pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession {
if self.machine_st.b > 0 {
let b = self.machine_st.b;
self.machine_st.p = self.machine_st.stack.index_or_frame(b).prelude.bp.clone();
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
self.machine_st.fail = true;
return EvalSession::QueryFailure;
}
self.run_query(alloc_locs);
if self.machine_st.fail {
EvalSession::QueryFailure
} else {
EvalSession::SubsequentQuerySuccess
}
} else {
EvalSession::QueryFailure
}
}
pub fn toplevel_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where
Outputter: HCValueOutputter,
{
for (var, addr) in self.machine_st.heap_locs.iter() {
let addr = self.machine_st.store(self.machine_st.deref(addr.clone()));
output = self
.machine_st
.print_var_eq(var.clone(), addr, &self.indices.op_dir, output);
}
output
}
#[cfg(test)] #[cfg(test)]
pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where where
@@ -904,56 +668,6 @@ impl Machine {
} }
impl MachineState { impl MachineState {
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict) {
for (var, var_data) in alloc_locs {
match var_data {
&VarData::Perm(p) if p > 0 => {
if !self.heap_locs.contains_key(var) {
let e = self.e;
let r = var_data.as_reg_type().reg_num();
let addr = self.stack.index_and_frame(e)[r].clone();
self.heap_locs.insert(var.clone(), addr);
}
}
&VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type();
if r.reg_num() != 0 {
let addr = self[r].clone();
self.heap_locs.insert(var.clone(), addr);
}
}
_ => {}
}
}
}
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
let flags = self.flags;
let mut output = {
self.flags = MachineFlags {
double_quotes: DoubleQuotes::Atom,
};
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.quoted = true;
printer.numbervars = false;
printer.drop_toplevel_spec();
printer.see_all_locs();
printer.print(addr)
};
self.flags = flags;
output.append(".");
output
}
fn dispatch_instr( fn dispatch_instr(
&mut self, &mut self,
instr: &Line, instr: &Line,

View File

@@ -1,10 +1,9 @@
driver(QueryVars, AttrVars) :- '$attribute_goals_driver'(QueryVars, AttrVars) :-
gather_modules(AttrVars, Modules0, _), gather_modules(AttrVars, Modules0, _),
sort(Modules0, Modules), sort(Modules0, Modules),
call_project_attributes(Modules, QueryVars, AttrVars), call_project_attributes(Modules, QueryVars, AttrVars),
call_attribute_goals(Modules, call_query_var_goals, QueryVars), call_attribute_goals(Modules, call_query_var_goals, QueryVars),
call_attribute_goals(Modules, call_attr_var_goals, AttrVars), call_attribute_goals(Modules, call_attr_var_goals, AttrVars).
'$return_from_attribute_goals'.
enqueue_goals(Goals0) :- enqueue_goals(Goals0) :-
nonvar(Goals0), nonvar(Goals0),

View File

@@ -22,11 +22,34 @@ use crate::ref_thread_local::RefThreadLocal;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::{stdout, Write}; use std::io::{stdin, stdout, Write};
use std::iter::once; use std::iter::once;
use std::mem; use std::mem;
use std::rc::Rc; use std::rc::Rc;
use crate::termion::event::Key;
use crate::termion::input::TermRead;
use crate::termion::raw::IntoRawMode;
pub enum ContinueResult {
ContinueQuery,
Conclude,
}
pub fn next_keypress() -> ContinueResult {
let stdin = stdin();
for c in stdin.keys() {
match c.unwrap() {
Key::Char(' ') | Key::Char(';') => return ContinueResult::ContinueQuery,
Key::Char('.') => return ContinueResult::Conclude,
_ => {}
}
}
ContinueResult::Conclude
}
struct BrentAlgState { struct BrentAlgState {
hare: usize, hare: usize,
tortoise: usize, tortoise: usize,
@@ -716,6 +739,17 @@ impl MachineState {
self.unify(a2, Addr::Con(Constant::Integer(len))); self.unify(a2, Addr::Con(Constant::Integer(len)));
} }
&SystemClauseType::CallAttributeGoals => {
let p = self.attr_var_init.project_attrs_loc;
if self.last_call {
self.execute_at_index(2, p);
} else {
self.call_at_index(2, p);
}
return Ok(());
}
&SystemClauseType::CharsToNumber => { &SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2); let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
@@ -1329,6 +1363,17 @@ impl MachineState {
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => { &SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
self.truncate_if_no_lifted_heap_diff(|_| Addr::Con(Constant::EmptyList)) self.truncate_if_no_lifted_heap_diff(|_| Addr::Con(Constant::EmptyList))
} }
&SystemClauseType::FetchAttributeGoals => {
let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
attr_goals.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
self.term_dedup(&mut attr_goals);
let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter()));
let target = self[temp_v!(1)].clone();
self.unify(attr_goals, target);
}
&SystemClauseType::GetAttributedVariableList => { &SystemClauseType::GetAttributedVariableList => {
let attr_var = self.store(self.deref(self[temp_v!(1)].clone())); let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
let attr_var_list = match attr_var { let attr_var_list = match attr_var {
@@ -1370,6 +1415,18 @@ impl MachineState {
self.unify(var_list_addr, list_addr); self.unify(var_list_addr, list_addr);
} }
Addr::Con(Constant::Integer(n)) => {
if let Some(b) = n.to_usize() {
let iter = self.gather_attr_vars_created_since(b);
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
let list_addr = self[temp_v!(2)].clone();
self.unify(var_list_addr, list_addr);
} else {
self.fail = true;
}
}
_ => self.fail = true, _ => self.fail = true,
} }
} }
@@ -1685,11 +1742,6 @@ impl MachineState {
self.p = CodePtr::DynamicTransaction(trans_type, p); self.p = CodePtr::DynamicTransaction(trans_type, p);
return Ok(()); return Ok(());
} }
&SystemClauseType::ReturnFromAttributeGoals => {
self.deallocate();
self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
return Ok(());
}
&SystemClauseType::ReturnFromVerifyAttr => { &SystemClauseType::ReturnFromVerifyAttr => {
let e = self.e; let e = self.e;
let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells; let frame_len = self.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
@@ -1839,6 +1891,21 @@ impl MachineState {
&SystemClauseType::InstallNewBlock => { &SystemClauseType::InstallNewBlock => {
self.install_new_block(temp_v!(1)); self.install_new_block(temp_v!(1));
} }
&SystemClauseType::RawInputReadChar => {
let keypress = {
let mut raw_stdout = stdout().into_raw_mode().unwrap();
raw_stdout.flush().unwrap();
next_keypress()
};
let c = match keypress {
ContinueResult::ContinueQuery => ';',
ContinueResult::Conclude => '.'
};
let target = self[temp_v!(1)].clone();
self.unify(Addr::Con(Constant::Char(c)), target);
}
&SystemClauseType::ReadQueryTerm => { &SystemClauseType::ReadQueryTerm => {
readline::set_prompt(true); readline::set_prompt(true);
let result = self.read_term(current_input_stream, indices); let result = self.read_term(current_input_stream, indices);

View File

@@ -137,11 +137,6 @@ impl<'a, R: Read> TermStream<'a, R> {
mem::replace(&mut self.top_level_terms, vec![]) mem::replace(&mut self.top_level_terms, vec![])
} }
#[inline]
pub fn add_to_top(&mut self, buf: &str) {
self.parser.add_to_top(buf);
}
#[inline] #[inline]
pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) { pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
match hook { match hook {

View File

@@ -303,13 +303,6 @@ fn is_consistent(tl: &TopLevel, clauses: &Vec<PredicateClause>) -> bool {
} }
} }
fn deque_to_packet(head: TopLevel, deque: VecDeque<TopLevel>) -> TopLevelPacket {
match head {
TopLevel::Query(query) => TopLevelPacket::Query(query, deque),
tl => TopLevelPacket::Decl(tl, deque),
}
}
fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError> { fn merge_clauses(tls: &mut VecDeque<TopLevel>) -> Result<TopLevel, ParserError> {
let mut clauses: Vec<PredicateClause> = vec![]; let mut clauses: Vec<PredicateClause> = vec![];
@@ -496,11 +489,6 @@ fn setup_declaration<'a, 'b, 'c, R: Read>(
} }
} }
pub enum TopLevelPacket {
Query(Vec<QueryTerm>, VecDeque<TopLevel>),
Decl(TopLevel, VecDeque<TopLevel>),
}
struct RelationWorker { struct RelationWorker {
flags: MachineFlags, flags: MachineFlags,
dynamic_clauses: Vec<(Term, Term)>, // Head, Body. dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
@@ -902,39 +890,6 @@ impl RelationWorker {
} }
} }
pub fn stream_to_toplevel<R: Read>(
mut buffer: ParsingStream<R>,
wam: &mut Machine,
) -> Result<TopLevelPacket, SessionError> {
let flags = wam.machine_flags();
let mut term_stream = TermStream::new(
&mut buffer,
wam.indices.atom_tbl(),
wam.machine_flags(),
wam,
);
term_stream.add_to_top("?- ");
let term = term_stream.read_term(&OpDir::new())?;
let mut code_dir = CodeDir::new();
let line_num = term_stream.line_num();
let col_num = term_stream.col_num();
let mut rel_worker = RelationWorker::new(flags, line_num, col_num);
let mut indices = CompositeIndices::new(
&mut term_stream,
IndexSource::TermStream,
Some(IndexSource::Local(&mut code_dir))
);
let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
let queue = rel_worker.parse_queue(&mut indices)?;
Ok(deque_to_packet(tl, queue))
}
pub type DynamicClauseMap = IndexMap<(ClauseName, usize), Vec<(Term, Term)>>; pub type DynamicClauseMap = IndexMap<(ClauseName, usize), Vec<(Term, Term)>>;
pub struct TopLevelBatchWorker<'a, R: Read> { pub struct TopLevelBatchWorker<'a, R: Read> {

View File

@@ -262,12 +262,6 @@ macro_rules! put_constant {
}; };
} }
macro_rules! top_level_code_ptr {
($p:expr, $q_sz:expr) => {
CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz))
};
}
macro_rules! get_level_and_unify { macro_rules! get_level_and_unify {
($r: expr) => { ($r: expr) => {
Line::Cut(CutInstruction::GetLevelAndUnify($r)) Line::Cut(CutInstruction::GetLevelAndUnify($r))

View File

@@ -1,8 +1,4 @@
/* :- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2]).
* inserting the modules should not result in the insertion of
* code. this is because they're already loaded by this point -- see
* Machine::new.
*/
:- use_module(library(lists)). :- use_module(library(lists)).
:- use_module(library(si)). :- use_module(library(si)).
@@ -40,6 +36,75 @@
'$submit_query_and_print_results'(Term, VarList), '$submit_query_and_print_results'(Term, VarList),
!. !.
'$submit_query_and_print_results'(Term0, VarList) :-
( expand_goals(Term0, Term) -> true
; Term = Term0
),
( '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList), !
; write('false.'), nl
).
'$write_goal'(G, VarList) :-
( G = (Var = Value) ->
write(Var),
write(' = '),
write_term(Value, [quoted(true), variable_names(VarList)])
; G == [] ->
write('true')
; write_term(G, [quoted(true), variable_names(VarList)])
).
'$write_eq'((G1, G2), VarList) :-
!,
'$write_goal'(G1, VarList),
write(', '),
'$write_eq'(G2, VarList).
'$write_eq'(G, VarList) :-
'$write_goal'(G, VarList).
'$write_eqs_and_read_input'(B, VarList) :-
sort(VarList, SortedVarList),
'$get_b_value'(B0),
'$gather_goals'(SortedVarList, VarList, Goals),
( B0 == B ->
( Goals == [] ->
write('true.'), nl
; thread_goals(Goals, ThreadedGoals, (',')),
'$write_eq'(ThreadedGoals, VarList),
write(' .'),
nl
)
; repeat,
thread_goals(Goals, ThreadedGoals, (',')),
'$write_eq'(ThreadedGoals, VarList),
'$raw_input_read_char'(C),
( C == (';'), !,
write(' ;'), nl, false
; C == ('.'), !,
write(' ...'), nl
)
).
'$gather_query_vars'([_ = Var | Vars], QueryVars) :-
( var(Var) ->
QueryVars = [Var | QueryVars1],
'$gather_query_vars'(Vars, QueryVars1)
; '$gather_query_vars'(Vars, QueryVars)
).
'$gather_query_vars'([], []).
'$gather_goals'([], VarList, Goals) :-
'$get_attr_var_queue_beyond'(0, AttrVars),
'$gather_query_vars'(VarList, QueryVars),
'$call_attribute_goals'(QueryVars, AttrVars),
'$fetch_attribute_goals'(Goals).
'$gather_goals'([Var = Value | Pairs], VarList, Goals) :-
( nonvar(Value) ->
Goals = [Var = Value | Goals0],
'$gather_goals'(Pairs, VarList, Goals0)
; '$gather_goals'(Pairs, VarList, Goals)
).
'$print_exception'(E) :- '$print_exception'(E) :-
write_term('caught: ', [quoted(false)]), write_term('caught: ', [quoted(false)]),
writeq(E), writeq(E),
@@ -102,40 +167,50 @@ user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
expand_goals(Goals, ExpandedGoals), expand_goals(Goals, ExpandedGoals),
Goals \== ExpandedGoals. Goals \== ExpandedGoals.
expand_goals(Goals, ExpandedGoals) :- expand_goals(UnexpandedGoals, ExpandedGoals) :-
nonvar(Goals), nonvar(UnexpandedGoals),
var(ExpandedGoals), var(ExpandedGoals),
( expand_goal(UnexpandedGoals, Goals) -> true
; Goals = UnexpandedGoals
),
( Goals = (Goal0, Goals0) -> ( Goals = (Goal0, Goals0) ->
( expand_goal(Goal0, Goal1) -> ( expand_goal(Goal0, Goal1) ->
Expanded = true, Expanded = true,
expand_goals(Goals0, Goals1), expand_goals(Goals0, Goals1),
thread_goals(Goal1, ExpandedGoals, Goals1) thread_goals(Goal1, ExpandedGoals, Goals1, (','))
; expand_goals(Goals0, Goals1), ; expand_goals(Goals0, Goals1),
ExpandedGoals = (Goal0, Goals1) ExpandedGoals = (Goal0, Goals1)
) )
; expand_goal(Goals, ExpandedGoals0) -> ; Goals = (Goals0 -> Goals1) ->
thread_goals(ExpandedGoals0, ExpandedGoals) expand_goals(Goals0, ExpandedGoals0),
expand_goals(Goals1, ExpandedGoals1),
ExpandedGoals = (ExpandedGoals0 -> ExpandedGoals1)
; Goals = (Goals0 ; Goals1) ->
expand_goals(Goals0, ExpandedGoals0),
expand_goals(Goals1, ExpandedGoals1),
ExpandedGoals = (ExpandedGoals0 ; ExpandedGoals1)
; thread_goals(Goals, ExpandedGoals, (','))
; Goals = ExpandedGoals ; Goals = ExpandedGoals
). ).
thread_goals(Goals0, Goals1, Hole) :- thread_goals(Goals0, Goals1, Hole, Functor) :-
nonvar(Goals0), nonvar(Goals0),
( Goals0 = [G | Gs] -> ( Goals0 = [G | Gs] ->
( Gs == [] -> ( Gs == [] ->
Goals1 = (G, Hole) Goals1 =.. [Functor, G, Hole]
; Goals1 = (G, Goals2), ; Goals1 =.. [Functor, G, Goals2],
thread_goals(Gs, Goals2, Hole) thread_goals(Gs, Goals2, Hole, Functor)
) )
; Goals1 = (Goals0, Hole) ; Goals1 =.. [Functor, Goals0, Hole]
). ).
thread_goals(Goals0, Goals1) :- thread_goals(Goals0, Goals1, Functor) :-
nonvar(Goals0), nonvar(Goals0),
( Goals0 = [G | Gs] -> ( Goals0 = [G | Gs] ->
( Gs = [] -> ( Gs = [] ->
Goals1 = G Goals1 = G
; Goals1 = (G, Goals2), ; Goals1 =.. [Functor, G, Goals2],
thread_goals(Gs, Goals2) thread_goals(Gs, Goals2, Functor)
) )
; Goals1 = Goals0 ; Goals1 = Goals0
). ).

View File

@@ -4,11 +4,7 @@ use crate::prolog::instructions::*;
use crate::prolog::machine::machine_errors::*; use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_indices::*;
use termion::event::Key;
use termion::input::TermRead;
use std::fmt; use std::fmt;
use std::io::stdin;
impl fmt::Display for LocalCodePtr { impl fmt::Display for LocalCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -29,10 +25,8 @@ impl fmt::Display for LocalCodePtr {
impl fmt::Display for REPLCodePtr { impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
REPLCodePtr::CompileBatch => write!(f, "REPLCodePtr::CompileBatch"), REPLCodePtr::CompileBatch =>
REPLCodePtr::SubmitQueryAndPrintResults => { write!(f, "REPLCodePtr::CompileBatch"),
write!(f, "REPLCodePtr::SubmitQueryAndPrintResults")
}
REPLCodePtr::UseModule => REPLCodePtr::UseModule =>
write!(f, "REPLCodePtr::UseModule"), write!(f, "REPLCodePtr::UseModule"),
REPLCodePtr::UseQualifiedModule => REPLCodePtr::UseQualifiedModule =>
@@ -275,7 +269,6 @@ impl fmt::Display for SessionError {
write!(f, "the predicate head is not an atom or clause.") write!(f, "the predicate head is not an atom or clause.")
} }
&SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()), &SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()),
&SessionError::UserPrompt => write!(f, "enter predicate at [user] prompt"),
} }
} }
} }
@@ -422,22 +415,3 @@ impl fmt::Display for Level {
} }
} }
} }
pub enum ContinueResult {
ContinueQuery,
Conclude,
}
pub fn next_keypress() -> ContinueResult {
let stdin = stdin();
for c in stdin.keys() {
match c.unwrap() {
Key::Char(' ') | Key::Char(';') => return ContinueResult::ContinueQuery,
Key::Char('.') => return ContinueResult::Conclude,
_ => {}
}
}
ContinueResult::Conclude
}

File diff suppressed because it is too large Load Diff

64
src/tests/builtins.pl Normal file
View File

@@ -0,0 +1,64 @@
:- use_module(library(lists)).
test_queries_on_builtins :-
\+ atom(_),
atom(a),
\+ atom("string"),
atom([]),
\+ atom(1),
\+ atom(0),
\+ atom(0.0),
\+ atom([a,b,c]),
\+ atom(atop(the_trees)),
\+ atomic(_),
atomic(a),
atomic("string"),
atomic([]),
atomic(1),
atomic(0),
atomic(0.0),
\+ atomic([a,b,c]),
\+ atomic(atop(the_trees)),
( var(X), X = 3, atomic(X) ),
\+ ( var(X), X = 3, var(X) ),
arg(1, f(a,b,c,d), a),
arg(2, f(a,b,c,d), b),
arg(3, f(a,b,c,d), c),
arg(4, f(a,b,c,d), d),
catch(arg(_, f, _), error(instantiation_error, _), true),
\+ arg(1, f(arg, not_arg, not_arg), not_arg),
arg(2, f(arg, not_arg, not_arg), not_arg),
arg(3, f(arg, not_arg, not_arg), not_arg),
functor(f(a,b,c), f, 3),
catch(functor(_,"sdf",3),error(type_error(atom,[s,d,f]),_),true),
f(1,2,3) =.. [f,1,2,3],
length([a,b,c], 3),
copy_term([[[[X,Y],Y],X]],[[[[Z,V],V],Z]]),
\+ ( X = g(X,Y), Y = f(X), copy_term(Y,g(Z)) ),
(X = g(X,Y), Y = f(X), copy_term(Y,f(Z))),
float(3.14159269),
\+ float(3),
\+ float("sdfsa"),
\+ float(structure(functor)),
\+ float([1,2,3]),
\+ float([1,2,_]),
\+ (X is 3 rdiv 4, float(X)),
( X is 3 rdiv 4, rational(X) ),
\+ rational(3),
\+ rational(f(_)),
\+ rational("sdfa"),
\+ rational(atom),
\+ rational(structure(f)),
\+ rational([1,2,3]),
\+ rational([1,2,_]),
compound(functor(compound)),
compound(f(_)),
compound([1,2,3]),
\+ compound([]),
\+ compound(3.14159269),
\+ compound(3),
\+ compound("sdfsa"),
\+ compound(atom).
:- initialization(test_queries_on_builtins).

26
src/tests/facts.pl Normal file
View File

@@ -0,0 +1,26 @@
:- dynamic(p/2).
:- dynamic(p/3).
p(Z, Z).
clouds(are, nice).
p(Z, h(Z, W), f(W)).
test_queries_on_facts :-
findall(Z, p(Z, Z), [Z]),
findall(Z, p(Z, z), [z]),
findall(Z, p(Z, w), [w]),
\+ p(z, w),
p(w, w),
\+ clouds(Z, Z),
findall(Z, clouds(are, Z), [nice]),
\+ p(z, h(z, z), f(w)),
p(z, h(z, w), f(w)),
findall(W, p(z, h(z, W), f(w)), [w]),
findall(Z, p(Z, h(Z, w), f(Z)), [w]),
\+ p(z, h(Z, w), f(Z)),
retract(p(_,_,_)),
assertz(p(Z, h(Z, W), f(W))),
p(f(f(a)), h(f(f(a)), f(a)), f(f(a))),
retract(p(Z, h(Z, W), f(W))).
:- initialization(test_queries_on_facts).

37
src/tests/predicates.pl Normal file
View File

@@ -0,0 +1,37 @@
:- dynamic(p/2).
:- dynamic(p/3).
:- dynamic(q/1).
p(_, a).
p(b, _).
test_queries_on_predicates :-
findall(Y, p(x, Y), [a]),
findall(X, p(X, a), [_,b]),
findall(X, p(b, X), [a,_]),
findall(X, p(X, X), [a,b]),
p(b, a),
\+ p(a, b),
retract(p(_,a)),
retract(p(b,_)),
assertz(p(_, _,a)),
assertz(p(_,a,_)),
assertz(p(_,_,a)),
findall(X, p(c,d,X), [a,a]),
findall(X, p(a,a,a), [a,a,a]),
\+ p(b,c,d),
findall(., retract(p(_,_,_)), _),
assertz(p(_, a)),
assertz(q(z)),
findall(Y, p(_,Y), [a]),
p(x,a),
p(_,a),
\+ p(_,b),
assertz((p(X, Y) :- q(Z), p(X, X))),
once(p(X,b)),
retract((p(X, Y) :- q(Z), p(X, X))),
retract(q(z)).
:- initialization(test_queries_on_predicates).

55
src/tests/rules.pl Normal file
View File

@@ -0,0 +1,55 @@
:- dynamic(p/3).
:- dynamic(p/2).
:- dynamic(q/2).
:- dynamic(r/2).
:- dynamic(r/1).
:- dynamic(h/1).
p(X, Y) :- q(X, Z), r(Z, Y).
q(q, s).
r(s, t).
test_queries_on_rules :-
findall([X,Y], p(X, Y), [[q, t]]),
p(q, t),
\+ p(t, q),
findall(T, p(q, T), [t]),
\+ p(t, t),
retract((p(X,Y) :- q(X,Z), r(Z, Y))),
retract(q(_,_)),
assertz((p(X,_) :- q(f(f(X)), _), r(_, _))),
assertz(q(f(f(X)), r)),
p(_,_),
retract(q(_,_)),
assertz(q(f(f(x)), r)),
findall(X, p(X,_), [x]),
retract((p(X,_) :- q(f(f(X)), _), r(_, _))),
retract(q(_,_)),
assertz((p(X, Y) :- q(X, Y), r(X, Y))),
assertz(q(s, t)),
retract(r(_,_)),
assertz((r(X, Y) :- r(a))),
assertz(r(a)),
findall([X,Y], p(X, Y), [[s,t]]),
\+ p(t, _),
findall(T, p(s, T), [t]),
findall(S, p(S, t), [s]),
assertz((p(f(f(a), g(b), X), g(b), h) :- q(X, Y))),
retract(q(_,_)),
assertz(q(_,_)),
findall([X,Y,Z], p(f(X, Y, Z), g(b), h), [[f(a), g(b), _]]),
\+ p(f(X, g(_), Z), g(Z), X),
findall([X,Y,Z], p(f(X, g(Y), Z), g(Z), h), [[f(a), b, b]]),
findall([X,Y,Z], p(Z, Y, X), [[h, g(b), f(f(a),g(b),_)]]),
findall([X,Y,Z], p(f(X, Y, Z), Y, h), [[f(a), g(b), _]]),
retract((p(X, Y) :- q(X, Y), r(X, Y))),
retract((p(f(f(a), g(b), X), g(b), h) :- q(X, _))),
assertz((p(_, f(_, Y, _)) :- h(Y))),
assertz(h(y)),
findall(Y, p(_, f(_, Y, _)), [y]).
p(_, f(_, y, _)),
\+ p(_, f(_, z, _)),
retract((p(_, f(_, Y, _)) :- h(Y))).
:- initialization(test_queries_on_rules).