move more of the toplevel from rust into prolog
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
use crate::prolog::machine::*;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
|
||||
use std::vec::IntoIter;
|
||||
|
||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||
@@ -101,35 +99,6 @@ impl MachineState {
|
||||
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);
|
||||
|
||||
@@ -149,57 +118,4 @@ impl MachineState {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,40 +243,6 @@ fn compile_query(
|
||||
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,
|
||||
|
||||
@@ -537,15 +537,11 @@ pub enum SessionError {
|
||||
NamelessEntry,
|
||||
OpIsInfixAndPostFix(ClauseName),
|
||||
ParserError(ParserError),
|
||||
UserPrompt,
|
||||
}
|
||||
|
||||
pub enum EvalSession {
|
||||
EntrySuccess,
|
||||
Error(SessionError),
|
||||
InitialQuerySuccess(AllocVarDict),
|
||||
QueryFailure,
|
||||
SubsequentQuerySuccess,
|
||||
}
|
||||
|
||||
impl From<SessionError> for EvalSession {
|
||||
|
||||
@@ -300,7 +300,6 @@ pub enum DynamicTransactionType {
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub enum REPLCodePtr {
|
||||
CompileBatch,
|
||||
SubmitQueryAndPrintResults,
|
||||
UseModule,
|
||||
UseQualifiedModule,
|
||||
UseModuleFromFile,
|
||||
@@ -468,13 +467,7 @@ pub struct IndexStore {
|
||||
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,
|
||||
|
||||
@@ -318,7 +318,7 @@ impl MachineState {
|
||||
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;
|
||||
|
||||
@@ -6,7 +6,6 @@ use crate::prolog::arithmetic::*;
|
||||
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::*;
|
||||
@@ -27,7 +26,6 @@ use indexmap::{IndexMap, IndexSet};
|
||||
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) => {{
|
||||
@@ -208,39 +206,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(
|
||||
&mut self,
|
||||
pdl: &mut Vec<Addr>,
|
||||
|
||||
@@ -2,13 +2,11 @@ use prolog_parser::ast::*;
|
||||
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;
|
||||
@@ -36,21 +34,18 @@ 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::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>,
|
||||
@@ -198,10 +193,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();
|
||||
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) {
|
||||
@@ -235,7 +243,7 @@ impl Machine {
|
||||
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);
|
||||
@@ -261,7 +269,7 @@ impl Machine {
|
||||
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 {
|
||||
@@ -296,7 +304,10 @@ impl Machine {
|
||||
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
|
||||
@@ -378,17 +389,6 @@ impl Machine {
|
||||
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;
|
||||
|
||||
@@ -537,6 +537,7 @@ impl Machine {
|
||||
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);
|
||||
@@ -593,6 +594,7 @@ impl Machine {
|
||||
self.indices.reset_global_variable_offsets();
|
||||
self.policies = policies;
|
||||
}
|
||||
*/
|
||||
REPLCodePtr::UseModule =>
|
||||
self.use_module(ModuleSource::Library),
|
||||
REPLCodePtr::UseModuleFromFile =>
|
||||
@@ -662,20 +664,7 @@ impl Machine {
|
||||
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 {
|
||||
@@ -795,24 +784,13 @@ impl Machine {
|
||||
|
||||
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,
|
||||
@@ -831,63 +809,18 @@ impl Machine {
|
||||
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
|
||||
@@ -904,63 +837,9 @@ impl Machine {
|
||||
|
||||
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,
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
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),
|
||||
|
||||
@@ -22,11 +22,34 @@ use crate::ref_thread_local::RefThreadLocal;
|
||||
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,
|
||||
@@ -716,6 +739,17 @@ impl MachineState {
|
||||
|
||||
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);
|
||||
|
||||
@@ -1329,6 +1363,17 @@ impl MachineState {
|
||||
&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 {
|
||||
@@ -1370,6 +1415,18 @@ impl MachineState {
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1685,11 +1742,6 @@ impl MachineState {
|
||||
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();
|
||||
@@ -1839,6 +1891,21 @@ impl MachineState {
|
||||
&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);
|
||||
|
||||
@@ -136,11 +136,6 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
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) {
|
||||
|
||||
@@ -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> {
|
||||
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 {
|
||||
flags: MachineFlags,
|
||||
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 struct TopLevelBatchWorker<'a, R: Read> {
|
||||
|
||||
Reference in New Issue
Block a user