suiron/
logic_var.rs

1//! Functions to support logic variables and the global LOGIC_VAR_ID.
2//!
3//! Logic variables ([LogicVar](../unifiable/enum.Unifiable.html#variant.LogicVar))
4//! consist of a name and an ID.
5//!
6//! The name should start with a dollar sign and a letter, for example: $H.
7//!
8//! Logic variables which are stored in rules can have an ID of 0, but when the
9//! rule is fetched from the knowledge base, its variables must be recreated
10//! to give them unique IDs.
11//! 
12//! See [recreate_variables()](../unifiable/enum.Unifiable.html#method.recreate_variables).
13//!
14
15use std::collections::HashMap;
16use super::unifiable::*;
17
18static mut LOGIC_VAR_ID: usize = 0; // Global ID number for logic variables.
19
20/// Increment and return the logic variable ID.
21/// # Return
22/// * LOGIC_VAR_ID
23pub fn next_id() -> usize {
24    unsafe {
25        LOGIC_VAR_ID += 1;
26        LOGIC_VAR_ID
27    }
28}
29
30/// Gets the logic variable ID.
31/// # Return
32/// * LOGIC_VAR_ID
33pub fn get_var_id() -> usize {
34    unsafe { LOGIC_VAR_ID }
35}
36
37/// Sets the logic variable ID to the given value.
38/// # Arguments
39/// * id
40pub fn set_var_id(id: usize) {
41    unsafe {
42        LOGIC_VAR_ID = id;
43    }
44}
45
46/// Sets the logic variable ID to zero.
47pub fn clear_id() {
48    unsafe { LOGIC_VAR_ID = 0; }
49}
50
51// VarMap defines a map which is used by recreate_variables(),
52// to keep track of previously recreated variables.
53// Key - variable name
54// Value - ID of variable
55pub type VarMap = HashMap<String, usize>;
56
57/// Creates a logic variable from a string.
58///
59/// Unlike the macro logic_var!, this function validates its arguments.<br>
60/// The variable name must begin with a dollar sign and a letter, eg. $X<br>
61/// If the name is invalid, an error message is returned.<br>
62/// This function creates new variables with an ID of 0. This is OK for defining
63/// rules in the knowledge base, but when a rule is fetched from the knowledge
64/// base, the logic variable must be recreated with a unique ID.
65/// # Arguments
66/// * name
67/// # Return
68/// * [logic variable](../unifiable/enum.Unifiable.html#variant.LogicVar)
69/// or error message
70pub fn make_logic_var<'a>(name: String) -> Result<Unifiable, String> {
71
72    let trimmed = name.trim();
73    let the_chars: Vec<_> = trimmed.chars().collect();
74
75    if the_chars.len() < 2 {
76        let err = mlv_error("Variable must start with $ and a letter", trimmed);
77        return Err(err);
78    }
79    if the_chars[0] != '$' {
80        let err = mlv_error("Variable must start with $", trimmed);
81        return Err(err);
82    }
83    if !the_chars[1].is_alphabetic() {
84        let err = mlv_error("Second character must be a letter", trimmed);
85        return Err(err);
86    }
87
88    let name = trimmed.to_string();
89    return Ok(Unifiable::LogicVar{ id: 0, name: name });
90
91} // make_logic_var()
92
93/// Formats an error message for make_logic_var().
94///
95/// # Arguments
96/// * error description
97/// * string which caused the error
98/// # Return
99/// * error message
100fn mlv_error(err: &str, bad: &str) -> String {
101    format!("make_logic_var() - {}: {}", err, bad)
102}