1use std::collections::{BTreeSet, HashMap};
2
3use either::Either;
4#[cfg(feature = "rand")]
5use rand::RngExt;
6use smodel::{
7 ProjectDoc,
8 attrs::{List, Variable},
9};
10use svalue::{SList, SNumber, SValue};
11
12use crate::state::{OutputKind, State};
13
14#[derive(Debug, PartialEq, PartialOrd, Clone)]
15pub enum Action {
16 Output {
17 kind: crate::state::OutputKind,
18 message: SValue,
19 },
20 AskQuestion {
21 message: SValue,
22 },
23 RequestRandom {
24 from: SNumber,
25 to: SNumber,
26 received: SNumber,
27 },
28 WaitFor {
29 secs: SNumber,
30 },
31}
32
33#[derive(Debug, Default, PartialEq, derive_getters::Getters)]
34pub struct DefaultState {
35 uninitialized_usages: BTreeSet<Either<Variable, List>>,
41 initialized_data: BTreeSet<Either<Variable, List>>,
47 variables: HashMap<Variable, SValue>,
48 lists: HashMap<List, SList>,
49 actions: Vec<Action>,
50
51 answer_index: Option<usize>,
52 answer_inputs: Vec<svalue::ARc<str>>,
53
54 #[cfg(feature = "rand")]
55 randoms: Option<rand::rngs::StdRng>,
56 predefined_randoms: Option<(svalue::ARc<[svalue::SNumber]>, usize)>,
57}
58
59#[allow(unused)]
60impl DefaultState {
61 pub fn new() -> Self {
62 DefaultState {
63 uninitialized_usages: Default::default(),
64 initialized_data: Default::default(),
65 variables: HashMap::new(),
66 lists: HashMap::new(),
67 actions: vec![],
68 answer_index: None,
69 answer_inputs: vec![],
70 #[cfg(feature = "rand")]
71 randoms: None,
72 predefined_randoms: None,
73 }
74 }
75
76 pub fn from_doc(doc: &ProjectDoc, max_list_length: i64) -> Self {
77 let mut s = Self::new();
78 s.add_data_from_doc(doc, max_list_length);
79 s
80 }
81
82 pub fn add_data_from_doc(&mut self, doc: &ProjectDoc, max_length: i64) -> &mut Self {
83 self.add_variables_from_doc(doc)
84 .add_lists_from_doc(doc, max_length)
85 }
86
87 pub fn add_variables_from_doc(&mut self, doc: &ProjectDoc) -> &mut Self {
88 self.variables.extend(
89 doc.targets()
90 .iter()
91 .flat_map(|t| t.variables().values())
92 .cloned(),
93 );
94 self
95 }
96
97 pub fn add_lists_from_doc(&mut self, doc: &ProjectDoc, max_length: i64) -> &mut Self {
98 self.lists
99 .extend(
100 doc.targets()
101 .iter()
102 .flat_map(|t| t.lists().values())
103 .map(|(dataid, v)| {
104 let mut list = SList::new(max_length);
105 for i in v {
106 list.append_item(i.clone());
108 }
109 (dataid.clone(), list)
110 }),
111 );
112 self
113 }
114
115 fn use_uninitialized_list(&mut self, list_id: &List) -> Result<(), <Self as State>::Error> {
116 let list_id = Either::Right(list_id.clone());
117 if !self.initialized_data.contains(&list_id) {
118 self.uninitialized_usages.insert(list_id);
119 }
120 Ok(())
121 }
122
123 fn use_uninitialized_variable(
124 &mut self,
125 variable_id: &Variable,
126 ) -> Result<(), <Self as State>::Error> {
127 let variable_id = Either::Left(variable_id.clone());
128 if !self.initialized_data.contains(&variable_id) {
129 self.uninitialized_usages.insert(variable_id);
130 }
131 Ok(())
132 }
133
134 pub fn output_lines(&self) -> impl DoubleEndedIterator<Item = (&SValue)> {
135 self.output_actions().map(|(_, text)| text)
136 }
137
138 pub fn output_actions(&self) -> impl DoubleEndedIterator<Item = (&OutputKind, &SValue)> {
139 self.actions().iter().flat_map(|a| {
140 if let Action::Output { kind, message } = a {
141 Some((kind, message))
142 } else {
143 None
144 }
145 })
146 }
147 pub fn used_randoms(&self) -> impl DoubleEndedIterator<Item = &SNumber> {
148 self.actions().iter().flat_map(|a| {
149 if let Action::RequestRandom { received, .. } = a {
150 Some(received)
151 } else {
152 None
153 }
154 })
155 }
156
157 #[cfg(feature = "rand")]
158 pub fn set_randoms(&mut self, rng: Option<rand::rngs::StdRng>) -> &mut Self {
159 self.randoms = rng;
160 self
161 }
162 pub fn set_predefined_randoms(
163 &mut self,
164 predefined: svalue::ARc<[svalue::SNumber]>,
165 ) -> &mut Self {
166 self.predefined_randoms = Some((predefined, 0));
167 self
168 }
169 pub fn set_answers(&mut self, answers: Vec<svalue::ARc<str>>) -> &mut Self {
170 self.answer_inputs = answers;
171 self.answer_index = None;
172 self
173 }
174 pub fn variables_mut(&mut self) -> &mut HashMap<Variable, SValue> {
175 &mut self.variables
176 }
177 pub fn lists_mut(&mut self) -> &mut HashMap<List, SList> {
178 &mut self.lists
179 }
180}
181
182#[derive(Debug, PartialEq, PartialOrd, Clone, thiserror::Error)]
183#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
184#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
185#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
186pub enum DefaultStateError {
187 #[error("variable {0:?} does not exist in state")]
188 VariableNotFound(Variable),
189 #[error("list {0:?} does not exist in state")]
190 ListNotFound(List),
191 #[error("list {id:?} is full, no item can be inserted")]
192 ListFull { id: List },
193 #[error("program is not allowed to request random numbers")]
194 RandomsDisabled,
195 #[error("program requested random number that doesn't match predefined ones")]
196 IncompatibleRandomRequested {
197 predefined: SNumber,
198 #[cfg_attr(feature = "utoipa", schema(value_type = Value))]
199 #[cfg_attr(feature = "schemars", schemars(skip))]
200 range: either::Either<(i64, i64), (f64, f64)>,
201 },
202 #[error("program asked question without a predefined answer remaining")]
203 NoMoreAnswers,
204}
205
206impl State for DefaultState {
207 type Error = DefaultStateError;
208
209 fn ask_question(&mut self, question: SValue) -> Result<(), Self::Error> {
210 self.actions.push(Action::AskQuestion { message: question });
211 self.answer_index = Some(self.answer_index.map(|x| x + 1).unwrap_or(0));
212
213 self.answer_index
214 .and_then(|index| self.answer_inputs.get(index))
215 .ok_or(DefaultStateError::NoMoreAnswers)?;
216 Ok(())
217 }
218 fn last_answer(&mut self) -> Result<&str, Self::Error> {
219 if let Some(index) = self.answer_index {
220 Ok(self
221 .answer_inputs
222 .get(index)
223 .or(self.answer_inputs.last())
224 .map(|s| s.as_ref())
225 .unwrap_or(""))
226 } else {
227 Ok("")
228 }
229 }
230
231 fn request_int_random(
232 &mut self,
233 range: std::ops::RangeInclusive<i64>,
234 ) -> Result<i64, Self::Error> {
235 let received = if let Some((pred, pos)) = self.predefined_randoms.as_mut()
236 && let Some(received) = pred.get(*pos)
237 {
238 match received {
239 SNumber::Float(_) => {
240 return Err(DefaultStateError::IncompatibleRandomRequested {
241 predefined: *received,
242 range: Either::Left(range.into_inner()),
243 });
244 }
245 SNumber::Int(i) => {
246 *pos += 1;
247 *i
248 }
249 }
250 } else {
251 #[cfg(not(feature = "rand"))]
252 return Err(DefaultStateError::RandomsDisabled);
253 #[cfg(feature = "rand")]
254 self.randoms
255 .as_mut()
256 .ok_or(DefaultStateError::RandomsDisabled)?
257 .random_range(range.clone())
258 };
259
260 let (from, to) = range.into_inner();
261 self.actions.push(Action::RequestRandom {
262 from: SNumber::Int(from),
263 to: SNumber::Int(to),
264 received: SNumber::Int(received),
265 });
266 Ok(received)
267 }
268
269 fn request_float_random(
270 &mut self,
271 range: std::ops::RangeInclusive<f64>,
272 ) -> Result<f64, Self::Error> {
273 let received = if let Some((pred, pos)) = self.predefined_randoms.as_mut()
274 && let Some(received) = pred.get(*pos)
275 {
276 match received {
277 SNumber::Int(_) => {
278 return Err(DefaultStateError::IncompatibleRandomRequested {
279 predefined: *received,
280 range: Either::Right(range.into_inner()),
281 });
282 }
283 SNumber::Float(i) => {
284 *pos += 1;
285 *i
286 }
287 }
288 } else {
289 #[cfg(not(feature = "rand"))]
290 return Err(DefaultStateError::RandomsDisabled);
291 #[cfg(feature = "rand")]
292 self.randoms
293 .as_mut()
294 .ok_or(DefaultStateError::RandomsDisabled)?
295 .random_range(range.clone())
296 };
297
298 let (from, to) = range.into_inner();
299 self.actions.push(Action::RequestRandom {
300 from: SNumber::Float(from),
301 to: SNumber::Float(to),
302 received: SNumber::Float(received),
303 });
304 Ok(received)
305 }
306 fn write_output(&mut self, output_kind: crate::state::OutputKind, message: SValue) {
307 self.actions.push(Action::Output {
308 kind: output_kind,
309 message,
310 });
311 }
312
313 fn wait_for_secs(&mut self, secs: SNumber) -> Result<(), Self::Error> {
314 self.actions.push(Action::WaitFor { secs });
315 Ok(())
316 }
317
318 fn data_set_variable(&mut self, var_id: &Variable, value: SValue) -> Result<(), Self::Error> {
319 let store = self
320 .variables
321 .get_mut(var_id)
322 .ok_or_else(|| unknown_var(var_id))?;
323 *store = value;
324 self.initialized_data.insert(Either::Left(var_id.clone()));
325 Ok(())
326 }
327 fn data_read_variable(&mut self, var_id: &Variable) -> Result<&SValue, Self::Error> {
328 self.use_uninitialized_variable(var_id)?;
329 self.variables
330 .get(var_id)
331 .ok_or_else(|| unknown_var(var_id))
332 }
333 fn data_insert_at_list(
334 &mut self,
335 list_id: &List,
336 one_based_index: &SValue,
337 item: SValue,
338 ) -> Result<(), Self::Error> {
339 self.use_uninitialized_list(list_id)?;
340 self.list_mut(list_id)?
341 .insert_item_at(one_based_index, item, &mut ())
342 .map_err(|_err| DefaultStateError::ListFull {
343 id: list_id.clone(),
344 })?;
345 Ok(())
346 }
347 fn data_replace_list_at(
348 &mut self,
349 list_id: &List,
350 one_based_index: &SValue,
351 item: SValue,
352 ) -> Result<(), Self::Error> {
353 self.use_uninitialized_list(list_id)?;
354 self.list_mut(list_id)?
355 .replace_nth_item(one_based_index, item, &mut ());
356 Ok(())
357 }
358 fn data_append_to_list(&mut self, list_id: &List, item: SValue) -> Result<(), Self::Error> {
359 self.use_uninitialized_list(list_id)?;
360 self.list_mut(list_id)?
361 .append_item(item)
362 .map_err(|_err| DefaultStateError::ListFull {
363 id: list_id.clone(),
364 })?;
365 Ok(())
366 }
367 fn data_list_contains_item(
368 &mut self,
369 list_id: &List,
370 item: &SValue,
371 ) -> Result<bool, Self::Error> {
372 self.use_uninitialized_list(list_id)?;
373 Ok(self.list_mut(list_id)?.contains_item(item))
374 }
375 fn data_delete_of_list(
376 &mut self,
377 list_id: &List,
378 one_based_index: &SValue,
379 ) -> Result<(), Self::Error> {
380 self.use_uninitialized_list(list_id)?;
381 self.list_mut(list_id)?.delete_nth(one_based_index, &mut ());
382 Ok(())
383 }
384 fn data_delete_all_of_list(&mut self, list_id: &List) -> Result<(), Self::Error> {
385 self.initialized_data.insert(Either::Right(list_id.clone()));
386 self.list_mut(list_id)?.delete_all();
387 Ok(())
388 }
389 fn data_read_textual_list_repr(&mut self, list_id: &List) -> Result<SValue, Self::Error> {
390 self.use_uninitialized_list(list_id)?;
391 Ok(self.list(list_id)?.textual_representation().into())
392 }
393 fn data_item_num_of_list(&mut self, list_id: &List, item: &SValue) -> Result<i64, Self::Error> {
394 self.use_uninitialized_list(list_id)?;
395 Ok(self.list(list_id)?.first_index_of_item_in_list(item))
396 }
397 fn data_item_of_list(
398 &mut self,
399 list_id: &List,
400 one_based_index: &SValue,
401 ) -> Result<SValue, Self::Error> {
402 self.use_uninitialized_list(list_id)?;
403 Ok(self.list(list_id)?.nth_item(one_based_index, &mut ()))
404 }
405 fn data_length_of_list(&mut self, list_id: &List) -> Result<i64, Self::Error> {
406 self.use_uninitialized_list(list_id)?;
407 Ok(self.list(list_id)?.length())
408 }
409}
410
411fn unknown_var(var_id: &Variable) -> DefaultStateError {
412 DefaultStateError::VariableNotFound(var_id.clone())
413}
414
415fn unknown_list(list_id: &List) -> DefaultStateError {
416 DefaultStateError::ListNotFound(list_id.clone())
417}
418
419impl DefaultState {
420 #[allow(unused)]
421 fn list_mut(&mut self, list_id: &List) -> Result<&mut SList, DefaultStateError> {
422 self.lists
423 .get_mut(list_id)
424 .ok_or_else(|| unknown_list(list_id))
425 }
426 #[allow(unused)]
427 fn list(&mut self, list_id: &List) -> Result<&SList, DefaultStateError> {
428 self.lists.get(list_id).ok_or_else(|| unknown_list(list_id))
429 }
430}