]> Repositorios git - scryer-prolog.git/commitdiff
add domain and type errors for compare/3 (#296)
authorMark Thom <[email protected]>
Sat, 18 Apr 2020 20:37:14 +0000 (14:37 -0600)
committerMark Thom <[email protected]>
Sat, 18 Apr 2020 20:37:14 +0000 (14:37 -0600)
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_state.rs

index 3e366322590dcaaaaf8341558416a67a1b9c1b5d..c5173afc035a753fc6a4ccee91ba58729483f7b4 100644 (file)
@@ -505,6 +505,7 @@ impl ValidType {
 #[derive(Clone, Copy)]
 pub enum DomainErrorType {
     NotLessThanZero,
+    Order,
     Stream,
     StreamOrAlias,
 }
@@ -513,6 +514,7 @@ impl DomainErrorType {
     pub fn as_str(self) -> &'static str {
         match self {
             DomainErrorType::NotLessThanZero => "not_less_than_zero",
+            DomainErrorType::Order => "order",
             DomainErrorType::Stream => "stream",
             DomainErrorType::StreamOrAlias => "stream_or_alias",
         }
index 9f50f530d0b8f20cbce2cded0f66c2a929c0881c..cc9a74c238e9d09fd5c10ddce727d4006a14050a 100644 (file)
@@ -1076,10 +1076,38 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             }
             &BuiltInClauseType::Compare => {
-                let a1 = machine_st[temp_v!(1)];
+                let a1 = machine_st.store(machine_st.deref(machine_st[temp_v!(1)]));
                 let a2 = machine_st[temp_v!(2)];
                 let a3 = machine_st[temp_v!(3)];
 
+                match a1 {
+                    Addr::Con(h) if machine_st.heap.atom_at(h) => {
+                        if let HeapCellValue::Atom(ref atom, _) = &machine_st.heap[h] {
+                            match atom.as_str() {
+                                ">" | "<" | "=" => {
+                                }
+                                _ => {
+                                    let stub =
+                                        MachineError::functor_stub(clause_name!("compare"), 3);
+
+                                    let err = MachineError::domain_error(DomainErrorType::Order, a1);
+                                    return Err(machine_st.error_form(err, stub));
+                                }
+                            }
+                        } else {
+                            unreachable!()
+                        }
+                    }
+                    addr if !addr.is_ref() => {
+                        let h = machine_st.heap.h();
+                        let stub = MachineError::functor_stub(clause_name!("compare"), 3);
+                        let err = MachineError::type_error(h, ValidType::Atom, a1);
+                        return Err(machine_st.error_form(err, stub));
+                    }
+                    _ => {
+                    }
+                }
+
                 let atom = match machine_st.compare_term_test(&a2, &a3) {
                     Some(Ordering::Greater) => {
                         let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);