[][src]Trait wlambda::vval::VValUserData

pub trait VValUserData {
    fn clone_ud(&self) -> Box<dyn VValUserData>;
fn as_any(&mut self) -> &mut dyn Any; fn s(&self) -> String { ... }
fn s_raw(&self) -> String { ... }
fn i(&self) -> i64 { ... }
fn f(&self) -> f64 { ... }
fn b(&self) -> bool { ... }
fn eqv(&self, _other: &Box<dyn VValUserData>) -> bool { ... }
fn set_key(&self, _key: &VVal, _val: VVal) { ... }
fn get_key(&self, _key: &str) -> Option<VVal> { ... } }

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:

This example deliberately fails to compile
 fn as_any(&mut self) -> &mut dyn std::any::Any { self }
Loading content...

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.

Loading content...

Trait Implementations

impl Debug for dyn VValUserData[src]

Implementors

Loading content...