mtots_core 0.1.2

Core implementation of the mtots scripting language
Documentation
use super::*;

pub(super) fn new(iterable: &Rc<Class>) -> Rc<Class> {
    Class::new(
        "Map".into(),
        Class::join_class_maps(
            Class::map_from_funcs(vec![
                NativeFunction::new("len", ["self"], "", |_globals, args, _| {
                    let mut args = args.into_iter();
                    let owner = args.next().unwrap().into_map()?;
                    let owner = owner.borrow();
                    Ok(owner.len().into())
                }),
                NativeFunction::new(
                    "get",
                    ArgSpec::builder()
                        .req("self")
                        .req("key")
                        .def("default", ConstVal::Invalid),
                    "",
                    |_globals, args, _| {
                        let mut args = args.into_iter();
                        let owner = args.next().unwrap().into_map()?;
                        let owner = owner.borrow();
                        let key = Key::try_from(args.next().unwrap())?;
                        let default = args.next().unwrap();
                        if let Some(value) = owner.get(&key) {
                            Ok(value.clone())
                        } else if let Value::Invalid = default {
                            Err(rterr!("Key {:?} not found in map", key))
                        } else {
                            Ok(default)
                        }
                    },
                ),
                NativeFunction::new("has_key", ["self", "key"], "", |_globals, args, _| {
                    let mut args = args.into_iter();
                    let owner = args.next().unwrap().into_map()?;
                    let owner = owner.borrow();
                    let key = Key::try_from(args.next().unwrap())?;
                    Ok(owner.contains_key(&key).into())
                }),
            ]),
            vec![iterable],
        ),
        Class::map_from_funcs(vec![NativeFunction::new(
            "__from_iterable",
            ["iterable"],
            "",
            |globals, args, _| {
                let mut args = args.into_iter();
                let iterable = args.next().unwrap();
                map_from_iterable(globals, iterable)
            },
        )]),
    )
}

fn map_from_iterable(globals: &mut Globals, iter: Value) -> Result<Value> {
    match iter {
        Value::Map(map) => Ok(Value::from(Map::unwrap_or_clone(map))),
        _ => Ok(iter
            .unpack(globals)?
            .into_iter()
            .map(|pair| pair.unpack_keyval(globals))
            .collect::<Result<Map>>()?
            .into()),
    }
}