InferenceLevel,
#[strum_discriminants(strum(props(Arity = "1", Name = "$clean_up_block")))]
CleanUpBlock,
- #[strum_discriminants(strum(props(Arity = "0", Name = "$erase_ball")))]
- EraseBall,
#[strum_discriminants(strum(props(Arity = "0", Name = "$fail")))]
Fail,
#[strum_discriminants(strum(props(Arity = "1", Name = "$get_ball")))]
ReturnFromVerifyAttr,
#[strum_discriminants(strum(props(Arity = "1", Name = "$set_ball")))]
SetBall,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$push_ball_stack")))]
+ PushBallStack,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$pop_ball_stack")))]
+ PopBallStack,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$pop_from_ball_stack")))]
+ PopFromBallStack,
#[strum_discriminants(strum(props(Arity = "1", Name = "$set_cp_by_default")))]
SetCutPointByDefault(RegType),
#[strum_discriminants(strum(props(Arity = "1", Name = "$set_double_quotes")))]
&Instruction::CallSetStreamPosition(_) |
&Instruction::CallInferenceLevel(_) |
&Instruction::CallCleanUpBlock(_) |
- &Instruction::CallEraseBall(_) |
&Instruction::CallFail(_) |
&Instruction::CallGetBall(_) |
&Instruction::CallGetCurrentBlock(_) |
&Instruction::CallResetBlock(_) |
&Instruction::CallReturnFromVerifyAttr(_) |
&Instruction::CallSetBall(_) |
+ &Instruction::CallPushBallStack(_) |
+ &Instruction::CallPopBallStack(_) |
+ &Instruction::CallPopFromBallStack(_) |
&Instruction::CallSetCutPointByDefault(..) |
&Instruction::CallSetDoubleQuotes(_) |
&Instruction::CallSetSeed(_) |
&Instruction::ExecuteSetStreamPosition(_) |
&Instruction::ExecuteInferenceLevel(_) |
&Instruction::ExecuteCleanUpBlock(_) |
- &Instruction::ExecuteEraseBall(_) |
&Instruction::ExecuteFail(_) |
&Instruction::ExecuteGetBall(_) |
&Instruction::ExecuteGetCurrentBlock(_) |
&Instruction::ExecuteResetBlock(_) |
&Instruction::ExecuteReturnFromVerifyAttr(_) |
&Instruction::ExecuteSetBall(_) |
+ &Instruction::ExecutePushBallStack(_) |
+ &Instruction::ExecutePopBallStack(_) |
+ &Instruction::ExecutePopFromBallStack(_) |
&Instruction::ExecuteSetCutPointByDefault(_, _) |
&Instruction::ExecuteSetDoubleQuotes(_) |
&Instruction::ExecuteSetSeed(_) |
catch(G,C,R,Bb) :-
'$reset_block'(Bb),
'$get_ball'(Ball),
+ '$push_ball_stack', % move ball to ball stack.
handle_ball(Ball, C, R).
handle_ball(C, C, R) :-
!,
- '$erase_ball',
+ '$pop_ball_stack', % remove ball from ball stack.
call(R).
handle_ball(_, _, _) :-
+ '$pop_from_ball_stack', % restore ball from ball stack.
'$unwind_stack'.
:- non_counted_backtracking throw/1.
'$get_cp'(Cp),
'$install_scc_cleaner'(C, NBb),
'$call_with_inference_counting'(call(G)),
- ( '$check_cp'(Cp) ->
- '$reset_block'(Bb),
- run_cleaners_without_handling(Cp)
- ; true
- ; '$reset_block'(NBb),
- '$fail'
+ ( '$check_cp'(Cp) ->
+ '$reset_block'(Bb),
+ run_cleaners_without_handling(Cp)
+ ; true
+ ; '$reset_block'(NBb),
+ '$fail'
).
scc_helper(_, _, Bb) :-
'$reset_block'(Bb),
- '$get_ball'(Ball),
- '$erase_ball',
+ '$push_ball_stack',
run_cleaners_with_handling,
- throw(Ball).
+ '$pop_from_ball_stack',
+ '$unwind_stack'.
scc_helper(_, _, _) :-
'$get_cp'(Cp),
run_cleaners_without_handling(Cp),
:- non_counted_backtracking handle_ile/3.
-handle_ile(B, inference_limit_exceeded(B), inference_limit_exceeded) :- !.
-handle_ile(B, E, _) :-
+handle_ile(B, inference_limit_exceeded(B), inference_limit_exceeded) :-
+ !,
+ '$pop_ball_stack'.
+handle_ile(B, _, _) :-
'$remove_call_policy_check'(B),
- throw(E).
+ '$pop_from_ball_stack',
+ '$unwind_stack'.
:- meta_predicate(call_with_inference_limit(0, ?, ?)).
'$call_with_inference_counting'(call(G)),
'$inference_level'(R, B),
'$remove_inference_counter'(B, Count1),
- is(Diff, L - (Count1 - Count0)),
+ Diff is L - (Count1 - Count0),
end_block(B, Bb, NBb, Diff).
call_with_inference_limit(_, _, R, Bb, B) :-
'$reset_block'(Bb),
'$remove_inference_counter'(B, _),
( '$get_ball'(Ball),
+ '$push_ball_stack',
'$get_level'(Cp),
'$set_cp_by_default'(Cp)
; '$remove_call_policy_check'(B),
'$fail'
),
- '$erase_ball',
handle_ile(B, Ball, R).
partial_string(String, L, L0) :-
),
write('.').
-'$print_message_and_fail'(inference_limit_exceeded(B)) :-
- integer(B),
- throw(inference_limit_exceeded(B)).
+% '$print_message_and_fail'(inference_limit_exceeded(B)) :-
+% integer(B),
+% throw(inference_limit_exceeded(B)).
'$print_message_and_fail'(Error) :-
write_error(Error),
nl,
self.clean_up_block();
self.machine_st.p = self.machine_st.cp;
}
- &Instruction::CallEraseBall(_) => {
- self.erase_ball();
- self.machine_st.p += 1;
- }
- &Instruction::ExecuteEraseBall(_) => {
- self.erase_ball();
- self.machine_st.p = self.machine_st.cp;
- }
&Instruction::CallFail(_) | &Instruction::ExecuteFail(_) => {
self.machine_st.backtrack();
}
self.set_ball();
self.machine_st.p = self.machine_st.cp;
}
+ &Instruction::CallPushBallStack(_) => {
+ self.push_ball_stack();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePushBallStack(_) => {
+ self.push_ball_stack();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPopBallStack(_) => {
+ self.pop_ball_stack();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePopBallStack(_) => {
+ self.pop_ball_stack();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPopFromBallStack(_) => {
+ self.pop_from_ball_stack();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePopFromBallStack(_) => {
+ self.pop_from_ball_stack();
+ self.machine_st.p = self.machine_st.cp;
+ }
&Instruction::CallSetCutPointByDefault(r, _) => {
self.set_cut_point_by_default(r);
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::CallPredicateDefined(_) => {
self.machine_st.fail = !self.predicate_defined();
- self.machine_st.p += 1;
+ step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecutePredicateDefined(_) => {
self.machine_st.fail = !self.predicate_defined();
- self.machine_st.p = self.machine_st.cp;
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallStripModule(_) => {
let (module_loc, qualified_goal) = self.machine_st.strip_module(
pub(super) hb: usize,
pub(super) block: usize, // an offset into the OR stack.
pub(super) ball: Ball,
+ pub(super) ball_stack: Vec<Ball>, // save current ball before jumping via, e.g., verify_attr interrupt.
pub(super) lifted_heap: Heap,
pub(super) interms: Vec<Number>, // intermediate numbers.
// locations of cleaners, cut points, the previous block. for setup_call_cleanup.
.field("hb", &self.hb)
.field("block", &self.block)
.field("ball", &self.ball)
+ .field("ball_stack", &self.ball_stack)
.field("lifted_heap", &self.lifted_heap)
.field("interms", &self.interms)
.field("flags", &self.flags)
hb: 0,
block: 0,
ball: Ball::new(),
+ ball_stack: vec![],
lifted_heap: Heap::new(),
interms: vec![Number::default();256],
cont_pts: Vec::with_capacity(256),
}
}
- #[inline(always)]
- pub(crate) fn erase_ball(&mut self) {
- self.machine_st.ball.reset();
- }
-
#[inline(always)]
pub(crate) fn get_ball(&mut self) {
let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
};
}
+ #[inline(always)]
+ pub(crate) fn push_ball_stack(&mut self) {
+ if self.machine_st.ball.stub.len() > 0 {
+ self.machine_st.ball_stack.push(
+ mem::replace(&mut self.machine_st.ball, Ball::new())
+ );
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn pop_ball_stack(&mut self) {
+ self.machine_st.ball_stack.pop();
+ }
+
+ #[inline(always)]
+ pub(crate) fn pop_from_ball_stack(&mut self) {
+ if let Some(ball) = self.machine_st.ball_stack.pop() {
+ self.machine_st.ball = ball;
+ }
+ }
+
#[inline(always)]
pub(crate) fn get_current_block(&mut self) {
let n = Fixnum::build_with(i64::try_from(self.machine_st.block).unwrap());