neige_lua/vm/
mod.rs

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}