]> Repositorios git - scryer-prolog.git/commitdiff
simplify detecting undefined goal_ and term_expansion
authorMark Thom <[email protected]>
Wed, 8 Jun 2022 03:45:26 +0000 (21:45 -0600)
committerMark Thom <[email protected]>
Mon, 13 Jun 2022 04:34:07 +0000 (22:34 -0600)
build/instructions_template.rs
src/loader.pl
src/machine/dispatch.rs
src/machine/system_calls.rs

index 0cf0a6b5d916f19daac15e0e3294f7254a208c46..336cf395ca20c89cb3cfefa87637472d6fc0ec6d 100644 (file)
@@ -542,6 +542,8 @@ enum SystemClauseType {
     DeterministicLengthRundown,
     #[strum_discriminants(strum(props(Arity = "7", Name = "$http_open")))]
     HttpOpen,
+    #[strum_discriminants(strum(props(Arity = "3", Name = "$predicate_defined")))]
+    PredicateDefined,
     REPL(REPLCodePtr),
 }
 
@@ -1665,6 +1667,7 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::CallCpuNow(_) |
                     &Instruction::CallDeterministicLengthRundown(_) |
                     &Instruction::CallHttpOpen(_) |
+                    &Instruction::CallPredicateDefined(_) |
                     &Instruction::CallCurrentTime(_) |
                     &Instruction::CallQuotedToken(_) |
                     &Instruction::CallReadTermFromChars(_) |
@@ -1869,6 +1872,7 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::ExecuteCpuNow(_) |
                     &Instruction::ExecuteDeterministicLengthRundown(_) |
                     &Instruction::ExecuteHttpOpen(_) |
+                    &Instruction::ExecutePredicateDefined(_) |
                     &Instruction::ExecuteCurrentTime(_) |
                     &Instruction::ExecuteQuotedToken(_) |
                     &Instruction::ExecuteReadTermFromChars(_) |
index ba036061c043994641e99e0d12c09739b00f6e33..4738494a8b51da3949304d85d5c503262b36df17 100644 (file)
@@ -34,23 +34,13 @@ write_error(Error) :-
     write('.').
 
 '$print_message_and_fail'(Error) :-
-    (  (  Error = error(existence_error(procedure, Expansion), Expansion)
-       ;  Error = error(evaluation_error((_:_)/_),Expansion)
-       )  ->
-       (  (  Expansion = goal_expansion/2
-          ;  Expansion = term_expansion/2
-          )  ->
-          true
-       ;  write_error(Error),
-          nl
-       )
-    ;  write_error(Error),
-       nl
-    ),
+    write_error(Error),
+    nl,
     '$fail'.
 
 expand_term(Term, ExpandedTerm) :-
-    (  catch('$call'(user:term_expansion(Term, ExpandedTerm0)),
+    (  '$predicate_defined'(user, term_expansion, 2),
+       catch('$call'(user:term_expansion(Term, ExpandedTerm0)),
              E,
              '$call'(loader:'$print_message_and_fail'(E))) ->
        (  var(ExpandedTerm0) ->
@@ -77,6 +67,7 @@ term_expansion_list([Term|Terms], ExpandedTermsHead, ExpandedTermsTail) :-
 
 goal_expansion(Goal, Module, ExpandedGoal) :-
     (  atom(Module),
+       '$predicate_defined'(Module, goal_expansion, 2),
        catch('$call'(Module:goal_expansion(Goal, ExpandedGoal0)),
              E,
              '$call'(loader:'$print_message_and_fail'(E))) ->
index 3664ebee6d204b8f4f2cae2800a85b8f752604b5..0e0baade15b0aa20c7b255565de012c9d1c0c20a 100644 (file)
@@ -4851,6 +4851,14 @@ impl Machine {
                     try_or_throw!(self.machine_st, self.add_non_counted_backtracking());
                     self.machine_st.p = self.machine_st.cp;
                 }
+                &Instruction::CallPredicateDefined(_) => {
+                    self.machine_st.fail = !self.predicate_defined();
+                    self.machine_st.p += 1;
+                }
+                &Instruction::ExecutePredicateDefined(_) => {
+                    self.machine_st.fail = !self.predicate_defined();
+                    self.machine_st.p = self.machine_st.cp;
+                }
             }
         }
 
index 6e9e7a1a3035904fbded1250fb00a016c256153c..9a2cd575327941d71ca711225e3fcb813e881be6 100644 (file)
@@ -3771,6 +3771,39 @@ impl Machine {
         self.machine_st.fail = !self.indices.modules.contains_key(&module_name);
     }
 
+    pub(crate) fn predicate_defined(&self) -> bool {
+        let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+            self.machine_st.registers[1]
+        )));
+
+        let name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+            self.machine_st.registers[2]
+        )));
+
+        let arity = match Number::try_from(self.machine_st.store(self.machine_st.deref(
+            self.machine_st.registers[3]
+        ))) {
+            Ok(Number::Fixnum(n))  => n.get_num() as usize,
+            Ok(Number::Integer(n)) => {
+                if let Some(n) = n.to_usize() {
+                    n
+                } else {
+                    return false;
+                }
+            }
+            _ => {
+                unreachable!()
+            }
+        };
+
+        self.indices.get_predicate_code_index(
+            name,
+            arity,
+            module_name,
+        ).map(|index| index.local().is_some())
+         .unwrap_or(false)
+    }
+
     #[inline(always)]
     pub(crate) fn no_such_predicate(&mut self) -> CallResult {
         let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(