Skip to main content

luaur_vm/functions/
lua_v_doarithimpl.rs

1use crate::enums::lua_type::lua_Type;
2use crate::functions::call_bin_tm::call_bin_tm;
3use crate::functions::lua_g_aritherror::luaG_aritherror;
4use crate::functions::lua_v_tonumber::lua_v_tonumber;
5use crate::functions::luai_numidiv::luai_numidiv;
6use crate::functions::luai_nummod::luai_nummod;
7use crate::macros::cast_to::cast_to;
8use crate::macros::luai_numadd::luai_numadd;
9use crate::macros::luai_numdiv::luai_numdiv;
10use crate::macros::luai_nummul::luai_nummul;
11use crate::macros::luai_numpow::luai_numpow;
12use crate::macros::luai_numsub::luai_numsub;
13use crate::macros::luai_numunm::luai_numunm;
14use crate::macros::nvalue::nvalue;
15use crate::macros::setnvalue::setnvalue;
16use crate::macros::setvvalue::setvvalue;
17use crate::macros::ttisnumber::ttisnumber;
18use crate::macros::ttisvector::ttisvector;
19use crate::macros::vvalue::vvalue;
20use crate::records::lua_state::lua_State;
21use crate::type_aliases::stk_id::StkId;
22use crate::type_aliases::t_value::TValue;
23use crate::type_aliases::tms::TMS;
24use luaur_common::macros::luau_assert::LUAU_ASSERT;
25
26#[allow(non_snake_case)]
27pub unsafe fn lua_v_doarithimpl(
28    L: *mut lua_State,
29    ra: StkId,
30    rb: *const TValue,
31    rc: *const TValue,
32    op: TMS,
33) {
34    let mut tempb = TValue::default();
35    let mut tempc = TValue::default();
36    let b: *const TValue;
37    let c: *const TValue;
38
39    let vb = if ttisvector!(rb) {
40        vvalue!(rb).as_ptr()
41    } else {
42        core::ptr::null()
43    };
44    let vc = if ttisvector!(rc) {
45        vvalue!(rc).as_ptr()
46    } else {
47        core::ptr::null()
48    };
49
50    if !vb.is_null() && !vc.is_null() {
51        match op {
52            TMS::TM_ADD => {
53                setvvalue!(
54                    ra,
55                    *vb.add(0) + *vc.add(0),
56                    *vb.add(1) + *vc.add(1),
57                    *vb.add(2) + *vc.add(2),
58                    *vb.add(3) + *vc.add(3)
59                );
60                return;
61            }
62            TMS::TM_SUB => {
63                setvvalue!(
64                    ra,
65                    *vb.add(0) - *vc.add(0),
66                    *vb.add(1) - *vc.add(1),
67                    *vb.add(2) - *vc.add(2),
68                    *vb.add(3) - *vc.add(3)
69                );
70                return;
71            }
72            TMS::TM_MUL => {
73                setvvalue!(
74                    ra,
75                    *vb.add(0) * *vc.add(0),
76                    *vb.add(1) * *vc.add(1),
77                    *vb.add(2) * *vc.add(2),
78                    *vb.add(3) * *vc.add(3)
79                );
80                return;
81            }
82            TMS::TM_DIV => {
83                setvvalue!(
84                    ra,
85                    *vb.add(0) / *vc.add(0),
86                    *vb.add(1) / *vc.add(1),
87                    *vb.add(2) / *vc.add(2),
88                    *vb.add(3) / *vc.add(3)
89                );
90                return;
91            }
92            TMS::TM_IDIV => {
93                setvvalue!(
94                    ra,
95                    luai_numidiv(*vb.add(0) as f64, *vc.add(0) as f64) as f32,
96                    luai_numidiv(*vb.add(1) as f64, *vc.add(1) as f64) as f32,
97                    luai_numidiv(*vb.add(2) as f64, *vc.add(2) as f64) as f32,
98                    luai_numidiv(*vb.add(3) as f64, *vc.add(3) as f64) as f32
99                );
100                return;
101            }
102            TMS::TM_UNM => {
103                setvvalue!(ra, -*vb.add(0), -*vb.add(1), -*vb.add(2), -*vb.add(3));
104                return;
105            }
106            _ => {}
107        }
108    } else if !vb.is_null() {
109        let c_ptr = if ttisnumber!(rc) {
110            rc
111        } else {
112            lua_v_tonumber(rc, &mut tempc)
113        };
114        if !c_ptr.is_null() {
115            let nc = cast_to!(f32, nvalue!(c_ptr));
116            match op {
117                TMS::TM_MUL => {
118                    setvvalue!(
119                        ra,
120                        *vb.add(0) * nc,
121                        *vb.add(1) * nc,
122                        *vb.add(2) * nc,
123                        *vb.add(3) * nc
124                    );
125                    return;
126                }
127                TMS::TM_DIV => {
128                    setvvalue!(
129                        ra,
130                        *vb.add(0) / nc,
131                        *vb.add(1) / nc,
132                        *vb.add(2) / nc,
133                        *vb.add(3) / nc
134                    );
135                    return;
136                }
137                TMS::TM_IDIV => {
138                    setvvalue!(
139                        ra,
140                        luai_numidiv(*vb.add(0) as f64, nc as f64) as f32,
141                        luai_numidiv(*vb.add(1) as f64, nc as f64) as f32,
142                        luai_numidiv(*vb.add(2) as f64, nc as f64) as f32,
143                        luai_numidiv(*vb.add(3) as f64, nc as f64) as f32
144                    );
145                    return;
146                }
147                _ => {}
148            }
149        }
150    } else if !vc.is_null() {
151        let b_ptr = if ttisnumber!(rb) {
152            rb
153        } else {
154            lua_v_tonumber(rb, &mut tempb)
155        };
156        if !b_ptr.is_null() {
157            let nb = cast_to!(f32, nvalue!(b_ptr));
158            match op {
159                TMS::TM_MUL => {
160                    setvvalue!(
161                        ra,
162                        nb * *vc.add(0),
163                        nb * *vc.add(1),
164                        nb * *vc.add(2),
165                        nb * *vc.add(3)
166                    );
167                    return;
168                }
169                TMS::TM_DIV => {
170                    setvvalue!(
171                        ra,
172                        nb / *vc.add(0),
173                        nb / *vc.add(1),
174                        nb / *vc.add(2),
175                        nb / *vc.add(3)
176                    );
177                    return;
178                }
179                TMS::TM_IDIV => {
180                    setvvalue!(
181                        ra,
182                        luai_numidiv(nb as f64, *vc.add(0) as f64) as f32,
183                        luai_numidiv(nb as f64, *vc.add(1) as f64) as f32,
184                        luai_numidiv(nb as f64, *vc.add(2) as f64) as f32,
185                        luai_numidiv(nb as f64, *vc.add(3) as f64) as f32
186                    );
187                    return;
188                }
189                _ => {}
190            }
191        }
192    }
193
194    let b_res = lua_v_tonumber(rb, &mut tempb);
195    let c_res = lua_v_tonumber(rc, &mut tempc);
196    if !b_res.is_null() && !c_res.is_null() {
197        let nb = nvalue!(b_res);
198        let nc = nvalue!(c_res);
199        match op {
200            TMS::TM_ADD => setnvalue!(ra, luai_numadd(nb, nc)),
201            TMS::TM_SUB => setnvalue!(ra, luai_numsub(nb, nc)),
202            TMS::TM_MUL => setnvalue!(ra, luai_nummul(nb, nc)),
203            TMS::TM_DIV => setnvalue!(ra, luai_numdiv(nb, nc)),
204            TMS::TM_IDIV => setnvalue!(ra, luai_numidiv(nb, nc)),
205            TMS::TM_MOD => setnvalue!(ra, luai_nummod(nb, nc)),
206            TMS::TM_POW => setnvalue!(ra, luai_numpow(nb, nc)),
207            TMS::TM_UNM => setnvalue!(ra, luai_numunm(nb)),
208            _ => LUAU_ASSERT!(false),
209        }
210    } else if call_bin_tm(L, rb, rc, ra, op) == 0 {
211        luaG_aritherror(L, rb, rc, op);
212    }
213}
214
215#[export_name = "luaV_doarithimpl_TM_ADD"]
216pub unsafe extern "C" fn lua_v_doarithimpl_tm_add(
217    L: *mut lua_State,
218    ra: StkId,
219    rb: *const TValue,
220    rc: *const TValue,
221) {
222    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_ADD);
223}
224
225#[export_name = "luaV_doarithimpl_TM_SUB"]
226pub unsafe extern "C" fn lua_v_doarithimpl_tm_sub(
227    L: *mut lua_State,
228    ra: StkId,
229    rb: *const TValue,
230    rc: *const TValue,
231) {
232    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_SUB);
233}
234
235#[export_name = "luaV_doarithimpl_TM_MUL"]
236pub unsafe extern "C" fn lua_v_doarithimpl_tm_mul(
237    L: *mut lua_State,
238    ra: StkId,
239    rb: *const TValue,
240    rc: *const TValue,
241) {
242    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_MUL);
243}
244
245#[export_name = "luaV_doarithimpl_TM_DIV"]
246pub unsafe extern "C" fn lua_v_doarithimpl_tm_div(
247    L: *mut lua_State,
248    ra: StkId,
249    rb: *const TValue,
250    rc: *const TValue,
251) {
252    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_DIV);
253}
254
255#[export_name = "luaV_doarithimpl_TM_IDIV"]
256pub unsafe extern "C" fn lua_v_doarithimpl_tm_idiv(
257    L: *mut lua_State,
258    ra: StkId,
259    rb: *const TValue,
260    rc: *const TValue,
261) {
262    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_IDIV);
263}
264
265#[export_name = "luaV_doarithimpl_TM_MOD"]
266pub unsafe extern "C" fn lua_v_doarithimpl_tm_mod(
267    L: *mut lua_State,
268    ra: StkId,
269    rb: *const TValue,
270    rc: *const TValue,
271) {
272    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_MOD);
273}
274
275#[export_name = "luaV_doarithimpl_TM_POW"]
276pub unsafe extern "C" fn lua_v_doarithimpl_tm_pow(
277    L: *mut lua_State,
278    ra: StkId,
279    rb: *const TValue,
280    rc: *const TValue,
281) {
282    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_POW);
283}
284
285#[export_name = "luaV_doarithimpl_TM_UNM"]
286pub unsafe extern "C" fn lua_v_doarithimpl_tm_unm(
287    L: *mut lua_State,
288    ra: StkId,
289    rb: *const TValue,
290    rc: *const TValue,
291) {
292    lua_v_doarithimpl(L, ra, rb, rc, TMS::TM_UNM);
293}