type QueryResult = Result<QueryResolution, String>

This commit is contained in:
Nicolas Luck
2023-07-20 22:31:20 +02:00
parent cae32d6a00
commit 7c93450aa7
2 changed files with 27 additions and 25 deletions

View File

@@ -1,17 +1,17 @@
use super::{Machine, MachineConfig, QueryResult, QueryResultLine, Atom}; use super::{Machine, MachineConfig, QueryResult, QueryResolution, QueryResolutionLine, Atom};
impl Machine { impl Machine {
pub fn new_lib() -> Self { pub fn new_lib() -> Self {
Machine::new(MachineConfig::in_memory().with_toplevel(include_str!("../lib_toplevel.pl"))) Machine::new(MachineConfig::in_memory().with_toplevel(include_str!("../lib_toplevel.pl")))
} }
pub fn run_query(&mut self, query: String) -> Result<QueryResult, String> { pub fn run_query(&mut self, query: String) -> QueryResult {
self.set_user_input(query); self.set_user_input(query);
self.run_top_level(atom!("$toplevel"), (atom!("run_input_once"), 0)); self.run_top_level(atom!("$toplevel"), (atom!("run_input_once"), 0));
self.parse_output() self.parse_output()
} }
pub fn parse_output(&self) -> Result<QueryResult, String> { pub fn parse_output(&self) -> QueryResult {
let output = self.get_user_output().trim().to_string(); let output = self.get_user_output().trim().to_string();
if output.starts_with("error(") { if output.starts_with("error(") {
Err(output) Err(output)
@@ -21,9 +21,9 @@ impl Machine {
.map(|s| s.trim()) .map(|s| s.trim())
.map(|s| s.replace(".", "")) .map(|s| s.replace(".", ""))
.filter(|s| !s.is_empty()) .filter(|s| !s.is_empty())
.map(QueryResultLine::try_from) .map(QueryResolutionLine::try_from)
.filter_map(Result::ok) .filter_map(Result::ok)
.collect::<Vec<QueryResultLine>>() .collect::<Vec<QueryResolutionLine>>()
.into()) .into())
} }
} }
@@ -52,7 +52,7 @@ mod tests {
let output = machine.run_query(query); let output = machine.run_query(query);
assert_eq!( assert_eq!(
output, output,
Ok(QueryResult::Matches(vec![ Ok(QueryResolution::Matches(vec![
QueryMatch::from(btreemap! { QueryMatch::from(btreemap! {
"P" => Value::from("p1"), "P" => Value::from("p1"),
}), }),
@@ -64,12 +64,12 @@ mod tests {
assert_eq!( assert_eq!(
machine.run_query(String::from(r#"triple("a","p1","b")."#)), machine.run_query(String::from(r#"triple("a","p1","b")."#)),
Ok(QueryResult::True) Ok(QueryResolution::True)
); );
assert_eq!( assert_eq!(
machine.run_query(String::from(r#"triple("x","y","z")."#)), machine.run_query(String::from(r#"triple("x","y","z")."#)),
Ok(QueryResult::False) Ok(QueryResolution::False)
); );
} }

View File

@@ -3,8 +3,10 @@ use ordered_float::OrderedFloat;
use rug::*; use rug::*;
use std::collections::BTreeMap; use std::collections::BTreeMap;
pub type QueryResult = Result<QueryResolution, String>;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum QueryResult { pub enum QueryResolution {
True, True,
False, False,
Matches(Vec<QueryMatch>), Matches(Vec<QueryMatch>),
@@ -16,7 +18,7 @@ pub struct QueryMatch {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum QueryResultLine { pub enum QueryResolutionLine {
True, True,
False, False,
Match(BTreeMap<String, Value>), Match(BTreeMap<String, Value>),
@@ -51,13 +53,13 @@ impl From<BTreeMap<String, Value>> for QueryMatch {
} }
} }
impl From<Vec<QueryResultLine>> for QueryResult { impl From<Vec<QueryResolutionLine>> for QueryResolution {
fn from(query_result_lines: Vec<QueryResultLine>) -> Self { fn from(query_result_lines: Vec<QueryResolutionLine>) -> Self {
// If there is only one line, and it is true or false, return that. // If there is only one line, and it is true or false, return that.
if query_result_lines.len() == 1 { if query_result_lines.len() == 1 {
match query_result_lines[0].clone() { match query_result_lines[0].clone() {
QueryResultLine::True => return QueryResult::True, QueryResolutionLine::True => return QueryResolution::True,
QueryResultLine::False => return QueryResult::False, QueryResolutionLine::False => return QueryResolution::False,
_ => {} _ => {}
} }
} }
@@ -65,49 +67,49 @@ impl From<Vec<QueryResultLine>> for QueryResult {
// If there is at least one line with true and no matches, return true. // If there is at least one line with true and no matches, return true.
if query_result_lines if query_result_lines
.iter() .iter()
.any(|l| l == &QueryResultLine::True) .any(|l| l == &QueryResolutionLine::True)
&& !query_result_lines.iter().any(|l| { && !query_result_lines.iter().any(|l| {
if let &QueryResultLine::Match(_) = l { if let &QueryResolutionLine::Match(_) = l {
true true
} else { } else {
false false
} }
}) })
{ {
return QueryResult::True; return QueryResolution::True;
} }
// If there is at least one match, return all matches. // If there is at least one match, return all matches.
let all_matches = query_result_lines let all_matches = query_result_lines
.into_iter() .into_iter()
.filter(|l| { .filter(|l| {
if let &QueryResultLine::Match(_) = l { if let &QueryResolutionLine::Match(_) = l {
true true
} else { } else {
false false
} }
}) })
.map(|l| match l { .map(|l| match l {
QueryResultLine::Match(m) => QueryMatch::from(m), QueryResolutionLine::Match(m) => QueryMatch::from(m),
_ => unreachable!(), _ => unreachable!(),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !all_matches.is_empty() { if !all_matches.is_empty() {
return QueryResult::Matches(all_matches); return QueryResolution::Matches(all_matches);
} }
QueryResult::False QueryResolution::False
} }
} }
impl TryFrom<String> for QueryResultLine { impl TryFrom<String> for QueryResolutionLine {
type Error = (); type Error = ();
fn try_from(string: String) -> Result<Self, Self::Error> { fn try_from(string: String) -> Result<Self, Self::Error> {
match string.as_str() { match string.as_str() {
"true" => Ok(QueryResultLine::True), "true" => Ok(QueryResolutionLine::True),
"false" => Ok(QueryResultLine::False), "false" => Ok(QueryResolutionLine::False),
_ => Ok(QueryResultLine::Match( _ => Ok(QueryResolutionLine::Match(
string string
.split(",") .split(",")
.map(|s| s.trim()) .map(|s| s.trim())