]> Repositorios git - scryer-prolog.git/commitdiff
change goal and term expansions, change call/N to use goal expansions
authorMark Thom <[email protected]>
Wed, 11 Dec 2019 04:36:02 +0000 (21:36 -0700)
committerMark Thom <[email protected]>
Wed, 11 Dec 2019 04:36:02 +0000 (21:36 -0700)
20 files changed:
README.md
src/prolog/clause_types.rs
src/prolog/iterators.rs
src/prolog/lib/atts.pl
src/prolog/lib/builtins.pl
src/prolog/lib/dcgs.pl
src/prolog/lib/non_iso.pl
src/prolog/machine/code_repo.rs
src/prolog/machine/compile.rs
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/machine/toplevel.rs
src/prolog/macros.rs
src/prolog/toplevel.pl
src/prolog/write.rs

index 2d060807dfe11829c2fe70ccd2c3c6022f538316..d5d387aa4c0452de91dd97d65cd4400bca814e51 100644 (file)
--- a/README.md
+++ b/README.md
@@ -166,7 +166,7 @@ The following predicates are built-in to Scryer.
 * `bb_get/2`
 * `bb_put/2`
 * `between/3`
-* `call/1..62`
+* `call/1..17`
 * `call_cleanup/2`
 * `call_with_inference_limit/3`
 * `call_residue_vars/2`
index 006ea3d48bf148431766fda48babe9e73b3cc0ba..e2175735e4d1b7035475705e4520743400121c33 100644 (file)
@@ -159,10 +159,12 @@ pub enum SystemClauseType {
     AbolishModuleClause,
     AssertDynamicPredicateToBack,
     AssertDynamicPredicateToFront,
+    AtEndOfExpansion,
     AtomChars,
     AtomCodes,
     AtomLength,
     CallAttributeGoals,
+    CallN,
     CharCode,
     CharsToNumber,
     ClearAttrVarBindings,
@@ -261,10 +263,12 @@ impl SystemClauseType {
             &SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
             &SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
             &SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
+            &SystemClauseType::AtEndOfExpansion => clause_name!("$at_end_of_expansion"),
             &SystemClauseType::AtomChars => clause_name!("$atom_chars"),
             &SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
             &SystemClauseType::AtomLength => clause_name!("$atom_length"),
             &SystemClauseType::CallAttributeGoals => clause_name!("$call_attribute_goals"),
+            &SystemClauseType::CallN => clause_name!("$call"),
             &SystemClauseType::CharCode => clause_name!("$char_code"),
             &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
             &SystemClauseType::ClearAttributeGoals => clause_name!("$clear_attribute_goals"),
@@ -388,6 +392,7 @@ impl SystemClauseType {
     pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
         match (name, arity) {
             ("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
+            ("$at_end_of_expansion", 0) => Some(SystemClauseType::AtEndOfExpansion),
             ("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
             ("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
             ("$atom_length", 2) => Some(SystemClauseType::AtomLength),
@@ -396,6 +401,7 @@ impl SystemClauseType {
             ("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
             ("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
             ("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
+            ("$call", 1) => Some(SystemClauseType::CallN),
             ("$call_attribute_goals", 2) => Some(SystemClauseType::CallAttributeGoals),
             ("$char_code", 2) => Some(SystemClauseType::CharCode),
             ("$chars_to_number", 2) => Some(SystemClauseType::CharsToNumber),
@@ -522,7 +528,6 @@ pub enum BuiltInClauseType {
 #[derive(Clone, PartialEq, Eq)]
 pub enum ClauseType {
     BuiltIn(BuiltInClauseType),
-    CallN,
     Hook(CompileTimeHook),
     Inlined(InlinedClauseType),
     Named(ClauseName, usize, CodeIndex), // name, arity, index.
@@ -589,7 +594,6 @@ impl ClauseType {
 
     pub fn name(&self) -> ClauseName {
         match self {
-            &ClauseType::CallN => clause_name!("call"),
             &ClauseType::BuiltIn(ref built_in) => built_in.name(),
             &ClauseType::Hook(ref hook) => hook.name(),
             &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
@@ -610,8 +614,6 @@ impl ClauseType {
                     .unwrap_or_else(|| {
                         if let Some(spec) = spec {
                             ClauseType::Op(name, spec, CodeIndex::default())
-                        } else if name.as_str() == "call" {
-                            ClauseType::CallN
                         } else {
                             ClauseType::Named(name, arity, CodeIndex::default())
                         }
index 2dd4ea7bc718e3d3f1f5c3a1eccb7219b28c74b4..48c72aa58028f94fbe25d7936766f964b049683a 100644 (file)
@@ -123,12 +123,6 @@ impl<'a> QueryIterator<'a> {
 
     fn new(term: &'a QueryTerm) -> Self {
         match term {
-            &QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms, _) => {
-                let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
-                QueryIterator {
-                    state_stack: vec![state],
-                }
-            }
             &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
                 let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
                 QueryIterator {
@@ -173,9 +167,6 @@ impl<'a> Iterator for QueryIterator<'a> {
                 TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
                     if child_num == child_terms.len() {
                         match ct {
-                            ClauseType::CallN => {
-                                self.push_subterm(Level::Shallow, child_terms[0].as_ref())
-                            }
                             ClauseType::Named(..) | ClauseType::Op(..) => {
                                 return match lvl {
                                     Level::Root => None,
@@ -454,16 +445,6 @@ impl<'a> ChunkedIterator<'a> {
                 ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => {
                     result.push(term)
                 }
-                ChunkedTerm::BodyTerm(&QueryTerm::Clause(
-                    _,
-                    ClauseType::CallN,
-                    ref subterms,
-                    _,
-                )) => {
-                    result.push(term);
-                    arity = subterms.len() + 1;
-                    break;
-                }
                 ChunkedTerm::BodyTerm(qt) => {
                     result.push(term);
                     arity = qt.arity();
index 711156391ed232cc2d4dff3f0c8c6f488305d858..1522e0ce1a8b0d7ce4922ffea06adf3dc071d68a 100644 (file)
 '$del_attr'(Ls0, V, Attr) :-
     Ls0 = [Att | Ls1],
     nonvar(Att),
-    ( Att \= Attr -> '$del_attr_buried'(Ls0, Ls1, V, Attr)
-    ; '$enqueue_attr_var'(V),
-      '$del_attr_head'(V), '$del_attr'(Ls1, V, Attr)
+    (  Att \= Attr -> '$del_attr_buried'(Ls0, Ls1, V, Attr)
+    ;  '$enqueue_attr_var'(V),
+       '$del_attr_head'(V),
+       '$del_attr'(Ls1, V, Attr)
     ).
 
 '$del_attr_step'(Ls1, V, Attr) :-
-    ( nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
-    ; true ).
+    (  nonvar(Ls1) -> Ls1 = [_ | Ls2], '$del_attr_buried'(Ls1, Ls2, V, Attr)
+    ;  true ).
 
 %% assumptions: Ls0 is a list, Ls1 is its tail;
 %%              the head of Ls0 can be ignored.
index f0a754533fdc311b40faa6d935cd7abb506310ef..34f1fcb68de39e4ffe5a32d8a9edcf0e38526db9 100644 (file)
@@ -43,7 +43,11 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
                      (:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12,
                      abolish/1, asserta/1, assertz/1, atom_chars/2,
                      atom_codes/2, atom_concat/3, atom_length/2,
-                     bagof/3, catch/3, char_code/2, clause/2,
+                     bagof/3, call/1, call/2, call/3, call/4,
+                    call/5, call/6, call/7, call/8, call/9,
+                    call/10, call/11, call/12, call/13,
+                    call/14, call/15, call/16, call/17,
+                    catch/3, char_code/2, clause/2,
                      current_op/3, current_predicate/1,
                      current_prolog_flag/2, expand_goal/2,
                      expand_term/2, fail/0, false/0, findall/3,
@@ -55,6 +59,76 @@ user:term_expansion((:- op(Pred, Spec, [Op | OtherOps])), OpResults) :-
                      true/0, unify_with_occurs_check/2, write/1,
                      write_canonical/1, write_term/2, writeq/1]).
 
+
+%% call/{1..17}
+
+call(Goal) :-
+    (  '$module_of'(Module, Goal),
+       Module:goal_expansion(Goal, ExpandedGoal) ->
+       true
+    ;  Goal = ExpandedGoal
+    ),
+    '$call'(ExpandedGoal).
+
+'$call_body'(Goal, As) :-
+    Goal =.. F,
+    lists:append(F, As, Fs),
+    ExpandedGoal0 =.. Fs,
+    (  '$module_of'(Module, ExpandedGoal0),
+       Module:goal_expansion(ExpandedGoal0, ExpandedGoal1) ->
+       true
+    ;  ExpandedGoal1 = ExpandedGoal0
+    ),
+    '$call'(ExpandedGoal1).
+
+call(Goal, A1) :-
+    '$call_body'(Goal, [A1]).
+
+call(Goal, A1, A2) :-
+    '$call_body'(Goal, [A1, A2]).
+
+call(Goal, A1, A2, A3) :-
+    '$call_body'(Goal, [A1, A2, A3]).
+
+call(Goal, A1, A2, A3, A4) :-
+    '$call_body'(Goal, [A1, A2, A3, A4]).
+
+call(Goal, A1, A2, A3, A4, A5) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5]).
+
+call(Goal, A1, A2, A3, A4, A5, A6) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15]).
+
+call(Goal, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) :-
+    '$call_body'(Goal, [A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16]).
+
 % the maximum arity flag. needs to be replaced with
 % current_prolog_flag(max_arity, MAX_ARITY).
 max_arity(255).
@@ -177,13 +251,13 @@ set_prolog_flag(Flag, _) :-
 
 fail :- '$fail'.
 
-\+ G :- G, !, false.
+\+ G :- call(G), !, false.
 \+ _.
 
 X \= X :- !, false.
 _ \= _.
 
-once(G) :- G, !.
+once(G) :- call(G), !.
 
 repeat.
 repeat :- repeat.
@@ -200,13 +274,14 @@ comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)).
                 '$set_cp'(B),
                 '$call_with_default_policy'(comma_errors(G1, G2, B)).
 ','(!, Atom, B) :- Atom == !, '$set_cp'(B).
-','(!, G, B)  :- '$set_cp'(B), G.
+','(!, G, B)  :- '$set_cp'(B), call(G).
 ','(G, CF, B) :- compound(CF),
                 '$call_with_default_policy'(CF = ','(G1, G2)),
-                !, G,
+                !,
+                call(G),
                 '$call_with_default_policy'(comma_errors(G1, G2, B)).
-','(G, Atom, B) :- Atom == !, !, G, '$set_cp'(B).
-','(G1, G2, _)  :- G1, G2.
+','(G, Atom, B) :- Atom == !, !, call(G), '$set_cp'(B).
+','(G1, G2, _)  :- call(G1), call(G2).
 
 ;(G1, G2) :- '$get_b_value'(B), ;(G1, G2, B).
 
@@ -214,37 +289,47 @@ comma_errors(G1, G2, B) :- '$call_with_default_policy'(','(G1, G2, B)).
 ;(G1, G4, B) :- compound(G1),
                '$call_with_default_policy'(G1 = ->(G2, G3)),
                !,
-               (G2 -> G3 ; '$set_cp'(B), G4).
-;(G1, G2, B) :- G1 == !, '$set_cp'(B), G2.
-;(G1, G2, B) :- G2 == !, G1, '$set_cp'(B).
-;(G, _, _) :- G.
-;(_, G, _) :- G.
+               (  call(G2) -> call(G3)
+               ;  '$set_cp'(B),
+                  call(G4)
+               ).
+;(G1, G2, B) :- G1 == !, '$set_cp'(B), call(G2).
+;(G1, G2, B) :- G2 == !, call(G1), '$set_cp'(B).
+;(G, _, _) :- call(G).
+;(_, G, _) :- call(G).
 
 G1 -> G2 :- '$get_b_value'(B), '$call_with_default_policy'(->(G1, G2, B)).
 
 :- non_counted_backtracking (->)/3.
-->(G1, G2, B) :- G2 == !, G1, '$set_cp'(B).
-->(G1, G2, B) :- G1, '$set_cp'(B), G2.
+->(G1, G2, B) :- G2 == !, call(G1), '$set_cp'(B).
+->(G1, G2, B) :- call(G1), '$set_cp'(B), call(G2).
 
 % univ.
 
 :- non_counted_backtracking univ_errors/3.
 univ_errors(Term, List, N) :-
     '$skip_max_list'(N, -1, List, R),
-    ( var(R)       -> ( var(Term), throw(error(instantiation_error, (=..)/2))      % 8.5.3.3 a)
-                     ; true )
-    ; R \== []     -> throw(error(type_error(list, List), (=..)/2))                % 8.5.3.3 b)
-    ; List = [H|T] -> ( var(H), var(Term), % R == [] => List is a proper list.
-                       throw(error(instantiation_error, (=..)/2))                 % 8.5.3.3 c)
-                     ; T \== [], nonvar(H), \+ atom(H),
-                       throw(error(type_error(atom, H), (=..)/2))                 % 8.5.3.3 d)
-                     ; compound(H), T == [],
-                       throw(error(type_error(atomic, H), (=..)/2))               % 8.5.3.3 e)
-                     ; var(Term), max_arity(M), N - 1 > M,
-                       throw(error(representation_error(max_arity), (=..)/2))     % 8.5.3.3 g)
-                     ; true )
-    ; var(Term)    -> throw(error(domain_error(non_empty_list, List), (=..)/2))    % 8.5.3.3 f)
-    ; true ).
+    ( var(R)       ->
+       (  var(Term), throw(error(instantiation_error, (=..)/2))      % 8.5.3.3 a)
+       ;  true
+       )
+    ;  R \== []     ->
+       throw(error(type_error(list, List), (=..)/2))                % 8.5.3.3 b)
+    ;  List = [H|T] ->
+       (  var(H), var(Term), % R == [] => List is a proper list.
+                 throw(error(instantiation_error, (=..)/2))                 % 8.5.3.3 c)
+       ;  T \== [], nonvar(H), \+ atom(H),
+                 throw(error(type_error(atom, H), (=..)/2))                 % 8.5.3.3 d)
+       ;  compound(H), T == [],
+                 throw(error(type_error(atomic, H), (=..)/2))               % 8.5.3.3 e)
+       ;  var(Term), max_arity(M), N - 1 > M,
+                 throw(error(representation_error(max_arity), (=..)/2))     % 8.5.3.3 g)
+       ;  true
+       )
+    ;  var(Term)    ->
+       throw(error(domain_error(non_empty_list, List), (=..)/2))    % 8.5.3.3 f)
+    ;  true
+    ).
 
 Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
                 '$call_with_default_policy'(univ_worker(Term, List, N)).
@@ -371,7 +456,8 @@ catch(G,C,R) :- '$get_current_block'(Bb), '$call_with_default_policy'(catch(G,C,
 
 :- non_counted_backtracking catch/4.
 catch(G,C,R,Bb) :-
-    '$install_new_block'(NBb), call(G),
+    '$install_new_block'(NBb),
+    call(G),
     '$call_with_default_policy'(end_block(Bb, NBb)).
 catch(G,C,R,Bb) :-
     '$reset_block'(Bb),
index 2ee8baacd39da1efe04a7c7fda8240ca7ccfc460..e144cd0d4f7a901fbd02f25faafdb64af32b0501 100644 (file)
@@ -4,8 +4,9 @@
 
 :- use_module(library(lists), [append/3]).
 
-user:term_expansion(Term0, (Head :- Body)) :-
-    dcg_rule(Term0, Term),
+user:term_expansion(Term0, Term) :-
+    nonvar(Term0),
+    dcg_rule(Term0, (Head :- Body)),
     Term = (Head :- Body).
 
 phrase(GRBody, S0) :-
@@ -33,7 +34,7 @@ phrase_((A ; B), S0, S) :-
 %% phrase_((A | B), S0, S) :-
 %%     (  phrase(A, S0, S) ; phrase(B, S0, S)  ).
 phrase_({G}, S0, S) :-
-    (  G, S0 = S  ).
+    (  call(G), S0 = S  ).
 phrase_(call(G), S0, S) :-
     call(G, S0, S).
 phrase_((A -> B), S0, S) :-
index b4f9394d68e3fdeac162f13faa2b84a94aa532ad..22f0001ecff5f8a5c4ddac208250a52cae3f2d80 100644 (file)
@@ -46,8 +46,11 @@ call_cleanup(G, C) :- setup_call_cleanup(true, G, C).
 
 % setup_call_cleanup.
 
-setup_call_cleanup(S, G, C) :- '$get_b_value'(B),
-    S, '$set_cp_by_default'(B), '$get_current_block'(Bb),
+setup_call_cleanup(S, G, C) :-
+    '$get_b_value'(B),
+    call(S),
+    '$set_cp_by_default'(B),
+    '$get_current_block'(Bb),
     (  '$call_with_default_policy'(var(C)) ->
        throw(error(instantiation_error, setup_call_cleanup/3))
     ;  '$call_with_default_policy'(scc_helper(C, G, Bb))
@@ -83,10 +86,14 @@ run_cleaners_with_handling :-
 
 :- non_counted_backtracking run_cleaners_without_handling/1.
 run_cleaners_without_handling(Cp) :-
-    '$get_scc_cleaner'(C), '$get_level'(B), C, '$set_cp_by_default'(B),
+    '$get_scc_cleaner'(C),
+    '$get_level'(B),
+    call(C),
+    '$set_cp_by_default'(B),
     '$call_with_default_policy'(run_cleaners_without_handling(Cp)).
 run_cleaners_without_handling(Cp) :-
-    '$set_cp_by_default'(Cp), '$restore_cut_policy'.
+    '$set_cp_by_default'(Cp),
+    '$restore_cut_policy'.
 
 % call_with_inference_limit
 
@@ -123,8 +130,12 @@ call_with_inference_limit(G, L, R, Bb, B) :-
 call_with_inference_limit(_, _, R, Bb, B) :-
     '$reset_block'(Bb),
     '$remove_inference_counter'(B, _),
-    (  '$get_ball'(Ball), '$get_level'(Cp), '$set_cp_by_default'(Cp)
-    ;  '$remove_call_policy_check'(B), '$fail' ),
+    (  '$get_ball'(Ball),
+       '$get_level'(Cp),
+       '$set_cp_by_default'(Cp)
+    ;  '$remove_call_policy_check'(B),
+       '$fail'
+    ),
     '$erase_ball',
     '$call_with_default_policy'(handle_ile(B, Ball, R)).
 
index fee126e9f3c66cb0a8422755dcb749a658b64fe9..073a79d0cd2cc84d0c3ce119f387dcce98fff17a 100644 (file)
@@ -134,12 +134,33 @@ impl CodeRepo {
                 );
                 Some(RefOrOwned::Owned(call_clause))
             }
-            &CodePtr::CallN(arity, _, last_call) => {
-                let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
-                Some(RefOrOwned::Owned(call_clause))
-            }
             &CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
             &CodePtr::DynamicTransaction(..) => None,
         }
     }
+
+    pub(super)
+    fn at_end_of_hook(&self, hook: CompileTimeHook, cp: LocalCodePtr) -> bool {
+        match hook {
+            CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
+                let len = self.goal_expanders.len();
+
+                if len > 0 {
+                    cp == LocalCodePtr::UserGoalExpansion(len - 1)
+                } else {
+                    true
+                }
+            }
+            CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
+                let len = self.term_expanders.len();
+
+                if len > 0 {
+                    cp == LocalCodePtr::UserTermExpansion(len - 1)
+                } else {
+                    true
+                }
+            }
+        }
+    }
+        
 }
index 75b03d3586a2d8b7f9670c5f7b12332a298a2519..b67c5d715a67503662527cc877c291ff2f0efaba 100644 (file)
@@ -83,7 +83,7 @@ fn load_module<R: Read>(
         // this impromptu definition (namely, its exports) will be filled out later.
         let module_decl = ModuleDecl { name: listing_src, exports: vec![] };
 
-        let mut module = Module::new(module_decl, wam.indices.atom_tbl.clone());
+        let mut module  = Module::new(module_decl, wam.indices.atom_tbl.clone());
         let module_name = module.module_decl.name.clone();
 
         module.is_impromptu_module = true;
@@ -201,6 +201,24 @@ pub fn compile_appendix(
     Ok(())
 }
 
+fn append_trivial_goal(name: &ClauseName, pred: &mut Predicate)
+{
+    let var = Box::new(Term::Var(Cell::default(), Rc::new(String::from("X"))));
+    let body = QueryTerm::Clause(
+        Cell::default(),
+        ClauseType::from(clause_name!("$at_end_of_expansion"), 0, None),
+        vec![],
+        false
+    );
+
+    let rule = Rule {
+        head: (name.clone(), vec![var.clone(), var], body),
+        clauses: vec![]
+    };
+
+    pred.0.push(PredicateClause::Rule(rule, 0, 0));
+}
+
 impl CodeRepo {
     pub fn compile_hook(
         &mut self,
@@ -209,13 +227,17 @@ impl CodeRepo {
     ) -> Result<(), ParserError> {
         let key = (hook.name(), hook.arity());
 
-        match self.term_dir.get(&key) {
-            Some(preds) => {
+        match self.term_dir.get_mut(&key) {
+            Some(ref mut preds) => {
+                append_trivial_goal(&key.0, &mut preds.0);
+
                 let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
                 let mut code = cg.compile_predicate(&(preds.0).0)?;
 
                 compile_appendix(&mut code, &preds.1, false, flags)?;
 
+                (preds.0).0.pop();
+
                 Ok(match hook {
                     CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
                         self.term_expanders = code
@@ -225,7 +247,26 @@ impl CodeRepo {
                     }
                 })
             }
-            None => Ok(()),
+            None => Ok(match hook {
+                CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
+                    if self.term_expanders.is_empty() {
+                        let mut preds = Predicate::new();
+                        append_trivial_goal(&key.0, &mut preds);
+
+                        let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
+                        self.term_expanders = cg.compile_predicate(&preds.0)?;
+                    }
+                }
+                CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
+                    if self.goal_expanders.is_empty() {
+                        let mut preds = Predicate::new();
+                        append_trivial_goal(&key.0, &mut preds);
+
+                        let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
+                        self.goal_expanders = cg.compile_predicate(&preds.0)?;
+                    }
+                }
+            })
         }
     }
 }
@@ -649,8 +690,8 @@ impl ListingCompiler {
             let idx = code_dir
                 .entry((name.clone(), arity))
                 .or_insert(CodeIndex::default());
-            
-            set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());            
+
+            set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
 
             self.localize_self_calls(name, arity, &mut decl_code, p);
             code.extend(decl_code.into_iter());
@@ -728,7 +769,7 @@ impl ListingCompiler {
             ),
         );
 
-        op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)        
+        op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
     }
 
     fn process_decl(
@@ -749,7 +790,7 @@ impl ListingCompiler {
                     .code_repo
                     .compile_hook(hook, flags)
                     .map_err(SessionError::from);
-                
+
                 wam.code_repo.truncate_terms(key, len, queue_len);
 
                 result
@@ -940,13 +981,16 @@ fn compile_work_impl(
     if let Some(ref mut module) = &mut compiler.module {
         // compile the module-level goal and term expansions and store
         // their locations to the module's code_dir.
-        let decls = module.take_local_expansions();
-            
+        let mut decls = module.take_local_expansions();
+
         if !decls.is_empty() {
+            append_trivial_goal(&clause_name!("term_expansion"), &mut decls[0].0);
+            append_trivial_goal(&clause_name!("goal_expansion"), &mut decls[1].0);
+
             results.worker_results.extend(decls.into_iter());
         }
     }
-    
+
     let module_code = compiler.generate_code(
         results.worker_results,
         wam,
@@ -999,7 +1043,7 @@ fn compile_work_impl(
 
             wam.indices.use_module(&mut wam.code_repo, wam.machine_st.flags, &module)?;
             wam.indices.insert_module(module);
-        } else {                  
+        } else {
             add_module_code(wam, module, module_code, indices);
         }
 
index 10afcbe4b5111b83c5590d499b0336fd2e7e33fb..dac06a40aebca62feb1697a084985fdf45fe4a88 100644 (file)
@@ -211,6 +211,8 @@ pub enum IndexPtr {
     DynamicUndefined, // a predicate, declared as dynamic, whose location in code is as yet undefined.
     Undefined,
     Index(usize),
+    UserGoalExpansion,
+    UserTermExpansion
 }
 
 #[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
@@ -309,7 +311,6 @@ pub enum REPLCodePtr {
 #[derive(Clone, PartialEq)]
 pub enum CodePtr {
     BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
-    CallN(usize, LocalCodePtr, bool),               // arity, local, last call.
     Local(LocalCodePtr),
     DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
     REPL(REPLCodePtr, LocalCodePtr),                          // the REPL code, the return pointer.
@@ -320,7 +321,6 @@ impl CodePtr {
     pub fn local(&self) -> LocalCodePtr {
         match self {
             &CodePtr::BuiltInClause(_, ref local)
-          | &CodePtr::CallN(_, ref local, _)
           | &CodePtr::Local(ref local) => local.clone(),
             &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
             &CodePtr::REPL(_, p) | &CodePtr::DynamicTransaction(_, p) => p,
@@ -418,7 +418,7 @@ impl Add<usize> for CodePtr {
           | p @ CodePtr::VerifyAttrInterrupt(_)
           | p @ CodePtr::DynamicTransaction(..) => p,
             CodePtr::Local(local) => CodePtr::Local(local + rhs),
-            CodePtr::CallN(_, local, _) | CodePtr::BuiltInClause(_, local) => {
+            CodePtr::BuiltInClause(_, local) => {
                 CodePtr::Local(local + rhs)
             }
         }
@@ -491,6 +491,19 @@ impl IndexStore {
         }
     }
 
+    pub fn add_term_and_goal_expansion_indices(&mut self) {
+        self.code_dir.insert((clause_name!("term_expansion"), 2), 
+                             CodeIndex(Rc::new(RefCell::new(
+                                 (IndexPtr::UserTermExpansion,
+                                  clause_name!("user"))
+                             ))));
+        self.code_dir.insert((clause_name!("goal_expansion"), 2), 
+                             CodeIndex(Rc::new(RefCell::new(
+                                 (IndexPtr::UserGoalExpansion,
+                                  clause_name!("user"))
+                             ))));
+    }
+    
     #[inline]
     pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
         self.dynamic_code_dir.swap_remove(&(module, name, arity));
index 6c6ec160efb32e239a8e44dc40eb0d4a99a95e46..0d8568178c8cf00303108d0389e01dccc3be1442 100644 (file)
@@ -261,6 +261,7 @@ pub struct MachineState {
     pub(super) last_call: bool,
     pub(crate) heap_locs: HeapVarDict,
     pub(crate) flags: MachineFlags,
+    pub(crate) at_end_of_expansion: LocalCodePtr
 }
 
 impl MachineState {
@@ -316,17 +317,17 @@ impl MachineState {
         Ok(codes)
     }
 
-    pub(super) fn call_at_index(&mut self, arity: usize, p: usize) {
+    pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
         self.cp.assign_if_local(self.p.clone() + 1);
         self.num_of_args = arity;
         self.b0 = self.b;
-        self.p = dir_entry!(p);
+        self.p = CodePtr::Local(p);
     }
 
-    pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
+    pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) {
         self.num_of_args = arity;
         self.b0 = self.b;
-        self.p = dir_entry!(p);
+        self.p = CodePtr::Local(p);
     }
 
     pub(super) fn module_lookup(
@@ -342,9 +343,9 @@ impl MachineState {
             match idx.0.borrow().0 {
                 IndexPtr::Index(compiled_tl_index) => {
                     if last_call {
-                        self.execute_at_index(arity, compiled_tl_index);
+                        self.execute_at_index(arity, dir_entry!(compiled_tl_index));
                     } else {
-                        self.call_at_index(arity, compiled_tl_index);
+                        self.call_at_index(arity, dir_entry!(compiled_tl_index));
                     }
 
                     return Ok(());
@@ -353,6 +354,24 @@ impl MachineState {
                     self.fail = true;
                     return Ok(());
                 }
+                IndexPtr::UserTermExpansion => {
+                    if last_call {
+                        self.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
+                    } else {
+                        self.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
+                    }
+
+                    return Ok(());
+                }
+                IndexPtr::UserGoalExpansion => {
+                    if last_call {
+                        self.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
+                    } else {
+                        self.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
+                    }
+
+                    return Ok(());
+                }
                 _ => {}
             }
         }
@@ -390,9 +409,9 @@ fn try_in_situ(
 ) -> CallResult {
     if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
         if last_call {
-            machine_st.execute_at_index(arity, p);
+            machine_st.execute_at_index(arity, LocalCodePtr::DirEntry(p));
         } else {
-            machine_st.call_at_index(arity, p);
+            machine_st.call_at_index(arity, LocalCodePtr::DirEntry(p));
         }
 
         machine_st.p = in_situ_dir_entry!(p);
@@ -619,7 +638,13 @@ pub(crate) trait CallPolicy: Any {
             IndexPtr::Undefined =>
                 return try_in_situ(machine_st, name, arity, indices, false),
             IndexPtr::Index(compiled_tl_index) => {
-                machine_st.call_at_index(arity, compiled_tl_index)
+                machine_st.call_at_index(arity, LocalCodePtr::DirEntry(compiled_tl_index))
+            }
+            IndexPtr::UserTermExpansion => {
+                machine_st.call_at_index(arity, LocalCodePtr::UserTermExpansion(0));
+            }
+            IndexPtr::UserGoalExpansion => {
+                machine_st.call_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
             }
         }
 
@@ -640,7 +665,13 @@ pub(crate) trait CallPolicy: Any {
             IndexPtr::Undefined =>
                 return try_in_situ(machine_st, name, arity, indices, true),
             IndexPtr::Index(compiled_tl_index) => {
-                machine_st.execute_at_index(arity, compiled_tl_index)
+                machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
+            }
+            IndexPtr::UserTermExpansion => {
+                machine_st.execute_at_index(arity, LocalCodePtr::UserTermExpansion(0));
+            }
+            IndexPtr::UserGoalExpansion => {
+                machine_st.execute_at_index(arity, LocalCodePtr::UserGoalExpansion(0));
             }
         }
 
@@ -834,49 +865,39 @@ pub(crate) trait CallPolicy: Any {
     fn call_n(
         &mut self,
         machine_st: &mut MachineState,
+        name: ClauseName,
         arity: usize,
         indices: &mut IndexStore,
         parsing_stream: &mut PrologStream,
     ) -> CallResult {
-        if let Some((name, arity)) = machine_st.setup_call_n(arity) {
-            match ClauseType::from(name.clone(), arity, None) {
-                ClauseType::CallN => {
-                    machine_st.handle_internal_call_n(arity);
-
-                    if machine_st.fail {
-                        return Ok(());
-                    }
-
-                    machine_st.p = CodePtr::CallN(arity, machine_st.p.local(), machine_st.last_call);
-                }
-                ClauseType::BuiltIn(built_in) => {
-                    machine_st.setup_built_in_call(built_in.clone());
-                    self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
-                }
-                ClauseType::Inlined(inlined) => {
-                    machine_st.execute_inlined(&inlined);
+        match ClauseType::from(name.clone(), arity, None) {
+            ClauseType::BuiltIn(built_in) => {
+                machine_st.setup_built_in_call(built_in.clone());
+                self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
+            }
+            ClauseType::Inlined(inlined) => {
+                machine_st.execute_inlined(&inlined);
 
-                    if machine_st.last_call {
-                        machine_st.p = CodePtr::Local(machine_st.cp);
-                    }
+                if machine_st.last_call {
+                    machine_st.p = CodePtr::Local(machine_st.cp);
                 }
-                ClauseType::Op(..) | ClauseType::Named(..) => {
-                    let module = name.owning_module();
+            }
+            ClauseType::Op(..) | ClauseType::Named(..) => {
+                let module = name.owning_module();
 
-                    if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
-                        self.context_call(machine_st, name, arity, idx, indices)?;
-                    } else {
-                        try_in_situ(machine_st, name, arity, indices, machine_st.last_call)?;
-                    }
+                if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
+                    self.context_call(machine_st, name, arity, idx, indices)?;
+                } else {
+                    try_in_situ(machine_st, name, arity, indices, machine_st.last_call)?;
                 }
-                ClauseType::Hook(_) | ClauseType::System(_) => {
-                    let name = Addr::Con(Constant::Atom(name, None));
-                    let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
+            }
+            ClauseType::Hook(_) | ClauseType::System(_) => {
+                let name = Addr::Con(Constant::Atom(name, None));
+                let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
 
-                    return Err(machine_st
-                        .error_form(MachineError::type_error(ValidType::Callable, name), stub));
-                }
-            };
+                return Err(machine_st
+                           .error_form(MachineError::type_error(ValidType::Callable, name), stub));
+            }
         }
 
         Ok(())
@@ -932,12 +953,13 @@ impl CallPolicy for CWILCallPolicy {
     fn call_n(
         &mut self,
         machine_st: &mut MachineState,
+        name: ClauseName,
         arity: usize,
         indices: &mut IndexStore,
         parsing_stream: &mut PrologStream,
     ) -> CallResult {
         self.prev_policy
-            .call_n(machine_st, arity, indices, parsing_stream)?;
+            .call_n(machine_st, name, arity, indices, parsing_stream)?;
         self.increment(machine_st)
     }
 }
@@ -1093,10 +1115,10 @@ impl SCCCutPolicy {
         if let Some(&(_, b_cutoff, prev_block)) = self.cont_pts.last() {
             if machine_st.b < b_cutoff {
                 let (idx, arity) = if machine_st.block < prev_block {
-                    (self.r_c_w_h, 0)
+                    (dir_entry!(self.r_c_w_h), 0)
                 } else {
                     machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
-                    (self.r_c_wo_h, 1)
+                    (dir_entry!(self.r_c_wo_h), 1)
                 };
 
                 if machine_st.last_call {
index 0af5e57881589b37ebe53d4f4e93480fdb37ae03..34497a17493416491ea984d9cf1ed7d77cd38a5d 100644 (file)
@@ -75,6 +75,7 @@ impl MachineState {
             last_call: false,
             heap_locs: HeapVarDict::new(),
             flags: MachineFlags::default(),
+            at_end_of_expansion: LocalCodePtr::TopLevel(0, 0),
         }
     }
 
@@ -105,6 +106,7 @@ impl MachineState {
             last_call: false,
             heap_locs: HeapVarDict::new(),
             flags: MachineFlags::default(),
+            at_end_of_expansion: LocalCodePtr::TopLevel(0, 0),
         }
     }
 
@@ -1988,22 +1990,6 @@ impl MachineState {
         }
     }
 
-    pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
-        let arity = arity + 1;
-        let pred = self.registers[1].clone();
-
-        for i in 2..arity {
-            self.registers[i - 1] = self.registers[i].clone();
-        }
-
-        if arity > 1 {
-            self.registers[arity - 1] = pred;
-            return;
-        }
-
-        self.fail = true;
-    }
-
     pub(super) fn set_ball(&mut self) {
         self.ball.reset();
 
@@ -2017,59 +2003,6 @@ impl MachineState {
         );
     }
 
-    pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
-        let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
-        let addr = self.store(self.deref(self.registers[arity].clone()));
-
-        let (name, narity) = match addr {
-            Addr::Str(a) => {
-                let result = self.heap[a].clone();
-
-                if let HeapCellValue::NamedStr(narity, name, _) = result {
-                    if narity + arity > 63 {
-                        let representation_error = self.error_form(
-                            MachineError::representation_error(RepFlag::MaxArity),
-                            stub,
-                        );
-
-                        self.throw_exception(representation_error);
-                        return None;
-                    }
-
-                    for i in (1 .. arity).rev() {
-                        self.registers[i + narity] = self.registers[i].clone();
-                    }
-
-                    for i in 1 .. narity + 1 {
-                        self.registers[i] = self.heap[a + i].as_addr(a + i);
-                    }
-
-                    (name, narity)
-                } else {
-                    self.fail = true;
-                    return None;
-                }
-            }
-            Addr::Con(Constant::Atom(name, _)) => (name, 0),
-            Addr::HeapCell(_) | Addr::StackCell(_, _) => {
-                let instantiation_error =
-                    self.error_form(MachineError::instantiation_error(), stub);
-                self.throw_exception(instantiation_error);
-
-                return None;
-            }
-            _ => {
-                let type_error =
-                    self.error_form(MachineError::type_error(ValidType::Callable, addr), stub);
-                self.throw_exception(type_error);
-
-                return None;
-            }
-        };
-
-        Some((name, arity + narity - 1))
-    }
-
     pub(super) fn unwind_stack(&mut self) {
         self.b = self.block;
         self.truncate_stack();
@@ -3154,10 +3087,6 @@ impl MachineState {
                 self,
                 call_policy.call_builtin(self, ct, indices, parsing_stream)
             ),
-            &ClauseType::CallN => try_or_fail!(
-                self,
-                call_policy.call_n(self, arity, indices, parsing_stream)
-            ),
             &ClauseType::Hook(ref hook) => try_or_fail!(self, call_policy.compile_hook(self, hook)),
             &ClauseType::Inlined(ref ct) => {
                 self.execute_inlined(ct);
@@ -3375,6 +3304,7 @@ impl MachineState {
         self.mode = MachineMode::Write;
         self.registers = vec![Addr::HeapCell(0); MAX_ARITY + 1]; // self.registers[0] is never used.
         self.block = 0;
+        self.at_end_of_expansion = LocalCodePtr::TopLevel(0, 0);
 
         self.ball.reset();
         self.heap_locs.clear();
index 5e613c7c828941651e1f4c9620e113e06a407249..b33373ca8c9f49fc88bd09e64261e1de4f07c9bc 100644 (file)
@@ -272,7 +272,8 @@ impl Machine {
         self.run_query();
     }
 
-    pub fn new(prolog_stream: PrologStream) -> Self {
+    pub fn new(prolog_stream: PrologStream) -> Self
+    {
         let mut wam = Machine {
             machine_st: MachineState::new(),
             inner_heap: Heap::with_capacity(256 * 256),
@@ -285,6 +286,8 @@ impl Machine {
 
         let atom_tbl = wam.indices.atom_tbl.clone();
 
+        wam.indices.add_term_and_goal_expansion_indices();
+        
         compile_listing(
             &mut wam,
             parsing_stream(BUILTINS.as_bytes()),
index 508eb77dde8dfec493a745f4a439c057479dd16b..0ed1c437158514d9af67311aa7b8aef5462120db 100644 (file)
@@ -108,17 +108,7 @@ impl Module {
         let goal_expansions =
             mem::replace(&mut self.local_goal_expansions, (Predicate::new(), VecDeque::new()));
 
-        let mut result = vec![];
-
-        if !(term_expansions.0).0.is_empty() {
-            result.push(term_expansions);
-        }
-
-        if !(goal_expansions.0).0.is_empty() {
-            result.push(goal_expansions);
-        }
-
-        result
+        vec![term_expansions, goal_expansions]
     }
 }
 
index fb702df32977c71743dd5953af5e8a9b121fc708..7e026d13f2e968c944568d9cc9898d2de03c543c 100644 (file)
@@ -618,6 +618,9 @@ impl MachineState {
                 self.p = CodePtr::DynamicTransaction(trans_type, p);
                 return Ok(());
             }
+            &SystemClauseType::AtEndOfExpansion => {
+                self.at_end_of_expansion = self.p.local();
+            }
             &SystemClauseType::AtomChars => {
                 let a1 = self[temp_v!(1)].clone();
 
@@ -753,13 +756,71 @@ impl MachineState {
                 let p = self.attr_var_init.project_attrs_loc;
 
                 if self.last_call {
-                    self.execute_at_index(2, p);
+                    self.execute_at_index(2, dir_entry!(p));
                 } else {
-                    self.call_at_index(2, p);
+                    self.call_at_index(2, dir_entry!(p));
                 }
 
                 return Ok(());
             }
+            &SystemClauseType::CallN => {
+                let (name, arity) = match self.store(self.deref(self[temp_v!(1)].clone())) {
+                    Addr::Str(a) => {
+                        let result = self.heap[a].clone();
+
+                        if let HeapCellValue::NamedStr(arity, name, _) = result {
+                            if arity > MAX_ARITY {
+                                let stub = MachineError::functor_stub(
+                                    clause_name!("$call"),
+                                    1,
+                                );
+
+                                return Err(self.error_form(
+                                    MachineError::representation_error(RepFlag::MaxArity),
+                                    stub,
+                                ));
+                            }
+
+                            for i in 1 .. arity + 1 {
+                                self.registers[i] = self.heap[a + i].as_addr(a + i);
+                            }
+
+                            (name, arity)
+                        } else {
+                            unreachable!()
+                        }
+                    }
+                    Addr::Con(Constant::Atom(name, _)) =>
+                        (name, 0),
+                    Addr::HeapCell(_) | Addr::StackCell(_, _) => {
+                        let stub = MachineError::functor_stub(
+                            clause_name!("$call"),
+                            1,
+                        );
+                        
+                        return Err(self.error_form(MachineError::instantiation_error(), stub));
+                    }
+                    addr => {
+                        let stub = MachineError::functor_stub(
+                            clause_name!("$call"),
+                            1,
+                        );
+
+                        return Err(self.error_form(
+                            MachineError::type_error(ValidType::Callable, addr),
+                            stub,
+                        ));
+                    }
+                };
+                
+                return call_policy.call_n(
+                    self,
+                    name,
+                    arity,
+                    indices,
+                    current_input_stream,
+                );
+            }
             &SystemClauseType::CharsToNumber => {
                 let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
 
@@ -991,7 +1052,10 @@ impl MachineState {
 
                 match subsection {
                     Some(dynamic_predicate_info) => {
-                        self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
+                        self.execute_at_index(
+                            2,
+                            dir_entry!(dynamic_predicate_info.clauses_subsection_p)
+                        );
                         return Ok(());
                     }
                     None => self.fail = true,
@@ -1626,7 +1690,9 @@ impl MachineState {
 
                             self.unify(target, module);
                         }
-                        _ => self.fail = true,
+                        _ => {
+                            unreachable!()
+                        }
                     },
                     _ => self.fail = true,
                 };
@@ -1925,7 +1991,10 @@ impl MachineState {
 
                 match subsection {
                     Some(dynamic_predicate_info) => {
-                        self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
+                        self.execute_at_index(
+                            2,
+                            dir_entry!(dynamic_predicate_info.clauses_subsection_p)
+                        );
                         return Ok(());
                     }
                     _ => unreachable!(),
index f322f712aa0965e48aa8d85a1db579fc99dffe5f..f7ae72f3222d574f287dd28281dc70977a894c74 100644 (file)
@@ -343,7 +343,7 @@ impl MachineState {
     // this prevents clashes between underscored variable names
     // in the same query.
     fn reset_with_heap_preservation(&mut self) {
-        let heap = self.heap.take();            
+        let heap = self.heap.take();
         self.reset();
         self.heap = heap;
     }
@@ -364,6 +364,9 @@ impl MachineState {
         let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
         wam.code_repo.cached_query = code;
 
+        self.cp = LocalCodePtr::TopLevel(0, 0);
+        self.at_end_of_expansion = self.cp;
+
         self.query_stepper(
             &mut wam.indices,
             &mut wam.policies,
@@ -371,8 +374,8 @@ impl MachineState {
             &mut readline::input_stream(),
         );
 
-        if self.fail {
-            self.reset_with_heap_preservation();            
+        if self.fail || wam.code_repo.at_end_of_hook(hook, self.at_end_of_expansion) {
+            self.reset_with_heap_preservation();
             None
         } else {
             let TermWriteResult { var_dict, .. } = term_write_result;
@@ -380,7 +383,7 @@ impl MachineState {
             self.heap_locs = var_dict;
             let output = self.print_with_locs(Addr::HeapCell(h), &wam.indices.op_dir);
 
-            self.reset_with_heap_preservation();            
+            self.reset_with_heap_preservation();
             Some(output.result())
         }
     }
index ea91d1e62e6211d731965ea8c166073137b71418..de779b9e19d575cb011eb0284b3987b79aa5dc75 100644 (file)
@@ -693,13 +693,11 @@ impl RelationWorker {
                     let ct = indices.get_clause_type(name, terms.len(), fixity);
                     Ok(QueryTerm::Clause(Cell::default(), ct, terms, false))
                 }
-            },
-            Term::Var(..) => Ok(QueryTerm::Clause(
-                Cell::default(),
-                ClauseType::CallN,
-                vec![Box::new(term)],
-                false,
-            )),
+            }
+            arg @ Term::Var(..) => {
+                let ct = ClauseType::Named(clause_name!("call"), 1, CodeIndex::default());
+                Ok(QueryTerm::Clause(Cell::default(), ct, vec![Box::new(arg)], false))
+            }
             _ => Err(ParserError::InadmissibleQueryTerm),
         }
     }
index 0db0299969ba96a5d2c91896a85fe492882e01e5..1d11a9028d7f932b53804c5177ecfbc81dbdbd43 100644 (file)
@@ -217,7 +217,7 @@ macro_rules! return_from_clause {
 
 macro_rules! dir_entry {
     ($idx:expr) => {
-        CodePtr::Local(LocalCodePtr::DirEntry($idx))
+        LocalCodePtr::DirEntry($idx)
     };
 }
 
index cf5616455a046c37b64fc31147e5b1dfaf0023bd..902537ee0a45e4b0df23c08c628d1d701eb500c4 100644 (file)
     !.
 
 '$submit_query_and_print_results'(Term0, VarList) :-
-    (  expand_goals(Term0, Term) -> true
-    ;  Term = Term0
+    (  expand_goal(Term0, Term) -> true
+    ;  Term0 = Term
     ),
     (  '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList),
        !
     %  clear attribute goal lists, which may be populated by
     %  copy_term/3 prior to failure.
-    ;  '$clear_attribute_goals', write('false.'), nl 
+    ;  '$clear_attribute_goals', write('false.'), nl
     ).
 
 '$needs_bracketing'(Value, Op) :-
@@ -239,18 +239,22 @@ use_module(Module, QualifiedExports) :-
 user:term_expansion(Term0, (:- initialization(ExpandedGoals))) :-
     nonvar(Term0),
     Term0 = (:- initialization(Goals)),
-    expand_goals(Goals, ExpandedGoals),
-    Goals \== ExpandedGoals.
+    expand_goals(Goals, ExpandedGoals).
+
+
+module_expand_goal(UnexpandedGoals, ExpandedGoals) :-
+    '$module_of'(Module, UnexpandedGoals),
+    Module:goal_expansion(UnexpandedGoals, ExpandedGoals).
 
 expand_goals(UnexpandedGoals, ExpandedGoals) :-
     nonvar(UnexpandedGoals),
     var(ExpandedGoals),
-    (  expand_goal(UnexpandedGoals, Goals) -> true
+    (  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, (','))
        ;  expand_goals(Goals0, Goals1),
index 2d552522bd7b7d1f260a922107dd8ef8a3402c4a..23c8076c05cb4b91a7c4ec699ff9a53067862cf6 100644 (file)
@@ -45,6 +45,8 @@ impl fmt::Display for IndexPtr {
             &IndexPtr::DynamicUndefined => write!(f, "undefined"),
             &IndexPtr::Undefined => write!(f, "undefined"),
             &IndexPtr::Index(i) => write!(f, "{}", i),
+            &IndexPtr::UserTermExpansion => write!(f, "user:term_expansion"),
+            &IndexPtr::UserGoalExpansion => write!(f, "user:goal_expansion"),
         }
     }
 }