add read support for user:term_expansion and user:goal_expansion

This commit is contained in:
Mark Thom
2019-01-05 19:22:38 -07:00
parent 36fdc8e822
commit 042779cff9
7 changed files with 70 additions and 23 deletions

View File

@@ -101,9 +101,9 @@ impl CodeRepo {
compile_appendix(&mut code, &preds.1, false, flags)?; compile_appendix(&mut code, &preds.1, false, flags)?;
Ok(match hook { Ok(match hook {
CompileTimeHook::TermExpansion => CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
self.term_expanders = code, self.term_expanders = code,
CompileTimeHook::GoalExpansion => CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion =>
self.goal_expanders = code self.goal_expanders = code
}) })
}, },

View File

@@ -371,21 +371,27 @@ pub enum BuiltInClauseType {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum CompileTimeHook { pub enum CompileTimeHook {
GoalExpansion, GoalExpansion,
TermExpansion TermExpansion,
UserGoalExpansion,
UserTermExpansion
} }
impl CompileTimeHook { impl CompileTimeHook {
pub fn name(self) -> ClauseName { pub fn name(self) -> ClauseName {
match self { match self {
CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"), CompileTimeHook::UserGoalExpansion
CompileTimeHook::TermExpansion => clause_name!("term_expansion") | CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"),
CompileTimeHook::UserTermExpansion
| CompileTimeHook::TermExpansion => clause_name!("term_expansion")
} }
} }
pub fn arity(self) -> usize { pub fn arity(self) -> usize {
match self { match self {
CompileTimeHook::GoalExpansion => 2, CompileTimeHook::UserGoalExpansion
CompileTimeHook::TermExpansion => 2 | CompileTimeHook::GoalExpansion => 2,
CompileTimeHook::UserTermExpansion
| CompileTimeHook::TermExpansion => 2
} }
} }
} }

View File

@@ -16,7 +16,10 @@
instructions are unchanged. */ instructions are unchanged. */
:- op(700, fx, non_counted_backtracking). :- 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([Op | OtherOps], Pred, Spec, OpResults).
expand_op_list([], _, _, []). expand_op_list([], _, _, []).
@@ -47,9 +50,6 @@ expand_op_list([Op | OtherOps], Pred, Spec, [(:- op(Pred, Spec, Op)) | OtherResu
% term comparison. % term comparison.
:- op(700, xfx, [==, \==, @=<, @>=, @<, @>, =@=, \=@=]). :- 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). % the maximum arity flag. needs to be replaced with current_prolog_flag(max_arity, MAX_ARITY).
max_arity(63). max_arity(63).

View File

@@ -20,7 +20,7 @@ phrase(G, Ls0, Ls2) :-
phrase(G, Ls0, Ls1) :- phrase(G, Ls0, Ls1) :-
call(G, Ls0, Ls1). call(G, Ls0, Ls1).
term_expansion(Term0, Term) :- user:term_expansion(Term0, Term) :-
numbervars(Term0, 0, N), numbervars(Term0, 0, N),
expand_dcgs(Term0, N, Term). expand_dcgs(Term0, N, Term).

View File

@@ -665,9 +665,9 @@ pub(crate) trait CallPolicy: Any {
machine_st.b0 = machine_st.b; machine_st.b0 = machine_st.b;
machine_st.p = match hook { machine_st.p = match hook {
CompileTimeHook::TermExpansion => CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
CodePtr::Local(LocalCodePtr::UserTermExpansion(0)), CodePtr::Local(LocalCodePtr::UserTermExpansion(0)),
CompileTimeHook::GoalExpansion => CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion =>
CodePtr::Local(LocalCodePtr::UserGoalExpansion(0)) CodePtr::Local(LocalCodePtr::UserGoalExpansion(0))
}; };

View File

@@ -131,14 +131,15 @@ impl<'a, R: Read> TermStream<'a, R> {
#[inline] #[inline]
pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) { pub fn incr_expansion_lens(&mut self, hook: CompileTimeHook, len: usize, queue_len: usize) {
match hook { match hook {
CompileTimeHook::TermExpansion => { CompileTimeHook::UserTermExpansion => {
self.term_expansion_lens.0 += len; self.term_expansion_lens.0 += len;
self.term_expansion_lens.1 += queue_len; self.term_expansion_lens.1 += queue_len;
}, },
CompileTimeHook::GoalExpansion => { CompileTimeHook::UserGoalExpansion => {
self.goal_expansion_lens.0 += len; self.goal_expansion_lens.0 += len;
self.goal_expansion_lens.1 += queue_len; self.goal_expansion_lens.1 += queue_len;
} },
_ => {}
} }
} }

View File

@@ -8,6 +8,7 @@ use prolog::machine::machine_state::MachineState;
use prolog::machine::term_expansion::*; use prolog::machine::term_expansion::*;
use prolog::num::*; use prolog::num::*;
use std::borrow::BorrowMut;
use std::collections::{HashSet, VecDeque}; use std::collections::{HashSet, VecDeque};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::io::Read; use std::io::Read;
@@ -70,11 +71,28 @@ impl<'a, 'b> CompositeIndices<'a, 'b>
} }
} }
#[inline] fn as_compile_time_hook(name: &str, arity: usize, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook>
fn as_compile_time_hook(name: &str, arity: usize) -> Option<CompileTimeHook> { {
match (name, arity) { match (name, arity) {
("term_expansion", 2) => Some(CompileTimeHook::TermExpansion), ("term_expansion", 2) => Some(CompileTimeHook::TermExpansion),
("goal_expansion", 2) => Some(CompileTimeHook::GoalExpansion), ("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 _ => None
} }
} }
@@ -83,13 +101,13 @@ fn as_compile_time_hook(name: &str, arity: usize) -> Option<CompileTimeHook> {
fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook> { fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook> {
if name.as_str() == ":-" { if name.as_str() == ":-" {
if let Some(ref term) = terms.first() { if let Some(ref term) = terms.first() {
if let &Term::Clause(_, ref name, ref terms, None) = term.as_ref() { if let &Term::Clause(_, ref name, ref terms, _) = term.as_ref() {
return as_compile_time_hook(name.as_str(), terms.len()); 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<TopLevel>); type CompileTimeHookCompileInfo = (CompileTimeHook, PredicateClause, VecDeque<TopLevel>);
@@ -349,6 +367,28 @@ fn module_resolution_call(mod_name: Term, body: Term) -> Result<QueryTerm, Parse
Err(ParserError::InvalidModuleResolution) Err(ParserError::InvalidModuleResolution)
} }
fn flatten_hook(mut term: Term) -> 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 { pub enum TopLevelPacket {
Query(Vec<QueryTerm>, VecDeque<TopLevel>), Query(Vec<QueryTerm>, VecDeque<TopLevel>),
Decl(TopLevel, VecDeque<TopLevel>) Decl(TopLevel, VecDeque<TopLevel>)
@@ -594,7 +634,7 @@ impl RelationWorker {
fn setup_hook(&mut self, hook: CompileTimeHook, indices: &mut CompositeIndices, term: Term) fn setup_hook(&mut self, hook: CompileTimeHook, indices: &mut CompositeIndices, term: Term)
-> Result<CompileTimeHookCompileInfo, ParserError> -> Result<CompileTimeHookCompileInfo, ParserError>
{ {
match term { match flatten_hook(term) {
Term::Clause(r, name, terms, _) => Term::Clause(r, name, terms, _) =>
if name == hook.name() && terms.len() == hook.arity() { if name == hook.name() && terms.len() == hook.arity() {
let term = setup_fact(Term::Clause(r, name, terms, None))?; let term = setup_fact(Term::Clause(r, name, terms, None))?;