1use crate::{state::LuaState, value::value::LuaValue};
2
3pub trait StackApi {
4 fn get_top(&self) -> isize;
5 fn abs_index(&self, idx: isize) -> isize;
6 fn check_stack(&mut self, n: usize) -> bool;
7 fn pop(&mut self, n: isize);
8 fn copy(&mut self, from_idx: isize, to_idx: isize);
9 fn push_value(&mut self, idx: isize);
10 fn replace(&mut self, idx: isize);
11 fn insert(&mut self, idx: isize);
12 fn remove(&mut self, idx: isize);
13 fn rotate(&mut self, idx: isize, n: isize);
14 fn set_top(&mut self, idx: isize);
15}
16
17impl StackApi for LuaState {
18 fn get_top(&self) -> isize {
19 let node = self.get_node();
20 let stack = node.get_stack();
21 stack.top as isize
22 }
23
24 fn abs_index(&self, idx: isize) -> isize {
25 self.stack_abs_index(idx)
26 }
27
28 fn check_stack(&mut self, n: usize) -> bool {
29 self.stack_check(n);
30 true
31 }
32
33 fn pop(&mut self, n: isize) {
34 self.set_top(-n - 1)
35 }
36
37 fn copy(&mut self, from_idx: isize, to_idx: isize) {
38 let val = self.stack_get(from_idx);
39 self.stack_set(to_idx, val)
40 }
41
42 fn push_value(&mut self, idx: isize) {
43 let val = self.stack_get(idx);
44 self.stack_push(val)
45 }
46
47 fn replace(&mut self, idx: isize) {
48 let val = self.stack_pop();
49 self.stack_set(idx, val);
50 }
51
52 fn insert(&mut self, idx: isize) {
53 self.rotate(idx, 1)
54 }
55
56 fn remove(&mut self, idx: isize) {
57 self.rotate(idx, -1);
58 self.pop(1)
59 }
60
61 fn rotate(&mut self, idx: isize, n: isize) {
62 let t = self.get_top() - 1;
63 let p = self.abs_index(idx) - 1;
64 let m = if n > 0 { t - n } else { p - n - 1 };
65 self.stack_reverse(p, m);
66 self.stack_reverse(m + 1, t);
67 self.stack_reverse(p, t);
68 }
69
70 fn set_top(&mut self, idx: isize) {
71 let new_top = self.stack_abs_index(idx);
72 if new_top < 0 {
73 panic!("stack overflow")
74 }
75 let n = self.get_top() - new_top;
76 if n > 0 {
77 self.stack_pop_n(n as usize);
78 } else {
79 for _ in n..0 {
80 self.stack_push(LuaValue::Nil)
81 }
82 }
83 }
84}