neige_lua/api/
compare.rs

1use std::rc::Rc;
2
3use neige_infra::LuaCompare;
4
5use crate::{state::LuaState, value::value::LuaValue};
6
7pub trait CompareApi {
8    fn compare(&mut self, idx1: isize, idx2: isize, op: LuaCompare) -> bool;
9    fn raw_equal(&mut self, idx1: isize, idx2: isize) -> bool;
10}
11
12impl CompareApi for LuaState {
13    fn compare(&mut self, idx1: isize, idx2: isize, op: LuaCompare) -> bool {
14        let a = self.stack_get(idx1);
15        let b = self.stack_get(idx2);
16        match op {
17            LuaCompare::Eq => self.eq(a, b, false),
18            LuaCompare::Lt => self.lt(a, b),
19            LuaCompare::Le => self.le(a, b),
20        }
21    }
22
23    fn raw_equal(&mut self, idx1: isize, idx2: isize) -> bool {
24        if !self.stack_is_valid(idx1) || self.stack_is_valid(idx2) {
25            false
26        } else {
27            let a = self.stack_get(idx1);
28            let b = self.stack_get(idx2);
29            self.eq(a, b, true)
30        }
31    }
32}
33
34impl LuaState {
35    fn eq(&mut self, a: LuaValue, b: LuaValue, raw: bool) -> bool {
36        match (a, b) {
37            (LuaValue::Nil, LuaValue::Nil) => return true,
38            (LuaValue::Boolean(x), LuaValue::Boolean(y)) => x == y,
39            (LuaValue::Integer(x), LuaValue::Integer(y)) => x == y,
40            (LuaValue::Integer(x), LuaValue::Number(y)) => x as f64 == y,
41            (LuaValue::Number(x), LuaValue::Integer(y)) => x == y as f64,
42            (LuaValue::Number(x), LuaValue::Number(y)) => x == y,
43            (LuaValue::Str(x), LuaValue::Str(y)) => x == y,
44            (a, b) => {
45                if !raw {
46                    let mt = self.call_meta_method(a.clone(), b.clone(), "__eq");
47                    if let Some(mt) = mt {
48                        return mt.convert_to_boolean();
49                    }
50                }
51                if let LuaValue::Table(x) = &a {
52                    if let LuaValue::Table(y) = &b {
53                        return Rc::ptr_eq(x, y);
54                    }
55                }
56                panic!("comparsion error!")
57            }
58        }
59    }
60
61    fn lt(&mut self, a: LuaValue, b: LuaValue) -> bool {
62        match (a, b) {
63            (LuaValue::Integer(x), LuaValue::Integer(y)) => x < y,
64            (LuaValue::Integer(x), LuaValue::Number(y)) => (x as f64) < y,
65            (LuaValue::Number(x), LuaValue::Integer(y)) => x < (y as f64),
66            (LuaValue::Number(x), LuaValue::Number(y)) => x < y,
67            (LuaValue::Str(x), LuaValue::Str(y)) => x < y,
68            (a, b) => {
69                let mt = self.call_meta_method(a, b, "__lt");
70                if let Some(mt) = mt {
71                    return mt.convert_to_boolean();
72                }
73
74                panic!("comparsion error!")
75            }
76        }
77    }
78
79    fn le(&mut self, a: LuaValue, b: LuaValue) -> bool {
80        match (a, b) {
81            (LuaValue::Integer(x), LuaValue::Integer(y)) => x <= y,
82            (LuaValue::Integer(x), LuaValue::Number(y)) => (x as f64) <= y,
83            (LuaValue::Number(x), LuaValue::Integer(y)) => x <= (y as f64),
84            (LuaValue::Number(x), LuaValue::Number(y)) => x <= y,
85            (LuaValue::Str(x), LuaValue::Str(y)) => x <= y,
86            (a, b) => {
87                let mt = self.call_meta_method(a.clone(), b.clone(), "__le");
88                if let Some(mt) = mt {
89                    return mt.convert_to_boolean();
90                }
91                let mt = self.call_meta_method(b, a, "__lt");
92                if let Some(mt) = mt {
93                    return mt.convert_to_boolean();
94                }
95                panic!("comparsion error!");
96            }
97        }
98    }
99}