1use crate::push::instructions::Instruction;
2use crate::push::instructions::InstructionCache;
3use crate::push::random::CodeGenerator;
4use crate::push::state::PushState;
5use crate::push::state::*;
6use std::collections::HashMap;
7
8pub fn load_name_instructions(map: &mut HashMap<String, Instruction>) {
16 map.insert(String::from("NAME.="), Instruction::new(name_equal));
17 map.insert(String::from("NAME.CAT"), Instruction::new(name_cat));
18 map.insert(String::from("NAME.DUP"), Instruction::new(name_dup));
19 map.insert(String::from("NAME.FLUSH"), Instruction::new(name_flush));
20 map.insert(String::from("NAME.ID"), Instruction::new(name_id));
21 map.insert(String::from("NAME.POP"), Instruction::new(name_pop));
22 map.insert(String::from("NAME.QUOTE"), Instruction::new(name_quote));
23 map.insert(String::from("NAME.RAND"), Instruction::new(name_rand));
24 map.insert(
25 String::from("NAME.RANDBOUNDNAME"),
26 Instruction::new(name_rand_bound),
27 );
28 map.insert(String::from("NAME.ROT"), Instruction::new(name_rot));
29 map.insert(String::from("NAME.SEND"), Instruction::new(name_send));
30 map.insert(String::from("NAME.SHOVE"), Instruction::new(name_shove));
31 map.insert(
32 String::from("NAME.STACKDEPTH"),
33 Instruction::new(name_stack_depth),
34 );
35 map.insert(String::from("NAME.SWAP"), Instruction::new(name_swap));
36 map.insert(String::from("NAME.YANK"), Instruction::new(name_yank));
37 map.insert(
38 String::from("NAME.YANKDUP"),
39 Instruction::new(name_yank_dup),
40 );
41}
42
43pub fn name_id(push_state: &mut PushState, _instruction_set: &InstructionCache) {
45 push_state.int_stack.push(NAME_STACK_ID);
46}
47
48fn name_cat(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
51 if let Some(nvals) = push_state.name_stack.pop_vec(2) {
52 let mut catstr = nvals[0].clone();
53 catstr.push_str(&" ".to_string());
54 catstr.push_str(&nvals[1]);
55 push_state.name_stack.push(catstr);
56 }
57}
58
59fn name_equal(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
61 if let Some(nvals) = push_state.name_stack.pop_vec(2) {
62 push_state.bool_stack.push(nvals[0] == nvals[1]);
63 }
64}
65
66pub fn name_dup(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
69 if let Some(nval) = push_state.name_stack.copy(0) {
70 push_state.name_stack.push(nval);
71 }
72}
73
74pub fn name_flush(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
76 push_state.name_stack.flush();
77}
78
79pub fn name_pop(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
81 push_state.name_stack.pop();
82}
83
84pub fn name_quote(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
89 push_state.quote_name = true;
90}
91
92pub fn name_rand(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
94 push_state.name_stack.push(CodeGenerator::new_random_name());
95}
96
97pub fn name_rand_bound(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
99 push_state
100 .name_stack
101 .push(CodeGenerator::existing_random_name(push_state));
102}
103
104pub fn name_rot(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
107 push_state.name_stack.yank(2);
108}
109
110pub fn name_send(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
112 push_state.send_name = true;
113}
114
115pub fn name_shove(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
118 if let Some(shove_index) = push_state.int_stack.pop() {
119 let corr_index = i32::max(
120 i32::min((push_state.name_stack.size() as i32) - 1, shove_index),
121 0,
122 ) as usize;
123 push_state.name_stack.shove(corr_index as usize);
124 }
125}
126
127pub fn name_stack_depth(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
129 push_state
130 .int_stack
131 .push(push_state.name_stack.size() as i32);
132}
133
134pub fn name_swap(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
136 push_state.name_stack.shove(1);
137}
138
139pub fn name_yank(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
142 if let Some(index) = push_state.int_stack.pop() {
143 let corr_index = i32::max(
144 i32::min((push_state.name_stack.size() as i32) - 1, index),
145 0,
146 ) as usize;
147 push_state.name_stack.yank(corr_index as usize);
148 }
149}
150
151pub fn name_yank_dup(push_state: &mut PushState, _instruction_cache: &InstructionCache) {
154 if let Some(index) = push_state.int_stack.pop() {
155 let corr_index = i32::max(
156 i32::min((push_state.name_stack.size() as i32) - 1, index),
157 0,
158 ) as usize;
159 if let Some(deep_item) = push_state.name_stack.copy(corr_index) {
160 push_state.name_stack.push(deep_item);
161 }
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168 use crate::push::item::Item;
169
170 pub fn icache() -> InstructionCache {
171 InstructionCache::new(vec![])
172 }
173
174 #[test]
175 fn name_cat_appends_second_item() {
176 let mut test_state = PushState::new();
177 test_state.name_stack.push(String::from("Test"));
178 test_state.name_stack.push(String::from("Test"));
179 name_cat(&mut test_state, &icache());
180 assert_eq!(test_state.name_stack.pop().unwrap(), "Test Test".to_string());
181 }
182
183 #[test]
184 fn name_equal_pushes_result() {
185 let mut test_state = PushState::new();
186 test_state.name_stack.push(String::from("Test"));
187 test_state.name_stack.push(String::from("Test"));
188 name_equal(&mut test_state, &icache());
189 assert_eq!(test_state.bool_stack.pop().unwrap(), true);
190 }
191
192 #[test]
193 fn name_dup_copies_top_element() {
194 let mut test_state = PushState::new();
195 test_state.name_stack.push(String::from("Test"));
196 name_dup(&mut test_state, &icache());
197 assert_eq!(test_state.name_stack.to_string(), "Test Test");
198 }
199
200 #[test]
201 fn name_flush_empties_stack() {
202 let mut test_state = PushState::new();
203 test_state.name_stack.push(String::from("I1"));
204 test_state.name_stack.push(String::from("I2"));
205 name_flush(&mut test_state, &icache());
206 assert_eq!(test_state.name_stack.to_string(), "");
207 }
208 #[test]
209 fn name_rand_generates_value() {
210 let mut test_state = PushState::new();
211 name_rand(&mut test_state, &icache());
212 assert_eq!(test_state.name_stack.size(), 1);
213 }
214 #[test]
215 fn name_rand_bound_generates_value() {
216 let mut test_state = PushState::new();
217 test_state
218 .name_bindings
219 .insert(CodeGenerator::new_random_name(), Item::int(1));
220 name_rand_bound(&mut test_state, &icache());
221 assert_eq!(test_state.name_stack.size(), 1);
222 }
223
224 #[test]
225 fn name_rot_shuffles_elements() {
226 let mut test_state = PushState::new();
227 test_state.name_stack.push(String::from("Test3"));
228 test_state.name_stack.push(String::from("Test2"));
229 test_state.name_stack.push(String::from("Test1"));
230 assert_eq!(
231 test_state.name_stack.to_string(),
232 "Test1 Test2 Test3"
233 );
234 name_rot(&mut test_state, &icache());
235 assert_eq!(
236 test_state.name_stack.to_string(),
237 "Test3 Test1 Test2"
238 );
239 }
240
241 #[test]
242 fn name_shove_inserts_at_right_position() {
243 let mut test_state = PushState::new();
244 test_state.name_stack.push(String::from("Test4"));
245 test_state.name_stack.push(String::from("Test3"));
246 test_state.name_stack.push(String::from("Test2"));
247 test_state.name_stack.push(String::from("Test1"));
248 assert_eq!(
249 test_state.name_stack.to_string(),
250 "Test1 Test2 Test3 Test4"
251 );
252 test_state.int_stack.push(2);
253 name_shove(&mut test_state, &icache());
254 assert_eq!(
255 test_state.name_stack.to_string(),
256 "Test2 Test3 Test1 Test4"
257 );
258 }
259
260 #[test]
261 fn name_stack_depth_returns_size() {
262 let mut test_state = PushState::new();
263 test_state.name_stack.push(String::from("Test4"));
264 test_state.name_stack.push(String::from("Test3"));
265 test_state.name_stack.push(String::from("Test2"));
266 test_state.name_stack.push(String::from("Test1"));
267 name_stack_depth(&mut test_state, &icache());
268 assert_eq!(test_state.int_stack.to_string(), "4");
269 }
270
271 #[test]
272 fn name_swaps_top_elements() {
273 let mut test_state = PushState::new();
274 test_state.name_stack.push(String::from("Test2"));
275 test_state.name_stack.push(String::from("Test1"));
276 assert_eq!(test_state.name_stack.to_string(), "Test1 Test2");
277 name_swap(&mut test_state, &icache());
278 assert_eq!(test_state.name_stack.to_string(), "Test2 Test1");
279 }
280
281 #[test]
282 fn name_yank_brings_item_to_top() {
283 let mut test_state = PushState::new();
284 test_state.name_stack.push(String::from("Test5"));
285 test_state.name_stack.push(String::from("Test4"));
286 test_state.name_stack.push(String::from("Test3"));
287 test_state.name_stack.push(String::from("Test2"));
288 test_state.name_stack.push(String::from("Test1"));
289 assert_eq!(
290 test_state.name_stack.to_string(),
291 "Test1 Test2 Test3 Test4 Test5"
292 );
293 test_state.int_stack.push(3);
294 name_yank(&mut test_state, &icache());
295 assert_eq!(
296 test_state.name_stack.to_string(),
297 "Test4 Test1 Test2 Test3 Test5"
298 );
299 }
300
301 #[test]
302 fn name_yank_dup_copies_item_to_top() {
303 let mut test_state = PushState::new();
304 test_state.name_stack.push(String::from("Test5"));
305 test_state.name_stack.push(String::from("Test4"));
306 test_state.name_stack.push(String::from("Test3"));
307 test_state.name_stack.push(String::from("Test2"));
308 test_state.name_stack.push(String::from("Test1"));
309 assert_eq!(
310 test_state.name_stack.to_string(),
311 "Test1 Test2 Test3 Test4 Test5"
312 );
313 test_state.int_stack.push(3);
314 name_yank_dup(&mut test_state, &icache());
315 assert_eq!(
316 test_state.name_stack.to_string(),
317 "Test4 Test1 Test2 Test3 Test4 Test5"
318 );
319 }
320}