| use tokio::process::Command; |
|
|
| pub async fn constrain(_query: &str, facts: &[&str]) -> String { |
| |
| let mut program = String::new(); |
| program.push_str(":- initialization(main, main).\n\n"); |
|
|
| |
| for fact in facts { |
| let safe = fact.replace(' ', "_").replace('"', "").to_lowercase(); |
| program.push_str(&format!("fact({}).\n", safe)); |
| } |
|
|
| |
| 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(), |
| } |
| } |
|
|