]> Repositorios git - scryer-prolog.git/commitdiff
throw exceptions when calling non-existent predicates. broken.
authorMark Thom <[email protected]>
Sun, 8 Apr 2018 21:17:58 +0000 (15:17 -0600)
committerMark Thom <[email protected]>
Sun, 8 Apr 2018 21:17:58 +0000 (15:17 -0600)
src/prolog/ast.rs
src/prolog/io.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/macros.rs

index 47fbf49cc935fabf0aaa4a62c030ef313b49aa18..fcb3356e636305008af73926421824f029f77ce5 100644 (file)
@@ -103,7 +103,7 @@ impl GenContext {
 
 pub struct Predicate(pub Vec<PredicateClause>);
 
-impl Predicate {    
+impl Predicate {
     pub fn clauses(self) -> Vec<PredicateClause> {
         self.0
     }
@@ -1400,18 +1400,23 @@ impl HeapCellValue {
     }
 }
 
+#[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)
     }
 }
 
@@ -1444,12 +1449,6 @@ impl PartialOrd<CodePtr> for CodePtr {
     }
 }
 
-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)
index 690b09b5c800ed79259b24604defa8404a163112..010306f0aa8150cac520f91750e1d677c9c03fb3 100644 (file)
@@ -13,6 +13,16 @@ use termion::event::Key;
 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())
@@ -461,10 +471,10 @@ impl TLInfo for DeclInfo {
     {
         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));
             }
         }
 
@@ -669,7 +679,7 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
 
                 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);
             }
         }
index ab3f4c7817d978d05c399cecf92dc549674af283..cecaf6fd2b045007cae97996dc1445ea52d2c0f1 100644 (file)
@@ -210,46 +210,62 @@ pub struct MachineState {
 
 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(())
@@ -412,8 +428,8 @@ pub(crate) trait CallPolicy: Any {
             },
             &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;
                     }
@@ -519,8 +535,8 @@ pub(crate) trait CallPolicy: Any {
                 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(())
index cbbbe9ee033d1a429792fd139bbf9cd60455aaef..da5aba13b16853ad70b1818e51f30212901ce4bb 100644 (file)
@@ -909,8 +909,8 @@ impl MachineState {
             self.registers[arity - 1] = pred;
 
             if let Some((name, arity)) = self.setup_call_n(arity - 1) {
-                if let Some(idx) = code_dirs.get(name, arity, &self.p.clone()) {
-                    try_or_fail!(self, call_policy.try_execute(self, arity, idx));
+                if let Some(idx) = code_dirs.get(name.clone(), arity, &self.p.clone()) {
+                    try_or_fail!(self, call_policy.try_execute(self, name, arity, idx));
                     return;
                 }
             }
index c06ecc3a88c660adc0bd64cdb5d4d1c7f84676d3..10ed207472f191e362f19b73556a82a6d4d631ab 100644 (file)
@@ -180,7 +180,9 @@ impl Machine {
     {
         match self.code_dir.get(&(name.clone(), arity)) {
             Some(&CodeIndex (_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
-                return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
+                return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}",
+                                                                               name,
+                                                                               arity))),
             _ => {}
         };
 
@@ -192,7 +194,7 @@ impl Machine {
         let entry = self.code_dir.entry((name, arity))
             .or_insert(CodeIndex::from((offset, clause_name!("user"))));
 
-        entry.0.set(offset);
+        entry.0.set(IndexPtr::Index(offset));
         entry.1 = clause_name!("user");
         
         EvalSession::EntrySuccess
index c48418ea12b5f14387646f4db1f66e89308f0ea7..05a5fff942d0fe1600ad638d95175c09eab74b88 100644 (file)
@@ -55,6 +55,18 @@ macro_rules! query {
     )
 }
 
+macro_rules! heap_str {
+    ($s:expr) => (
+        HeapCellValue::Addr(Addr::Str($s))
+    )
+}
+
+macro_rules! heap_integer {
+    ($i:expr) => (
+        HeapCellValue::Addr(Addr::Con(integer!($i)))
+    )
+}
+
 macro_rules! heap_atom {
     ($name:expr) => (
         HeapCellValue::Addr(Addr::Con(atom!($name)))
@@ -70,6 +82,9 @@ macro_rules! functor {
     );
     ($name:expr, $len:expr, [$($args:expr),*]) => (
         vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
+    );
+    ($name:expr, $len:expr, [$($args:expr),*], $fix: expr) => (
+        vec![ HeapCellValue::NamedStr($len, clause_name!($name), Some($fix)), $($args),* ]
     )
 }