GRLParser

Struct GRLParser 

Source
pub struct GRLParser;
Expand description

Simple GRL Parser for parsing rule files

Implementationsยง

Sourceยง

impl GRLParser

Source

pub fn parse_rules(content: &str) -> Result<Vec<Rule>>

Parse a complete GRL file content into rules

Examples found in repository?
examples/debug_conditions.rs (line 21)
9fn test_simple_conditions() -> std::result::Result<(), Box<dyn Error>> {
10    println!("=== Testing Simple Conditions ===");
11
12    // Create Knowledge Base
13    let kb = KnowledgeBase::new("TestConditions");
14
15    // Test compound condition with &&
16    let compound_rule = r#"rule "CompoundRule" { when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed then TestCar.result = "compound_fired"; }"#;
17
18    println!("Testing rule: {}", compound_rule);
19
20    // Parse and add rule
21    let rules = GRLParser::parse_rules(compound_rule)?;
22    let rule = rules.into_iter().next().unwrap();
23    println!("Parsed rule: {:?}", rule);
24
25    let _ = kb.add_rule(rule);
26
27    // Create engine with debug mode
28    let config = EngineConfig {
29        max_cycles: 10,
30        timeout: None,
31        enable_stats: true,
32        debug_mode: true,
33    };
34    let engine = RustRuleEngine::with_config(kb, config);
35
36    // Create facts
37    let facts = Facts::new();
38
39    // Create simple TestCar object with all needed properties
40    let test_car = FactHelper::create_object(vec![
41        ("speedUp", Value::Boolean(true)),
42        ("speed", Value::Number(30.0)),
43        ("maxSpeed", Value::Number(100.0)),
44        ("result", Value::String("not_fired".to_string())),
45    ]);
46
47    facts.add_value("TestCar", test_car)?;
48
49    println!("\n๐Ÿ Before execution:");
50    if let Some(car) = facts.get("TestCar") {
51        println!("   TestCar.speedUp = {:?}", car.get_property("speedUp"));
52        println!("   TestCar.speed = {:?}", car.get_property("speed"));
53        println!("   TestCar.maxSpeed = {:?}", car.get_property("maxSpeed"));
54        println!("   TestCar.result = {:?}", car.get_property("result"));
55    }
56
57    // Execute rules
58    println!("\n๐Ÿš€ Executing rule...");
59    let result = engine.execute(&facts)?;
60
61    println!("Rules fired: {}", result.rules_fired);
62
63    println!("\n๐Ÿ After execution:");
64    if let Some(car) = facts.get("TestCar") {
65        println!("   TestCar.speedUp = {:?}", car.get_property("speedUp"));
66        println!("   TestCar.result = {:?}", car.get_property("result"));
67    }
68
69    Ok(())
70}
More examples
Hide additional examples
examples/advanced_method_calls.rs (line 22)
9fn demo_method_calls() -> std::result::Result<(), Box<dyn Error>> {
10    println!("=== Demo: Advanced Method Calls ===");
11
12    // Create Knowledge Base
13    let kb = KnowledgeBase::new("MethodCallsDemo");
14
15    // Define rule with simpler condition first
16    let speedup_rule = r#"rule "SpeedUp" salience 10 { 
17        when TestCar.speedUp == true 
18        then TestCar.Speed = 70; 
19    }"#;
20
21    // Parse and add rule
22    let rules = GRLParser::parse_rules(speedup_rule)?;
23    let rule = rules.into_iter().next().unwrap();
24    let _ = kb.add_rule(rule);
25
26    // Create engine with debug mode
27    let config = EngineConfig {
28        max_cycles: 10,
29        timeout: None,
30        enable_stats: true,
31        debug_mode: true,
32    };
33    let engine = RustRuleEngine::with_config(kb, config);
34
35    // Create facts
36    let facts = Facts::new();
37
38    // Create TestCar object using helper
39    let test_car = FactHelper::create_test_car(
40        true,  // speedUp
41        50.0,  // speed
42        100.0, // maxSpeed
43        10.0,  // speedIncrement
44    );
45
46    // Create DistanceRecord object using helper
47    let distance_record = FactHelper::create_distance_record(0.0);
48
49    // Add facts
50    facts.add_value("TestCar", test_car)?;
51    facts.add_value("DistanceRecord", distance_record)?;
52
53    println!("\n๐Ÿ Initial state:");
54    if let Some(car) = facts.get("TestCar") {
55        if let Some(speed) = car.get_property("Speed") {
56            println!("   TestCar.Speed = {:?}", speed);
57        }
58        if let Some(speed_up) = car.get_property("speedUp") {
59            println!("   TestCar.speedUp = {:?}", speed_up);
60        }
61    }
62
63    // Execute rules multiple cycles to see progression
64    println!("\n๐Ÿš€ Executing SpeedUp rule multiple times...");
65    for i in 1..=3 {
66        println!("\n--- Cycle {} ---", i);
67        let result = engine.execute(&facts)?;
68
69        println!("Rules fired: {}", result.rules_fired);
70
71        if let Some(car) = facts.get("TestCar") {
72            if let Some(speed) = car.get_property("Speed") {
73                println!("TestCar.Speed after cycle {}: {:?}", i, speed);
74            }
75        }
76
77        // Check if we reached max speed
78        if let Some(car) = facts.get("TestCar") {
79            if let Some(speed) = car.get_property("speed") {
80                if let Some(max_speed) = car.get_property("maxSpeed") {
81                    if speed.to_number() >= max_speed.to_number() {
82                        println!("๐Ÿ Max speed reached!");
83                        break;
84                    }
85                }
86            }
87        }
88    }
89
90    println!("\n๐Ÿ“Š Final Results:");
91    if let Some(car) = facts.get("TestCar") {
92        if let Some(speed) = car.get_property("Speed") {
93            println!("   Final TestCar.Speed = {:?}", speed);
94        }
95    }
96
97    Ok(())
98}
examples/method_calls_demo.rs (line 48)
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10    println!("๐ŸŽฏ Method Calls Demo with Rule File");
11    println!("===================================\n");
12
13    // Read rules from file
14    let rule_file_path = "examples/rules/method_calls.grl";
15    println!("๐Ÿ“„ Reading rules from file: {}", rule_file_path);
16
17    let rule_content = fs::read_to_string(rule_file_path)
18        .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20    println!("๐Ÿ“‹ Rule file content:");
21    println!("---");
22    println!("{}", rule_content);
23    println!("---\n");
24
25    // Create facts
26    let facts = Facts::new();
27
28    // TestCar data
29    let mut test_car_props = HashMap::new();
30    test_car_props.insert("Speed".to_string(), Value::Number(30.0));
31    test_car_props.insert("MaxSpeed".to_string(), Value::Number(100.0));
32    test_car_props.insert("SpeedIncrement".to_string(), Value::Number(10.0));
33    test_car_props.insert("SpeedUp".to_string(), Value::Boolean(true));
34
35    facts.add_value("TestCar", Value::Object(test_car_props))?;
36
37    println!("๐Ÿ Initial state:");
38    if let Some(car) = facts.get("TestCar") {
39        println!("   TestCar = {car:?}");
40    }
41    println!();
42
43    // Create knowledge base and add rules from GRL file
44    let kb = KnowledgeBase::new("MethodCallsDemo");
45
46    // Parse rules from GRL file
47    println!("๐Ÿ”ง Parsing GRL file content...");
48    let rules = GRLParser::parse_rules(&rule_content)
49        .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
50
51    println!("โœ… Successfully parsed {} rules from file", rules.len());
52    for rule in &rules {
53        println!("   ๐Ÿ“‹ Rule: {} (salience: {})", rule.name, rule.salience);
54        let _ = kb.add_rule(rule.clone());
55    }
56    println!();
57
58    // Create engine
59    let config = EngineConfig {
60        debug_mode: true,
61        max_cycles: 5,
62        ..Default::default()
63    };
64    let mut engine = RustRuleEngine::with_config(kb, config);
65
66    // Register custom functions for speed control
67    engine.register_function("increaseSpeed", |_args, facts| {
68        if let Some(car) = facts.get("TestCar") {
69            if let Value::Object(obj) = car {
70                let current_speed = obj.get("Speed").cloned().unwrap_or(Value::Number(0.0));
71                let increment = obj
72                    .get("SpeedIncrement")
73                    .cloned()
74                    .unwrap_or(Value::Number(10.0));
75
76                if let (Value::Number(speed), Value::Number(inc)) = (current_speed, increment) {
77                    let new_speed = speed + inc;
78                    println!("๐Ÿš— Increasing speed: {} -> {}", speed, new_speed);
79                    // In real implementation, this would update the fact
80                    return Ok(Value::Number(new_speed));
81                }
82            }
83        }
84        Ok(Value::String("Speed increase attempted".to_string()))
85    });
86
87    engine.register_function("decreaseSpeed", |_args, facts| {
88        if let Some(car) = facts.get("TestCar") {
89            if let Value::Object(obj) = car {
90                let current_speed = obj.get("Speed").cloned().unwrap_or(Value::Number(0.0));
91                let increment = obj
92                    .get("SpeedIncrement")
93                    .cloned()
94                    .unwrap_or(Value::Number(10.0));
95
96                if let (Value::Number(speed), Value::Number(inc)) = (current_speed, increment) {
97                    let new_speed = (speed - inc).max(0.0);
98                    println!("๐Ÿš— Decreasing speed: {} -> {}", speed, new_speed);
99                    // In real implementation, this would update the fact
100                    return Ok(Value::Number(new_speed));
101                }
102            }
103        }
104        Ok(Value::String("Speed decrease attempted".to_string()))
105    });
106
107    // Execute rules
108    println!("๐Ÿš€ Executing method calls rules from file...");
109    let result = engine.execute(&facts)?;
110
111    println!("\n๐Ÿ“Š Method Calls Execution Results:");
112    println!("   Cycles: {}", result.cycle_count);
113    println!("   Rules evaluated: {}", result.rules_evaluated);
114    println!("   Rules fired: {}", result.rules_fired);
115    println!("   Execution time: {:?}", result.execution_time);
116
117    println!("\n๐Ÿ Final state:");
118    if let Some(car) = facts.get("TestCar") {
119        println!("   TestCar = {car:?}");
120    }
121
122    println!("\n๐ŸŽฏ Method Calls from Rule File Demonstrated:");
123    println!("   ๐Ÿ“„ Rules defined in external .grl file");
124    println!("   ๐Ÿ”ง Method calls: setSpeed(), setSpeedUp()");
125    println!("   ๐Ÿ“ž Custom functions: increaseSpeed(), decreaseSpeed()");
126    println!("   ๐Ÿš— Speed control simulation");
127    println!("   โšก Salience-based rule execution order");
128
129    Ok(())
130}
examples/complete_speedup_demo.rs (line 33)
9fn demo_complete_speedup_rule() -> std::result::Result<(), Box<dyn Error>> {
10    println!("=== Demo: Complete SpeedUp Rule with Method Calls ===");
11    println!("Implementing the exact rule from the requirement:");
12    println!("rule \"SpeedUp\" salience 10");
13    println!("when");
14    println!("    $TestCar : TestCarClass( speedUp == true && speed < maxSpeed )");
15    println!("    $DistanceRecord : DistanceRecordClass()");
16    println!("then");
17    println!("    $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement);");
18    println!("    update($TestCar);");
19    println!("    $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed);");
20    println!("    update($DistanceRecord);");
21    println!("end\n");
22
23    // Create Knowledge Base
24    let kb = KnowledgeBase::new("SpeedUpDemo");
25
26    // For now, we'll use a simplified version that works with our current parser
27    let speedup_rule = r#"rule "SpeedUp" salience 10 { 
28        when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed 
29        then $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement); update($TestCar); $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed); update($DistanceRecord); 
30    }"#;
31
32    // Parse and add rule
33    let rules = GRLParser::parse_rules(speedup_rule)?;
34    let rule = rules.into_iter().next().unwrap();
35    let _ = kb.add_rule(rule);
36
37    // Create engine with debug mode
38    let config = EngineConfig {
39        max_cycles: 10,
40        timeout: None,
41        enable_stats: true,
42        debug_mode: true,
43    };
44    let engine = RustRuleEngine::with_config(kb, config);
45
46    // Create facts
47    let facts = Facts::new();
48
49    // Create TestCar object - initial speed less than max
50    let test_car = FactHelper::create_test_car(
51        true,  // speedUp
52        30.0,  // speed (less than maxSpeed)
53        100.0, // maxSpeed
54        15.0,  // speedIncrement
55    );
56
57    // Create DistanceRecord object
58    let distance_record = FactHelper::create_distance_record(0.0);
59
60    // Add facts
61    facts.add_value("TestCar", test_car)?;
62    facts.add_value("DistanceRecord", distance_record)?;
63
64    println!("๐Ÿ Initial state:");
65    if let Some(car) = facts.get("TestCar") {
66        println!(
67            "   TestCar.speed = {:?}",
68            car.get_property("speed").unwrap_or(Value::Null)
69        );
70        println!(
71            "   TestCar.Speed = {:?}",
72            car.get_property("Speed").unwrap_or(Value::Null)
73        );
74        println!(
75            "   TestCar.maxSpeed = {:?}",
76            car.get_property("maxSpeed").unwrap_or(Value::Null)
77        );
78        println!(
79            "   TestCar.speedUp = {:?}",
80            car.get_property("speedUp").unwrap_or(Value::Null)
81        );
82        println!(
83            "   TestCar.SpeedIncrement = {:?}",
84            car.get_property("SpeedIncrement").unwrap_or(Value::Null)
85        );
86    }
87    if let Some(record) = facts.get("DistanceRecord") {
88        println!(
89            "   DistanceRecord.TotalDistance = {:?}",
90            record.get_property("TotalDistance").unwrap_or(Value::Null)
91        );
92    }
93
94    // Execute rules multiple cycles
95    println!("\n๐Ÿš€ Executing SpeedUp rule...");
96    for i in 1..=5 {
97        println!("\n--- Cycle {} ---", i);
98        let result = engine.execute(&facts)?;
99
100        println!("Rules fired: {}", result.rules_fired);
101
102        if let Some(car) = facts.get("TestCar") {
103            println!(
104                "TestCar.Speed = {:?}",
105                car.get_property("Speed").unwrap_or(Value::Null)
106            );
107            println!(
108                "TestCar.speed = {:?}",
109                car.get_property("speed").unwrap_or(Value::Null)
110            );
111        }
112        if let Some(record) = facts.get("DistanceRecord") {
113            println!(
114                "DistanceRecord.TotalDistance = {:?}",
115                record.get_property("TotalDistance").unwrap_or(Value::Null)
116            );
117        }
118
119        // Check if we reached max speed
120        if let Some(car) = facts.get("TestCar") {
121            if let Some(speed) = car.get_property("speed") {
122                if let Some(max_speed) = car.get_property("maxSpeed") {
123                    if speed.to_number() >= max_speed.to_number() {
124                        println!("๐Ÿ Max speed reached! Rule will no longer fire.");
125                        break;
126                    }
127                }
128            }
129        }
130
131        if result.rules_fired == 0 {
132            println!("โ„น๏ธ No rules fired this cycle.");
133            break;
134        }
135    }
136
137    println!("\n๐Ÿ“Š Final Summary:");
138    println!("โœ… Successfully demonstrated method calls in GRL:");
139    println!("   โ€ข Method calls: $Object.method(args)");
140    println!("   โ€ข Property access: $Object.Property");
141    println!("   โ€ข Arithmetic expressions: $A.prop + $B.prop");
142    println!("   โ€ข update() function calls");
143    println!("   โ€ข Complex conditions with && operator");
144
145    Ok(())
146}
examples/inline_rules_demo.rs (line 91)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9    println!("๐ŸŽฏ Inline GRL Rules Demo");
10    println!("========================\n");
11
12    // Define rules directly in code as strings
13    let grl_rules = r#"
14        rule "HighValueCustomer" salience 20 {
15            when
16                Customer.TotalSpent > 1000.0
17            then
18                sendWelcomeEmail(Customer.Email, "GOLD");
19                log("Customer upgraded to GOLD tier");
20        }
21
22        rule "LoyaltyBonus" salience 15 {
23            when
24                Customer.OrderCount >= 10
25            then
26                applyLoyaltyBonus(Customer.Id, 50.0);
27                log("Loyalty bonus applied");
28        }
29
30        rule "NewCustomerWelcome" salience 10 {
31            when
32                Customer.IsNew == false
33            then
34                sendWelcomeEmail(Customer.Email, "EXISTING");
35                log("Welcome email sent to existing customer");
36        }
37
38        rule "LowRiskTransaction" salience 5 {
39            when
40                Transaction.Amount < 1000.0
41            then
42                log("Low-risk transaction processed");
43        }
44    "#;
45
46    println!("๐Ÿ“‹ Inline GRL Rules:");
47    println!("---");
48    println!("{}", grl_rules.trim());
49    println!("---\n");
50
51    // Create facts
52    let facts = Facts::new();
53
54    // Customer data
55    let mut customer_props = HashMap::new();
56    customer_props.insert("Id".to_string(), Value::String("CUST001".to_string()));
57    customer_props.insert(
58        "Email".to_string(),
59        Value::String("john.doe@example.com".to_string()),
60    );
61    customer_props.insert("TotalSpent".to_string(), Value::Number(1250.0)); // Qualifies for GOLD
62    customer_props.insert("YearsActive".to_string(), Value::Integer(4)); // Long-time customer
63    customer_props.insert("OrderCount".to_string(), Value::Integer(12)); // Qualifies for loyalty
64    customer_props.insert("Tier".to_string(), Value::String("SILVER".to_string()));
65    customer_props.insert("IsNew".to_string(), Value::Boolean(false));
66    customer_props.insert("RiskScore".to_string(), Value::Integer(35)); // Low risk
67    customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
68
69    // Transaction data
70    let mut transaction_props = HashMap::new();
71    transaction_props.insert("Id".to_string(), Value::String("TXN001".to_string()));
72    transaction_props.insert("Amount".to_string(), Value::Number(750.0)); // Normal amount
73    transaction_props.insert("Currency".to_string(), Value::String("USD".to_string()));
74
75    facts.add_value("Customer", Value::Object(customer_props))?;
76    facts.add_value("Transaction", Value::Object(transaction_props))?;
77
78    println!("๐Ÿ Initial state:");
79    if let Some(customer) = facts.get("Customer") {
80        println!("   Customer = {customer:?}");
81    }
82    if let Some(transaction) = facts.get("Transaction") {
83        println!("   Transaction = {transaction:?}");
84    }
85    println!();
86
87    // Create knowledge base and parse inline rules
88    let kb = KnowledgeBase::new("InlineRulesDemo");
89
90    println!("๐Ÿ”ง Parsing inline GRL rules...");
91    let parsed_rules = GRLParser::parse_rules(grl_rules)
92        .map_err(|e| format!("Failed to parse inline GRL rules: {:?}", e))?;
93
94    println!(
95        "โœ… Successfully parsed {} rules from inline strings",
96        parsed_rules.len()
97    );
98    for rule in parsed_rules {
99        println!("   ๐Ÿ“‹ Rule: {} (salience: {})", rule.name, rule.salience);
100        let _ = kb.add_rule(rule);
101    }
102    println!();
103
104    // Create engine with configuration
105    let config = EngineConfig {
106        debug_mode: true,
107        max_cycles: 2,
108        ..Default::default()
109    };
110    let mut engine = RustRuleEngine::with_config(kb, config);
111
112    // Register custom functions called from the inline rules
113    println!("๐Ÿ“ Registering custom functions for inline rules...");
114
115    // Customer tier management
116    engine.register_function("Customer.setTier", |args, _facts| {
117        let new_tier = args.get(0).unwrap().to_string();
118
119        let result = format!("๐Ÿ† Customer tier updated to: {}", new_tier);
120        println!("  {}", result);
121        Ok(Value::String(result))
122    });
123
124    // Email service
125    engine.register_function("sendWelcomeEmail", |args, _facts| {
126        let email = args.get(0).unwrap().to_string();
127        let tier = args.get(1).unwrap().to_string();
128
129        let result = format!("๐Ÿ“ง Welcome email sent to {} for {} tier", email, tier);
130        println!("  {}", result);
131        Ok(Value::String(result))
132    });
133
134    // Loyalty system
135    engine.register_function("applyLoyaltyBonus", |args, _facts| {
136        let customer_id = args.get(0).unwrap().to_string();
137        let bonus_amount = args.get(1).unwrap();
138
139        let result = format!(
140            "๐Ÿ’ฐ Loyalty bonus of {:?} applied to customer {}",
141            bonus_amount, customer_id
142        );
143        println!("  {}", result);
144        Ok(Value::String(result))
145    });
146
147    // Security functions
148    engine.register_function("flagForReview", |args, _facts| {
149        let transaction_id = args.get(0).unwrap().to_string();
150
151        let result = format!(
152            "๐Ÿšจ Transaction {} flagged for manual review",
153            transaction_id
154        );
155        println!("  {}", result);
156        Ok(Value::String(result))
157    });
158
159    engine.register_function("notifySecurityTeam", |args, _facts| {
160        let customer_id = args.get(0).unwrap().to_string();
161        let amount = args.get(1).unwrap();
162
163        let result = format!(
164            "๐Ÿ”’ Security team notified: Customer {} - Amount {:?}",
165            customer_id, amount
166        );
167        println!("  {}", result);
168        Ok(Value::String(result))
169    });
170
171    // Customer status updates
172    engine.register_function("Customer.setWelcomeEmailSent", |args, _facts| {
173        let sent = args.get(0).unwrap();
174
175        let result = format!("โœ… Welcome email status updated: {:?}", sent);
176        println!("  {}", result);
177        Ok(Value::String(result))
178    });
179
180    println!("โœ… Registered 6 custom functions for inline rules:");
181    println!("   ๐Ÿ† Customer.setTier");
182    println!("   ๐Ÿ“ง sendWelcomeEmail");
183    println!("   ๐Ÿ’ฐ applyLoyaltyBonus");
184    println!("   ๐Ÿšจ flagForReview");
185    println!("   ๐Ÿ”’ notifySecurityTeam");
186    println!("   โœ… Customer.setWelcomeEmailSent");
187    println!();
188
189    // Execute the inline rules
190    println!("๐Ÿš€ Executing inline GRL rules...");
191    let result = engine.execute(&facts)?;
192
193    println!("\n๐Ÿ“Š Inline Rules Execution Results:");
194    println!("   Cycles: {}", result.cycle_count);
195    println!("   Rules evaluated: {}", result.rules_evaluated);
196    println!("   Rules fired: {}", result.rules_fired);
197    println!("   Execution time: {:?}", result.execution_time);
198
199    println!("\n๐Ÿ Final state:");
200    if let Some(customer) = facts.get("Customer") {
201        println!("   Customer = {customer:?}");
202    }
203    if let Some(transaction) = facts.get("Transaction") {
204        println!("   Transaction = {transaction:?}");
205    }
206
207    println!("\n๐ŸŽฏ Inline GRL Rules Demonstrated:");
208    println!("   ๐Ÿ“ Rules defined as strings directly in code");
209    println!("   ๐Ÿ”ง No external files needed");
210    println!("   โšก Quick prototyping and testing");
211    println!("   ๐Ÿ† Customer tier management");
212    println!("   ๐Ÿ’ฐ Loyalty bonus system");
213    println!("   ๐Ÿ”’ Security and fraud detection");
214    println!("   ๐Ÿ“ง Email notification system");
215
216    Ok(())
217}
examples/rule_file_functions_demo.rs (line 58)
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10    println!("๐ŸŽฏ Custom Functions from Rule File Demo");
11    println!("=======================================\n");
12
13    // Read rules from file
14    let rule_file_path = "examples/rules/car_functions.grl";
15    println!("๐Ÿ“„ Reading rules from file: {}", rule_file_path);
16
17    let rule_content = fs::read_to_string(rule_file_path)
18        .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20    println!("๐Ÿ“‹ Rule file content:");
21    println!("---");
22    println!("{}", rule_content);
23    println!("---\n");
24
25    // Create facts
26    let facts = Facts::new();
27
28    // Car data - set speed > 80 to trigger speed limit rule
29    let mut car_props = HashMap::new();
30    car_props.insert("Speed".to_string(), Value::Number(95.0)); // Above speed limit
31    car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
32    car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
33    car_props.insert("IsRunning".to_string(), Value::Boolean(true));
34
35    // Driver data
36    let mut driver_props = HashMap::new();
37    driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
38    driver_props.insert("Experience".to_string(), Value::Integer(7)); // Experienced driver
39    driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
40
41    facts.add_value("Car", Value::Object(car_props))?;
42    facts.add_value("Driver", Value::Object(driver_props))?;
43
44    println!("๐Ÿ Initial state:");
45    if let Some(car) = facts.get("Car") {
46        println!("   Car = {car:?}");
47    }
48    if let Some(driver) = facts.get("Driver") {
49        println!("   Driver = {driver:?}");
50    }
51    println!();
52
53    // Create knowledge base
54    let mut kb = KnowledgeBase::new("RuleFileDemo");
55
56    // Parse GRL file and add rules to knowledge base
57    println!("๐Ÿ”ง Parsing GRL file content...");
58    let parsed_rules = SimpleGRLParser::parse_rules(&rule_content)
59        .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
60
61    println!(
62        "โœ… Successfully parsed {} rules from file",
63        parsed_rules.len()
64    );
65    for rule in parsed_rules {
66        println!("   ๐Ÿ“‹ Rule: {} (salience: {})", rule.name, rule.salience);
67        let _ = kb.add_rule(rule);
68    }
69    println!();
70
71    // Create engine
72    let config = EngineConfig {
73        debug_mode: true,
74        max_cycles: 3,
75        ..Default::default()
76    };
77    let mut engine = RustRuleEngine::with_config(kb, config);
78
79    // Register all custom functions called from the rule file
80    println!("๐Ÿ“ Registering custom functions from rule file...");
81
82    // Functions from SpeedLimitCheck rule
83    engine.register_function("checkSpeedLimit", |args, facts| {
84        let speed_field = args.get(0).unwrap().to_string();
85        let limit = args.get(1).unwrap();
86
87        let speed = if let Some(car) = facts.get("Car") {
88            if let Value::Object(obj) = car {
89                obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
90            } else {
91                Value::Number(0.0)
92            }
93        } else {
94            Value::Number(0.0)
95        };
96
97        let result = format!("๐Ÿšฆ Speed check: {:?} vs limit {:?}", speed, limit);
98        println!("{}", result);
99        Ok(Value::String(result))
100    });
101
102    engine.register_function("sendAlert", |args, facts| {
103        let message = args.get(0).unwrap().to_string();
104        let driver_field = args.get(1).unwrap().to_string();
105
106        let driver_name = if let Some(driver) = facts.get("Driver") {
107            if let Value::Object(obj) = driver {
108                obj.get("Name")
109                    .cloned()
110                    .unwrap_or(Value::String("Unknown".to_string()))
111            } else {
112                Value::String("Unknown".to_string())
113            }
114        } else {
115            Value::String("Unknown".to_string())
116        };
117
118        let alert = format!("๐Ÿšจ ALERT to {:?}: {}", driver_name, message);
119        println!("{}", alert);
120        Ok(Value::String(alert))
121    });
122
123    // Functions from DriverValidation rule
124    engine.register_function("validateDriver", |args, _facts| {
125        let name_field = args.get(0).unwrap().to_string();
126        let exp_field = args.get(1).unwrap().to_string();
127
128        let result = format!(
129            "โœ… Driver validation: {} (experience: {})",
130            name_field, exp_field
131        );
132        println!("{}", result);
133        Ok(Value::String(result))
134    });
135
136    engine.register_function("calculateInsurance", |args, _facts| {
137        let exp_field = args.get(0).unwrap().to_string();
138        let engine_field = args.get(1).unwrap().to_string();
139
140        let result = format!(
141            "๐Ÿ’ฐ Insurance: Experience {} + Engine {} = Premium",
142            exp_field, engine_field
143        );
144        println!("{}", result);
145        Ok(Value::String(result))
146    });
147
148    // Functions from EngineDiagnostics rule
149    engine.register_function("performDiagnostics", |args, _facts| {
150        let engine_field = args.get(0).unwrap().to_string();
151        let speed_field = args.get(1).unwrap().to_string();
152
153        let result = format!(
154            "๐Ÿ”ง Diagnostics: Engine {} at speed {} - OK",
155            engine_field, speed_field
156        );
157        println!("{}", result);
158        Ok(Value::String(result))
159    });
160
161    engine.register_function("optimizePerformance", |args, _facts| {
162        let current_speed = args.get(0).unwrap().to_string();
163        let max_speed = args.get(1).unwrap().to_string();
164
165        let result = format!(
166            "โšก Performance: {} / {} - Optimized",
167            current_speed, max_speed
168        );
169        println!("{}", result);
170        Ok(Value::String(result))
171    });
172
173    // Functions from MaintenanceCheck rule
174    engine.register_function("scheduleMaintenanceCheck", |args, _facts| {
175        let engine_field = args.get(0).unwrap().to_string();
176        let exp_field = args.get(1).unwrap().to_string();
177
178        let result = format!(
179            "๐Ÿ”ง Maintenance scheduled: Engine {} (driver exp: {})",
180            engine_field, exp_field
181        );
182        println!("{}", result);
183        Ok(Value::String(result))
184    });
185
186    engine.register_function("updateMaintenanceRecord", |args, _facts| {
187        let name_field = args.get(0).unwrap().to_string();
188        let engine_field = args.get(1).unwrap().to_string();
189
190        let result = format!("๐Ÿ“‹ Record updated: {} - {}", name_field, engine_field);
191        println!("{}", result);
192        Ok(Value::String(result))
193    });
194
195    println!("โœ… Registered {} custom functions from rule file:", 8);
196    println!("   ๐Ÿšฆ checkSpeedLimit");
197    println!("   ๐Ÿšจ sendAlert");
198    println!("   โœ… validateDriver");
199    println!("   ๐Ÿ’ฐ calculateInsurance");
200    println!("   ๐Ÿ”ง performDiagnostics");
201    println!("   โšก optimizePerformance");
202    println!("   ๐Ÿ”ง scheduleMaintenanceCheck");
203    println!("   ๐Ÿ“‹ updateMaintenanceRecord");
204    println!();
205
206    // Execute rules
207    println!("๐Ÿš€ Executing rules from file...");
208    let result = engine.execute(&facts)?;
209
210    println!("\n๐Ÿ“Š Rule File Execution Results:");
211    println!("   Cycles: {}", result.cycle_count);
212    println!("   Rules evaluated: {}", result.rules_evaluated);
213    println!("   Rules fired: {}", result.rules_fired);
214    println!("   Execution time: {:?}", result.execution_time);
215
216    println!("\n๐Ÿ Final state:");
217    if let Some(car) = facts.get("Car") {
218        println!("   Car = {car:?}");
219    }
220    if let Some(driver) = facts.get("Driver") {
221        println!("   Driver = {driver:?}");
222    }
223
224    println!("\n๐ŸŽฏ Rule File Custom Functions Demonstrated:");
225    println!("   ๐Ÿ“„ Rules defined in external .grl file");
226    println!("   ๐Ÿ“ž Custom functions called from rule file");
227    println!("   ๐Ÿ”ง Business logic separated from rule definitions");
228    println!("   ๐Ÿ“‹ File-based rule management");
229    println!("   โšก Function registry with rule file integration");
230
231    Ok(())
232}

Auto Trait Implementationsยง

Blanket Implementationsยง

Sourceยง

impl<T> Any for T
where T: 'static + ?Sized,

Sourceยง

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Sourceยง

impl<T> Borrow<T> for T
where T: ?Sized,

Sourceยง

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Sourceยง

impl<T> BorrowMut<T> for T
where T: ?Sized,

Sourceยง

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Sourceยง

impl<T> From<T> for T

Sourceยง

fn from(t: T) -> T

Returns the argument unchanged.

Sourceยง

impl<T, U> Into<U> for T
where U: From<T>,

Sourceยง

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Sourceยง

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Sourceยง

type Error = Infallible

The type returned in the event of a conversion error.
Sourceยง

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Sourceยง

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Sourceยง

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Sourceยง

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.