pub struct Predicate(pub Vec<PredicateClause>);
-impl Predicate {
+impl Predicate {
pub fn clauses(self) -> Vec<PredicateClause> {
self.0
}
}
}
+#[derive(Clone, Copy, PartialEq)]
+pub enum IndexPtr {
+ Undefined, Index(usize)
+}
+
#[derive(Clone)]
-pub struct CodeIndex(pub Rc<Cell<usize>>, pub ClauseName);
+pub struct CodeIndex(pub Rc<Cell<IndexPtr>>, pub ClauseName);
-impl CodeIndex {
- pub fn is_undefined(&self) -> bool {
- self.0.get() == 0 && self.1 == clause_name!("")
+impl Default for CodeIndex {
+ fn default() -> Self {
+ CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)), clause_name!(""))
}
}
impl From<(usize, ClauseName)> for CodeIndex {
fn from(value: (usize, ClauseName)) -> Self {
- CodeIndex(Rc::new(Cell::new(value.0)), value.1)
+ CodeIndex(Rc::new(Cell::new(IndexPtr::Index(value.0))), value.1)
}
}
}
}
-impl Default for CodeIndex {
- fn default() -> Self {
- CodeIndex(Rc::new(Cell::new(0)), clause_name!(""))
- }
-}
-
impl Default for CodePtr {
fn default() -> Self {
CodePtr::TopLevel(0, 0)
use std::io::{Write, stdin, stdout};
use std::fmt;
+
+impl fmt::Display for IndexPtr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &IndexPtr::Undefined => write!(f, "undefined"),
+ &IndexPtr::Index(i) => write!(f, "{}", i)
+ }
+ }
+}
+
impl fmt::Display for ClauseName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
{
let (name, arity) = (self.name.clone(), self.arity);
- if entry.0.get() == 0 {
+ if entry.0.get() == IndexPtr::Undefined {
if &name == n1 && arity == a1 {
// *entry = default(); // implement logical view update semantics.
- entry.0.set(code_size);
+ entry.0.set(IndexPtr::Index(code_size));
}
}
code.extend(decl_code.into_iter());
- let index = CodeIndex::from((p, get_module_name(&module)));
+ let index = CodeIndex::default();
code_dir.insert((decl_info.name.clone(), decl_info.arity), index);
}
}
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
+fn predicate_existence_error(name: ClauseName, arity: usize) -> Vec<HeapCellValue>
+{
+ let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
+
+ let mut error = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(4)]);
+ error.append(&mut functor!("/", 2, [name, heap_integer!(arity)], Fixity::In));
+
+ error
+}
+
pub(crate) trait CallPolicy: Any {
- fn context_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex, lco: bool)
+ fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
+ arity: usize, idx: CodeIndex, lco: bool)
-> CallResult
{
if lco {
- self.try_execute(machine_st, arity, idx)
+ self.try_execute(machine_st, name, arity, idx)
} else {
- self.try_call(machine_st, arity, idx)
+ self.try_call(machine_st, name, arity, idx)
}
}
- fn try_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex) -> CallResult
- {
- if idx.is_undefined() {
- machine_st.fail = true;
- } else {
- let compiled_tl_index = idx.0.get();
- let module_name = idx.1;
-
- machine_st.cp = machine_st.p.clone() + 1;
- machine_st.num_of_args = arity;
- machine_st.b0 = machine_st.b;
- machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
+ fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
+ arity: usize, idx: CodeIndex)
+ -> CallResult
+ {
+ match idx.0.get() {
+ IndexPtr::Undefined =>
+ return Err(predicate_existence_error(name, arity)),
+ IndexPtr::Index(compiled_tl_index) => {
+ let module_name = idx.1;
+
+ machine_st.cp = machine_st.p.clone() + 1;
+ machine_st.num_of_args = arity;
+ machine_st.b0 = machine_st.b;
+ machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
+ }
}
Ok(())
}
- fn try_execute<'a>(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex)
+ fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName,
+ arity: usize, idx: CodeIndex)
-> CallResult
- {
- if idx.is_undefined() {
- machine_st.fail = true;
- } else {
- let compiled_tl_index = idx.0.get();
- let module_name = idx.1;
+ {
+ match idx.0.get() {
+ IndexPtr::Undefined =>
+ return Err(predicate_existence_error(name, arity)),
+ IndexPtr::Index(compiled_tl_index) => {
+ let module_name = idx.1;
- machine_st.num_of_args = arity;
- machine_st.b0 = machine_st.b;
- machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
+ machine_st.num_of_args = arity;
+ machine_st.b0 = machine_st.b;
+ machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
+ }
}
Ok(())
},
&ClauseType::CallN => {
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
- if let Some(idx) = code_dirs.get(name, arity, &machine_st.p.clone()) {
- return self.context_call(machine_st, arity, idx, lco);
+ if let Some(idx) = code_dirs.get(name.clone(), arity, &machine_st.p.clone()) {
+ return self.context_call(machine_st, name, arity, idx, lco);
} else {
machine_st.fail = true;
}
machine_st.goto_throw();
Ok(())
},
- &ClauseType::Named(_, ref idx) | &ClauseType::Op(_, _, ref idx) =>
- self.context_call(machine_st, arity, idx.clone(), lco),
+ &ClauseType::Named(ref name, ref idx) | &ClauseType::Op(ref name, _, ref idx) =>
+ self.context_call(machine_st, name.clone(), arity, idx.clone(), lco),
&ClauseType::CallWithInferenceLimit => {
machine_st.goto_ptr(CodePtr::DirEntry(409, clause_name!("builtin")), 3, lco);
Ok(())