This commit is contained in:
jackjohn7 2025-10-29 21:51:24 -05:00
commit 0de67fd423
13 changed files with 1263 additions and 0 deletions

1
iagorithms/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

7
iagorithms/Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "iagorithms"
version = "0.1.0"
edition = "2024"
[dependencies]
neorusticus.workspace = true

226
iagorithms/src/lib.rs Normal file
View file

@ -0,0 +1,226 @@
use neorusticus::{PrologEngine, quick_query};
use std::error::Error;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn init() -> Result<(), Box<dyn Error>> {
println!("=== Neorusticus Prolog Engine Demo ===\n");
// Create engine with conservative limits for safety
let mut engine = PrologEngine::with_limits(50);
// Test basic parsing with error handling
println!("=== Testing Basic Operations ===");
// Test successful operations
match engine.parse_and_add("parent(tom, bob).") {
Ok(()) => println!("✓ Successfully added: parent(tom, bob)."),
Err(e) => {
println!("✗ Failed to add clause:");
engine.print_error(&e);
}
}
match engine.parse_and_add("parent(bob, ann).") {
Ok(()) => println!("✓ Successfully added: parent(bob, ann)."),
Err(e) => {
println!("✗ Failed to add clause:");
engine.print_error(&e);
}
}
// Test error cases
println!("\n=== Testing Error Handling ===");
// Test syntax errors
println!("Testing syntax errors:");
if let Err(e) = engine.parse_and_add("parent(tom bob).") {
// Missing comma
println!("✓ Caught syntax error: {}", e);
}
if let Err(e) = engine.parse_and_add("parent(tom, bob") {
// Missing closing paren
println!("✓ Caught delimiter error: {}", e);
}
if let Err(e) = engine.parse_and_add("parent(tom, bob)") {
// Missing dot
println!("✓ Caught missing dot error: {}", e);
}
if let Err(e) = engine.parse_and_add("parent(tom, 999999999999999999999).") {
// Number too large
println!("✓ Caught number overflow error: {}", e);
}
// Test arithmetic operations with error handling
println!("\n=== Testing Arithmetic Error Handling ===");
engine.parse_and_add("test_arith :- X is 5 + 3.")?;
// Test division by zero
if let Err(e) = engine.parse_query("X is 5 // 0.") {
println!("✓ Caught division by zero: {}", e);
}
// Test uninstantiated variable in arithmetic
if let Err(e) = engine.parse_query("X is Y + 1.") {
println!("✓ Caught uninstantiated variable: {}", e);
}
// Test type mismatch
if let Err(e) = engine.parse_query("X is atom + 1.") {
println!("✓ Caught type mismatch: {}", e);
}
// Test successful arithmetic
match engine.parse_query("X is 2 + 3 * 4.") {
Ok(solutions) => {
println!("✓ Arithmetic success:");
engine.print_solutions(&solutions, &["X".to_string()]);
}
Err(e) => {
println!("✗ Unexpected arithmetic error:");
engine.print_boxed_error(&e);
}
}
// Test list operations with error handling
println!("\n=== Testing List Error Handling ===");
// Test invalid list structure
if let Err(e) = engine.parse_query("member(X, not_a_list).") {
println!("✓ Caught invalid list structure: {}", e);
}
// Test uninstantiated list
if let Err(e) = engine.parse_query("length(L, 3).") {
println!("✓ Caught uninstantiated list: {}", e);
}
// Test successful list operations
match engine.parse_query("append([1, 2], [3, 4], X).") {
Ok(solutions) => {
println!("✓ List append success:");
engine.print_solutions(&solutions, &["X".to_string()]);
}
Err(e) => {
println!("✗ Unexpected list error:");
engine.print_boxed_error(&e);
}
}
// Test predicate suggestions
println!("\n=== Testing Predicate Suggestions ===");
if let Err(e) = engine.parse_query("lentgh([1, 2, 3], X).") {
// Typo in "length"
println!("✓ Predicate suggestion: {}", e);
}
if let Err(e) = engine.parse_query("appendd([1], [2], X).") {
// Typo in "append"
println!("✓ Predicate suggestion: {}", e);
}
// Test stack overflow protection with a safer approach
println!("\n=== Testing Stack Overflow Protection ===");
// Use a very conservative engine for this test
let mut test_engine = PrologEngine::with_limits(5);
// Add the infinite recursion rule to the test engine only
match test_engine.parse_and_add("infinite(X) :- infinite(X).") {
Ok(_) => {
// Now test the query with the dangerous rule
match test_engine.parse_query("infinite(test).") {
Ok(_) => println!("✗ Failed to catch infinite recursion"),
Err(e) => println!("✓ Caught infinite recursion: {}", e),
}
}
Err(e) => {
println!("✗ Failed to add infinite rule: {}", e);
}
}
// Test cut operations
println!("\n=== Testing Cut Operations ===");
engine.parse_and_add("max(X, Y, X) :- X >= Y, !.")?;
engine.parse_and_add("max(X, Y, Y).")?;
match engine.parse_query("max(5, 3, Z).") {
Ok(solutions) => {
println!("✓ Cut operation success:");
engine.print_solutions(&solutions, &["Z".to_string()]);
}
Err(e) => {
println!("✗ Unexpected cut error:");
engine.print_boxed_error(&e);
}
}
// Display engine statistics
println!("\n=== Engine Statistics ===");
println!("{}", engine.get_stats());
// Test complex query with multiple error possibilities
println!("\n=== Testing Complex Query ===");
engine.parse_and_add("complex(X, Y) :- X > 0, Y is X * 2, Y < 20.")?;
match engine.parse_query("complex(5, Z).") {
Ok(solutions) => {
println!("✓ Complex query success:");
engine.print_solutions(&solutions, &["Z".to_string()]);
}
Err(e) => {
println!("✗ Complex query error:");
engine.print_boxed_error(&e);
}
}
// Test recovery from errors
println!("\n=== Testing Error Recovery ===");
// Even after errors, the engine should continue to work
match engine.parse_query("parent(tom, X).") {
Ok(solutions) => {
println!("✓ Engine recovered, normal operation:");
engine.print_solutions(&solutions, &["X".to_string()]);
}
Err(e) => {
println!("✗ Engine failed to recover:");
engine.print_boxed_error(&e);
}
}
// Demonstrate the quick_query convenience function
println!("\n=== Testing Quick Query Function ===");
let clauses = &[
"ancestor(X, Y) :- parent(X, Y).",
"ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).",
"parent(alice, bob).",
"parent(bob, charlie).",
"parent(charlie, diana).",
];
match quick_query(clauses, "ancestor(alice, diana).") {
Ok(solutions) => {
println!("✓ Quick query found {} solutions", solutions.len());
}
Err(e) => {
println!("✗ Quick query failed: {}", e);
}
}
println!("\n=== All tests completed ===");
panic!();
Ok(())
}
}