add string keys to dicts
This commit is contained in:
parent
d334e483a5
commit
659fdd3506
38
src/base.rs
38
src/base.rs
|
@ -60,7 +60,15 @@ pub fn doc(f: &Value) -> Value {
|
||||||
|
|
||||||
pub fn assoc(dict: &Value, key: &Value, value: &Value) -> Value {
|
pub fn assoc(dict: &Value, key: &Value, value: &Value) -> Value {
|
||||||
match (dict, key) {
|
match (dict, key) {
|
||||||
(Value::Dict(d), Value::Keyword(k)) => Value::Dict(Box::new(d.update(k, value.clone()))),
|
(Value::Dict(d), Value::Keyword(k)) => {
|
||||||
|
Value::Dict(Box::new(d.update(Key::Keyword(k), value.clone())))
|
||||||
|
}
|
||||||
|
(Value::Dict(d), Value::Interned(k)) => {
|
||||||
|
Value::Dict(Box::new(d.update(Key::Interned(k), value.clone())))
|
||||||
|
}
|
||||||
|
(Value::Dict(d), Value::String(s)) => {
|
||||||
|
Value::Dict(Box::new(d.update(Key::String(s.clone()), value.clone())))
|
||||||
|
}
|
||||||
_ => unreachable!("internal Ludus error calling assoc with ({dict}, {key}, {value})"),
|
_ => unreachable!("internal Ludus error calling assoc with ({dict}, {key}, {value})"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +183,17 @@ pub fn dissoc(dict: &Value, key: &Value) -> Value {
|
||||||
match (dict, key) {
|
match (dict, key) {
|
||||||
(Value::Dict(dict), Value::Keyword(key)) => {
|
(Value::Dict(dict), Value::Keyword(key)) => {
|
||||||
let mut new = dict.clone();
|
let mut new = dict.clone();
|
||||||
new.remove(key);
|
new.remove(&Key::Keyword(key));
|
||||||
|
Value::Dict(new)
|
||||||
|
}
|
||||||
|
(Value::Dict(dict), Value::Interned(key)) => {
|
||||||
|
let mut new = dict.clone();
|
||||||
|
new.remove(&Key::Interned(key));
|
||||||
|
Value::Dict(new)
|
||||||
|
}
|
||||||
|
(Value::Dict(dict), Value::String(key)) => {
|
||||||
|
let mut new = dict.clone();
|
||||||
|
new.remove(&Key::String(key.clone()));
|
||||||
Value::Dict(new)
|
Value::Dict(new)
|
||||||
}
|
}
|
||||||
_ => unreachable!("internal Ludus error"),
|
_ => unreachable!("internal Ludus error"),
|
||||||
|
@ -220,7 +238,15 @@ pub fn at(ordered: &Value, i: &Value) -> Value {
|
||||||
|
|
||||||
pub fn get(dict: &Value, key: &Value) -> Value {
|
pub fn get(dict: &Value, key: &Value) -> Value {
|
||||||
match (dict, key) {
|
match (dict, key) {
|
||||||
(Value::Dict(dict), Value::Keyword(key)) => match dict.get(key) {
|
(Value::Dict(dict), Value::Keyword(key)) => match dict.get(&Key::Keyword(key)) {
|
||||||
|
Some(x) => x.clone(),
|
||||||
|
None => Value::Nil,
|
||||||
|
},
|
||||||
|
(Value::Dict(dict), Value::Interned(key)) => match dict.get(&Key::Interned(key)) {
|
||||||
|
Some(x) => x.clone(),
|
||||||
|
None => Value::Nil,
|
||||||
|
},
|
||||||
|
(Value::Dict(dict), Value::String(key)) => match dict.get(&Key::String(key.clone())) {
|
||||||
Some(x) => x.clone(),
|
Some(x) => x.clone(),
|
||||||
None => Value::Nil,
|
None => Value::Nil,
|
||||||
},
|
},
|
||||||
|
@ -344,7 +370,7 @@ pub fn list(x: &Value) -> Value {
|
||||||
let kvs = d.iter();
|
let kvs = d.iter();
|
||||||
let mut list = vector![];
|
let mut list = vector![];
|
||||||
for (key, value) in kvs {
|
for (key, value) in kvs {
|
||||||
let kv = Value::Tuple(Rc::new(vec![Value::Keyword(key), value.clone()]));
|
let kv = Value::Tuple(Rc::new(vec![key.to_value(), value.clone()]));
|
||||||
list.push_back(kv);
|
list.push_back(kv);
|
||||||
}
|
}
|
||||||
Value::List(Box::new(list))
|
Value::List(Box::new(list))
|
||||||
|
@ -645,5 +671,9 @@ pub fn make_base() -> Value {
|
||||||
("unbox", Value::BaseFn(BaseFn::Unary("unbox", unbox))),
|
("unbox", Value::BaseFn(BaseFn::Unary("unbox", unbox))),
|
||||||
("upcase", Value::BaseFn(BaseFn::Unary("upcase", upcase))),
|
("upcase", Value::BaseFn(BaseFn::Unary("upcase", upcase))),
|
||||||
];
|
];
|
||||||
|
let members = members
|
||||||
|
.iter()
|
||||||
|
.map(|(name, bfn)| (Key::Keyword(name), bfn.clone()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
Value::Dict(Box::new(HashMap::from(members)))
|
Value::Dict(Box::new(HashMap::from(members)))
|
||||||
}
|
}
|
||||||
|
|
62
src/value.rs
62
src/value.rs
|
@ -112,6 +112,42 @@ pub struct Partial {
|
||||||
pub function: Value,
|
pub function: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Key {
|
||||||
|
Keyword(&'static str),
|
||||||
|
Interned(&'static str),
|
||||||
|
String(Rc<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Key {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Key::Keyword(s) => write!(f, ":{s}"),
|
||||||
|
Key::Interned(s) => write!(f, "\"{s}\""),
|
||||||
|
Key::String(s) => write!(f, "\"{s}\""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Key {
|
||||||
|
pub fn to_value(&self) -> Value {
|
||||||
|
match self {
|
||||||
|
Key::Keyword(s) => Value::Keyword(s),
|
||||||
|
Key::Interned(s) => Value::Interned(s),
|
||||||
|
Key::String(s) => Value::String(s.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_value(value: Value) -> Key {
|
||||||
|
match value {
|
||||||
|
Value::Keyword(s) => Key::Keyword(s),
|
||||||
|
Value::Interned(s) => Key::Keyword(s),
|
||||||
|
Value::String(s) => Key::String(s.clone()),
|
||||||
|
_ => unreachable!("dict keys must be keywords or strings"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Nothing,
|
Nothing,
|
||||||
|
@ -124,7 +160,7 @@ pub enum Value {
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Tuple(Rc<Vec<Value>>),
|
Tuple(Rc<Vec<Value>>),
|
||||||
List(Box<Vector<Value>>),
|
List(Box<Vector<Value>>),
|
||||||
Dict(Box<HashMap<&'static str, Value>>),
|
Dict(Box<HashMap<Key, Value>>),
|
||||||
Box(Rc<RefCell<Value>>),
|
Box(Rc<RefCell<Value>>),
|
||||||
Fn(Rc<LFn>),
|
Fn(Rc<LFn>),
|
||||||
BaseFn(BaseFn),
|
BaseFn(BaseFn),
|
||||||
|
@ -234,9 +270,8 @@ impl Value {
|
||||||
let members = d
|
let members = d
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
let key_show = Value::Keyword(k).show();
|
|
||||||
let value_show = v.show();
|
let value_show = v.show();
|
||||||
format!("{key_show} {value_show}")
|
format!("{k} {value_show}")
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
@ -338,9 +373,8 @@ impl Value {
|
||||||
let members = d
|
let members = d
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
let key_show = Value::Keyword(k).stringify();
|
|
||||||
let value_show = v.stringify();
|
let value_show = v.stringify();
|
||||||
format!("{key_show} {value_show}")
|
format!("{k} {value_show}")
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
@ -437,13 +471,13 @@ impl Value {
|
||||||
Value::Tuple(Rc::new(vec))
|
Value::Tuple(Rc::new(vec))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_shared_box(&self, name: &'static str) -> Value {
|
// pub fn get_shared_box(&self, name: &'static str) -> Value {
|
||||||
match self {
|
// match self {
|
||||||
Value::Dict(dict) => dict
|
// Value::Dict(dict) => dict
|
||||||
.get(name)
|
// .get(name)
|
||||||
.expect("expected dict to have requested value")
|
// .expect("expected dict to have requested value")
|
||||||
.clone(),
|
// .clone(),
|
||||||
_ => unreachable!("expected dict"),
|
// _ => unreachable!("expected dict"),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user