use sim_kernel::{Cx, Result, Symbol, Value};
pub trait MetaObjectProtocol: Send + Sync {
fn raw_get(&self, cx: &mut Cx, value: &Value, key: &Value) -> Result<Option<Value>>;
fn get_meta(&self, cx: &mut Cx, value: &Value, slot: &Symbol) -> Result<Option<Value>>;
fn apply_meta(
&self,
cx: &mut Cx,
_receiver: &Value,
key: &Value,
_index_slot: &Symbol,
meta_value: &Value,
) -> Result<Option<Value>> {
self.raw_get(cx, meta_value, key)
}
}
pub fn meta_index(
cx: &mut Cx,
proto: &dyn MetaObjectProtocol,
receiver: &Value,
key: &Value,
index_slot: &Symbol,
) -> Result<Option<Value>> {
if let Some(value) = proto.raw_get(cx, receiver, key)? {
return Ok(Some(value));
}
let Some(meta_value) = proto.get_meta(cx, receiver, index_slot)? else {
return Ok(None);
};
proto.apply_meta(cx, receiver, key, index_slot, &meta_value)
}