1use std::collections::hash_map::DefaultHasher;
2use std::fmt::{Debug, Display, Formatter};
3use std::hash::Hash;
4use std::{collections::HashMap, hash::Hasher};
5
6pub use error::DataError;
7use garnish_lang_traits::helpers::iterate_concatenation_mut;
8use garnish_lang_traits::{GarnishData, GarnishDataType, Instruction};
9
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12
13mod clone;
14mod data;
15mod error;
16mod instruction;
17mod runtime;
18
19pub use data::*;
20pub use instruction::SimpleInstruction;
21
22pub fn symbol_value(value: &str) -> u64 {
24 let mut h = DefaultHasher::new();
25 value.hash(&mut h);
26 let hv = h.finish();
27
28 hv
29}
30
31#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Debug, Hash)]
34pub struct NoCustom {}
35
36impl Display for NoCustom {
37 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38 f.write_str("NoCustom")
39 }
40}
41
42impl DisplayForCustomItem for NoCustom {
43 fn display_with_list(&self, _list: &SimpleDataList, _level: usize) -> String {
44 format!("{}", self)
45 }
46}
47
48#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
50#[derive(Debug, Clone)]
51pub struct SimpleGarnishData<T = NoCustom>
52where
53 T: Clone + PartialEq + Eq + PartialOrd + Debug + Hash,
54{
55 register: Vec<usize>,
56 data: SimpleDataList<T>,
57 end_of_constant_data: usize,
58 values: Vec<usize>,
59 instructions: Vec<SimpleInstruction>,
60 instruction_cursor: usize,
61 expression_table: Vec<usize>,
62 current_list: Option<(Vec<usize>, Vec<usize>)>,
63 current_char_list: Option<String>,
64 current_byte_list: Option<Vec<u8>>,
65 cache: HashMap<u64, usize>,
66 max_char_list_depth: usize,
67}
68
69pub type SimpleDataRuntimeNC = SimpleGarnishData<NoCustom>;
71
72impl SimpleGarnishData<NoCustom> {
73 pub fn new() -> Self {
74 SimpleGarnishData {
75 register: vec![],
76 data: SimpleDataList::default(),
77 end_of_constant_data: 0,
78 values: vec![],
79 instruction_cursor: 0,
80 instructions: vec![],
81 expression_table: vec![],
82 current_list: None,
83 current_char_list: None,
84 current_byte_list: None,
85 cache: HashMap::new(),
86 max_char_list_depth: 1000,
87 }
88 }
89}
90
91impl<T> SimpleGarnishData<T>
92where
93 T: Clone + PartialEq + Eq + PartialOrd + Debug + Hash,
94{
95 pub fn new_custom() -> Self {
96 SimpleGarnishData {
97 register: vec![],
98 data: SimpleDataList::<T>::default(),
99 end_of_constant_data: 0,
100 values: vec![],
101 instruction_cursor: 0,
102 instructions: vec![],
103 expression_table: vec![],
104 current_list: None,
105 current_char_list: None,
106 current_byte_list: None,
107 cache: HashMap::new(),
108 max_char_list_depth: 1000,
109 }
110 }
111
112 pub(crate) fn get(&self, index: usize) -> Result<&SimpleData<T>, DataError> {
113 match self.data.get(index) {
114 None => Err(format!("No data at addr {:?}", index))?,
115 Some(d) => Ok(d),
116 }
117 }
118
119 pub fn add_custom(&mut self, data: T) -> Result<usize, DataError> {
120 self.data.push(SimpleData::Custom(data));
121 Ok(self.data.len() - 1)
122 }
123
124 pub fn add_stack_frame(&mut self, frame: SimpleStackFrame) -> Result<usize, DataError> {
125 self.data.push(SimpleData::StackFrame(frame));
126 Ok(self.data.len() - 1)
127 }
128
129 pub fn get_custom(&self, addr: usize) -> Result<T, DataError> {
130 self.get(addr)?.as_custom()
131 }
132
133 pub fn get_symbols(&self) -> &HashMap<u64, String> {
134 self.data.symbol_to_name()
135 }
136
137 pub fn get_registers(&self) -> &Vec<usize> {
138 &self.register
139 }
140
141 pub fn get_jump_points(&self) -> &Vec<usize> {
142 &self.expression_table
143 }
144
145 pub fn get_instructions(&self) -> &Vec<SimpleInstruction> {
146 &self.instructions
147 }
148
149 pub fn get_data(&self) -> &SimpleDataList<T> {
150 &self.data
151 }
152
153 pub fn get_data_mut(&mut self) -> &mut SimpleDataList<T> {
154 &mut self.data
155 }
156
157 pub fn get_raw_data(&self, index: usize) -> Option<SimpleData<T>> {
158 self.data.get(index).cloned()
159 }
160
161 pub fn set_end_of_constant(&mut self, addr: usize) -> Result<(), DataError> {
162 if addr >= self.data.len() {
163 Err(DataError::from("Cannot set end of constant data to be over current data amount".to_string()))
164 } else {
165 self.end_of_constant_data = addr;
166 Ok(())
167 }
168 }
169
170 pub fn get_end_of_constant_data(&self) -> usize {
171 self.end_of_constant_data
172 }
173
174 pub fn get_current_instruction(&self) -> Option<(Instruction, Option<usize>)> {
175 self.get_instruction(self.get_instruction_cursor())
176 }
177
178 pub fn advance_instruction_cursor(&mut self) -> Result<(), String> {
179 self.instruction_cursor += 1;
180 Ok(())
181 }
182
183 pub fn display_current_value(&self) -> String
184 where
185 T: Display + DisplayForCustomItem,
186 {
187 self.values.last().and_then(|l| Some(self.data.display_for_item(*l))).unwrap_or("<NoData>".to_string())
188 }
189
190 pub fn collect_concatenation_indices(&self, left: usize, right: usize) -> Vec<usize> {
191 let mut items = vec![];
192 let mut con_stack = vec![right, left];
193
194 while let Some(item) = con_stack.pop() {
195 match self.get_data().get(item) {
196 None => items.push(UNIT_INDEX),
197 Some(SimpleData::Concatenation(left, right)) => {
198 con_stack.push(right.clone());
199 con_stack.push(left.clone());
200 }
201 Some(SimpleData::List(list_items, _)) => {
202 for item in list_items {
203 items.push(item.clone());
204 }
205 }
206 Some(SimpleData::Slice(list, range)) => match (self.get_data().get(*list), self.get_data().get(*range)) {
207 (Some(SimpleData::List(_, _)), Some(SimpleData::Range(_, _))) => {
208 let iter = self.get_list_slice_item_iter(item);
209
210 for item in iter {
211 items.push(item.clone());
212 }
213 }
214 (Some(SimpleData::Concatenation(left, right)), Some(SimpleData::Range(start, end))) => match (self.get_data().get(*start), self.get_data().get(*end)) {
215 (Some(SimpleData::Number(SimpleNumber::Integer(start))), Some(SimpleData::Number(SimpleNumber::Integer(end)))) => {
216 let mut nested_con_stack = vec![*right, *left];
217 let mut top_level_con_items = vec![];
218
219 while let Some(item) = nested_con_stack.pop() {
220 match self.get_data().get(item) {
221 None => items.push(UNIT_INDEX),
222 Some(SimpleData::Concatenation(left, right)) => {
223 nested_con_stack.push(right.clone());
224 nested_con_stack.push(left.clone());
225 }
226 _ => top_level_con_items.push(item.clone()),
227 }
228 }
229
230 top_level_con_items
231 .iter()
232 .skip(*start as usize)
233 .take((end - start) as usize + 1)
234 .map(usize::clone)
235 .for_each(|i| items.push(i));
236 }
237 _ => items.push(UNIT_INDEX),
238 },
239 _ => items.push(UNIT_INDEX),
240 },
241 Some(_) => items.push(item),
242 }
243 }
244
245 items
246 }
247
248 fn cache_add(&mut self, value: SimpleData<T>) -> Result<usize, DataError> {
249 let mut h = DefaultHasher::new();
250 value.hash(&mut h);
251 value.get_data_type().hash(&mut h);
252 let hv = h.finish();
253
254 match self.cache.get(&hv) {
255 Some(addr) => Ok(*addr),
256 None => {
257 let addr = self.data.len();
258 self.data.push(value);
259 self.cache.insert(hv, addr);
260 Ok(addr)
261 }
262 }
263 }
264
265 fn add_to_current_char_list(&mut self, from: usize, depth: usize) -> Result<(), DataError> {
266 if depth >= self.max_char_list_depth {
267 return Ok(());
268 }
269
270 match self.get_data_type(from)? {
271 GarnishDataType::Invalid => todo!(),
272 GarnishDataType::Custom => todo!(),
273 GarnishDataType::Unit => {
274 self.add_to_char_list('(')?;
275 self.add_to_char_list(')')?;
276 }
277 GarnishDataType::True => {
278 self.add_to_char_list('$')?;
279 self.add_to_char_list('?')?;
280 }
281 GarnishDataType::False => {
282 self.add_to_char_list('$')?;
283 self.add_to_char_list('!')?;
284 }
285 GarnishDataType::Type => {
286 let s = format!("{:?}", self.get_type(from)?);
287 for c in s.chars() {
288 self.add_to_char_list(c)?;
289 }
290 }
291 GarnishDataType::Number => {
292 let x = self.get_number(from)?;
293 let s = x.to_string();
294 for c in s.chars() {
295 self.add_to_char_list(c)?;
296 }
297 }
298 GarnishDataType::Char => {
299 let c = self.get_char(from)?;
300 self.add_to_char_list(c)?;
301 }
302 GarnishDataType::CharList => {
303 let len = self.get_char_list_len(from)?;
304 for i in 0..len {
305 let c = self.get_char_list_item(from, i.into())?;
306 self.add_to_char_list(c)?;
307 }
308 }
309 GarnishDataType::Byte => {
310 let b = self.get_byte(from)?;
311 let s = b.to_string();
312 self.start_char_list()?;
313 for c in s.chars() {
314 self.add_to_char_list(c)?;
315 }
316 }
317 GarnishDataType::ByteList => {
318 let len = self.get_byte_list_len(from)?;
319 let mut strs = vec![];
320 for i in 0..len {
321 let b = self.get_byte_list_item(from, i.into())?;
322 strs.push(format!("'{}'", b));
323 }
324 let s = strs.join(" ");
325 self.start_char_list()?;
326 for c in s.chars() {
327 self.add_to_char_list(c)?;
328 }
329 }
330 GarnishDataType::Symbol => {
331 let sym = self.get_symbol(from)?;
332 let s = match self.data.get_symbol(sym) {
333 None => sym.to_string(),
334 Some(s) => s.clone(),
335 };
336
337 for c in s.chars() {
338 self.add_to_char_list(c)?;
339 }
340 }
341 GarnishDataType::SymbolList => {
342 let len = self.get_symbol_list_len(from)?;
343 let mut strs = vec![];
344 for i in 0..len {
345 let sym = self.get_symbol_list_item(from, i.into())?;
346 let s = match self.data.get_symbol(sym) {
347 None => sym.to_string(),
348 Some(s) => s.clone(),
349 };
350 strs.push(format!("{}", s));
351 }
352 let s = strs.join(", ");
353 self.start_char_list()?;
354 for c in s.chars() {
355 self.add_to_char_list(c)?;
356 }
357 }
358 GarnishDataType::Expression => {
359 let e = self.get_expression(from)?;
360 let s = format!("Expression({})", e);
361
362 for c in s.chars() {
363 self.add_to_char_list(c)?;
364 }
365 }
366 GarnishDataType::External => {
367 let e = self.get_external(from)?;
368 let s = format!("External({})", e);
369
370 for c in s.chars() {
371 self.add_to_char_list(c)?;
372 }
373 }
374 GarnishDataType::Range => {
375 let (start, end) = self.get_range(from).and_then(|(start, end)| Ok((self.get_number(start)?, self.get_number(end)?)))?;
376
377 let s = format!("{}..{}", start, end);
378
379 for c in s.chars() {
380 self.add_to_char_list(c)?;
381 }
382 }
383 GarnishDataType::Pair => {
384 let (left, right) = self.get_pair(from)?;
385 if depth > 0 {
386 self.add_to_char_list('(')?;
387 }
388 self.add_to_current_char_list(left, depth + 1)?;
389 self.add_to_char_list(' ')?;
390 self.add_to_char_list('=')?;
391 self.add_to_char_list(' ')?;
392 self.add_to_current_char_list(right, depth + 1)?;
393 if depth > 0 {
394 self.add_to_char_list(')')?;
395 }
396 }
397 GarnishDataType::Partial => {
398 let (left, right) = self.get_pair(from)?;
399 if depth > 0 {
400 self.add_to_char_list('(')?;
401 }
402 self.add_to_current_char_list(left, depth + 1)?;
403 self.add_to_char_list(' ')?;
404 self.add_to_char_list('~')?;
405 self.add_to_char_list(' ')?;
406 self.add_to_current_char_list(right, depth + 1)?;
407 if depth > 0 {
408 self.add_to_char_list(')')?;
409 }
410 }
411 GarnishDataType::Concatenation => {
412 let (left, right) = self.get_concatenation(from)?;
413 self.add_to_current_char_list(left, depth + 1)?;
414 self.add_to_current_char_list(right, depth + 1)?;
415 }
416 GarnishDataType::List => {
417 let len = self.get_list_len(from)?;
418
419 if depth > 0 {
420 self.add_to_char_list('(')?;
421 }
422
423 for i in 0..len {
424 let item = self.get_list_item(from, i.into())?;
425 self.add_to_current_char_list(item, depth + 1)?;
426
427 if i < len - 1 {
428 self.add_to_char_list(',')?;
429 self.add_to_char_list(' ')?;
430 }
431 }
432
433 if depth > 0 {
434 self.add_to_char_list(')')?;
435 }
436 }
437 GarnishDataType::Slice => {
438 let (value, range) = self.get_slice(from)?;
439 let (start, end) = self.get_range(range)?;
440 let (start, end) = (self.get_number(start)?.to_integer().as_integer()?, self.get_number(end)?.to_integer().as_integer()?);
441
442 match self.get_data_type(value)? {
443 GarnishDataType::CharList => {
444 for i in start..=end {
445 let c = self.get_char_list_item(value, i.into())?;
446 self.add_to_char_list(c)?;
447 }
448 }
449 GarnishDataType::List => {
450 if depth > 0 {
451 self.add_to_char_list('(')?;
452 }
453
454 for i in start..=end {
455 let item = self.get_list_item(value, i.into())?;
456 self.add_to_current_char_list(item, depth + 1)?;
457
458 if i != end {
459 self.add_to_char_list(',')?;
460 self.add_to_char_list(' ')?;
461 }
462 }
463
464 if depth > 0 {
465 self.add_to_char_list(')')?;
466 }
467 }
468 GarnishDataType::Concatenation => {
469 iterate_concatenation_mut(self, value, |this, index, addr| {
470 let i = index.to_integer().as_integer()?;
471 if i >= start && i <= end {
472 this.add_to_current_char_list(addr, depth + 1)?;
473 }
474
475 Ok(None)
476 })
477 .or_else(|err| Err(DataError::from(format!("{:?}", err))))?;
478 }
479 _ => {
480 self.add_to_current_char_list(value, depth + 1)?;
481 self.add_to_char_list(' ')?;
482 self.add_to_char_list('~')?;
483 self.add_to_char_list(' ')?;
484 self.add_to_current_char_list(range, depth + 1)?;
485 }
486 }
487 }
488 }
489
490 Ok(())
491 }
492}
493
494#[cfg(test)]
495mod utilities {
496 use crate::SimpleGarnishData;
497
498 #[test]
499 fn set_end_of_constant_data_error_over_max_data() {
500 let mut data = SimpleGarnishData::new();
501 let result = data.set_end_of_constant(10);
502
503 assert!(result.is_err());
504 }
505
506 #[test]
507 fn set_end_of_constant_data_is_inclusive() {
508 let mut data = SimpleGarnishData::new();
509 data.set_end_of_constant(2).unwrap();
510
511 assert_eq!(data.end_of_constant_data, 2);
512 }
513}
514
515#[cfg(test)]
516mod data_storage {
517 use crate::{GarnishData, SimpleGarnishData};
518
519 #[test]
520 fn unit() {
521 let mut runtime = SimpleGarnishData::new();
522
523 assert_eq!(runtime.add_unit().unwrap(), 0);
524 assert_eq!(runtime.add_unit().unwrap(), 0);
525 assert_eq!(runtime.add_unit().unwrap(), 0);
526
527 assert_eq!(runtime.get_data_len(), 3);
528 assert!(runtime.data.get(0).unwrap().is_unit());
529 }
530
531 #[test]
532 fn false_data() {
533 let mut runtime = SimpleGarnishData::new();
534
535 assert_eq!(runtime.add_false().unwrap(), 1);
536 assert_eq!(runtime.add_false().unwrap(), 1);
537 assert_eq!(runtime.add_false().unwrap(), 1);
538
539 assert_eq!(runtime.get_data_len(), 3);
540 assert!(runtime.data.get(1).unwrap().is_false());
541 }
542
543 #[test]
544 fn true_data() {
545 let mut runtime = SimpleGarnishData::new();
546
547 assert_eq!(runtime.add_true().unwrap(), 2);
548 assert_eq!(runtime.add_true().unwrap(), 2);
549 assert_eq!(runtime.add_true().unwrap(), 2);
550
551 assert_eq!(runtime.get_data_len(), 3);
552 assert!(runtime.data.get(2).unwrap().is_true());
553 }
554
555 #[test]
556 fn integers() {
557 let mut runtime = SimpleGarnishData::new();
558
559 let start = runtime.get_data_len();
560 let i1 = runtime.add_number(10.into()).unwrap();
561 let i2 = runtime.add_number(20.into()).unwrap();
562 let i3 = runtime.add_number(10.into()).unwrap();
563
564 assert_eq!(i1, start);
565 assert_eq!(i2, start + 1);
566 assert_eq!(i3, i1);
567
568 assert_eq!(runtime.get_data_len(), 5);
569 assert_eq!(runtime.data.get(3).unwrap().as_number().unwrap(), 10.into());
570 assert_eq!(runtime.data.get(4).unwrap().as_number().unwrap(), 20.into());
571 }
572
573 #[test]
574 fn symbols() {
575 let mut runtime = SimpleGarnishData::new();
576
577 let start = runtime.get_data_len();
578 let i1 = runtime.add_symbol(1).unwrap();
579 let i2 = runtime.add_symbol(2).unwrap();
580 let i3 = runtime.add_symbol(1).unwrap();
581
582 assert_eq!(i1, start);
583 assert_eq!(i2, start + 1);
584 assert_eq!(i3, i1);
585
586 assert_eq!(runtime.get_data_len(), 5);
587 assert_eq!(runtime.data.get(3).unwrap().as_symbol().unwrap(), 1);
588 assert_eq!(runtime.data.get(4).unwrap().as_symbol().unwrap(), 2);
589 }
590
591 #[test]
592 fn expression() {
593 let mut runtime = SimpleGarnishData::new();
594
595 let start = runtime.get_data_len();
596 let i1 = runtime.add_expression(10).unwrap();
597 let i2 = runtime.add_expression(20).unwrap();
598 let i3 = runtime.add_expression(10).unwrap();
599
600 assert_eq!(i1, start);
601 assert_eq!(i2, start + 1);
602 assert_eq!(i3, i1);
603
604 assert_eq!(runtime.get_data_len(), 5);
605 assert_eq!(runtime.data.get(3).unwrap().as_expression().unwrap(), 10);
606 assert_eq!(runtime.data.get(4).unwrap().as_expression().unwrap(), 20);
607 }
608
609 #[test]
610 fn external() {
611 let mut runtime = SimpleGarnishData::new();
612
613 let start = runtime.get_data_len();
614 let i1 = runtime.add_external(10).unwrap();
615 let i2 = runtime.add_external(20).unwrap();
616 let i3 = runtime.add_external(10).unwrap();
617
618 assert_eq!(i1, start);
619 assert_eq!(i2, start + 1);
620 assert_eq!(i3, i1);
621
622 assert_eq!(runtime.get_data_len(), 5);
623 assert_eq!(runtime.data.get(3).unwrap().as_external().unwrap(), 10);
624 assert_eq!(runtime.data.get(4).unwrap().as_external().unwrap(), 20);
625 }
626
627 #[test]
628 fn similar_values_cache_differently() {
629 let mut runtime = SimpleGarnishData::new();
630
631 let start = runtime.get_data_len();
632 let i1 = runtime.add_external(10).unwrap();
633 let i2 = runtime.add_expression(10).unwrap();
634
635 assert_eq!(i1, start);
636 assert_eq!(i2, start + 1);
637 assert_ne!(i1, i2);
638
639 assert_eq!(runtime.get_data_len(), 5);
640 assert_eq!(runtime.data.get(3).unwrap().as_external().unwrap(), 10);
641 assert_eq!(runtime.data.get(4).unwrap().as_expression().unwrap(), 10);
642 }
643}
644
645#[cfg(test)]
646mod to_symbol {
647 use crate::{GarnishData, SimpleGarnishData, symbol_value};
648
649 #[test]
650 fn unit() {
651 let mut runtime = SimpleGarnishData::new();
652
653 let d1 = runtime.add_unit().unwrap();
654 let addr = runtime.add_symbol_from(d1).unwrap();
655
656 let val = symbol_value("()");
657 assert_eq!(runtime.get_symbol(addr).unwrap(), val);
658 }
659}
660
661#[cfg(test)]
662mod to_byte_list {
663 use crate::{GarnishData, SimpleGarnishData};
664
665 #[test]
666 fn unit() {
667 let mut runtime = SimpleGarnishData::new();
668
669 let d1 = runtime.add_unit().unwrap();
670 let addr = runtime.add_byte_list_from(d1).unwrap();
671 let len = runtime.get_byte_list_len(addr).unwrap();
672
673 assert_eq!(len, 0);
674 }
675}
676
677#[cfg(test)]
678mod to_char_list {
679 use crate::{GarnishData, GarnishDataType, NoCustom, SimpleGarnishData};
680
681 fn assert_to_char_list<Func>(expected: &str, setup: Func)
682 where
683 Func: FnOnce(&mut SimpleGarnishData) -> usize,
684 {
685 let mut runtime = SimpleGarnishData::new();
686
687 let d1 = setup(&mut runtime);
688
689 let addr = runtime.add_char_list_from(d1).unwrap();
690 let len = runtime.get_char_list_len(addr).unwrap();
691
692 let mut chars = String::new();
693
694 for i in 0..len {
695 let c = runtime.get_char_list_item(addr, i.into()).unwrap();
696 chars.push(c);
697 }
698
699 assert_eq!(chars, expected, "{:?} != {:?}", chars, expected);
700 }
701
702 #[test]
703 fn unit() {
704 assert_to_char_list("()", |runtime| runtime.add_unit().unwrap())
705 }
706
707 #[test]
708 fn true_boolean() {
709 assert_to_char_list("$?", |runtime| runtime.add_true().unwrap())
710 }
711
712 #[test]
713 fn false_boolean() {
714 assert_to_char_list("$!", |runtime| runtime.add_false().unwrap())
715 }
716
717 #[test]
718 fn integer() {
719 assert_to_char_list("10", |runtime| runtime.add_number(10.into()).unwrap())
720 }
721
722 #[test]
723 fn char() {
724 assert_to_char_list("c", |runtime| runtime.add_char('c').unwrap())
725 }
726
727 #[test]
728 fn type_data() {
729 assert_to_char_list("Unit", |runtime| runtime.add_type(GarnishDataType::Unit).unwrap())
730 }
731
732 #[test]
733 fn char_list() {
734 assert_to_char_list("characters", |runtime| {
735 runtime.start_char_list().unwrap();
736 runtime.add_to_char_list('c').unwrap();
737 runtime.add_to_char_list('h').unwrap();
738 runtime.add_to_char_list('a').unwrap();
739 runtime.add_to_char_list('r').unwrap();
740 runtime.add_to_char_list('a').unwrap();
741 runtime.add_to_char_list('c').unwrap();
742 runtime.add_to_char_list('t').unwrap();
743 runtime.add_to_char_list('e').unwrap();
744 runtime.add_to_char_list('r').unwrap();
745 runtime.add_to_char_list('s').unwrap();
746 runtime.end_char_list().unwrap()
747 })
748 }
749
750 #[test]
751 fn byte() {
752 assert_to_char_list("100", |runtime| runtime.add_byte(100).unwrap())
753 }
754
755 #[test]
756 fn byte_list() {
757 assert_to_char_list("'10' '20' '30'", |runtime| {
758 runtime.start_byte_list().unwrap();
759 runtime.add_to_byte_list(10).unwrap();
760 runtime.add_to_byte_list(20).unwrap();
761 runtime.add_to_byte_list(30).unwrap();
762 runtime.end_byte_list().unwrap()
763 })
764 }
765
766 #[test]
767 fn symbol() {
768 let s = SimpleGarnishData::<NoCustom>::parse_symbol("my_symbol").unwrap().to_string();
769 assert_to_char_list(s.as_str(), |runtime| runtime.add_symbol(SimpleGarnishData::<NoCustom>::parse_symbol("my_symbol").unwrap()).unwrap())
770 }
771
772 #[test]
773 fn symbol_list() {
774 assert_to_char_list("symbol_one, symbol_two", |runtime| {
775 let sym1 = runtime.parse_add_symbol("symbol_one").unwrap();
776 let sym2 = runtime.parse_add_symbol("symbol_two").unwrap();
777 runtime.merge_to_symbol_list(sym1, sym2).unwrap()
778 })
779 }
780
781 #[test]
782 fn expression() {
783 assert_to_char_list("Expression(10)", |runtime| runtime.add_expression(10).unwrap())
784 }
785
786 #[test]
787 fn external() {
788 assert_to_char_list("External(10)", |runtime| runtime.add_external(10).unwrap())
789 }
790
791 #[test]
792 fn range() {
793 assert_to_char_list("5..10", |runtime| {
794 let d1 = runtime.add_number(5.into()).unwrap();
795 let d2 = runtime.add_number(10.into()).unwrap();
796 runtime.add_range(d1, d2).unwrap()
797 })
798 }
799
800 #[test]
801 fn pair() {
802 assert_to_char_list("10 = 10", |runtime| {
803 let d1 = runtime.add_number(10.into()).unwrap();
804 let d2 = runtime.add_number(10.into()).unwrap();
805 runtime.add_pair((d1, d2)).unwrap()
806 })
807 }
808
809 #[test]
810 fn pair_nested() {
811 assert_to_char_list("10 = (20 = 30)", |runtime| {
812 let d1 = runtime.add_number(10.into()).unwrap();
813 let d2 = runtime.add_number(20.into()).unwrap();
814 let d3 = runtime.add_number(30.into()).unwrap();
815 let d4 = runtime.add_pair((d2, d3)).unwrap();
816 runtime.add_pair((d1, d4)).unwrap()
817 })
818 }
819
820 #[test]
821 fn pair_nested_two() {
822 assert_to_char_list("10 = (20 = (30 = 40))", |runtime| {
823 let d1 = runtime.add_number(10.into()).unwrap();
824 let d2 = runtime.add_number(20.into()).unwrap();
825 let d3 = runtime.add_number(30.into()).unwrap();
826 let d4 = runtime.add_number(40.into()).unwrap();
827 let d5 = runtime.add_pair((d3, d4)).unwrap();
828 let d6 = runtime.add_pair((d2, d5)).unwrap();
829 runtime.add_pair((d1, d6)).unwrap()
830 })
831 }
832
833 #[test]
834 fn list() {
835 assert_to_char_list("10, 20, 30", |runtime| {
836 let d1 = runtime.add_number(10.into()).unwrap();
837 let d2 = runtime.add_number(20.into()).unwrap();
838 let d3 = runtime.add_number(30.into()).unwrap();
839 runtime.start_list(3).unwrap();
840 runtime.add_to_list(d1, false).unwrap();
841 runtime.add_to_list(d2, false).unwrap();
842 runtime.add_to_list(d3, false).unwrap();
843 runtime.end_list().unwrap()
844 })
845 }
846
847 #[test]
848 fn list_nested() {
849 assert_to_char_list("10, (20, 30), 40", |runtime| {
850 let d1 = runtime.add_number(10.into()).unwrap();
851 let d2 = runtime.add_number(20.into()).unwrap();
852 let d3 = runtime.add_number(30.into()).unwrap();
853 let d4 = runtime.add_number(40.into()).unwrap();
854
855 runtime.start_list(2).unwrap();
856 runtime.add_to_list(d2, false).unwrap();
857 runtime.add_to_list(d3, false).unwrap();
858 let list = runtime.end_list().unwrap();
859
860 runtime.start_list(3).unwrap();
861 runtime.add_to_list(d1, false).unwrap();
862 runtime.add_to_list(list, false).unwrap();
863 runtime.add_to_list(d4, false).unwrap();
864 runtime.end_list().unwrap()
865 })
866 }
867
868 #[test]
869 fn slice_of_char_list() {
870 assert_to_char_list("cde", |runtime| {
871 let s = runtime.parse_add_char_list("abcdef").unwrap();
872
873 let start = runtime.add_number(2.into()).unwrap();
874 let end = runtime.add_number(4.into()).unwrap();
875 let range = runtime.add_range(start, end).unwrap();
876
877 runtime.add_slice(s, range).unwrap()
878 })
879 }
880
881 #[test]
882 fn slice_of_concatenation() {
883 assert_to_char_list("304050", |runtime| {
884 let d1 = runtime.add_number(10.into()).unwrap();
885 let d2 = runtime.add_number(20.into()).unwrap();
886 let d3 = runtime.add_number(30.into()).unwrap();
887 let d4 = runtime.add_number(40.into()).unwrap();
888 let d5 = runtime.add_number(50.into()).unwrap();
889 let d6 = runtime.add_number(60.into()).unwrap();
890
891 let cat1 = runtime.add_concatenation(d1, d2).unwrap();
892 let cat2 = runtime.add_concatenation(cat1, d3).unwrap();
893 let cat3 = runtime.add_concatenation(cat2, d4).unwrap();
894 let cat4 = runtime.add_concatenation(cat3, d5).unwrap();
895 let cat5 = runtime.add_concatenation(cat4, d6).unwrap();
896
897 let start = runtime.add_number(2.into()).unwrap();
898 let end = runtime.add_number(4.into()).unwrap();
899 let range = runtime.add_range(start, end).unwrap();
900
901 runtime.add_slice(cat5, range).unwrap()
902 })
903 }
904
905 #[test]
906 fn slice_of_list() {
907 assert_to_char_list("30, 40, 50", |runtime| {
908 let d1 = runtime.add_number(10.into()).unwrap();
909 let d2 = runtime.add_number(20.into()).unwrap();
910 let d3 = runtime.add_number(30.into()).unwrap();
911 let d4 = runtime.add_number(40.into()).unwrap();
912 let d5 = runtime.add_number(50.into()).unwrap();
913 let d6 = runtime.add_number(60.into()).unwrap();
914
915 runtime.start_list(3).unwrap();
916 runtime.add_to_list(d1, false).unwrap();
917 runtime.add_to_list(d2, false).unwrap();
918 runtime.add_to_list(d3, false).unwrap();
919 runtime.add_to_list(d4, false).unwrap();
920 runtime.add_to_list(d5, false).unwrap();
921 runtime.add_to_list(d6, false).unwrap();
922 let list = runtime.end_list().unwrap();
923
924 let start = runtime.add_number(2.into()).unwrap();
925 let end = runtime.add_number(4.into()).unwrap();
926 let range = runtime.add_range(start, end).unwrap();
927
928 runtime.add_slice(list, range).unwrap()
929 })
930 }
931
932 #[test]
933 fn concatenation() {
934 assert_to_char_list("Hello World!", |runtime| {
935 let d1 = runtime.parse_add_char_list("Hello ").unwrap();
936 let d2 = runtime.parse_add_char_list("World!").unwrap();
937 runtime.add_concatenation(d1, d2).unwrap()
938 })
939 }
940}