neige_lua/state/
stack.rs

1use std::{
2    cell::RefCell,
3    collections::HashMap,
4    rc::{Rc, Weak},
5};
6
7use neige_infra::{math::random, LUA_REGISTRY_INDEX};
8
9use crate::value::{closure::Closure, upval::LuaUpval, value::LuaValue};
10
11use super::node::LuaNode;
12
13#[derive(Clone, Debug)]
14pub struct LuaStack {
15    pub slots: Vec<LuaValue>,                // 值信息
16    pub prev: Option<Rc<RefCell<LuaStack>>>, // 上级节点信息
17    pub closure: Rc<Closure>,                // 函数信息
18    pub varargs: Vec<LuaValue>,              // 传入参数信息
19    pub pc: isize,                           // 函数指令执行位置
20    pub top: usize,                          // 栈顶位置
21    pub node: Weak<RefCell<LuaNode>>,        // state 信息
22    pub openuvs: HashMap<isize, LuaUpval>,   // 捕获的上值信息
23    rdm: usize,
24}
25
26impl PartialEq for LuaStack {
27    fn eq(&self, other: &Self) -> bool {
28        self.rdm == other.rdm
29    }
30}
31
32impl LuaStack {
33    pub fn new(
34        size: usize,
35        node: &Rc<RefCell<LuaNode>>,
36        closure: Rc<Closure>,
37    ) -> Rc<RefCell<Self>> {
38        let mut slots = Vec::with_capacity(size);
39        for _ in 0..size {
40            slots.push(LuaValue::Nil)
41        }
42        let stack = Self {
43            slots,
44            closure,
45            varargs: Vec::new(),
46            pc: 0,
47            top: 0,
48            node: Rc::downgrade(node),
49            prev: None,
50            openuvs: HashMap::new(),
51            rdm: random(),
52        };
53        Rc::new(RefCell::new(stack))
54    }
55}
56
57impl LuaStack {
58    pub(crate) fn check(&mut self, n: usize) {
59        let free = self.slots.len() - self.top;
60        for _ in free..n {
61            self.slots.push(LuaValue::Nil)
62        }
63    }
64
65    pub(crate) fn push(&mut self, val: LuaValue) {
66        if self.slots.len() == self.top {
67            panic!("stack overflow!")
68        }
69        if !val.is_nil() {
70            self.slots[self.top] = val;
71        }
72        self.top += 1;
73    }
74
75    pub(crate) fn push_n(&mut self, mut vals: Vec<LuaValue>, n: isize) {
76        vals.reverse();
77        let n_vals = vals.len();
78        let un = if n < 0 { n_vals } else { n as usize };
79        for i in 0..un {
80            if i < n_vals {
81                self.push(vals.pop().unwrap())
82            } else {
83                self.push(LuaValue::Nil)
84            }
85        }
86    }
87
88    pub(crate) fn pop(&mut self) -> LuaValue {
89        if self.top < 1 {
90            panic!("stack overflow!")
91        }
92        self.top -= 1;
93        std::mem::replace(&mut self.slots[self.top], LuaValue::Nil)
94    }
95
96    pub(crate) fn pop_n(&mut self, n: usize) -> Vec<LuaValue> {
97        let mut vec = Vec::with_capacity(n);
98        for _ in 0..n {
99            vec.push(self.pop());
100        }
101        vec.reverse();
102        vec
103    }
104
105    pub(crate) fn abs_index(&self, idx: isize) -> isize {
106        if idx <= LUA_REGISTRY_INDEX || idx > 0 {
107            idx
108        } else {
109            idx + (self.top as isize) + 1
110        }
111    }
112
113    pub(crate) fn is_valid(&self, idx: isize) -> bool {
114        if idx < LUA_REGISTRY_INDEX {
115            let uv_idx = LUA_REGISTRY_INDEX - idx - 1;
116            return self.has_closure() && uv_idx < (self.closure.upvals.borrow().len() as isize);
117        }
118        if idx == LUA_REGISTRY_INDEX {
119            return true;
120        }
121        let abs_index = self.abs_index(idx) as usize;
122        abs_index > 0 && abs_index <= self.top
123    }
124
125    pub(crate) fn get(&self, idx: isize) -> LuaValue {
126        if idx < LUA_REGISTRY_INDEX {
127            let uv_idx = (LUA_REGISTRY_INDEX - idx - 1) as usize;
128            return if !self.has_closure() || uv_idx >= self.closure.upvals.borrow().len() {
129                LuaValue::Nil
130            } else {
131                self.closure.upvals.borrow()[uv_idx].val.clone()
132            };
133        }
134        if idx == LUA_REGISTRY_INDEX {
135            if let Some(node) = self.node.upgrade() {
136                let n = node.borrow();
137                return LuaValue::Table(n.registry.clone());
138            }
139        }
140        let abs_idx = self.abs_index(idx) as usize;
141        if abs_idx > 0 && abs_idx <= self.top {
142            self.slots[abs_idx - 1].clone()
143        } else {
144            LuaValue::Nil
145        }
146    }
147
148    pub(crate) fn set(&mut self, idx: isize, val: LuaValue) {
149        if idx < LUA_REGISTRY_INDEX {
150            let uv_idx = (LUA_REGISTRY_INDEX - idx - 1) as usize;
151            if self.has_closure() && uv_idx < self.closure.upvals.borrow().len() {
152                self.closure.upvals.borrow_mut()[uv_idx].set_val(val);
153                return;
154            }
155        }
156        if idx == LUA_REGISTRY_INDEX {
157            if let Some(node) = self.node.upgrade() {
158                if let LuaValue::Table(tb) = val {
159                    node.borrow_mut().registry = tb;
160                    return;
161                } else {
162                    panic!("set value is not table!!!")
163                }
164            }
165        }
166        let abs_idx = self.abs_index(idx) as usize;
167        if abs_idx > 0 {
168            self.slots[abs_idx - 1] = val;
169            return;
170        }
171        panic!("invalid index!!!")
172    }
173
174    pub(crate) fn reverse(&mut self, mut from: isize, mut to: isize) {
175        while from < to {
176            self.slots.swap(from as usize, to as usize);
177            from += 1;
178            to -= 1;
179        }
180    }
181
182    fn has_closure(&self) -> bool {
183        if let Some(_) = self.closure.rust_fn {
184            true
185        } else if let Some(_) = self.closure.proto {
186            true
187        } else {
188            false
189        }
190    }
191}