1mod arith;
2mod call;
3mod utils;
4
5use neige_infra::{code::inst::Instruction, math::fpb::fb_2_isize, LuaArith, LuaCompare};
6use utils::{i32_isize, lua_upvalue_index, u16_isize, u32_isize, u8_isize};
7
8use crate::{
9 api::{
10 AccessApi, ArithApi, CallApi, CompareApi, GetApi, LuaVm, MiscApi, PushApi, SetApi, StackApi,
11 },
12 state::LuaState,
13};
14
15impl LuaState {
16 pub fn execute(&mut self, inst: &Instruction) {
17 match inst {
18 Instruction::Move(a, b, _) => {
19 let a = u8_isize(a) + 1;
20 let b = u16_isize(b) + 1;
21 self.copy(b, a)
22 }
23 Instruction::LoadK(a, bx) => {
24 let a = u8_isize(a) + 1;
25 let bx = u32_isize(bx);
26 self.get_const(bx);
27 self.replace(a)
28 }
29 Instruction::LoadKx(a, _) => {
30 let a = u8_isize(a) + 1;
31 let inst = self.fetch();
32 if let Instruction::ExtraArg(ax) = inst {
33 let ax = u32_isize(&ax);
34 self.get_const(ax);
35 self.replace(a)
36 }
37 }
38 Instruction::LoadBool(a, b, c) => {
39 let a = u8_isize(a) + 1;
40 self.push_boolean(*b != 0);
41 self.replace(a);
42 if *c != 0 {
43 self.add_pc(1)
44 }
45 }
46 Instruction::LoadNil(a, b, _) => {
47 let a = u8_isize(a) + 1;
48 let b = u16_isize(b);
49 self.push_nil();
50 for i in a..=a + b {
51 self.copy(-1, i)
52 }
53 self.pop(1)
54 }
55 Instruction::GetUpVal(a, b, _) => {
56 let a = u8_isize(a) + 1;
57 let b = u16_isize(b) + 1;
58 self.copy(lua_upvalue_index(b), a)
59 }
60 Instruction::GetTabUp(a, b, c) => {
61 let a = u8_isize(a) + 1;
62 let b = u16_isize(b) + 1;
63 let c = u16_isize(c);
64 self.get_rk(c);
65 self.get_table(lua_upvalue_index(b));
66 self.replace(a)
67 }
68 Instruction::GetTable(a, b, c) => {
69 let a = u8_isize(a) + 1;
70 let b = u16_isize(b) + 1;
71 let c = u16_isize(c);
72 self.get_rk(c);
73 self.get_table(b);
74 self.replace(a);
75 }
76 Instruction::SetTabUp(a, b, c) => {
77 let a = u8_isize(a) + 1;
78 let b = u16_isize(b);
79 let c = u16_isize(c);
80 self.get_rk(b);
81 self.get_rk(c);
82 self.set_table(lua_upvalue_index(a))
83 }
84 Instruction::SetUpVal(a, b, _) => {
85 let a = u8_isize(a) + 1;
86 let b = u16_isize(b) + 1;
87 self.copy(a, lua_upvalue_index(b))
88 }
89 Instruction::SetTable(a, b, c) => {
90 let a = u8_isize(a) + 1;
91 let b = u16_isize(b);
92 let c = u16_isize(c);
93 self.get_rk(b);
94 self.get_rk(c);
95 self.set_table(a)
96 }
97 Instruction::NetTable(a, b, c) => {
98 let a = u8_isize(a) + 1;
99 let b = u16_isize(b);
100 let c = u16_isize(c);
101 self.create_table(fb_2_isize(b), fb_2_isize(c));
102 self.replace(a)
103 }
104 Instruction::_Self(a, b, c) => {
105 let a = u8_isize(a) + 1;
106 let b = u16_isize(b) + 1;
107 let c = u16_isize(c);
108 self.copy(b, a + 1);
109 self.get_rk(c);
110 self.get_table(b);
111 self.replace(a);
112 }
113 Instruction::Add(a, b, c) => self.binary_arith(LuaArith::Add, a, b, c),
114 Instruction::Sub(a, b, c) => self.binary_arith(LuaArith::Sub, a, b, c),
115 Instruction::Mul(a, b, c) => self.binary_arith(LuaArith::Mul, a, b, c),
116 Instruction::Mod(a, b, c) => self.binary_arith(LuaArith::Mod, a, b, c),
117 Instruction::Pow(a, b, c) => self.binary_arith(LuaArith::Pow, a, b, c),
118 Instruction::Div(a, b, c) => self.binary_arith(LuaArith::Div, a, b, c),
119 Instruction::IDiv(a, b, c) => self.binary_arith(LuaArith::IDiv, a, b, c),
120 Instruction::BAnd(a, b, c) => self.binary_arith(LuaArith::BAnd, a, b, c),
121 Instruction::Bor(a, b, c) => self.binary_arith(LuaArith::Bor, a, b, c),
122 Instruction::BXor(a, b, c) => self.binary_arith(LuaArith::BXor, a, b, c),
123 Instruction::Shl(a, b, c) => self.binary_arith(LuaArith::Shl, a, b, c),
124 Instruction::Shr(a, b, c) => self.binary_arith(LuaArith::Shr, a, b, c),
125 Instruction::Unm(a, b, _) => self.unary_arith(LuaArith::Unm, a, b),
126 Instruction::BNot(a, b, _) => self.unary_arith(LuaArith::BNot, a, b),
127 Instruction::Not(a, b, _) => {
128 let a = u8_isize(a) + 1;
129 let b = u16_isize(b) + 1;
130 self.push_boolean(!self.to_boolean(b));
131 self.replace(a)
132 }
133 Instruction::Length(a, b, _) => {
134 let a = u8_isize(a) + 1;
135 let b = u16_isize(b) + 1;
136 self.len(b);
137 self.replace(a)
138 }
139 Instruction::Concat(a, b, c) => {
140 let a = u8_isize(a) + 1;
141 let b = u16_isize(b) + 1;
142 let c = u16_isize(c) + 1;
143 let n = (c - b + 1) as usize;
144 self.check_stack(n);
145 for i in b..=c {
146 self.push_value(i)
147 }
148 self.concat(n);
149 self.replace(a)
150 }
151 Instruction::Jmp(a, sbx) => {
152 let a = u8_isize(a);
153 let sbx = i32_isize(sbx);
154 self.add_pc(sbx);
155 if a != 0 {
156 self.close_upvalue(a)
157 }
158 }
159 Instruction::Eq(a, b, c) => self.inline_compare(LuaCompare::Eq, a, b, c),
160 Instruction::Lt(a, b, c) => self.inline_compare(LuaCompare::Lt, a, b, c),
161 Instruction::Le(a, b, c) => self.inline_compare(LuaCompare::Le, a, b, c),
162 Instruction::Test(a, _, c) => {
163 let a = u8_isize(a) + 1;
164 let c = u16_isize(c);
165 if self.to_boolean(a) != (c != 0) {
166 self.add_pc(1)
167 }
168 }
169 Instruction::TestSet(a, b, c) => {
170 let a = u8_isize(a) + 1;
171 let b = u16_isize(b) + 1;
172 let c = u16_isize(c);
173 if self.to_boolean(b) != (c != 0) {
174 self.copy(b, a)
175 } else {
176 self.add_pc(1)
177 }
178 }
179 Instruction::Call(a, b, c) => {
180 let a = u8_isize(a) + 1;
181 let b = u16_isize(b);
182 let c = u16_isize(c);
183 let n_args = self.push_func_and_args(a, b);
184 self.call(n_args, c - 1);
185 self.pop_result(a, c)
186 }
187 Instruction::TailCall(a, b, _) => {
188 let a = u8_isize(a) + 1;
189 let b = u16_isize(b);
190 let n_args = self.push_func_and_args(a, b);
191 self.call(n_args, -1);
192 self.pop_result(a, 0)
193 }
194 Instruction::Return(a, b, _) => {
195 let a = u8_isize(a) + 1;
196 let b = u16_isize(b);
197 if b > 1 {
198 self.check_stack(b as usize - 1);
199 for i in a..=a + b - 2 {
200 self.push_value(i)
201 }
202 } else if b < 1 {
203 self.fix_stack(a)
204 }
205 }
206 Instruction::ForLoop(a, sbx) => {
207 let a = u8_isize(a) + 1;
208 let sbx = i32_isize(sbx);
209 self.push_value(a + 2);
210 self.push_value(a);
211 self.arith(neige_infra::LuaArith::Add);
212 self.replace(a);
213 let is_positive_step = self.to_number(a + 2) >= 0.0;
214 if (is_positive_step && self.compare(a, a + 1, neige_infra::LuaCompare::Le))
215 || (!is_positive_step && self.compare(a + 1, a, neige_infra::LuaCompare::Le))
216 {
217 self.add_pc(sbx);
218 self.copy(a, a + 3)
219 }
220 }
221 Instruction::ForPrep(a, sbx) => {
222 let a = u8_isize(a) + 1;
223 let sbx = i32_isize(sbx);
224
225 self.push_value(a);
226 self.push_value(a + 2);
227 self.arith(LuaArith::Sub);
228 self.replace(a);
229
230 self.add_pc(sbx)
231 }
232 Instruction::TForCall(a, _, c) => {
233 let a = u8_isize(a) + 1;
234 let c = u16_isize(c);
235 self.push_func_and_args(a, 3);
236 self.call(2, c);
237 self.pop_result(a + 3, c + 1)
238 }
239 Instruction::TForLoop(a, sbx) => {
240 let a = u8_isize(a) + 1;
241 let sbx = i32_isize(sbx);
242 if !self.is_nil(a + 1) {
243 self.copy(a + 1, a);
244 self.add_pc(sbx)
245 }
246 }
247 Instruction::SetList(a, b, c) => {
248 let a = u8_isize(a) + 1;
249 let c = if *c > 0 {
250 u16_isize(c) - 1
251 } else {
252 if let Instruction::ExtraArg(ax) = self.fetch() {
253 u32_isize(&ax)
254 } else {
255 panic!("SetList error")
256 }
257 };
258
259 let b_is_zero = *b == 0;
260 let b = if b_is_zero {
261 let b = self.to_integer(-1) as isize;
262 self.pop(1);
263 b - a - 1
264 } else {
265 u16_isize(b)
266 };
267 let mut idx = (c * 50) as i64;
268 for j in 1..=b {
269 idx += 1;
270 self.push_value(a + j);
271 self.set_i(a, idx)
272 }
273
274 if b_is_zero {
275 for j in self.register_count() as isize + 1..=self.get_top() as isize {
276 idx += 1;
277 self.push_value(j);
278 self.set_i(a, idx)
279 }
280 self.set_top(self.register_count() as isize)
281 }
282 }
283 Instruction::Closure(a, bx) => {
284 let a = u8_isize(a) + 1;
285 let bx = u32_isize(bx);
286 self.load_proto(bx);
287 self.replace(a)
288 }
289 Instruction::Vararg(a, b, _) => {
290 let a = u8_isize(a) + 1;
291 let b = u16_isize(b);
292 if b != 1 {
293 self.load_vararg(b - 1);
294 self.pop_result(a, b)
295 }
296 }
297 Instruction::ExtraArg(_) => todo!(),
298 }
299 }
300}