neige_lua/api/
stack.rs

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}