File size: 1,673 Bytes
3d2a871 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | use tokio::process::Command;
pub async fn constrain(_query: &str, facts: &[&str]) -> String {
// Build Prolog constraint program from query + facts
let mut program = String::new();
program.push_str(":- initialization(main, main).\n\n");
// Encode facts
for fact in facts {
let safe = fact.replace(' ', "_").replace('"', "").to_lowercase();
program.push_str(&format!("fact({}).\n", safe));
}
// Sovereign constraints
program.push_str(r#"
% Sovereign constraints
sovereign(X) :- fact(X).
evidence(X) :- fact(X), X \= unknown.
silence :- \+ fact(_).
main :-
(fact(_) ->
write('PROLOG:EVIDENCE'), nl
;
write('PROLOG:SILENCE'), nl
),
halt.
"#);
let tmp = std::env::temp_dir().join("sovereign_prolog.pl");
if tokio::fs::write(&tmp, &program).await.is_err() {
return "PROLOG: unavailable (write error)".to_string();
}
match Command::new("swipl")
.arg("-g").arg("main")
.arg("-t").arg("halt")
.arg(tmp.to_str().unwrap_or(""))
.output()
.await
{
Ok(output) => {
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
if stdout.contains("EVIDENCE") {
format!("Λ PROLOG CONSTRAINT: EVIDENCE — facts satisfy constraint\n{}", stdout)
} else if stdout.contains("SILENCE") {
"Λ PROLOG CONSTRAINT: SILENCE — no facts provided".to_string()
} else {
format!("Λ PROLOG CONSTRAINT: {}", stdout)
}
}
Err(_) => "Λ PROLOG: UNAVAILABLE (install SWI-Prolog: swipl)".to_string(),
}
}
|