greatly reduce the number of goal expansions done in callable if/then/else

This commit is contained in:
Mark Thom
2021-11-15 21:27:42 -07:00
parent 0404c3bd94
commit ffd1b7069f
5 changed files with 184 additions and 159 deletions

View File

@@ -284,6 +284,7 @@ pub enum SystemClauseType {
GetBall, GetBall,
GetCurrentBlock, GetCurrentBlock,
GetCutPoint, GetCutPoint,
GetStaggeredCutPoint,
GetDoubleQuotes, GetDoubleQuotes,
InstallNewBlock, InstallNewBlock,
Maybe, Maybe,
@@ -525,6 +526,7 @@ impl SystemClauseType {
&SystemClauseType::Fail => atom!("$fail"), &SystemClauseType::Fail => atom!("$fail"),
&SystemClauseType::GetBall => atom!("$get_ball"), &SystemClauseType::GetBall => atom!("$get_ball"),
&SystemClauseType::GetCutPoint => atom!("$get_cp"), &SystemClauseType::GetCutPoint => atom!("$get_cp"),
&SystemClauseType::GetStaggeredCutPoint => atom!("$get_staggered_cp"),
&SystemClauseType::GetCurrentBlock => atom!("$get_current_block"), &SystemClauseType::GetCurrentBlock => atom!("$get_current_block"),
&SystemClauseType::InstallNewBlock => atom!("$install_new_block"), &SystemClauseType::InstallNewBlock => atom!("$install_new_block"),
&SystemClauseType::NextEP => atom!("$nextEP"), &SystemClauseType::NextEP => atom!("$nextEP"),
@@ -705,6 +707,7 @@ impl SystemClauseType {
(atom!("$get_cont_chunk"), 3) => Some(SystemClauseType::GetContinuationChunk), (atom!("$get_cont_chunk"), 3) => Some(SystemClauseType::GetContinuationChunk),
(atom!("$get_current_block"), 1) => Some(SystemClauseType::GetCurrentBlock), (atom!("$get_current_block"), 1) => Some(SystemClauseType::GetCurrentBlock),
(atom!("$get_cp"), 1) => Some(SystemClauseType::GetCutPoint), (atom!("$get_cp"), 1) => Some(SystemClauseType::GetCutPoint),
(atom!("$get_staggered_cp"), 1) => Some(SystemClauseType::GetStaggeredCutPoint),
(atom!("$install_new_block"), 1) => Some(SystemClauseType::InstallNewBlock), (atom!("$install_new_block"), 1) => Some(SystemClauseType::InstallNewBlock),
(atom!("$quoted_token"), 1) => Some(SystemClauseType::QuotedToken), (atom!("$quoted_token"), 1) => Some(SystemClauseType::QuotedToken),
(atom!("$nextEP"), 3) => Some(SystemClauseType::NextEP), (atom!("$nextEP"), 3) => Some(SystemClauseType::NextEP),

View File

@@ -1,4 +1,4 @@
:- module(builtins, [(=)/2, (\=)/2, (\+)/1, (',')/2, (->)/2, (;)/2, :- module(builtins, [(=)/2, (\=)/2, (\+)/1, !/0, (',')/2, (->)/2, (;)/2,
(=..)/2, (:)/2, (:)/3, (:)/4, (:)/5, (:)/6, (=..)/2, (:)/2, (:)/3, (:)/4, (:)/5, (:)/6,
(:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12, (:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12,
abolish/1, asserta/1, assertz/1, abolish/1, asserta/1, assertz/1,
@@ -61,10 +61,8 @@ call(G, A, B, C, D, E, F, G, H) :- '$call'(G, A, B, C, D, E, F, G, H).
Module : Predicate :- Module : Predicate :-
( atom(Module) -> ( atom(Module) -> '$module_call'(Module, Predicate)
'$module_call'(Module, Predicate) ; throw(error(type_error(atom, Module), (:)/2))
;
throw(error(type_error(atom, Module), (:)/2))
). ).
@@ -205,143 +203,116 @@ repeat.
repeat :- repeat. repeat :- repeat.
:- meta_predicate ','(0,0).
:- meta_predicate ','(0, 0). :- meta_predicate ;(0,0).
:- meta_predicate ','(0, +, +). :- meta_predicate ->(0,0).
:- meta_predicate ;(0, 0). % '!' is for internal use as a callable no-op within if/then/else.
% Where it shouldn't be a no-op, it's interpreted under the expected
% semantics by comma_dispatch/3.
:- meta_predicate ;(0, 0, +). ! :- '$get_staggered_cp'(B), '$set_cp'(B).
:- meta_predicate ->(0, 0). G1 -> G2 :- '$get_staggered_cp'(B), call('$call'(G1)), '$set_cp'(B), call('$call'(G2)).
:- meta_predicate ->(0, 0, +). G ; _ :- call('$call'(G)).
_ ; G :- call('$call'(G)).
','(G1, G2) :- '$get_staggered_cp'(B), comma_dispatch(G1,G2,B).
','(G1, G2) :- set_cp(B) :- '$set_cp'(B).
'$get_b_value'(B),
( '$call_with_default_policy'(var(G1)) ->
throw(error(instantiation_error, (',')/2))
; '$call_with_default_policy'(','(G1, G2, B))
).
:- non_counted_backtracking comma_dispatch_prep/3.
';'(G1, G2) :- comma_dispatch_prep(Gs, B, [Cont|Conts]) :-
'$get_b_value'(B), ( callable(Gs) ->
( '$call_with_default_policy'(var(G1)) -> ( functor(Gs, ',', 2) ->
throw(error(instantiation_error, (';')/2)) arg(1, Gs, G1),
; '$call_with_default_policy'(';'(G1, G2, B)) arg(2, Gs, G2),
). ( G1 == ! ->
Cont = builtins:set_cp(B)
; callable(G1) ->
G1 -> G2 :- Cont = G1
'$get_b_value'(B), ; Cont = throw(error(type_error(callable, G1), call/1))
( '$call_with_default_policy'(var(G1)) -> ),
throw(error(instantiation_error, (->)/2)) comma_dispatch_prep(G2, B, Conts)
; '$call_with_default_policy'(->(G1, G2, B)) ; Cont = Gs,
). Conts = []
:-non_counted_backtracking call_or_cut/3.
call_or_cut(G, B, ErrorPI) :-
( '$call_with_default_policy'(var(G)) ->
throw(error(instantiation_error, ErrorPI))
; '$call_with_default_policy'(call_or_cut(G, B))
).
:- non_counted_backtracking control_functor/1.
control_functor(_:G) :- nonvar(G), control_functor(G).
control_functor(call(_:C)) :- C == !.
control_functor(!).
control_functor((_,_)).
control_functor((_;_)).
control_functor((_->_)).
:- non_counted_backtracking call_or_cut/2.
call_or_cut(G, B) :-
( nonvar(G),
'$call_with_default_policy'(control_functor(G)) ->
'$call_with_default_policy'(call_or_cut_interp(G, B))
; call(G)
).
:- non_counted_backtracking call_or_cut_interp/2.
call_or_cut_interp(_ : G, B) :-
call_or_cut_interp(G, B).
call_or_cut_interp(call(_ : !), B) :-
!. % '$set_cp'(B).
call_or_cut_interp(!, B) :-
'$set_cp'(B).
call_or_cut_interp((G1, G2), B) :-
'$call_with_default_policy'(','(G1, G2, B)).
call_or_cut_interp((G1 ; G2), B) :-
'$call_with_default_policy'(';'(G1, G2, B)).
call_or_cut_interp((G1 -> G2), B) :-
'$call_with_default_policy'(->(G1, G2, B)).
:- non_counted_backtracking (',')/3.
','(G1, G2, B) :-
( nonvar(G1),
'$call_with_default_policy'(control_functor(G1)) ->
'$call_with_default_policy'(call_or_cut_interp(G1, B)),
'$call_with_default_policy'(call_or_cut(G2, B, (',')/2))
; call(G1),
'$call_with_default_policy'(call_or_cut(G2, B, (',')/2))
).
:- non_counted_backtracking (;)/3.
';'(G1, G2, B) :-
( nonvar(G1),
'$call_with_default_policy'(control_functor(G1)) ->
'$call_with_default_policy'(';-interp'(G1, G2, B))
; call(G1)
; '$call_with_default_policy'(call_or_cut(G2, B, (;)/2))
).
:- non_counted_backtracking ';-interp'/3.
';-interp'((G1 -> G2), G3, B) :-
!,
( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) ->
'$call_with_default_policy'(call_or_cut(G2, B, (->)/2))
; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2))
).
';-interp'(_:(G1 -> G2), G3, B) :-
!,
( '$call_with_default_policy'(call_or_cut(G1, B, (->)/2)) ->
'$call_with_default_policy'(call_or_cut(G2, B, (->)/2))
; '$call_with_default_policy'(call_or_cut(G3, B, (;)/2))
).
';-interp'(G1, G2, B) :-
( '$call_with_default_policy'(call_or_cut_interp(G1, B))
; '$call_with_default_policy'(call_or_cut(G2, B, (;)/2))
).
:- non_counted_backtracking (->)/3.
->(G1, G2, B) :-
( nonvar(G1),
'$call_with_default_policy'(control_functor(G1)) ->
( '$call_with_default_policy'(call_or_cut_interp(G1, B)) ->
'$call_with_default_policy'(call_or_cut(G2, B, (->)/2))
) )
; call(G1) -> ; Gs == ! ->
'$call_with_default_policy'(call_or_cut(G2, B, (->)/2)) Cont = builtins:set_cp(B),
Conts = []
; Cont = throw(error(type_error(callable, Gs), call/1)),
Conts = []
). ).
:- non_counted_backtracking comma_dispatch_call_list/1.
comma_dispatch_call_list([]).
comma_dispatch_call_list([G1,G2,G3,G4,G5,G6,G7,G8|Gs]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3),
'$call'(G4),
'$call'(G5),
'$call'(G6),
'$call'(G7),
'$call'(G8),
comma_dispatch_call_list(Gs).
comma_dispatch_call_list([G1,G2,G3,G4,G5,G6,G7]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3),
'$call'(G4),
'$call'(G5),
'$call'(G6),
'$call'(G7).
comma_dispatch_call_list([G1,G2,G3,G4,G5,G6]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3),
'$call'(G4),
'$call'(G5),
'$call'(G6).
comma_dispatch_call_list([G1,G2,G3,G4,G5]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3),
'$call'(G4),
'$call'(G5).
comma_dispatch_call_list([G1,G2,G3,G4]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3),
'$call'(G4).
comma_dispatch_call_list([G1,G2,G3]) :-
!,
'$call'(G1),
'$call'(G2),
'$call'(G3).
comma_dispatch_call_list([G1,G2]) :-
!,
'$call'(G1),
'$call'(G2).
comma_dispatch_call_list([G1]) :-
'$call'(G1).
:- non_counted_backtracking comma_dispatch/3.
comma_dispatch(G1, G2, B) :-
comma_dispatch_prep((G1, G2), B, Conts),
comma_dispatch_call_list(Conts).
% univ. % univ.
:- non_counted_backtracking univ_errors/3. :- non_counted_backtracking univ_errors/3.

View File

@@ -629,6 +629,8 @@ expand_module_name(ESG0, M, ESG) :-
ESG = M:ESG0 ESG = M:ESG0
; ESG0 = _:_ -> ; ESG0 = _:_ ->
ESG = ESG0 ESG = ESG0
; predicate_property(ESG0, built_in) ->
ESG = ESG0
; ESG = M:ESG0 ; ESG = M:ESG0
). ).
@@ -656,7 +658,8 @@ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars) :-
( GoalFunctor == (:), ( GoalFunctor == (:),
SubGoals = [M, SubGoal] -> SubGoals = [M, SubGoal] ->
expand_module_names(SubGoal, MetaSpecs, M, ExpandedSubGoal, HeadVars), expand_module_names(SubGoal, MetaSpecs, M, ExpandedSubGoal, HeadVars),
ExpandedGoals = M:ExpandedSubGoal expand_module_name(ExpandedSubGoal, M, ExpandedGoals)
% ExpandedGoals = M:ExpandedSubGoal
; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars), ; expand_meta_predicate_subgoals(SubGoals, MetaSpecs, Module, ExpandedGoalList, HeadVars),
ExpandedGoals =.. [GoalFunctor | ExpandedGoalList] ExpandedGoals =.. [GoalFunctor | ExpandedGoalList]
). ).

View File

@@ -3580,6 +3580,54 @@ impl MachineState {
let n = Fixnum::build_with(i64::try_from(self.b0).unwrap()); let n = Fixnum::build_with(i64::try_from(self.b0).unwrap());
self.unify_fixnum(n, self.registers[1]); self.unify_fixnum(n, self.registers[1]);
} }
&SystemClauseType::GetStaggeredCutPoint => {
use std::sync::Once;
let b = self.store(self.deref(self.registers[1]));
static mut SEMICOLON_SECOND_BRANCH_LOC: usize = 0;
static LOC_INIT: Once = Once::new();
let semicolon_second_clause_p = unsafe {
LOC_INIT.call_once(|| {
match indices.code_dir.get(&(atom!(";"), 2)).map(|cell| cell.get()) {
Some(IndexPtr::Index(p)) => {
match code_repo.code[p] {
Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
SEMICOLON_SECOND_BRANCH_LOC = p + o;
}
_ => {
unreachable!();
}
}
}
_ => {
unreachable!();
}
}
});
LocalCodePtr::DirEntry(SEMICOLON_SECOND_BRANCH_LOC)
};
let staggered_b0 = if self.b > 0 {
let or_frame = self.stack.index_or_frame(self.b);
if or_frame.prelude.bp == semicolon_second_clause_p {
or_frame.prelude.b0
} else {
self.b0
}
} else {
self.b0
};
let staggered_b0 = integer_as_cell!(
Number::arena_from(staggered_b0, &mut self.arena)
);
self.bind(b.as_var().unwrap(), staggered_b0);
}
&SystemClauseType::InstallNewBlock => { &SystemClauseType::InstallNewBlock => {
self.install_new_block(self.registers[1]); self.install_new_block(self.registers[1]);
} }