1use neige_infra::{LuaType, LUA_RIDX_GLOBALS};
2
3use crate::{api::CallApi, state::LuaState, value::value::LuaValue};
4
5pub trait GetApi {
6 fn new_table(&mut self);
7 fn create_table(&mut self, n_arr: usize, n_rec: usize);
8 fn get_table(&mut self, idx: isize) -> LuaType;
9 fn get_field(&mut self, idx: isize, key: String) -> LuaType;
10 fn get_i(&mut self, idx: isize, i: i64) -> LuaType;
11 fn get_meta_table(&mut self, idx: isize) -> bool;
12 fn raw_get(&mut self, idx: isize) -> LuaType;
13 fn raw_get_i(&mut self, idx: isize, i: i64) -> LuaType;
14 fn get_global(&mut self, name: String) -> LuaType;
15}
16
17impl GetApi for LuaState {
18 fn new_table(&mut self) {
19 self.create_table(0, 0)
20 }
21
22 fn create_table(&mut self, n_arr: usize, n_rec: usize) {
23 let tb = LuaValue::new_table(n_arr, n_rec);
24 self.stack_push(tb);
25 }
26
27 fn get_table(&mut self, idx: isize) -> LuaType {
28 let t = self.stack_get(idx);
29 let k = self.stack_pop();
30 self.inline_get_table(t, k, false)
31 }
32
33 fn get_field(&mut self, idx: isize, key: String) -> LuaType {
34 let t = self.stack_get(idx);
35 self.inline_get_table(t, LuaValue::Str(key), false)
36 }
37
38 fn get_i(&mut self, idx: isize, i: i64) -> LuaType {
39 let t = self.stack_get(idx);
40 self.inline_get_table(t, LuaValue::Integer(i), false)
41 }
42
43 fn get_meta_table(&mut self, idx: isize) -> bool {
44 let val = self.stack_get(idx);
45 if let Some(mt) = self.inline_get_meta_table(&val) {
46 self.stack_push(LuaValue::Table(mt));
47 true
48 } else {
49 false
50 }
51 }
52
53 fn raw_get(&mut self, idx: isize) -> LuaType {
54 let t = self.stack_get(idx);
55 let k = self.stack_pop();
56 self.inline_get_table(t, k, true)
57 }
58
59 fn raw_get_i(&mut self, idx: isize, i: i64) -> LuaType {
60 let t = self.stack_get(idx);
61 self.inline_get_table(t, LuaValue::Integer(i), true)
62 }
63
64 fn get_global(&mut self, name: String) -> LuaType {
65 let t = self.registry_get(&LuaValue::Integer(LUA_RIDX_GLOBALS));
66 self.inline_get_table(t, LuaValue::Str(name), true)
67 }
68}
69
70impl LuaState {
71 fn inline_get_table(&mut self, t: LuaValue, k: LuaValue, raw: bool) -> LuaType {
72 if let LuaValue::Table(tbl) = &t {
73 let v = tbl.get(&k);
74 let v_type = v.type_of();
75 if raw || !v.is_nil() || !tbl.has_meta_field("__index") {
76 self.stack_push(v);
77 return v_type;
78 }
79 }
80
81 if !raw {
82 let mf = self.inline_get_meta_field(&t, "__index");
83 match mf {
84 LuaValue::Table(_) => {
85 return self.inline_get_table(mf, k, false);
86 }
87 LuaValue::Function(_) => {
88 self.stack_push(mf);
89 self.stack_push(t);
90 self.stack_push(k);
91 self.call(2, 1);
92 return self.stack_get(-1).type_of();
93 }
94 _ => {}
95 }
96 }
97
98 panic!("not a lua table!")
99 }
100}