sim_lib_lang_lua/
metatable.rs1use sim_kernel::{Args, Cx, Result, Symbol, Value};
2use sim_lib_dispatch::{MetaObjectProtocol, meta_index};
3
4use crate::table::{lua_rawget, lua_table_value};
5
6pub fn lua_index_slot() -> Symbol {
8 Symbol::new("__index")
9}
10
11pub fn lua_get(cx: &mut Cx, receiver: &Value, key: &Value) -> Result<Option<Value>> {
13 meta_index(cx, &LuaMetaProtocol, receiver, key, &lua_index_slot())
14}
15
16pub fn lua_metamethod(cx: &mut Cx, value: &Value, slot: &Symbol) -> Result<Option<Value>> {
18 let table = match lua_table_value(value) {
19 Ok(table) => table,
20 Err(_) => return Ok(None),
21 };
22 let Some(metatable) = table.metatable()? else {
23 return Ok(None);
24 };
25 let slot = cx.factory().string(slot.name.to_string())?;
26 lua_rawget(cx, &metatable, &slot)
27}
28
29struct LuaMetaProtocol;
30
31impl MetaObjectProtocol for LuaMetaProtocol {
32 fn raw_get(&self, cx: &mut Cx, value: &Value, key: &Value) -> Result<Option<Value>> {
33 let Ok(table) = lua_table_value(value) else {
34 return Ok(None);
35 };
36 table.raw_get(cx, key)
37 }
38
39 fn get_meta(&self, cx: &mut Cx, value: &Value, slot: &Symbol) -> Result<Option<Value>> {
40 lua_metamethod(cx, value, slot)
41 }
42
43 fn apply_meta(
44 &self,
45 cx: &mut Cx,
46 receiver: &Value,
47 key: &Value,
48 index_slot: &Symbol,
49 meta_value: &Value,
50 ) -> Result<Option<Value>> {
51 if lua_table_value(meta_value).is_ok() {
52 return meta_index(cx, self, meta_value, key, index_slot);
53 }
54 cx.call_value(
55 meta_value.clone(),
56 Args::new(vec![receiver.clone(), key.clone()]),
57 )
58 .map(Some)
59 }
60}