[−][src]Trait wlambda::vval::VValUserData
You can implement your own VVal data type and provide it via global functions:
use std::rc::Rc; use std::cell::RefCell; use wlambda::vval::Env; use wlambda::vval::VVal; let global_env = wlambda::prelude::create_wlamba_prelude(); #[derive(Clone, Debug)] struct MyType { x: Rc<RefCell<(i64, i64)>>, } impl wlambda::vval::VValUserData for MyType { fn s(&self) -> String { format!("$<MyType({:?})>", self.x.borrow()) } fn i(&self) -> i64 { self.x.borrow_mut().1 } fn as_any(&mut self) -> &mut dyn std::any::Any { self } fn clone_ud(&self) -> Box<dyn wlambda::vval::VValUserData> { Box::new(self.clone()) } } global_env.borrow_mut().add_func( "new_mytype", |_env: &mut Env, _argc: usize| { Ok(VVal::Usr(Box::new(MyType { x: Rc::new(RefCell::new((13, 42))) }))) }, Some(0), Some(0)); global_env.borrow_mut().add_func( "modify_mytype", |env: &mut Env, _argc: usize| { Ok(if let VVal::Usr(mut u) = env.arg(0) { if let Some(ud) = u.as_any().downcast_mut::<MyType>() { ud.x.borrow_mut().0 += 1; ud.x.borrow_mut().1 *= 2; VVal::Int(ud.x.borrow().0 + ud.x.borrow().1) } else { VVal::Nul } } else { VVal::Nul }) }, Some(1), Some(1)); let mut ctx = wlambda::compiler::EvalContext::new(global_env); let r = &mut ctx.eval(r#" !x = new_mytype[]; !i = modify_mytype x; $[i, x] "#).unwrap(); assert_eq!( r.s(), "$[98,$<MyType((14, 84))>]", "Userdata implementation works");
Required methods
fn clone_ud(&self) -> Box<dyn VValUserData>
Should clone your user data instance. Whether you are doing a deep clone or a shallow cloen or something else is up to you.
fn as_any(&mut self) -> &mut dyn Any
This should be implemented simply by returning a mutable reference to the concrete type self. It allows you to access your data structure from inside a function yourself.
This is a good default implementation for your struct/type:
fn as_any(&mut self) -> &mut dyn std::any::Any { self }
Provided methods
fn s(&self) -> String
This method should return a human readable syntax representation of your VValUserData.
fn s_raw(&self) -> String
If your data has a plain string representation, you can return the string directly from here.
fn i(&self) -> i64
Returns the i64 representation of your data.
fn f(&self) -> f64
Returns the f64 representation of your data.
fn b(&self) -> bool
Returns the boolean representation of your data. Can for instance be used to check if your data is valid or something.
fn eqv(&self, _other: &Box<dyn VValUserData>) -> bool
Allows you to specify how two instances of your data should be compared for equivalentness.
fn set_key(&self, _key: &VVal, _val: VVal)
Makes your user data act like a map. This can be useful for implementing your own registries or data structures. Implement this method for setting a key to a value.
fn get_key(&self, _key: &str) -> Option<VVal>
This method returns some value that your user data associates with the given key.