From 042779cff92554b0fac08082f06391a46a5f279f Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 5 Jan 2019 19:22:38 -0700 Subject: [PATCH] add read support for user:term_expansion and user:goal_expansion --- src/prolog/compile.rs | 4 +-- src/prolog/instructions.rs | 16 ++++++--- src/prolog/lib/builtins.pl | 8 ++--- src/prolog/lib/dcgs.pl | 2 +- src/prolog/machine/machine_state.rs | 4 +-- src/prolog/machine/term_expansion.rs | 7 ++-- src/prolog/toplevel.rs | 52 ++++++++++++++++++++++++---- 7 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index 7cd4e2c5..cb8ba974 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -101,9 +101,9 @@ impl CodeRepo { compile_appendix(&mut code, &preds.1, false, flags)?; Ok(match hook { - CompileTimeHook::TermExpansion => + CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => self.term_expanders = code, - CompileTimeHook::GoalExpansion => + CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => self.goal_expanders = code }) }, diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 43c1fd55..f9057795 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -371,21 +371,27 @@ pub enum BuiltInClauseType { #[derive(Clone, Copy)] pub enum CompileTimeHook { GoalExpansion, - TermExpansion + TermExpansion, + UserGoalExpansion, + UserTermExpansion } impl CompileTimeHook { pub fn name(self) -> ClauseName { match self { - CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"), - CompileTimeHook::TermExpansion => clause_name!("term_expansion") + CompileTimeHook::UserGoalExpansion + | CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"), + CompileTimeHook::UserTermExpansion + | CompileTimeHook::TermExpansion => clause_name!("term_expansion") } } pub fn arity(self) -> usize { match self { - CompileTimeHook::GoalExpansion => 2, - CompileTimeHook::TermExpansion => 2 + CompileTimeHook::UserGoalExpansion + | CompileTimeHook::GoalExpansion => 2, + CompileTimeHook::UserTermExpansion + | CompileTimeHook::TermExpansion => 2 } } } diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index bb0bdb72..2c90076b 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -16,7 +16,10 @@ instructions are unchanged. */ :- op(700, fx, non_counted_backtracking). -term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :- +% module resolution operator. +:- op(600, xfy, :). + +user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :- expand_op_list([Op | OtherOps], Pred, Spec, OpResults). expand_op_list([], _, _, []). @@ -47,9 +50,6 @@ expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResu % term comparison. :- op(700, xfx, [==, \==, @=<, @>=, @<, @>, =@=, \=@=]). -% module resolution operator. -:- op(600, xfy, :). - % the maximum arity flag. needs to be replaced with current_prolog_flag(max_arity, MAX_ARITY). max_arity(63). diff --git a/src/prolog/lib/dcgs.pl b/src/prolog/lib/dcgs.pl index 6f3e092f..5356b5c8 100644 --- a/src/prolog/lib/dcgs.pl +++ b/src/prolog/lib/dcgs.pl @@ -20,7 +20,7 @@ phrase(G, Ls0, Ls2) :- phrase(G, Ls0, Ls1) :- call(G, Ls0, Ls1). -term_expansion(Term0, Term) :- +user:term_expansion(Term0, Term) :- numbervars(Term0, 0, N), expand_dcgs(Term0, N, Term). diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index d6aa9786..8e3c157d 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -665,9 +665,9 @@ pub(crate) trait CallPolicy: Any { machine_st.b0 = machine_st.b; machine_st.p = match hook { - CompileTimeHook::TermExpansion => + CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => CodePtr::Local(LocalCodePtr::UserTermExpansion(0)), - CompileTimeHook::GoalExpansion => + CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => CodePtr::Local(LocalCodePtr::UserGoalExpansion(0)) }; diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 4d64f9e8..19d15760 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -131,14 +131,15 @@ impl<'a, R: Read> TermStream<'a, R> { #[inline] pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) { match hook { - CompileTimeHook::TermExpansion => { + CompileTimeHook::UserTermExpansion => { self.term_expansion_lens.0 += len; self.term_expansion_lens.1 += queue_len; }, - CompileTimeHook::GoalExpansion => { + CompileTimeHook::UserGoalExpansion => { self.goal_expansion_lens.0 += len; self.goal_expansion_lens.1 += queue_len; - } + }, + _ => {} } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index ef8793a5..0fd65d30 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -8,6 +8,7 @@ use prolog::machine::machine_state::MachineState; use prolog::machine::term_expansion::*; use prolog::num::*; +use std::borrow::BorrowMut; use std::collections::{HashSet, VecDeque}; use std::cell::{Cell, RefCell}; use std::io::Read; @@ -70,11 +71,28 @@ impl<'a, 'b> CompositeIndices<'a, 'b> } } -#[inline] -fn as_compile_time_hook(name: &str, arity: usize) -> Option { +fn as_compile_time_hook(name: &str, arity: usize, terms: &Vec>) -> Option +{ match (name, arity) { ("term_expansion", 2) => Some(CompileTimeHook::TermExpansion), ("goal_expansion", 2) => Some(CompileTimeHook::GoalExpansion), + (":", 2) => { + if let &Term::Constant(_, Constant::Atom(ref name, _)) = &terms[0].as_ref() { + if name.as_str() == "user" { + if let &Term::Clause(_, ref name, ref terms, _) = &terms[1].as_ref() { + return match name.as_str() { + "term_expansion" if terms.len() == 2 => + Some(CompileTimeHook::UserTermExpansion), + "goal_expansion" if terms.len() == 2 => + Some(CompileTimeHook::UserGoalExpansion), + _ => None + } + } + } + } + + None + }, _ => None } } @@ -83,13 +101,13 @@ fn as_compile_time_hook(name: &str, arity: usize) -> Option { fn is_compile_time_hook(name: &ClauseName, terms: &Vec>) -> Option { if name.as_str() == ":-" { if let Some(ref term) = terms.first() { - if let &Term::Clause(_, ref name, ref terms, None) = term.as_ref() { - return as_compile_time_hook(name.as_str(), terms.len()); + if let &Term::Clause(_, ref name, ref terms, _) = term.as_ref() { + return as_compile_time_hook(name.as_str(), terms.len(), terms); } } } - as_compile_time_hook(name.as_str(), terms.len()) + as_compile_time_hook(name.as_str(), terms.len(), terms) } type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque); @@ -349,6 +367,28 @@ fn module_resolution_call(mod_name: Term, body: Term) -> Result Term { + if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term { + if name.as_str() == ":-" && terms.len() == 2 { + let inner_term = match terms.first_mut().map(|term| term.borrow_mut()) { + Some(&mut Term::Clause(_, ref name, ref mut inner_terms, _)) => + if name.as_str() == ":" && inner_terms.len() == 2 { + Some(*inner_terms.pop().unwrap()) + } else { + None + }, + _ => None + }; + + if let Some(mut inner_term) = inner_term { + mem::swap(&mut terms[0], &mut Box::new(inner_term)); + } + } + } + + term +} + pub enum TopLevelPacket { Query(Vec, VecDeque), Decl(TopLevel, VecDeque) @@ -594,7 +634,7 @@ impl RelationWorker { fn setup_hook(&mut self, hook: CompileTimeHook, indices: &mut CompositeIndices, term: Term) -> Result { - match term { + match flatten_hook(term) { Term::Clause(r, name, terms, _) => if name == hook.name() && terms.len() == hook.arity() { let term = setup_fact(Term::Clause(r, name, terms, None))?; -- 2.54.0