1use std::{collections::HashMap, sync::RwLock};
10
11#[derive(Debug)]
14pub struct AST {
15 pub version: f32, pub globals: RwLock<HashMap<String, String>>, pub vars: RwLock<HashMap<String, String>>, pub subs: HashMap<String, String>, pub person: HashMap<String, String>, pub arrays: HashMap<String, Vec<String>>, pub topics: HashMap<String, Topic>,
25
26 pub objects: HashMap<String, Object>,
28}
29
30#[derive(Debug, Clone)]
39pub struct Topic {
40 pub name: String,
41 pub triggers: Vec<Trigger>,
42 pub includes: HashMap<String, bool>,
43 pub inherits: HashMap<String, bool>,
44}
45
46impl AST {
47 pub fn new() -> Self {
49 Self {
50 version: 0.0,
51 globals: RwLock::new(HashMap::new()),
52 vars: RwLock::new(HashMap::new()),
53 subs: HashMap::new(),
54 person: HashMap::new(),
55 arrays: HashMap::new(),
56 topics: HashMap::new(),
57 objects: HashMap::new(),
58 }
59 }
60
61 pub fn extend(&mut self, other: AST) {
66 if other.version != 0.0 {
67 self.version = other.version;
68 }
69
70 let mut global_guard = self.globals.write().expect("RwLock poisoned");
71 let mut other_globals = other.globals.write().expect("RwLock poisoned");
72 global_guard.extend(other_globals.drain());
73
74 let mut vars_guard = self.vars.write().expect("RwLock poisoned");
75 let mut other_vars = other.vars.write().expect("RwLock poisoned");
76 vars_guard.extend(other_vars.drain());
77
78 self.subs.extend(other.subs.into_iter());
79 self.person.extend(other.person.into_iter());
80 self.arrays.extend(other.arrays.into_iter());
81 self.objects.extend(other.objects.into_iter());
83
84 for (name, topic) in other.topics {
86 match self.topics.get_mut(&name) {
87 Some(mine) => {
88 mine.triggers.extend(topic.triggers);
89 }
90 None => {
91 self.topics.insert(name, topic);
92 }
93 }
94 }
95 }
96
97 pub fn init_topic(&mut self, name: &String) {
99 if self.topics.contains_key(name) {
100 return;
101 }
102
103 self.topics.insert(
104 name.to_string(),
105 Topic {
106 name: name.to_string(),
107 triggers: Vec::new(),
108 includes: HashMap::new(),
109 inherits: HashMap::new(),
110 },
111 );
112 }
113
114 pub fn has_begin_block(&self) -> bool {
116 self.topics.contains_key(crate::BEGIN_TOPIC)
117 }
118
119 pub fn has_topic(&self, name: &str) -> bool {
121 self.topics.contains_key(name)
122 }
123
124 pub fn get_global(&self, name: &str) -> String {
126 let globals_guard = self.globals.read().expect("RwLock poisoned");
127 if let Some(value) = globals_guard.get(name) {
128 return value.to_string();
129 }
130 crate::UNDEFINED.to_string()
131 }
132
133 pub fn set_global(&self, name: &str, value: &str) {
135 let mut globals_guard = self.globals.write().expect("RwLock poisoned");
136 globals_guard.insert(name.to_string(), value.to_string());
137 }
138
139 pub fn get_bot_var(&self, name: &str) -> String {
141 let vars_guard = self.vars.read().expect("RwLock poisoned");
142 if let Some(value) = vars_guard.get(name) {
143 return value.to_string();
144 }
145 crate::UNDEFINED.to_string()
146 }
147
148 pub fn set_bot_var(&self, name: &str, value: &str) {
150 let mut vars_guard = self.vars.write().expect("RwLock poisoned");
151 vars_guard.insert(name.to_string(), value.to_string());
152 }
153}
154
155impl Topic {
156 pub fn set_includes(&mut self, includes: String) {
157 self.includes.insert(includes.to_string(), true);
158 }
159
160 pub fn set_inherits(&mut self, inherits: String) {
161 self.inherits.insert(inherits.to_string(), true);
162 }
163
164 pub fn add_trigger(&mut self, trigger: Trigger) {
165 self.triggers.push(trigger);
166 }
167}
168
169#[derive(Debug, Clone)]
176pub struct Trigger {
177 pub trigger: String,
178 pub reply: Vec<String>,
179 pub condition: Vec<Condition>,
180 pub redirect: String,
181 pub previous: String,
182}
183
184impl Trigger {
185 pub fn new(trigger: &str) -> Self {
186 Self {
187 trigger: trigger.to_string(),
188 reply: Vec::new(),
189 condition: Vec::new(),
190 redirect: String::from(""),
191 previous: String::from(""),
192 }
193 }
194
195 pub fn is_populated(&self) -> bool {
196 self.trigger.len() > 0
197 }
198}
199
200#[derive(Debug, Clone)]
202pub struct Condition {
203 pub left: String,
204 pub operator: String,
205 pub right: String,
206 pub reply: String,
207}
208
209#[derive(Debug, Clone)]
216pub struct Object {
217 pub name: String,
218 pub language: String,
219 pub code: Vec<String>,
220}
221
222impl Object {
223 pub fn new(name: &str, language: &str, code: Vec<String>) -> Self {
224 Self {
225 name: name.to_string(),
226 language: language.to_string(),
227 code,
228 }
229 }
230}