Skip to content

Commit

Permalink
updated tests, rebase onto @Baqak's new parser #2493
Browse files Browse the repository at this point in the history
  • Loading branch information
james.j.tolton@toltontechnology.ai committed Aug 26, 2024
1 parent 09d9a7b commit 8b307a1
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 134 deletions.
15 changes: 8 additions & 7 deletions src/ffi/shared_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use std::ffi::{c_char, CStr, CString};

use serde_json::json;

use crate::machine::lib_machine::QueryState;
use crate::machine::parsed_results::QueryResolution;
use crate::machine::Machine;
use serde_json::{json, Value};

/// Create a new instance of the Scryer Machine.
///
Expand Down Expand Up @@ -106,13 +106,13 @@ pub extern "C" fn run_query_next(query_state: &mut QueryState) -> *mut c_char {
match query_state.next() {
None => std::ptr::null_mut(),
Some(Ok(query_resolution_line)) => {
let v = QueryResolution::from(vec![query_resolution_line]).to_string();
// let v = QueryResolution::from(vec![query_resolution_line]).to_string();

let obj = serde_json::from_str::<serde_json::Value>(&v).expect("Bad JSON");
// let obj = serde_json::from_str::<serde_json::Value>(query_resolution_line).expect("Bad JSON");

let output_string = json!({
"status": "ok",
"result": obj
"result": query_resolution_line
})
.to_string();

Expand Down Expand Up @@ -222,10 +222,11 @@ pub unsafe extern "C" fn run_query(machine: &mut Machine, input: *const c_char)

let output_string: String = match query_resolution {
Ok(query_resolution_line) => {
let value: Value = serde_json::from_str(&format!("{}", query_resolution_line)).unwrap();
// let value: Value =
// serde_json::from_str(&format!("{:?}", query_resolution_line)).unwrap();
json!( {
"status": "ok",
"result": value
"result": query_resolution_line
})
.to_string()
}
Expand Down
100 changes: 0 additions & 100 deletions src/machine/parsed_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,106 +23,6 @@ use serde::Serializer;
pub type QueryResult = Result<QueryResolution, String>;

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub enum QueryResolution {
True,
False,
Matches(Vec<QueryMatch>),
}

pub fn write_prolog_value_as_json<W: Write>(
writer: &mut W,
value: &Value,
) -> Result<(), std::fmt::Error> {
match value {
Value::Integer(i) => write!(writer, "{}", i),
Value::Float(f) => write!(writer, "{}", f),
Value::Rational(r) => write!(writer, "{}", r),
Value::Atom(a) => writer.write_str(a.as_str()),
Value::String(s) => {
if let Err(_e) = serde_json::from_str::<serde_json::Value>(s.as_str()) {
//treat as string literal
//escape double quotes
write!(
writer,
"\"{}\"",
s.replace('\"', "\\\"")
.replace('\n', "\\n")
.replace('\t', "\\t")
.replace('\r', "\\r")
)
} else {
//return valid json string
writer.write_str(&format!("{s:?}"))
}
}
Value::List(l) => {
writer.write_char('[')?;
if let Some((first, rest)) = l.split_first() {
write_prolog_value_as_json(writer, first)?;

for other in rest {
writer.write_char(',')?;
write_prolog_value_as_json(writer, other)?;
}
}
writer.write_char(']')
}
Value::Structure(s, l) => {
write!(writer, "\"{}\":[", s.as_str())?;

if let Some((first, rest)) = l.split_first() {
write_prolog_value_as_json(writer, first)?;
for other in rest {
writer.write_char(',')?;
write_prolog_value_as_json(writer, other)?;
}
}
writer.write_char(']')
}
_ => writer.write_str("null"),
}
}

fn write_prolog_match_as_json<W: std::fmt::Write>(
writer: &mut W,
query_match: &QueryMatch,
) -> Result<(), std::fmt::Error> {
writer.write_char('{')?;
let mut iter = query_match.bindings.iter();

if let Some((k, v)) = iter.next() {
write!(writer, "\"{k}\":")?;
write_prolog_value_as_json(writer, v)?;

for (k, v) in iter {
write!(writer, ",\"{k}\":")?;
write_prolog_value_as_json(writer, v)?;
}
}
writer.write_char('}')
}

impl Display for QueryResolution {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
QueryResolution::True => f.write_str("true"),
QueryResolution::False => f.write_str("false"),
QueryResolution::Matches(matches) => {
f.write_char('[')?;
if let Some((first, rest)) = matches.split_first() {
write_prolog_match_as_json(f, first)?;
for other in rest {
f.write_char(',')?;
write_prolog_match_as_json(f, other)?;
}
}
f.write_char(']')
}
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QueryMatch {
pub bindings: BTreeMap<String, Value>,
}
Expand Down
99 changes: 72 additions & 27 deletions tests/scryer/shared_library_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ mod shared_library_tests {
run_query, run_query_iter, run_query_next,
};
use serde_json::{json, Value};
// uncomment if we can figure out why this isn't working
// use crate::lib::dll::{machine_free};

use scryer_prolog::machine::Machine;

#[test]
Expand All @@ -19,18 +16,27 @@ mod shared_library_tests {
CString::new("false.").unwrap(),
CString::new("X=2.").unwrap(),
CString::new("member(a, [a, b, c]).").unwrap(),
CString::new(r#"member(A, [a, b, c, "a", "b", "c", f(a), "f(a)"])."#).unwrap(),
CString::new(r#"member(A, [a, b, c, "a", "b", "c", f(a), "f(a)", [1, 2, 3]])."#).unwrap(),
];

let expected_results = vec![
json!({"status": "ok", "result": true}),
json!({"status": "ok", "result": false}),
json!({"status": "ok", "result": [{"X":2}]}),
json!({"status": "ok", "result": [{"bindings": {"X":2}}]}),
json!({"status": "ok", "result": true}),
json!({"status": "ok", "result": [{"A": "a"}, {"A": "b"}, {"A": "c"},
{"A": "\"a\""}, {"A": "\"b\""}, {"A": "\"c\""}, {"A": "f(a)"}, {"A": "\"f(a)\""}]}
),
];
json!({"status": "ok", "result": [
{"bindings": {"A": {"atom": "a"}}},
{"bindings": {"A": {"atom": "b"}}},
{"bindings": {"A": {"atom": "c"}}},
{"bindings": {"A": "a"}},
{"bindings": {"A": "b"}},
{"bindings": {"A": "c"}},
{"bindings": {"A": {"args": [{"atom": "a"}], "functor": "f"}}},
{"bindings": {"A": "f(a)"}},
{"bindings": {"A": [1, 2, 3]}}
]})];



let machine_ptr: *mut Machine = machine_new();
let module_name = CString::new("tests").unwrap();
Expand Down Expand Up @@ -71,8 +77,8 @@ mod shared_library_tests {
// should be X=Y not Y=X, see https://github.com/mthom/scryer-prolog/pull/2465#issuecomment-2294961856
// expected fix with https://github.com/mthom/scryer-prolog/pull/2475
let expected_results = [
r#"{"result":[{"Y":"X"}],"status":"ok"}"#, // should be:
// "{\"result\":[{\"X\":\"Y\"}],\"status\":\"ok\"}"
r#"{"result":{"bindings": {"X":{"variable": "Y"}}},"status":"ok"}"#,

];

let query_state_ref = unsafe { &mut *query_state };
Expand All @@ -84,7 +90,7 @@ mod shared_library_tests {
let expected_obj =
serde_json::from_str::<serde_json::Value>(expected).expect("Bad JSON");
println!("{result_s:?}");
assert_eq!(result_obj, expected_obj);
assert_eq!(expected_obj, result_obj);
unsafe {
free_c_string(result_ptr);
}
Expand All @@ -110,16 +116,19 @@ mod shared_library_tests {
}
let query_state = unsafe { run_query_iter(&mut *machine_ptr, query.as_ptr()) };

let expected_results = [
r#"{"result":[{"X":"a"}],"status":"ok"}"#,
r#"{"result":[{"X":"\"a\""}],"status":"ok"}"#,
r#"{"result":[{"X":"f(a)"}],"status":"ok"}"#,
r#"{"result":[{"X":"\"f(a)\""}],"status":"ok"}"#,
r#"{"result":[{"X": true}],"status":"ok"}"#,
r#"{"result":[{"X":"\"true\""}],"status":"ok"}"#,
r#"{"result":[{"X": false}],"status":"ok"}"#,
r#"{"result":[{"X":"\"false\""}],"status":"ok"}"#,
];


let expected_results = vec![
json!({"status": "ok", "result": {"bindings": {"X": {"atom": "a"}}}}),
json!({"status": "ok", "result": {"bindings": {"X": "a"}}}),
json!({"status": "ok", "result": {"bindings": {"X": {"args": [{"atom": "a"}], "functor": "f"}}}}),
json!({"status": "ok", "result": {"bindings": {"X": "f(a)"}}}),
json!({"status": "ok", "result": {"bindings": {"X": true}}}),
json!({"status": "ok", "result": {"bindings": {"X": "true"}}}),
json!({"status": "ok", "result": {"bindings": {"X": false}}}),
json!({"status": "ok", "result": {"bindings": {"X": "false"}}}),
];


let query_state_ref = unsafe { &mut *query_state };
for expected in &expected_results {
Expand All @@ -128,9 +137,7 @@ mod shared_library_tests {
let result_s = result_char.to_str().unwrap();
let result_obj =
serde_json::from_str::<serde_json::Value>(&result_s).expect("Bad JSON");
let expected_obj =
serde_json::from_str::<serde_json::Value>(&expected).expect("Bad JSON");
assert_eq!(result_obj, expected_obj);
assert_eq!(expected, &result_obj);
unsafe {
free_c_string(result_ptr);
}
Expand Down Expand Up @@ -206,14 +213,16 @@ solve(N, Moves) :-
}
let query_state = unsafe { run_query_iter(&mut *machine_ptr, query.as_ptr()) };

let expected_results =
[r#"{"status": "ok", "results": [{"Moves": ["\"from_to(a,c)\""]}]}"#];
let expected_results = [
r#"{"status": "ok", "result": {"bindings": {"Moves": [{"args": [{"atom": "a"}, {"atom": "c"}], "functor": "from_to"}], "N": 1}}}"#,
];

let query_state_ref = unsafe { &mut *query_state };
for expected in &expected_results {
let result_ptr = run_query_next(query_state_ref);
let result_char = unsafe { CStr::from_ptr(result_ptr) };
let result_s = result_char.to_str().unwrap();
println!("{result_s}");
let result_obj =
serde_json::from_str::<serde_json::Value>(&result_s).expect("Bad JSON");
println!("{result_obj}");
Expand All @@ -227,4 +236,40 @@ solve(N, Moves) :-
unsafe { query_state_free(query_state) }
unsafe { machine_free(machine_ptr) };
}

#[test]
fn test_scryer_run_query_clpz() {
let program = CString::new(":- use_module(library(clpz)).").unwrap();
let module_name = CString::new("facts").unwrap();
let query = CString::new(r#"X in 1 .. 3."#).unwrap();
let machine_ptr: *mut Machine = machine_new();
unsafe {
consult_module_string(&mut *machine_ptr, module_name.as_ptr(), program.as_ptr());
}
let query_state = unsafe { run_query_iter(&mut *machine_ptr, query.as_ptr()) };

let expected_results =
// should be
// [r#"{"status": "ok", "result": {"args": [{"variable": "X"}, {"args": [1, 5], "functor": ".."}], "functor": "in"}}"#];
[r#"{"status": "ok", "result": {"bindings": {"X": {"variable": "_A"}}}}"#]; // incorrect

let query_state_ref = unsafe { &mut *query_state };
for expected in &expected_results {
let result_ptr = run_query_next(query_state_ref);
let result_char = unsafe { CStr::from_ptr(result_ptr) };
let result_s = result_char.to_str().unwrap();
println!("{result_s}");
let result_obj =
serde_json::from_str::<serde_json::Value>(&result_s).expect("Bad JSON");
println!("{result_obj}");
let expected_obj =
serde_json::from_str::<serde_json::Value>(&expected).expect("Bad JSON");
assert_eq!(expected_obj, result_obj);
unsafe {
free_c_string(result_ptr);
}
}
unsafe { query_state_free(query_state) }
unsafe { machine_free(machine_ptr) };
}
}

0 comments on commit 8b307a1

Please sign in to comment.