From ed985c3cfe15add440f8036865007d06c840172d Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 16 Nov 2019 00:26:15 -0700 Subject: [PATCH] move more of the toplevel from rust into prolog --- src/prolog/clause_types.rs | 36 ++--- src/prolog/instructions.rs | 8 - src/prolog/machine/attributed_variables.rs | 84 ---------- src/prolog/machine/compile.rs | 34 ---- src/prolog/machine/machine_errors.rs | 4 - src/prolog/machine/machine_indices.rs | 9 +- src/prolog/machine/machine_state.rs | 2 +- src/prolog/machine/machine_state_impl.rs | 35 ---- src/prolog/machine/mod.rs | 177 ++++----------------- src/prolog/machine/project_attributes.pl | 5 +- src/prolog/machine/system_calls.rs | 79 ++++++++- src/prolog/machine/term_expansion.rs | 5 - src/prolog/machine/toplevel.rs | 45 ------ src/prolog/macros.rs | 6 - src/prolog/toplevel.pl | 97 ++++++++--- src/prolog/write.rs | 30 +--- 16 files changed, 203 insertions(+), 453 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index cd1dd14b..8f67177d 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -162,8 +162,7 @@ pub enum SystemClauseType { AtomChars, AtomCodes, AtomLength, - ModuleAssertDynamicPredicateToFront, - ModuleAssertDynamicPredicateToBack, + CallAttributeGoals, CharCode, CharsToNumber, CodesToNumber, @@ -176,6 +175,7 @@ pub enum SystemClauseType { EnqueueAttributedVar, ExpandGoal, ExpandTerm, + FetchAttributeGoals, FetchGlobalVar, FetchGlobalVarWithOffset, GetChar, @@ -200,6 +200,8 @@ pub enum SystemClauseType { InstallSCCCleaner, InstallInferenceCounter, LiftedHeapLength, + ModuleAssertDynamicPredicateToFront, + ModuleAssertDynamicPredicateToBack, ModuleOf, ModuleRetractClause, NoSuchPredicate, @@ -229,8 +231,8 @@ pub enum SystemClauseType { GetDoubleQuotes, InstallNewBlock, Maybe, + RawInputReadChar, ResetBlock, - ReturnFromAttributeGoals, ReturnFromVerifyAttr, SetBall, SetCutPointByDefault(RegType), @@ -257,20 +259,12 @@ impl SystemClauseType { &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") @@ -289,6 +283,7 @@ impl SystemClauseType { &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") @@ -327,11 +322,18 @@ impl SystemClauseType { } &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"), @@ -357,9 +359,6 @@ impl SystemClauseType { &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"), @@ -387,6 +386,7 @@ impl SystemClauseType { ("$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), @@ -404,6 +404,7 @@ impl SystemClauseType { ("$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), @@ -449,13 +450,13 @@ impl SystemClauseType { ("$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))), @@ -464,9 +465,6 @@ impl SystemClauseType { ("$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), diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 75a7d893..ef919e55 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -364,14 +364,6 @@ pub enum 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 { match self { &ControlInstruction::Allocate(num_frames) => { diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index 80fd11bc..992ba98d 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -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) - } } diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 25ab171a..0f959a6e 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -243,40 +243,6 @@ fn compile_query( Ok((code, cg.take_vars())) } -fn compile_decl( - wam: &mut Machine, - compiler: &mut ListingCompiler, - decl: Declaration, -) -> Result { - 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, diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index fe648303..6ef4ed9f 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -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 for EvalSession { diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index 40fda8a7..ef3b7d2c 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -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, diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 318d8c13..8bcd2018 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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; diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 0bbdcf38..7392d65c 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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( - &self, - var: Rc, - 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, diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index ecf15caa..f97afc20 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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, cut_policy: Box, @@ -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(&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(&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, diff --git a/src/prolog/machine/project_attributes.pl b/src/prolog/machine/project_attributes.pl index 3b399f98..7349bdf5 100644 --- a/src/prolog/machine/project_attributes.pl +++ b/src/prolog/machine/project_attributes.pl @@ -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), diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 483ceeeb..cd494313 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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); diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index d2bc1362..1c45b49e 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -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) { diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index c54e0515..542dd131 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -303,13 +303,6 @@ fn is_consistent(tl: &TopLevel, clauses: &Vec) -> bool { } } -fn deque_to_packet(head: TopLevel, deque: VecDeque) -> TopLevelPacket { - match head { - TopLevel::Query(query) => TopLevelPacket::Query(query, deque), - tl => TopLevelPacket::Decl(tl, deque), - } -} - fn merge_clauses(tls: &mut VecDeque) -> Result { let mut clauses: Vec = vec![]; @@ -496,11 +489,6 @@ fn setup_declaration<'a, 'b, 'c, R: Read>( } } -pub enum TopLevelPacket { - Query(Vec, VecDeque), - Decl(TopLevel, VecDeque), -} - struct RelationWorker { flags: MachineFlags, dynamic_clauses: Vec<(Term, Term)>, // Head, Body. @@ -902,39 +890,6 @@ impl RelationWorker { } } -pub fn stream_to_toplevel( - mut buffer: ParsingStream, - wam: &mut Machine, -) -> Result { - 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> { diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index ec17b8e1..0db02999 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -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 { ($r: expr) => { Line::Cut(CutInstruction::GetLevelAndUnify($r)) diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl index 26b5a862..d8e36a3d 100644 --- a/src/prolog/toplevel.pl +++ b/src/prolog/toplevel.pl @@ -1,12 +1,13 @@ -/* - * 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. @@ -40,6 +41,56 @@ '$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), @@ -102,40 +153,50 @@ user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :- 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 ). diff --git a/src/prolog/write.rs b/src/prolog/write.rs index 03a884c8..2d552522 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -4,11 +4,7 @@ use crate::prolog::instructions::*; 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 { @@ -29,10 +25,8 @@ impl fmt::Display for LocalCodePtr { 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 => @@ -275,7 +269,6 @@ impl fmt::Display for SessionError { 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"), } } } @@ -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 -} -- 2.54.0