push of preliminary delimited continuations library cont.pl (#136)
This commit is contained in:
@@ -117,7 +117,7 @@ impl MachineState {
|
||||
self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)].clone();
|
||||
}
|
||||
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::Con(Constant::Usize(self.b0));
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] = Addr::Con(Constant::CutPoint(self.b0));
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] = Addr::Con(Constant::Usize(self.num_of_args));
|
||||
|
||||
self.verify_attributes();
|
||||
|
||||
@@ -82,6 +82,50 @@ impl Heap {
|
||||
self.push(hcv);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match self.heap[s].as_addr(s) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize(),
|
||||
_ => None
|
||||
}
|
||||
};
|
||||
|
||||
match addr {
|
||||
Addr::Str(s) => {
|
||||
match &self.heap[*s] {
|
||||
HeapCellValue::NamedStr(arity, ref name, _) => {
|
||||
match (name.as_str(), *arity) {
|
||||
("dir_entry", 1) => {
|
||||
extract_integer(s+1).map(LocalCodePtr::DirEntry)
|
||||
}
|
||||
("in_situ_dir_entry", 1) => {
|
||||
extract_integer(s+1).map(LocalCodePtr::InSituDirEntry)
|
||||
}
|
||||
("top_level", 2) => {
|
||||
if let Some(chunk_num) = extract_integer(s+1) {
|
||||
if let Some(p) = extract_integer(s+2) {
|
||||
return Some(LocalCodePtr::TopLevel(chunk_num, p));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
("user_goal_expansion", 1) => {
|
||||
extract_integer(s+1).map(LocalCodePtr::UserGoalExpansion)
|
||||
}
|
||||
("user_term_expansion", 1) => {
|
||||
extract_integer(s+1).map(LocalCodePtr::UserTermExpansion)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Heap {
|
||||
|
||||
@@ -4,7 +4,11 @@ use prolog_parser::tabled_rc::*;
|
||||
use crate::prolog::clause_types::*;
|
||||
use crate::prolog::fixtures::*;
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::machine::code_repo::CodeRepo;
|
||||
use crate::prolog::machine::Ball;
|
||||
use crate::prolog::machine::heap::Heap;
|
||||
use crate::prolog::instructions::*;
|
||||
use crate::prolog::rug::Integer;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
@@ -346,6 +350,69 @@ impl LocalCodePtr {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool {
|
||||
match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) {
|
||||
Some(line) => {
|
||||
match line.as_ref() {
|
||||
Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
|
||||
if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn as_functor(&self, heap: &mut Heap) -> Addr {
|
||||
let addr = Addr::HeapCell(heap.h);
|
||||
|
||||
match self {
|
||||
LocalCodePtr::DirEntry(p) => {
|
||||
heap.append(functor!(
|
||||
"dir_entry",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::InSituDirEntry(p) => {
|
||||
heap.append(functor!(
|
||||
"in_situ_dir_entry",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||
heap.append(functor!(
|
||||
"top_level",
|
||||
2,
|
||||
[heap_integer!(Integer::from(*chunk_num)),
|
||||
heap_integer!(Integer::from(*offset))]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::UserGoalExpansion(p) => {
|
||||
heap.append(functor!(
|
||||
"user_goal_expansion",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::UserTermExpansion(p) => {
|
||||
heap.append(functor!(
|
||||
"user_term_expansion",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd<CodePtr> for CodePtr {
|
||||
@@ -399,6 +466,25 @@ impl Add<usize> for LocalCodePtr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<usize> for LocalCodePtr {
|
||||
type Output = Option<LocalCodePtr>;
|
||||
|
||||
fn sub(self, rhs: usize) -> Self::Output {
|
||||
match self {
|
||||
LocalCodePtr::InSituDirEntry(p) =>
|
||||
p.checked_sub(rhs).map(LocalCodePtr::InSituDirEntry),
|
||||
LocalCodePtr::DirEntry(p) =>
|
||||
p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
|
||||
LocalCodePtr::TopLevel(cn, p) =>
|
||||
p.checked_sub(rhs).map(|r| LocalCodePtr::TopLevel(cn, r)),
|
||||
LocalCodePtr::UserTermExpansion(p) =>
|
||||
p.checked_sub(rhs).map(LocalCodePtr::UserTermExpansion),
|
||||
LocalCodePtr::UserGoalExpansion(p) =>
|
||||
p.checked_sub(rhs).map(LocalCodePtr::UserGoalExpansion),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<usize> for LocalCodePtr {
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
match self {
|
||||
|
||||
@@ -1063,17 +1063,20 @@ downcast!(dyn CutPolicy);
|
||||
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
||||
let b = machine_st.b;
|
||||
|
||||
if let Addr::Con(Constant::Usize(b0)) = addr {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
machine_st.tidy_pstr_trail();
|
||||
machine_st.truncate_stack();
|
||||
match addr {
|
||||
Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
machine_st.tidy_pstr_trail();
|
||||
machine_st.truncate_stack();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
machine_st.fail = true;
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
machine_st.fail = true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
false
|
||||
}
|
||||
@@ -1148,15 +1151,19 @@ impl CutPolicy for SCCCutPolicy {
|
||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
||||
let b = machine_st.b;
|
||||
|
||||
if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
machine_st.tidy_pstr_trail();
|
||||
match machine_st[r].clone() {
|
||||
Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
machine_st.tidy_pstr_trail();
|
||||
machine_st.truncate_stack();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
machine_st.fail = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
machine_st.fail = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
self.run_cleaners(machine_st)
|
||||
|
||||
@@ -3337,7 +3337,7 @@ impl MachineState {
|
||||
&CutInstruction::GetLevel(r) => {
|
||||
let b0 = self.b0;
|
||||
|
||||
self[r] = Addr::Con(Constant::Usize(b0));
|
||||
self[r] = Addr::Con(Constant::CutPoint(b0));
|
||||
self.p += 1;
|
||||
}
|
||||
&CutInstruction::GetLevelAndUnify(r) => {
|
||||
|
||||
@@ -580,6 +580,51 @@ impl MachineState {
|
||||
functors
|
||||
}
|
||||
|
||||
fn call_continuation_chunk(&mut self, chunk: Addr, return_p: LocalCodePtr) -> LocalCodePtr {
|
||||
let chunk = self.store(self.deref(chunk));
|
||||
|
||||
match chunk {
|
||||
Addr::Str(s) => {
|
||||
match &self.heap[s] {
|
||||
HeapCellValue::NamedStr(arity, ..) => {
|
||||
let num_cells = arity - 1;
|
||||
let p_functor = self.heap[s+1].as_addr(s+1);
|
||||
|
||||
let cp = self.heap.to_local_code_ptr(&p_functor).unwrap();
|
||||
let prev_e = self.e;
|
||||
|
||||
let e = self.stack.allocate_and_frame(num_cells);
|
||||
let and_frame = self.stack.index_and_frame_mut(e);
|
||||
|
||||
and_frame.prelude.e = prev_e;
|
||||
and_frame.prelude.cp = return_p;
|
||||
|
||||
self.p = CodePtr::Local(cp + 1);
|
||||
|
||||
// adjust cut point to occur after call_continuation.
|
||||
if num_cells > 0 {
|
||||
if let Addr::Con(Constant::CutPoint(_)) = self.heap[s+2].as_addr(s+2) {
|
||||
and_frame[1] = Addr::Con(Constant::CutPoint(self.b));
|
||||
} else {
|
||||
and_frame[1] = self.heap[s+2].as_addr(s+2);
|
||||
}
|
||||
}
|
||||
|
||||
for index in s+3 .. s+2+num_cells {
|
||||
and_frame[index - (s+1)] = self.heap[index].as_addr(index);
|
||||
}
|
||||
|
||||
self.e = e;
|
||||
|
||||
self.p.local()
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn system_call(
|
||||
&mut self,
|
||||
ct: &SystemClauseType,
|
||||
@@ -610,17 +655,17 @@ impl MachineState {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
|
||||
if let Some(n) = n {
|
||||
if n <= MAX_ARITY {
|
||||
let target = self[temp_v!(n)].clone();
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
|
||||
self.unify(addr, target);
|
||||
return return_from_clause!(self.last_call, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
&SystemClauseType::AssertDynamicPredicateToFront => {
|
||||
@@ -784,6 +829,28 @@ impl MachineState {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
&SystemClauseType::CallContinuation => {
|
||||
let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1);
|
||||
|
||||
match self.try_from_list(temp_v!(1), stub) {
|
||||
Err(e) => return Err(e),
|
||||
Ok(cont_chunks) => {
|
||||
let mut return_p = if self.last_call {
|
||||
self.cp
|
||||
} else {
|
||||
self.p.local() + 1
|
||||
};
|
||||
|
||||
self.p = CodePtr::Local(return_p);
|
||||
|
||||
for chunk in cont_chunks.into_iter().rev() {
|
||||
return_p = self.call_continuation_chunk(chunk, return_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
&SystemClauseType::CharsToNumber => {
|
||||
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
|
||||
|
||||
@@ -897,7 +964,7 @@ impl MachineState {
|
||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match addr {
|
||||
Addr::Con(Constant::Usize(old_b)) => {
|
||||
Addr::Con(Constant::Usize(old_b)) | Addr::Con(Constant::CutPoint(old_b)) => {
|
||||
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
|
||||
let prev_b = self.stack.index_or_frame(prev_b).prelude.b;
|
||||
|
||||
@@ -1477,6 +1544,50 @@ impl MachineState {
|
||||
_ => self.fail = true,
|
||||
}
|
||||
}
|
||||
&SystemClauseType::GetContinuationChunk => {
|
||||
let e = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
let e = if let Addr::Con(Constant::Usize(e)) = e {
|
||||
e
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let p_functor = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
let p = self.heap.to_local_code_ptr(&p_functor).unwrap();
|
||||
|
||||
let num_cells = match code_repo.lookup_instr(self.last_call, &CodePtr::Local(p)) {
|
||||
Some(line) => {
|
||||
let perm_vars = match line.as_ref() {
|
||||
Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(),
|
||||
_ => None
|
||||
};
|
||||
|
||||
perm_vars.unwrap()
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let mut addrs = vec![];
|
||||
|
||||
for index in 1 .. num_cells + 1 {
|
||||
addrs.push(self.stack.index_and_frame(e)[index].clone());
|
||||
}
|
||||
|
||||
let chunk = Addr::HeapCell(self.heap.h);
|
||||
|
||||
self.heap.push(HeapCellValue::NamedStr(
|
||||
1 + num_cells,
|
||||
clause_name!("cont_chunk"),
|
||||
None,
|
||||
));
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(p_functor));
|
||||
self.heap.extend(addrs.into_iter().map(HeapCellValue::Addr));
|
||||
|
||||
self.unify(self[temp_v!(3)].clone(), chunk);
|
||||
}
|
||||
&SystemClauseType::GetLiftedHeapFromOffsetDiff => {
|
||||
let lh_offset = self[temp_v!(1)].clone();
|
||||
|
||||
@@ -1609,7 +1720,8 @@ impl MachineState {
|
||||
}
|
||||
|
||||
match (a1, a2.clone()) {
|
||||
(Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Integer(n))) => {
|
||||
(Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Integer(n)))
|
||||
| (Addr::Con(Constant::CutPoint(bp)), Addr::Con(Constant::Integer(n))) => {
|
||||
match call_policy.downcast_mut::<CWILCallPolicy>().ok() {
|
||||
Some(call_policy) => {
|
||||
let count = call_policy.add_limit(n, bp);
|
||||
@@ -1771,14 +1883,17 @@ impl MachineState {
|
||||
Some(call_policy) => {
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
if let Addr::Con(Constant::Usize(bp)) = a1 {
|
||||
if call_policy.is_empty() && bp == self.b {
|
||||
Some(call_policy.into_inner())
|
||||
} else {
|
||||
None
|
||||
match a1 {
|
||||
Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
|
||||
if call_policy.is_empty() && bp == self.b {
|
||||
Some(call_policy.into_inner())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("remove_call_policy_check: expected Usize in A1.");
|
||||
}
|
||||
} else {
|
||||
panic!("remove_call_policy_check: expected Usize in A1.");
|
||||
}
|
||||
}
|
||||
None => panic!(
|
||||
@@ -1796,15 +1911,18 @@ impl MachineState {
|
||||
Some(call_policy) => {
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
if let Addr::Con(Constant::Usize(bp)) = a1 {
|
||||
let count = call_policy.remove_limit(bp);
|
||||
let count = Addr::Con(Constant::Integer(count.clone()));
|
||||
match a1 {
|
||||
Addr::Con(Constant::Usize(bp)) | Addr::Con(Constant::CutPoint(bp)) => {
|
||||
let count = call_policy.remove_limit(bp);
|
||||
let count = Addr::Con(Constant::Integer(count.clone()));
|
||||
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
|
||||
self.unify(a2, count);
|
||||
} else {
|
||||
panic!("remove_inference_counter: expected Usize in A1.");
|
||||
self.unify(a2, count);
|
||||
}
|
||||
_ => {
|
||||
panic!("remove_inference_counter: expected Usize in A1.");
|
||||
}
|
||||
}
|
||||
}
|
||||
None => panic!(
|
||||
@@ -1836,7 +1954,7 @@ impl MachineState {
|
||||
self[RegType::Temp(i)] = self.stack.index_and_frame(e)[i].clone();
|
||||
}
|
||||
|
||||
if let &Addr::Con(Constant::Usize(b0)) = &self.stack.index_and_frame(e)[frame_len - 1] {
|
||||
if let &Addr::Con(Constant::CutPoint(b0)) = &self.stack.index_and_frame(e)[frame_len - 1] {
|
||||
self.b0 = b0;
|
||||
}
|
||||
|
||||
@@ -1884,7 +2002,7 @@ impl MachineState {
|
||||
let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
|
||||
match a2 {
|
||||
Addr::Con(Constant::Usize(bp)) => {
|
||||
Addr::Con(Constant::CutPoint(bp)) | Addr::Con(Constant::Usize(bp)) => {
|
||||
let prev_b = self.stack.index_or_frame(self.b).prelude.b;
|
||||
|
||||
if prev_b <= bp {
|
||||
@@ -1975,7 +2093,7 @@ impl MachineState {
|
||||
}
|
||||
&SystemClauseType::GetCutPoint => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
let a2 = Addr::Con(Constant::Usize(self.b0));
|
||||
let a2 = Addr::Con(Constant::CutPoint(self.b0));
|
||||
|
||||
self.unify(a1, a2);
|
||||
}
|
||||
@@ -1997,6 +2115,72 @@ impl MachineState {
|
||||
let target = self[temp_v!(1)].clone();
|
||||
self.unify(Addr::Con(Constant::Char(c)), target);
|
||||
}
|
||||
&SystemClauseType::NextEP => {
|
||||
let first_arg = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match first_arg {
|
||||
Addr::Con(Constant::Atom(ref name, _))
|
||||
if name.as_str() == "first" => {
|
||||
if self.e == 0 {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let cp = (self.stack.index_and_frame(self.e).prelude.cp - 1).unwrap();
|
||||
|
||||
let e = self.stack.index_and_frame(self.e).prelude.e;
|
||||
let e = Addr::Con(Constant::Usize(e));
|
||||
|
||||
let p = cp.as_functor(&mut self.heap);
|
||||
|
||||
self.unify(self[temp_v!(2)].clone(), e);
|
||||
|
||||
if !self.fail {
|
||||
self.unify(self[temp_v!(3)].clone(), p);
|
||||
}
|
||||
},
|
||||
Addr::Con(Constant::Usize(e)) => {
|
||||
if e == 0 {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// get the call site so that the number of active permanent variables can be read
|
||||
// from it later.
|
||||
let cp = (self.stack.index_and_frame(e).prelude.cp - 1).unwrap();
|
||||
|
||||
let p = cp.as_functor(&mut self.heap);
|
||||
let e = self.stack.index_and_frame(e).prelude.e;
|
||||
|
||||
let e = Addr::Con(Constant::Usize(e));
|
||||
|
||||
self.unify(self[temp_v!(2)].clone(), e);
|
||||
|
||||
if !self.fail {
|
||||
self.unify(self[temp_v!(3)].clone(), p);
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
&SystemClauseType::PointsToContinuationResetMarker => {
|
||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
let p = match self.heap.to_local_code_ptr(&addr) {
|
||||
Some(p) => p + 1,
|
||||
None => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
if p.is_reset_cont_marker(code_repo, self.last_call) {
|
||||
return return_from_clause!(self.last_call, self);
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
&SystemClauseType::ReadQueryTerm => {
|
||||
readline::set_prompt(true);
|
||||
let result = self.read_term(current_input_stream, indices);
|
||||
@@ -2013,6 +2197,8 @@ impl MachineState {
|
||||
self.reset_block(addr);
|
||||
}
|
||||
&SystemClauseType::ResetContinuationMarker => {
|
||||
self[temp_v!(3)] = Addr::Con(Constant::Integer(Integer::from(0)));
|
||||
self[temp_v!(4)] = Addr::Con(Constant::Integer(Integer::from(0)));
|
||||
}
|
||||
&SystemClauseType::SetBall =>
|
||||
self.set_ball(),
|
||||
@@ -2123,6 +2309,22 @@ impl MachineState {
|
||||
|
||||
self.unify_with_occurs_check(a1, a2);
|
||||
}
|
||||
&SystemClauseType::UnwindEnvironments => {
|
||||
let mut e = self.e;
|
||||
let mut cp = self.cp;
|
||||
|
||||
while e > 0 {
|
||||
if cp.is_reset_cont_marker(code_repo, self.last_call) {
|
||||
self.e = e;
|
||||
self.p = CodePtr::Local(cp + 1); // skip the reset marker.
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
cp = self.stack.index_and_frame(e).prelude.cp;
|
||||
e = self.stack.index_and_frame(e).prelude.e;
|
||||
}
|
||||
}
|
||||
&SystemClauseType::UnwindStack => self.unwind_stack(),
|
||||
&SystemClauseType::Variant => self.fail = self.structural_eq_test(),
|
||||
&SystemClauseType::WAMInstructions => {
|
||||
|
||||
Reference in New Issue
Block a user