]> Repositorios git - scryer-prolog.git/commitdiff
Add test for programatic queries
authorNicolas Luck <[email protected]>
Wed, 12 Jul 2023 09:57:53 +0000 (11:57 +0200)
committerNicolas Luck <[email protected]>
Wed, 12 Jul 2023 09:57:53 +0000 (11:57 +0200)
Cargo.lock
Cargo.toml
src/lib.rs
src/machine/mod.rs
src/machine/parsed_results.rs

index 05e549112a72f1c577fcf58bcee5fef910b3c3d1..29cf7f677cf9769acb652bf3992776f92980676b 100644 (file)
@@ -1004,6 +1004,12 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
 [[package]]
 name = "markup5ever"
 version = "0.8.1"
@@ -1833,6 +1839,7 @@ dependencies = [
  "lazy_static",
  "lexical",
  "libc",
+ "maplit",
  "modular-bitfield",
  "native-tls",
  "ordered-float",
index 6e42de23b6fbb85bbd76a9e9e8407315ff73d875..a6f97b04695712b17ccbc3eb26da529ce0e339d7 100644 (file)
@@ -68,6 +68,7 @@ futures = "0.3"
 assert_cmd = "1.0.3"
 predicates-core = "1.0.2"
 serial_test = "0.5.1"
+maplit = "1.0.2"
 
 [patch.crates-io]
 modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" }
index 2846fd0e64448dbfe4ad778e2cb26cf801153a2e..d643296fb373fa7093ff391bae5fb4f92fa87c8c 100644 (file)
@@ -2,6 +2,8 @@
 
 #[macro_use]
 extern crate static_assertions;
+#[cfg(test)]
+#[macro_use] extern crate maplit;
 
 #[macro_use]
 pub mod macros;
index 1aca907f6d4d427d88eff5d9f0e16feb65ff4f21..c45d7cb49fa0b39a07aa0c2d9c52d77deec47dcd 100644 (file)
@@ -936,3 +936,40 @@ impl Machine {
         }
     }
 }
+
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn programatic_query() {
+        let mut machine = Machine::with_test_streams();
+
+        machine.load_module_string("facts", String::from(r#"
+            triple("a", "p1", "b").
+            triple("a", "p2", "b").
+        "#));
+        
+        let query = String::from(r#"triple("a",P,"b")."#);
+        let output = machine.run_query(query);
+        assert_eq!(output, QueryResult::Matches(vec![
+            QueryMatch::from(btreemap!{
+                "P" => Value::from("p1"),
+            }),
+            QueryMatch::from(btreemap!{
+                "P" => Value::from("p2"),
+            }),
+        ]));
+
+        assert_eq!(
+            machine.run_query(String::from(r#"triple("a","p1","b")."#)), 
+            QueryResult::True
+        );
+
+        assert_eq!(
+            machine.run_query(String::from(r#"triple("x","y","z")."#)), 
+            QueryResult::False
+        );
+    }
+}
index 3b47ad6b4d80457f7e8fab3b063b78c4834c8205..984c74395f39cc02dc9c70c2ce543536bb2259f1 100644 (file)
@@ -8,7 +8,12 @@ use crate::atom_table::*;
 pub enum QueryResult {
     True,
     False,
-    Matches(Vec<QueryResultLine>),
+    Matches(Vec<QueryMatch>),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct QueryMatch {
+    pub bindings: BTreeMap<String, Value>
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -30,6 +35,24 @@ pub enum Value {
     Var,
 }
 
+impl From<BTreeMap<&str, Value>> for QueryMatch {
+    fn from(bindings: BTreeMap<&str, Value>) -> Self {
+        QueryMatch {
+            bindings: bindings.into_iter()
+                .map(|(k, v)| (k.to_string(), v))
+                .collect::<BTreeMap<_, _>>()
+        }
+    }
+}
+
+impl From<BTreeMap<String, Value>> for QueryMatch {
+    fn from(bindings: BTreeMap<String, Value>) -> Self {
+        QueryMatch {
+            bindings
+        }
+    }
+}
+
 impl From<Vec<QueryResultLine>> for QueryResult {
     fn from(query_result_lines: Vec<QueryResultLine>) -> Self {
         // If there is only one line, and it is true or false, return that.
@@ -50,14 +73,21 @@ impl From<Vec<QueryResultLine>> for QueryResult {
         }
 
         // If there is at least one match, return all matches.
-        if query_result_lines.iter().any(|l| {
-            if let &QueryResultLine::Match(_) = l { true } else { false }
-        }) {
-            let all_matches = query_result_lines.into_iter()
-                .filter(|l| {
-                    if let &QueryResultLine::Match(_) = l { true } else { false }
-                })
-                .collect::<Vec<_>>();
+        let all_matches = query_result_lines.into_iter()
+            .filter(|l| {
+                if let &QueryResultLine::Match(_) = l { true } else { false }
+            })
+            .map(|l| {
+                match l {
+                    QueryResultLine::Match(m) => {
+                        QueryMatch::from(m)
+                    },
+                    _ => unreachable!()
+                }
+            })
+            .collect::<Vec<_>>();
+
+        if !all_matches.is_empty() {
             return QueryResult::Matches(all_matches);
         }
 
@@ -145,4 +175,10 @@ impl TryFrom<String> for Value {
             Err(())
         }
     }
+}
+
+impl From<&str> for Value {
+    fn from(str: &str) -> Self {
+        Value::String(str.to_string())
+    }
 }
\ No newline at end of file