]> Repositorios git - scryer-prolog.git/commitdiff
add read support for user:term_expansion and user:goal_expansion
authorMark Thom <[email protected]>
Sun, 6 Jan 2019 02:22:38 +0000 (19:22 -0700)
committerMark Thom <[email protected]>
Sun, 6 Jan 2019 02:22:38 +0000 (19:22 -0700)
src/prolog/compile.rs
src/prolog/instructions.rs
src/prolog/lib/builtins.pl
src/prolog/lib/dcgs.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/term_expansion.rs
src/prolog/toplevel.rs

index 7cd4e2c5957cfd7df35f659436275f21dee9b94c..cb8ba974e89436c7548d551d07052fed1d91897e 100644 (file)
@@ -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
                 })
             },
index 43c1fd5521d80c532ab047f7498903993b7f3942..f90577951709c79a7a90ec19d202d1797c00d154 100644 (file)
@@ -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
         }
     }
 }
index bb0bdb7205301847bd3ce11c85b11b2a9631640f..2c90076b3241c68afbf560372337f179ef1b6a4c 100644 (file)
    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).
 
index 6f3e092f95f11597bd9793bfd60b047c3a18c57e..5356b5c8232f9906c0a07bd32aa4aa15856ec477 100644 (file)
@@ -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).
 
index d6aa978677227e885dd7cbd0c07d10dafd6a6129..8e3c157d27733d919538bbb2f3dbd16d9e9e5294 100644 (file)
@@ -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))
         };
 
index 4d64f9e8c0a4bc6cbd67fb7acb838829223b85a0..19d1576035101c049bcc0f1ee9e2ce24e7e661a9 100644 (file)
@@ -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;
-            }
+            },
+            _ => {}
         }
     }
 
index ef8793a51f28488e11e2b840f2c9f44ec0ff30a3..0fd65d307d0869c0c7092571f56baf5af1585b05 100644 (file)
@@ -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<CompileTimeHook> {
+fn as_compile_time_hook(name: &str, arity: usize, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook>
+{
     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<CompileTimeHook> {
 fn is_compile_time_hook(name: &ClauseName, terms: &Vec<Box<Term>>) -> Option<CompileTimeHook> {
     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<TopLevel>);
@@ -349,6 +367,28 @@ fn module_resolution_call(mod_name: Term, body: Term) -> Result<QueryTerm, Parse
     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 {
     Query(Vec<QueryTerm>, VecDeque<TopLevel>),
     Decl(TopLevel, VecDeque<TopLevel>)
@@ -594,7 +634,7 @@ impl RelationWorker {
     fn setup_hook(&mut self, hook: CompileTimeHook, indices: &mut CompositeIndices, term: Term)
                   -> Result<CompileTimeHookCompileInfo, ParserError>
     {
-        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))?;