AtomChars,
AtomCodes,
AtomLength,
- ModuleAssertDynamicPredicateToFront,
- ModuleAssertDynamicPredicateToBack,
+ CallAttributeGoals,
CharCode,
CharsToNumber,
CodesToNumber,
EnqueueAttributedVar,
ExpandGoal,
ExpandTerm,
+ FetchAttributeGoals,
FetchGlobalVar,
FetchGlobalVarWithOffset,
GetChar,
InstallSCCCleaner,
InstallInferenceCounter,
LiftedHeapLength,
+ ModuleAssertDynamicPredicateToFront,
+ ModuleAssertDynamicPredicateToBack,
ModuleOf,
ModuleRetractClause,
NoSuchPredicate,
GetDoubleQuotes,
InstallNewBlock,
Maybe,
+ RawInputReadChar,
ResetBlock,
- ReturnFromAttributeGoals,
ReturnFromVerifyAttr,
SetBall,
SetCutPointByDefault(RegType),
&SystemClauseType::AtomChars => clause_name!("$atom_chars"),
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
- &SystemClauseType::ModuleAssertDynamicPredicateToFront => {
- clause_name!("$module_asserta")
- }
- &SystemClauseType::ModuleAssertDynamicPredicateToBack => {
- clause_name!("$module_assertz")
- }
+ &SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
&SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
&SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
&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::UseQualifiedModule) => {
clause_name!("$use_qualified_module")
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
+ &SystemClauseType::FetchAttributeGoals => clause_name!("$fetch_attribute_goals"),
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
&SystemClauseType::FetchGlobalVarWithOffset => {
clause_name!("$fetch_global_var_with_offset")
}
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
&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::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::NumberToChars => clause_name!("$number_to_chars"),
&SystemClauseType::NumberToCodes => clause_name!("$number_to_codes"),
+ &SystemClauseType::RawInputReadChar => clause_name!("$raw_input_read_char"),
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
&SystemClauseType::ResetGlobalVarAtOffset => clause_name!("$reset_global_var_at_offset"),
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
- &SystemClauseType::ReturnFromAttributeGoals => {
- clause_name!("$return_from_attribute_goals")
- }
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
&SystemClauseType::SetBall => clause_name!("$set_ball"),
&SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"),
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
+ ("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
("$char_code", 2) => Some(SystemClauseType::CharCode),
("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
("$codes_to_number", 2) => Some(SystemClauseType::CodesToNumber),
("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
+ ("$fetch_attribute_goals", 1) => Some(SystemClauseType::FetchAttributeGoals),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$fetch_global_var_with_offset", 3) => Some(SystemClauseType::FetchGlobalVarWithOffset),
("$get_char", 1) => Some(SystemClauseType::GetChar),
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
+ ("$raw_input_read_char", 1) => Some(SystemClauseType::RawInputReadChar),
("$read_query_term", 2) => Some(SystemClauseType::ReadQueryTerm),
("$read_term", 2) => Some(SystemClauseType::ReadTerm),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
("$reset_global_var_at_key", 1) => Some(SystemClauseType::ResetGlobalVarAtKey),
("$reset_global_var_at_offset", 3) => Some(SystemClauseType::ResetGlobalVarAtOffset),
("$retract_clause", 4) => Some(SystemClauseType::RetractClause),
- ("$return_from_attribute_goals", 0) => Some(SystemClauseType::ReturnFromAttributeGoals),
("$return_from_verify_attr", 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
("$set_ball", 1) => Some(SystemClauseType::SetBall),
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
("$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),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
}
impl ControlInstruction {
- pub fn is_jump_instr(&self) -> bool {
- match self {
- &ControlInstruction::CallClause(..) => true,
- &ControlInstruction::JmpBy(..) => true,
- _ => false,
- }
- }
-
pub fn to_functor(&self) -> MachineStub {
match self {
&ControlInstruction::Allocate(num_frames) => {
use crate::prolog::machine::*;
-use indexmap::IndexSet;
-
use std::vec::IntoIter;
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
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) {
self.allocate(self.num_of_args + 2);
self.b0 = self.b;
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)
- }
}
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(
code_repo: &mut CodeRepo,
hook: CompileTimeHook,
NamelessEntry,
OpIsInfixAndPostFix(ClauseName),
ParserError(ParserError),
- UserPrompt,
}
pub enum EvalSession {
EntrySuccess,
Error(SessionError),
- InitialQuerySuccess(AllocVarDict),
- QueryFailure,
- SubsequentQuerySuccess,
}
impl From<SessionError> for EvalSession {
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr {
CompileBatch,
- SubmitQueryAndPrintResults,
UseModule,
UseQualifiedModule,
UseModuleFromFile,
pub(super) op_dir: OpDir,
}
-impl IndexStore {
- pub fn reset_global_variable_offsets(&mut self) {
- for (_, ref mut offset) in self.global_variables.values_mut() {
- *offset = None;
- }
- }
-
+impl IndexStore {
pub fn predicate_exists(
&self,
name: ClauseName,
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.num_of_args = arity;
self.b0 = self.b;
use crate::prolog::clause_types::*;
use crate::prolog::forms::*;
use crate::prolog::heap_iter::*;
-use crate::prolog::heap_print::*;
use crate::prolog::instructions::*;
use crate::prolog::machine::INTERRUPT;
use crate::prolog::machine::and_stack::*;
use std::cmp::{max, min, Ordering};
use std::f64;
use std::mem;
-use std::rc::Rc;
macro_rules! try_numeric_result {
($s: ident, $e: expr, $caller: expr) => {{
}
}
- 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(
&mut self,
pdl: &mut Vec<Addr>,
use prolog_parser::tabled_rc::*;
use crate::prolog::clause_types::*;
-use crate::prolog::fixtures::*;
use crate::prolog::forms::*;
use crate::prolog::heap_print::*;
use crate::prolog::instructions::*;
use crate::prolog::machine::heap::Heap;
use crate::prolog::read::*;
-use crate::prolog::write::{next_keypress, ContinueResult};
mod and_stack;
mod attributed_variables;
use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::machine_state::*;
use crate::prolog::machine::modules::*;
-use crate::prolog::machine::toplevel::stream_to_toplevel;
use crate::prolog::read::PrologStream;
use indexmap::IndexMap;
use std::collections::VecDeque;
use std::fs::File;
-use std::io::{stdout, Read, Write};
+use std::io::Read;
use std::mem;
use std::ops::Index;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
-use termion::raw::IntoRawMode;
-
pub struct MachinePolicies {
call_policy: Box<dyn CallPolicy>,
cut_policy: Box<dyn CutPolicy>,
}
}
- fn compile_top_level(&mut self) {
+ fn compile_top_level(&mut self) -> Result<(), SessionError>
+ {
self.toplevel_idx = self.code_repo.code.len();
compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()),
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) {
self.machine_st.reset();
self.code_repo.cached_query = code;
- self.run_query(&AllocVarDict::new());
+ self.run_query();
let result = self.machine_st.fail;
self.absorb_snapshot(old_machine_st);
self.machine_st[temp_v!(1)] = list_addr;
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 {
compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true,
clause_name!("si"));
- wam.compile_top_level();
+ if wam.compile_top_level().is_err() {
+ panic!("Loading '$toplevel' module failed");
+ }
+
wam.compile_scryerrc();
wam
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) {
let h = self.machine_st.heap.h;
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);
self.indices.reset_global_variable_offsets();
self.policies = policies;
}
+ */
REPLCodePtr::UseModule =>
self.use_module(ModuleSource::Library),
REPLCodePtr::UseModuleFromFile =>
self.machine_st.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]);
}
- fn propagate_exception_to_toplevel(&mut self, snapshot: MachineState) {
- 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 {
self.absorb_snapshot(snapshot);
}
+*/
- pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) {
+ pub(super) fn run_query(&mut self) {
self.machine_st.cp = LocalCodePtr::TopLevel(0, self.code_repo.size_of_cached_query());
let end_ptr = CodePtr::Local(self.machine_st.cp);
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(
&mut self.indices,
&mut self.policies,
self.dynamic_transaction(trans_type, 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;
break;
}
self.code_repo.cached_query = cached_query;
}
- _ => {
- if self.machine_st.heap_locs.is_empty() {
- self.machine_st.record_var_places(0, alloc_locs);
- }
-
- break;
- }
+ _ =>
+ break
};
}
}
- pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession {
- if !self.or_stack_is_empty() {
- let b = self.machine_st.b - 1;
- self.machine_st.p = self.machine_st.or_stack[b].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)]
pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where
output
}
-
- pub fn or_stack_is_empty(&self) -> bool {
- self.machine_st.b == 0
- }
}
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.and_stack[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(
&mut self,
instr: &Line,
-driver(QueryVars, AttrVars) :-
+'$attribute_goals_driver'(QueryVars, AttrVars) :-
gather_modules(AttrVars, Modules0, _),
sort(Modules0, Modules),
call_project_attributes(Modules, QueryVars, AttrVars),
call_attribute_goals(Modules, call_query_var_goals, QueryVars),
- call_attribute_goals(Modules, call_attr_var_goals, AttrVars),
- '$return_from_attribute_goals'.
+ call_attribute_goals(Modules, call_attr_var_goals, AttrVars).
enqueue_goals(Goals0) :-
nonvar(Goals0),
use indexmap::{IndexMap, IndexSet};
use std::collections::VecDeque;
-use std::io::{stdout, Write};
+use std::io::{stdin, stdout, Write};
use std::iter::once;
use std::mem;
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 {
hare: usize,
tortoise: usize,
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 => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
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 => {
let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
let attr_var_list = match attr_var {
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.p = CodePtr::DynamicTransaction(trans_type, p);
return Ok(());
}
- &SystemClauseType::ReturnFromAttributeGoals => {
- self.deallocate();
- self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
- return Ok(());
- }
&SystemClauseType::ReturnFromVerifyAttr => {
let e = self.e;
let frame_len = self.and_stack[e].len();
&SystemClauseType::InstallNewBlock => {
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 => {
readline::set_prompt(true);
let result = self.read_term(current_input_stream, indices);
pub fn top_level_terms(&mut self) -> Vec<(Term, usize, usize)> {
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]
pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
}
}
-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> {
let mut clauses: Vec<PredicateClause> = vec![];
}
}
-pub enum TopLevelPacket {
- Query(Vec<QueryTerm>, VecDeque<TopLevel>),
- Decl(TopLevel, VecDeque<TopLevel>),
-}
-
struct RelationWorker {
flags: MachineFlags,
dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
}
}
-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 struct TopLevelBatchWorker<'a, R: Read> {
};
}
-macro_rules! top_level_code_ptr {
- ($p:expr, $q_sz:expr) => {
- CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz))
- };
-}
-
macro_rules! get_level_and_unify {
($r: expr) => {
Line::Cut(CutInstruction::GetLevelAndUnify($r))
-/*
- * inserting the modules should not result in the insertion of
- * code. this is because they're already loaded by this point -- see
- * Machine::new.
-*/
+:- module('$toplevel', ['$repl'/1, consult/1, use_module/1, use_module/2]).
:- use_module(library(lists)).
:- use_module(library(si)).
+% internal operators defined for spacing purposes.
+:- op(1200, xf, ('.')).
+:- op(700, xfx, (' = ')).
+:- op(1000, xfy, (', ')).
+
'$repl'(ListOfModules) :-
maplist('$use_list_of_modules', ListOfModules),
false.
'$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_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_term((ThreadedGoals)., [quoted(false), variable_names(VarList)]),
+ nl
+ )
+ ; repeat,
+ thread_goals(Goals, ThreadedGoals, (', ')),
+ write_term(ThreadedGoals, [quoted(false), variable_names(VarList)]),
+ '$raw_input_read_char'(C),
+ ( C == (';'), !,
+ write_term(' ;', [quoted(false)]), nl, false
+ ; C == ('.'), !,
+ write_term(' ...', [quoted(false)]), 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) :-
write_term('caught: ', [quoted(false)]),
writeq(E),
expand_goals(Goals, ExpandedGoals),
Goals \== ExpandedGoals.
-expand_goals(Goals, ExpandedGoals) :-
- nonvar(Goals),
+expand_goals(UnexpandedGoals, ExpandedGoals) :-
+ nonvar(UnexpandedGoals),
var(ExpandedGoals),
+ ( expand_goal(UnexpandedGoals, Goals) -> true
+ ; Goals = UnexpandedGoals
+ ),
( Goals = (Goal0, Goals0) ->
( expand_goal(Goal0, Goal1) ->
Expanded = true,
expand_goals(Goals0, Goals1),
- thread_goals(Goal1, ExpandedGoals, Goals1)
+ thread_goals(Goal1, ExpandedGoals, Goals1, (','))
; expand_goals(Goals0, Goals1),
ExpandedGoals = (Goal0, Goals1)
)
- ; expand_goal(Goals, ExpandedGoals0) ->
- thread_goals(ExpandedGoals0, ExpandedGoals)
+ ; Goals = (Goals0 -> Goals1) ->
+ 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
).
-thread_goals(Goals0, Goals1, Hole) :-
+thread_goals(Goals0, Goals1, Hole, Functor) :-
nonvar(Goals0),
( Goals0 = [G | Gs] ->
( Gs == [] ->
- Goals1 = (G, Hole)
- ; Goals1 = (G, Goals2),
- thread_goals(Gs, Goals2, Hole)
+ Goals1 =.. [Functor, G, Hole]
+ ; Goals1 =.. [Functor, G, Goals2],
+ thread_goals(Gs, Goals2, Hole, Functor)
)
- ; Goals1 = (Goals0, Hole)
+ ; Goals1 =.. [Functor, Goals0, Hole]
).
-thread_goals(Goals0, Goals1) :-
+thread_goals(Goals0, Goals1, Functor) :-
nonvar(Goals0),
( Goals0 = [G | Gs] ->
( Gs = [] ->
Goals1 = G
- ; Goals1 = (G, Goals2),
- thread_goals(Gs, Goals2)
+ ; Goals1 =.. [Functor, G, Goals2],
+ thread_goals(Gs, Goals2, Functor)
)
; Goals1 = Goals0
).
use crate::prolog::machine::machine_errors::*;
use crate::prolog::machine::machine_indices::*;
-use termion::event::Key;
-use termion::input::TermRead;
-
use std::fmt;
-use std::io::stdin;
impl fmt::Display for LocalCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- REPLCodePtr::CompileBatch => write!(f, "REPLCodePtr::CompileBatch"),
- REPLCodePtr::SubmitQueryAndPrintResults => {
- write!(f, "REPLCodePtr::SubmitQueryAndPrintResults")
- }
+ REPLCodePtr::CompileBatch =>
+ write!(f, "REPLCodePtr::CompileBatch"),
REPLCodePtr::UseModule =>
write!(f, "REPLCodePtr::UseModule"),
REPLCodePtr::UseQualifiedModule =>
write!(f, "the predicate head is not an atom or clause.")
}
&SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()),
- &SessionError::UserPrompt => write!(f, "enter predicate at [user] prompt"),
}
}
}
}
}
}
-
-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
-}