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>, pub prev: Option<Rc<RefCell<LuaStack>>>, pub closure: Rc<Closure>, pub varargs: Vec<LuaValue>, pub pc: isize, pub top: usize, pub node: Weak<RefCell<LuaNode>>, pub openuvs: HashMap<isize, LuaUpval>, 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}