make system calls exempt from call policy.
This commit is contained in:
@@ -19,7 +19,7 @@ impl BrentAlgState {
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
impl MachineState {
|
||||
// a step in Brent's algorithm.
|
||||
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
||||
{
|
||||
@@ -54,8 +54,7 @@ impl MachineState {
|
||||
pub(super) fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult
|
||||
{
|
||||
let addr = self.store(self.deref(addr));
|
||||
|
||||
let mut hare = match addr {
|
||||
let hare = match addr {
|
||||
Addr::Lis(offset) if max_steps > 0 => offset + 1,
|
||||
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
|
||||
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
|
||||
@@ -63,7 +62,7 @@ impl MachineState {
|
||||
};
|
||||
|
||||
let mut brent_st = BrentAlgState::new(hare);
|
||||
|
||||
|
||||
loop {
|
||||
if brent_st.steps == max_steps {
|
||||
return CycleSearchResult::PartialList(brent_st.steps, brent_st.hare);
|
||||
@@ -78,22 +77,21 @@ impl MachineState {
|
||||
pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult
|
||||
{
|
||||
let addr = self.store(self.deref(addr));
|
||||
|
||||
let mut hare = match addr {
|
||||
let hare = match addr {
|
||||
Addr::Lis(offset) => offset + 1,
|
||||
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
|
||||
_ => return CycleSearchResult::NotList
|
||||
};
|
||||
|
||||
let mut brent_st = BrentAlgState::new(hare);
|
||||
|
||||
|
||||
loop {
|
||||
if let Some(result) = self.brents_alg_step(&mut brent_st) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) {
|
||||
let target_n = self[temp_v!(1)].clone();
|
||||
self.unify(Addr::Con(integer!(n)), target_n);
|
||||
@@ -111,7 +109,7 @@ impl MachineState {
|
||||
Number::Integer(ref max_steps)
|
||||
if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) => {
|
||||
let n = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
|
||||
match n {
|
||||
Addr::Con(Constant::Number(Number::Integer(ref n))) if n.is_zero() => {
|
||||
let xs0 = self[temp_v!(3)].clone();
|
||||
@@ -152,5 +150,97 @@ impl MachineState {
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn system_call(&mut self, ct: &SystemClauseType) -> CallResult
|
||||
{
|
||||
match ct {
|
||||
&SystemClauseType::CleanUpBlock => {
|
||||
let nb = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match nb {
|
||||
Addr::Con(Constant::Usize(nb)) => {
|
||||
let b = self.b - 1;
|
||||
|
||||
if nb > 0 && self.or_stack[b].b == nb {
|
||||
self.b = self.or_stack[nb - 1].b;
|
||||
self.or_stack.truncate(self.b);
|
||||
}
|
||||
},
|
||||
_ => self.fail = true
|
||||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::EraseBall => {
|
||||
self.ball.reset();
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::Fail => {
|
||||
self.fail = true;
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::GetBall => {
|
||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let h = self.heap.h;
|
||||
|
||||
if self.ball.stub.len() > 0 {
|
||||
self.copy_and_align_ball_to_heap();
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ball = self.heap[h].as_addr(h);
|
||||
|
||||
match addr.as_var() {
|
||||
Some(r) => self.bind(r, ball),
|
||||
_ => self.fail = true
|
||||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::GetCurrentBlock => {
|
||||
let c = Constant::Usize(self.block);
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
self.write_constant_to_var(addr, c);
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::GetCutPoint(r) => {
|
||||
let c = Constant::Usize(self.b);
|
||||
self[r] = Addr::Con(c);
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::InstallNewBlock => {
|
||||
self.block = self.b;
|
||||
|
||||
let c = Constant::Usize(self.block);
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
self.write_constant_to_var(addr, c);
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::ResetBlock => {
|
||||
let addr = self.deref(self[temp_v!(1)].clone());
|
||||
self.reset_block(addr);
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::SetBall => {
|
||||
self.set_ball();
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::SkipMaxList => {
|
||||
self.skip_max_list()?;
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::Succeed => {
|
||||
Ok(())
|
||||
},
|
||||
&SystemClauseType::UnwindStack => {
|
||||
self.unwind_stack();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user