system calls preliminary

This commit is contained in:
Mark Thom
2018-05-07 22:27:58 -06:00
parent a1bfcf4c9d
commit 1a0f50200f
5 changed files with 52 additions and 187 deletions

View File

@@ -683,6 +683,26 @@ pub struct Rule {
pub clauses: Vec<QueryTerm>
}
#[derive(Clone)]
pub enum SystemClauseType {
SkipMaxList
}
impl SystemClauseType {
pub fn name(&self) -> ClauseName {
match self {
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
}
}
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
_ => None
}
}
}
#[derive(Clone)]
pub enum ClauseType {
AcyclicTerm,
@@ -705,8 +725,8 @@ pub enum ClauseType {
Op(ClauseName, Fixity, CodeIndex),
Named(ClauseName, CodeIndex),
SetupCallCleanup,
SkipMaxList,
Sort,
System(SystemClauseType),
Throw,
}
@@ -788,14 +808,14 @@ impl ClauseType {
pub fn name(&self) -> ClauseName {
match self {
&ClauseType::AcyclicTerm => clause_name!("acyclic_term"),
&ClauseType::AcyclicTerm => clause_name!("$acyclic_term"),
&ClauseType::Arg => clause_name!("arg"),
&ClauseType::CallN => clause_name!("call"),
&ClauseType::CallWithInferenceLimit => clause_name!("call_with_inference_limit"),
&ClauseType::Catch => clause_name!("catch"),
&ClauseType::Compare => clause_name!("compare"),
&ClauseType::CompareTerm(qt) => clause_name!(qt.name()),
&ClauseType::CyclicTerm => clause_name!("cyclic_term"),
&ClauseType::CyclicTerm => clause_name!("$cyclic_term"),
&ClauseType::Display => clause_name!("display"),
&ClauseType::DuplicateTerm => clause_name!("duplicate_term"),
&ClauseType::Eq => clause_name!("=="),
@@ -803,26 +823,26 @@ impl ClauseType {
&ClauseType::Ground => clause_name!("ground"),
&ClauseType::Inlined(inlined) => clause_name!(inlined.name()),
&ClauseType::Is => clause_name!("is"),
&ClauseType::KeySort => clause_name!("keysort"),
&ClauseType::KeySort => clause_name!("$keysort"),
&ClauseType::NotEq => clause_name!("\\=="),
&ClauseType::Op(ref name, ..) => name.clone(),
&ClauseType::Named(ref name, ..) => name.clone(),
&ClauseType::SetupCallCleanup => clause_name!("setup_call_cleanup"),
&ClauseType::SkipMaxList => clause_name!("$skip_max_list"),
&ClauseType::Sort => clause_name!("sort"),
&ClauseType::System(ref system) => system.name(),
&ClauseType::Sort => clause_name!("$sort"),
&ClauseType::Throw => clause_name!("throw")
}
}
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
match (name.as_str(), arity) {
("acyclic_term", 1) => ClauseType::AcyclicTerm,
("$acyclic_term", 1) => ClauseType::AcyclicTerm,
("arg", 3) => ClauseType::Arg,
("call", _) => ClauseType::CallN,
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
("catch", 3) => ClauseType::Catch,
("compare", 3) => ClauseType::Compare,
("cyclic_term", 1) => ClauseType::CyclicTerm,
("$cyclic_term", 1) => ClauseType::CyclicTerm,
("@>", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThan),
("@<", 2) => ClauseType::CompareTerm(CompareTermQT::LessThan),
("@>=", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual),
@@ -835,11 +855,10 @@ impl ClauseType {
("functor", 3) => ClauseType::Functor,
("ground", 1) => ClauseType::Ground,
("is", 2) => ClauseType::Is,
("keysort", 2) => ClauseType::KeySort,
("$keysort", 2) => ClauseType::KeySort,
("\\==", 2) => ClauseType::NotEq,
("setup_call_cleanup", 3) => ClauseType::SetupCallCleanup,
("$skip_max_list", 4) => ClauseType::SkipMaxList,
("sort", 2) => ClauseType::Sort,
("$sort", 2) => ClauseType::Sort,
("throw", 1) => ClauseType::Throw,
_ => if let Some(fixity) = fixity {
ClauseType::Op(name, fixity, CodeIndex::default())

View File

@@ -736,7 +736,6 @@ fn get_builtins() -> Code {
keysort_execute!(), // keysort/2, 484.
acyclic_term_execute!(), // acyclic_term/1, 485.
cyclic_term_execute!(), // cyclic_term/1, 486.
skip_max_list_execute!() // '$skip_max_list', 487.
]
}
@@ -856,7 +855,6 @@ pub fn build_code_and_op_dirs() -> (CodeDir, OpDir)
code_dir.insert((clause_name!("keysort"), 2), CodeIndex::from((484, builtin.clone())));
code_dir.insert((clause_name!("acyclic_term"), 1), CodeIndex::from((485, builtin.clone())));
code_dir.insert((clause_name!("cyclic_term"), 1), CodeIndex::from((486, builtin.clone())));
code_dir.insert((clause_name!("$skip_max_list"), 4), CodeIndex::from((487, builtin.clone())));
(code_dir, op_dir)
}

View File

@@ -569,11 +569,9 @@ pub(crate) trait CallPolicy: Any {
machine_st.execute_inlined(inlined, &vec![temp_v!(1), temp_v!(2)]);
Ok(())
},
&ClauseType::SkipMaxList => {
machine_st.skip_max_list()?;
machine_st.p += 1;
Ok(())
&ClauseType::System(ref system) => {
machine_st.execute_system(system)?;
return_from_clause!(lco, machine_st)
}
}
}

View File

@@ -1841,157 +1841,6 @@ 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 {
Addr::Lis(offset) if max_steps > 0 => offset + 1,
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
_ => return CycleSearchResult::NotList
};
// use Brent's algorithm to detect cycles.
let mut tortoise = hare;
let mut power = 2;
let mut steps = 1;
loop {
if steps == max_steps {
return CycleSearchResult::PartialList(steps, hare);
}
match self.heap[hare].clone() {
HeapCellValue::Addr(Addr::Lis(l)) => {
hare = l + 1;
steps += 1;
if tortoise == hare {
return CycleSearchResult::NotList;
} else if steps == power {
tortoise = hare;
power <<= 1;
}
},
HeapCellValue::NamedStr(..) =>
return CycleSearchResult::NotList,
HeapCellValue::Addr(addr) =>
match self.store(self.deref(addr)) {
Addr::Con(Constant::EmptyList) =>
return CycleSearchResult::ProperList(steps),
Addr::HeapCell(_) | Addr::StackCell(..) =>
return CycleSearchResult::PartialList(steps, hare),
_ =>
return CycleSearchResult::NotList
}
}
}
}
pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult
{
let addr = self.store(self.deref(addr));
let mut hare = match addr {
Addr::Lis(offset) => offset + 1,
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
_ => return CycleSearchResult::NotList
};
// use Brent's algorithm to detect cycles.
let mut tortoise = hare;
let mut power = 2;
let mut steps = 1;
loop {
match self.heap[hare].clone() {
HeapCellValue::Addr(Addr::Lis(l)) => {
hare = l + 1;
steps += 1;
if tortoise == hare {
return CycleSearchResult::NotList;
} else if steps == power {
tortoise = hare;
power <<= 1;
}
},
HeapCellValue::NamedStr(..) =>
return CycleSearchResult::NotList,
HeapCellValue::Addr(addr) =>
match self.store(self.deref(addr)) {
Addr::Con(Constant::EmptyList) =>
return CycleSearchResult::ProperList(steps),
Addr::HeapCell(_) | Addr::StackCell(..) =>
return CycleSearchResult::PartialList(steps, hare),
_ =>
return CycleSearchResult::NotList
}
}
}
}
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);
if !self.fail {
let xs = self[temp_v!(4)].clone();
self.unify(addr, xs);
}
}
pub(super) fn skip_max_list(&mut self) -> Result<(), MachineError> {
let max_steps = self.arith_eval_by_metacall(temp_v!(2))?;
match max_steps {
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();
let xs = self[temp_v!(4)].clone();
self.unify(xs0, xs);
},
_ => {
let search_result = if let Some(max_steps) = max_steps.to_isize() {
if max_steps == -1 {
self.detect_cycles(self[temp_v!(3)].clone())
} else {
self.detect_cycles_with_max(max_steps as usize,
self[temp_v!(3)].clone())
}
} else {
self.detect_cycles(self[temp_v!(3)].clone())
};
match search_result {
CycleSearchResult::UntouchedList(l) =>
self.finalize_skip_max_list(0, Addr::Lis(l)),
CycleSearchResult::EmptyList =>
self.finalize_skip_max_list(0, Addr::Con(Constant::EmptyList)),
CycleSearchResult::PartialList(n, hc) =>
self.finalize_skip_max_list(n, Addr::HeapCell(hc)),
CycleSearchResult::ProperList(n) =>
self.finalize_skip_max_list(n, Addr::Con(Constant::EmptyList)),
CycleSearchResult::NotList => {
let xs0 = self[temp_v!(3)].clone();
self.finalize_skip_max_list(0, xs0);
}
}
}
}
},
_ => self.fail = true
};
Ok(())
}
pub(super) fn duplicate_term(&mut self) {
let old_h = self.heap.h;

View File

@@ -7,6 +7,7 @@ mod machine_errors;
pub(super) mod machine_state;
#[macro_use]
mod machine_state_impl;
mod system_calls;
use prolog::machine::machine_state::*;