Value

Enum Value 

Source
pub enum Value {
    String(String),
    Number(f64),
    Integer(i64),
    Boolean(bool),
    Array(Vec<Value>),
    Object(HashMap<String, Value>),
    Null,
}
Expand description

Represents a value that can be used in rule conditions and actions

Variants§

§

String(String)

String value

§

Number(f64)

Floating point number

§

Integer(i64)

Integer value

§

Boolean(bool)

Boolean value

§

Array(Vec<Value>)

Array of values

§

Object(HashMap<String, Value>)

Object with key-value pairs

§

Null

Null value

Implementations§

Source§

impl Value

Source

pub fn to_string(&self) -> String

Convert Value to string representation

Examples found in repository?
examples/inline_rules_demo.rs (line 117)
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}
More examples
Hide additional examples
examples/rule_file_functions_demo.rs (line 84)
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}
examples/custom_functions_demo.rs (line 139)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9    println!("🎯 Custom Function Calls Demo");
10    println!("=============================\n");
11
12    // Create facts
13    let facts = Facts::new();
14
15    // Car data
16    let mut car_props = HashMap::new();
17    car_props.insert("Speed".to_string(), Value::Number(60.0));
18    car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
19    car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
20    car_props.insert("IsRunning".to_string(), Value::Boolean(true));
21
22    // Driver data
23    let mut driver_props = HashMap::new();
24    driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
25    driver_props.insert("Experience".to_string(), Value::Integer(5));
26    driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
27
28    facts.add_value("Car", Value::Object(car_props))?;
29    facts.add_value("Driver", Value::Object(driver_props))?;
30
31    println!("🏁 Initial state:");
32    if let Some(car) = facts.get("Car") {
33        println!("   Car = {car:?}");
34    }
35    if let Some(driver) = facts.get("Driver") {
36        println!("   Driver = {driver:?}");
37    }
38    println!();
39
40    // Create knowledge base
41    let mut kb = KnowledgeBase::new("CustomFunctionRules");
42
43    // Rule 1: Speed Check with custom function
44    let speed_check_rule = Rule::new(
45        "SpeedCheck".to_string(),
46        ConditionGroup::single(Condition::new(
47            "Car.Speed".to_string(),
48            Operator::GreaterThan,
49            Value::Number(80.0),
50        )),
51        vec![
52            ActionType::Call {
53                function: "checkSpeedLimit".to_string(),
54                args: vec![Value::String("Car.Speed".to_string()), Value::Number(80.0)],
55            },
56            ActionType::Call {
57                function: "sendAlert".to_string(),
58                args: vec![
59                    Value::String("Speed limit exceeded!".to_string()),
60                    Value::String("Driver.Name".to_string()),
61                ],
62            },
63        ],
64    )
65    .with_salience(20);
66
67    // Rule 2: Driver validation
68    let driver_validation_rule = Rule::new(
69        "DriverValidation".to_string(),
70        ConditionGroup::single(Condition::new(
71            "Driver.License".to_string(),
72            Operator::Equal,
73            Value::String("VALID".to_string()),
74        )),
75        vec![
76            ActionType::Call {
77                function: "validateDriver".to_string(),
78                args: vec![
79                    Value::String("Driver.Name".to_string()),
80                    Value::String("Driver.Experience".to_string()),
81                ],
82            },
83            ActionType::Call {
84                function: "calculateInsurance".to_string(),
85                args: vec![
86                    Value::String("Driver.Experience".to_string()),
87                    Value::String("Car.Engine".to_string()),
88                ],
89            },
90        ],
91    )
92    .with_salience(15);
93
94    // Rule 3: Engine diagnostics
95    let engine_diagnostics_rule = Rule::new(
96        "EngineDiagnostics".to_string(),
97        ConditionGroup::single(Condition::new(
98            "Car.IsRunning".to_string(),
99            Operator::Equal,
100            Value::Boolean(true),
101        )),
102        vec![
103            ActionType::Call {
104                function: "performDiagnostics".to_string(),
105                args: vec![
106                    Value::String("Car.Engine".to_string()),
107                    Value::String("Car.Speed".to_string()),
108                ],
109            },
110            ActionType::Call {
111                function: "optimizePerformance".to_string(),
112                args: vec![
113                    Value::String("Car.Speed".to_string()),
114                    Value::String("Car.MaxSpeed".to_string()),
115                ],
116            },
117        ],
118    )
119    .with_salience(10);
120
121    // Add rules to knowledge base
122    let _ = kb.add_rule(speed_check_rule);
123    let _ = kb.add_rule(driver_validation_rule);
124    let _ = kb.add_rule(engine_diagnostics_rule);
125
126    // Create engine
127    let config = EngineConfig {
128        debug_mode: true,
129        max_cycles: 3,
130        ..Default::default()
131    };
132    let mut engine = RustRuleEngine::with_config(kb, config);
133
134    // Register custom functions
135    println!("📝 Registering custom functions...");
136
137    // Function 1: Check speed limit
138    engine.register_function("checkSpeedLimit", |args, facts| {
139        let speed_field = args.get(0).unwrap().to_string();
140        let limit = args.get(1).unwrap();
141
142        // Get actual speed value from facts
143        let speed = if let Some(car) = facts.get("Car") {
144            if let Value::Object(obj) = car {
145                obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
146            } else {
147                Value::Number(0.0)
148            }
149        } else {
150            Value::Number(0.0)
151        };
152
153        let result = format!("Speed check: {:?} vs limit {:?}", speed, limit);
154        println!("🚦 {}", result);
155        Ok(Value::String(result))
156    });
157
158    // Function 2: Send alert
159    engine.register_function("sendAlert", |args, facts| {
160        let message = args.get(0).unwrap().to_string();
161        let driver_field = args.get(1).unwrap().to_string();
162
163        // Get driver name from facts
164        let driver_name = if let Some(driver) = facts.get("Driver") {
165            if let Value::Object(obj) = driver {
166                obj.get("Name")
167                    .cloned()
168                    .unwrap_or(Value::String("Unknown".to_string()))
169            } else {
170                Value::String("Unknown".to_string())
171            }
172        } else {
173            Value::String("Unknown".to_string())
174        };
175
176        let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
177        println!("{}", alert);
178        Ok(Value::String(alert))
179    });
180
181    // Function 3: Validate driver
182    engine.register_function("validateDriver", |args, _facts| {
183        let name_field = args.get(0).unwrap().to_string();
184        let exp_field = args.get(1).unwrap().to_string();
185
186        let result = format!(
187            "✅ Driver validation passed for {} (experience: {})",
188            name_field, exp_field
189        );
190        println!("{}", result);
191        Ok(Value::String(result))
192    });
193
194    // Function 4: Calculate insurance
195    engine.register_function("calculateInsurance", |args, _facts| {
196        let exp_field = args.get(0).unwrap().to_string();
197        let engine_field = args.get(1).unwrap().to_string();
198
199        let result = format!(
200            "💰 Insurance calculated: Experience {} + Engine {} = Premium rate",
201            exp_field, engine_field
202        );
203        println!("{}", result);
204        Ok(Value::String(result))
205    });
206
207    // Function 5: Perform diagnostics
208    engine.register_function("performDiagnostics", |args, _facts| {
209        let engine_field = args.get(0).unwrap().to_string();
210        let speed_field = args.get(1).unwrap().to_string();
211
212        let result = format!(
213            "🔧 Diagnostics: Engine {} running at speed {} - All systems OK",
214            engine_field, speed_field
215        );
216        println!("{}", result);
217        Ok(Value::String(result))
218    });
219
220    // Function 6: Optimize performance
221    engine.register_function("optimizePerformance", |args, _facts| {
222        let current_speed = args.get(0).unwrap().to_string();
223        let max_speed = args.get(1).unwrap().to_string();
224
225        let result = format!(
226            "⚡ Performance optimization: Current {} / Max {} - Efficiency tuned",
227            current_speed, max_speed
228        );
229        println!("{}", result);
230        Ok(Value::String(result))
231    });
232
233    println!("✅ Registered {} custom functions:", 6);
234    println!("   🚦 checkSpeedLimit - Check if speed exceeds limit");
235    println!("   🚨 sendAlert - Send alert message to driver");
236    println!("   ✅ validateDriver - Validate driver credentials");
237    println!("   💰 calculateInsurance - Calculate insurance premium");
238    println!("   🔧 performDiagnostics - Run engine diagnostics");
239    println!("   ⚡ optimizePerformance - Optimize engine performance");
240    println!();
241
242    // Execute rules
243    println!("🚀 Executing rules with custom functions...");
244    let result = engine.execute(&facts)?;
245
246    println!("\n📊 Custom Function Execution Results:");
247    println!("   Cycles: {}", result.cycle_count);
248    println!("   Rules evaluated: {}", result.rules_evaluated);
249    println!("   Rules fired: {}", result.rules_fired);
250    println!("   Execution time: {:?}", result.execution_time);
251
252    println!("\n🏁 Final state:");
253    if let Some(car) = facts.get("Car") {
254        println!("   Car = {car:?}");
255    }
256    if let Some(driver) = facts.get("Driver") {
257        println!("   Driver = {driver:?}");
258    }
259
260    println!("\n🎯 Custom Function Calls Demonstrated:");
261    println!("   📞 User-defined functions called from rules");
262    println!("   🔧 Custom business logic execution");
263    println!("   🎪 Function registry system");
264    println!("   📋 Rule-based custom function invocation");
265    println!("   ⚡ Real-time function parameter resolution");
266
267    Ok(())
268}
Source

pub fn to_number(&self) -> Option<f64>

Convert Value to number if possible

Examples found in repository?
examples/advanced_method_calls.rs (line 81)
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}
More examples
Hide additional examples
examples/complete_speedup_demo.rs (line 123)
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}
Source

pub fn as_string(&self) -> Option<String>

Get string value if this is a string

Source

pub fn as_integer(&self) -> Option<i64>

Get integer value if this is an integer

Source

pub fn as_boolean(&self) -> Option<bool>

Get boolean value if this is a boolean

Source

pub fn as_number(&self) -> Option<f64>

Get number value if this is a number

Source

pub fn to_bool(&self) -> bool

Convert Value to boolean

Source

pub fn call_method( &mut self, method: &str, args: Vec<Value>, ) -> Result<Value, String>

Call a method on this value with given arguments

Source

pub fn get_property(&self, property: &str) -> Option<Value>

Get a property from this object

Examples found in repository?
examples/debug_conditions.rs (line 51)
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 55)
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/complete_speedup_demo.rs (line 68)
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}
Source

pub fn set_property( &mut self, property: &str, value: Value, ) -> Result<(), String>

Set a property on this object

Trait Implementations§

Source§

impl Clone for Value

Source§

fn clone(&self) -> Value

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Value

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Value

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl From<&str> for Value

Source§

fn from(s: &str) -> Self

Converts to this type from the input type.
Source§

impl From<String> for Value

Source§

fn from(s: String) -> Self

Converts to this type from the input type.
Source§

impl From<Value> for Value

Source§

fn from(json_value: Value) -> Self

Converts to this type from the input type.
Source§

impl From<bool> for Value

Source§

fn from(b: bool) -> Self

Converts to this type from the input type.
Source§

impl From<f64> for Value

Source§

fn from(n: f64) -> Self

Converts to this type from the input type.
Source§

impl From<i64> for Value

Source§

fn from(i: i64) -> Self

Converts to this type from the input type.
Source§

impl PartialEq for Value

Source§

fn eq(&self, other: &Value) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Value

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Value

Auto Trait Implementations§

§

impl Freeze for Value

§

impl RefUnwindSafe for Value

§

impl Send for Value

§

impl Sync for Value

§

impl Unpin for Value

§

impl UnwindSafe for Value

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,