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)]
176#[derive(Clone)]
177pub struct Trigger {
178 pub trigger: String,
179 pub reply: Vec<String>,
180 pub condition: Vec<Condition>,
181 pub redirect: String,
182 pub previous: String,
183}
184
185impl Trigger {
186 pub fn new(trigger: &str) -> Self {
187 Self {
188 trigger: trigger.to_string(),
189 reply: Vec::new(),
190 condition: Vec::new(),
191 redirect: String::from(""),
192 previous: String::from(""),
193 }
194 }
195
196 pub fn is_populated(&self) -> bool {
197 self.trigger.len() > 0
198 }
199}
200
201#[derive(Debug, Clone)]
203pub struct Condition {
204 pub left: String,
205 pub operator: String,
206 pub right: String,
207 pub reply: String,
208}
209
210#[derive(Debug)]
217pub struct Object {
218 pub name: String,
219 pub language: String,
220 pub code: Vec<String>,
221}
222
223impl Object {
224 pub fn new(name: &str, language: &str, code: Vec<String>) -> Self {
225 Self {
226 name: name.to_string(),
227 language: language.to_string(),
228 code,
229 }
230 }
231}