lunify/function/
constant.rs1use crate::number::Number;
2
3#[derive(Debug, PartialEq)]
4pub(crate) enum Constant {
5 Nil,
6 Boolean(bool),
7 Number(Number),
8 String(String),
9}
10
11pub(super) struct ConstantManager<'a> {
12 pub(super) constants: &'a mut Vec<Constant>,
13}
14
15impl<'a> ConstantManager<'a> {
16 pub(super) fn create_unique(&mut self, program_counter: usize) -> u64 {
17 let constant_index = self.constants.len() as u64;
18 let mut index = 0;
19
20 let constant = loop {
21 let constant_name = format!("__%lunify%__temp{program_counter}_{index}\0");
22 let constant = Constant::String(constant_name);
23
24 if !self.constants.contains(&constant) {
25 break constant;
26 }
27
28 index += 1;
29 };
30
31 self.constants.push(constant);
32 constant_index
33 }
34
35 pub(super) fn constant_for_str(&mut self, constant_str: &'static str) -> u64 {
36 let zero_terminated = format!("{constant_str}\0");
37
38 let matches = |constant: &_| matches!(constant, Constant::String(string) if string == zero_terminated.as_str());
40 if let Some(index) = self.constants.iter().position(matches) {
41 return index as u64;
42 }
43
44 let constant_index = self.constants.len() as u64;
45 self.constants.push(Constant::String(zero_terminated));
46 constant_index
47 }
48
49 pub(super) fn constant_nil(&mut self) -> u64 {
50 let matches = |constant: &_| matches!(constant, Constant::Nil);
52 if let Some(index) = self.constants.iter().position(matches) {
53 return index as u64;
54 }
55
56 let constant_index = self.constants.len() as u64;
57 self.constants.push(Constant::Nil);
58 constant_index
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{Constant, ConstantManager};
65
66 #[test]
67 fn create_unique() {
68 let mut constants = Vec::new();
69 let mut constant_manager = ConstantManager { constants: &mut constants };
70
71 assert_eq!(constant_manager.create_unique(9), 0);
72 assert_eq!(&constants[0], &Constant::String("__%lunify%__temp9_0\0".to_owned()));
73 }
74
75 #[test]
76 fn create_unique_twice() {
77 let mut constants = vec![Constant::String("__%lunify%__temp9_0\0".to_owned())];
78 let mut constant_manager = ConstantManager { constants: &mut constants };
79
80 assert_eq!(constant_manager.create_unique(9), 1);
81 assert_eq!(&constants[1], &Constant::String("__%lunify%__temp9_1\0".to_owned()));
82 }
83
84 #[test]
85 fn constant_for_str() {
86 let mut constants = vec![Constant::String("constant".to_owned())];
87 let mut constant_manager = ConstantManager { constants: &mut constants };
88
89 assert_eq!(constant_manager.constant_for_str("test"), 1);
90 assert_eq!(&constants[1], &Constant::String("test\0".to_owned()));
91 }
92
93 #[test]
94 fn constant_for_str_duplicate() {
95 let mut constants = vec![Constant::String("test\0".to_owned()), Constant::String("constant".to_owned())];
96 let mut constant_manager = ConstantManager { constants: &mut constants };
97
98 assert_eq!(constant_manager.constant_for_str("test"), 0);
99 }
100
101 #[test]
102 fn constant_nil() {
103 let mut constants = vec![Constant::String("constant".to_owned())];
104 let mut constant_manager = ConstantManager { constants: &mut constants };
105
106 assert_eq!(constant_manager.constant_nil(), 1);
107 assert_eq!(&constants[1], &Constant::Nil);
108 }
109
110 #[test]
111 fn constant_nil_duplicate() {
112 let mut constants = vec![Constant::Nil, Constant::String("constant".to_owned())];
113 let mut constant_manager = ConstantManager { constants: &mut constants };
114
115 assert_eq!(constant_manager.constant_nil(), 0);
116 }
117}