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}