sylt_common/
value.rs

1use serde::{Deserialize, Serialize};
2use std::cell::RefCell;
3use std::collections::{HashMap, HashSet};
4use std::fmt::Debug;
5use std::hash::{Hash, Hasher};
6use std::rc::Rc;
7
8use crate::{ty::Type, upvalue::UpValue};
9
10#[derive(Clone)]
11#[derive(Deserialize, Serialize)]
12pub enum Value {
13    Field(String),
14    Ty(Type),
15    Blob(usize),
16    Instance(usize, Rc<RefCell<HashMap<String, Value>>>),
17    Tuple(Rc<Vec<Value>>),
18    List(Rc<RefCell<Vec<Value>>>),
19    Set(Rc<RefCell<HashSet<Value>>>),
20    Dict(Rc<RefCell<HashMap<Value, Value>>>),
21    Union(HashSet<Value>),
22    Float(f64),
23    Int(i64),
24    Bool(bool),
25    String(Rc<String>),
26    Function(Rc<Vec<Rc<RefCell<UpValue>>>>, Type, usize),
27    ExternFunction(usize),
28    /// This value should not be present when running, only when type checking.
29    /// Most operations are valid but produce funky results.
30    Unknown,
31    /// Should not be present when running.
32    Nil,
33}
34
35impl From<&str> for Value {
36    fn from(s: &str) -> Self {
37        Value::String(Rc::new(s.to_string()))
38    }
39}
40
41impl From<&Type> for Value {
42    fn from(ty: &Type) -> Self {
43        match ty {
44            Type::Field(s) => Value::Field(s.clone()),
45            Type::Void => Value::Nil,
46            Type::Blob(b) => Value::Blob(*b),
47            Type::Instance(b) => Value::Instance(*b, Rc::new(RefCell::new(HashMap::new()))),
48            Type::Tuple(fields) => Value::Tuple(Rc::new(fields.iter().map(Value::from).collect())),
49            Type::Union(v) => Value::Union(v.iter().map(Value::from).collect()),
50            Type::List(v) => Value::List(Rc::new(RefCell::new(vec![Value::from(v.as_ref())]))),
51            Type::Set(v) => {
52                let mut s = HashSet::new();
53                s.insert(Value::from(v.as_ref()));
54                Value::Set(Rc::new(RefCell::new(s)))
55            }
56            Type::Dict(k, v) => {
57                let mut s = HashMap::new();
58                s.insert(Value::from(k.as_ref()), Value::from(v.as_ref()));
59                Value::Dict(Rc::new(RefCell::new(s)))
60            }
61            Type::Unknown | Type::Invalid => Value::Unknown,
62            Type::Int => Value::Int(1),
63            Type::Float => Value::Float(1.0),
64            Type::Bool => Value::Bool(true),
65            Type::String => Value::String(Rc::new("".to_string())),
66            Type::Function(a, r) => {
67                Value::Function(Rc::new(Vec::new()), Type::Function(a.clone(), r.clone()), 0)
68            }
69            Type::ExternFunction(x) => Value::ExternFunction(*x),
70            Type::Ty => Value::Ty(Type::Void),
71        }
72    }
73}
74
75impl From<Type> for Value {
76    fn from(ty: Type) -> Self {
77        Value::from(&ty)
78    }
79}
80
81//NOTE(gu): Macro hygienics makes the following From<&Value> for .. hard to make into a macro.
82
83impl From<&Value> for f64 {
84    fn from(v: &Value) -> Self {
85        if let Value::Float(f) = v {
86            *f
87        } else {
88            panic!("Value is not a float")
89        }
90    }
91}
92
93impl From<&Value> for i64 {
94    fn from(v: &Value) -> Self {
95        if let Value::Int(i) = v {
96            *i
97        } else {
98            panic!("Value is not a float")
99        }
100    }
101}
102
103impl Debug for Value {
104    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        // TODO(ed): This needs some cleaning
106        match self {
107            Value::Field(s) => write!(fmt, "( .{} )", s),
108            Value::Ty(ty) => write!(fmt, "(type {:?})", ty),
109            Value::Blob(b) => write!(fmt, "(blob b{})", b),
110            Value::Instance(b, v) => write!(fmt, "(inst b{} {:?})", b, v),
111            Value::Float(f) => write!(fmt, "(float {})", f),
112            Value::Int(i) => write!(fmt, "(int {})", i),
113            Value::Bool(b) => write!(fmt, "(bool {})", b),
114            Value::String(s) => write!(fmt, "(string \"{}\")", s),
115            Value::List(v) => write!(fmt, "(array {:?})", v),
116            Value::Set(v) => write!(fmt, "(set {:?})", v),
117            Value::Dict(v) => write!(fmt, "(dict {:?})", v),
118            Value::Function(_, ty, block) => {
119                write!(fmt, "(fn #{} {:?})", block, ty)
120            }
121            Value::ExternFunction(slot) => write!(fmt, "(extern fn {})", slot),
122            Value::Unknown => write!(fmt, "(unknown)"),
123            Value::Nil => write!(fmt, "(nil)"),
124            Value::Tuple(v) => write!(fmt, "({:?})", v),
125            Value::Union(v) => write!(fmt, "(U {:?})", v),
126        }
127    }
128}
129
130impl PartialEq<Value> for Value {
131    fn eq(&self, other: &Value) -> bool {
132        match (self, other) {
133            (Value::Float(a), Value::Float(b)) => a == b,
134            (Value::Int(a), Value::Int(b)) => a == b,
135            (Value::Bool(a), Value::Bool(b)) => a == b,
136            (Value::String(a), Value::String(b)) => a == b,
137            (Value::Tuple(a), Value::Tuple(b)) => {
138                a.len() == b.len() && a.iter().zip(b.iter()).all(|(a, b)| a == b)
139            }
140            (Value::List(a), Value::List(b)) => a == b,
141            (Value::Set(a), Value::Set(b)) => a == b,
142            (Value::Dict(a), Value::Dict(b)) => a == b,
143            (Value::Union(a), b) | (b, Value::Union(a)) => a.iter().any(|x| x == b),
144            (Value::Nil, Value::Nil) => true,
145            _ => false,
146        }
147    }
148}
149
150impl Eq for Value {}
151
152impl Hash for Value {
153    fn hash<H: Hasher>(&self, state: &mut H) {
154        match self {
155            Value::Float(a) => {
156                // We have to limit the values, because
157                // floats are wierd.
158                assert!(a.is_finite());
159                a.to_bits().hash(state);
160            }
161            Value::Int(a) => a.hash(state),
162            Value::Bool(a) => a.hash(state),
163            Value::String(a) => a.hash(state),
164            Value::Tuple(a) => a.hash(state),
165            Value::Nil => state.write_i8(0),
166            _ => {}
167        };
168    }
169}
170
171impl Value {
172    pub fn is_nil(&self) -> bool {
173        matches!(self, Value::Nil)
174    }
175
176    pub fn unique_id(&self) -> usize {
177        match self {
178            Value::Field(s) => s as *const _ as usize,
179            Value::Ty(ty) => ty as *const _ as usize,
180            Value::Blob(b) => b as *const _ as usize,
181            Value::Float(f) => f as *const _ as usize,
182            Value::Int(i) => i as *const _ as usize,
183            Value::Bool(b) => b as *const _ as usize,
184            Value::Union(v) => v as *const _ as usize,
185            Value::Instance(_, v) => Rc::as_ptr(v) as usize,
186            Value::String(s) => Rc::as_ptr(s) as usize,
187            Value::List(v) => Rc::as_ptr(v) as usize,
188            Value::Set(v) => Rc::as_ptr(v) as usize,
189            Value::Dict(v) => Rc::as_ptr(v) as usize,
190            Value::Function(v, _, _) => Rc::as_ptr(v) as usize,
191            Value::Tuple(v) => Rc::as_ptr(v) as usize,
192            Value::Nil => 0,  // TODO(ed): This is not a valid pointer - right?
193            Value::Unknown => 1, // TODO(ed): This is not a valid pointer - right?
194            Value::ExternFunction(slot) => slot + 2,
195        }
196    }
197}
198
199#[derive(Clone)]
200pub enum MatchableValue<'t> {
201    Empty,
202    One(&'t Value),
203    Two(&'t Value, &'t Value),
204    Three(&'t Value, &'t Value, &'t Value),
205    Four(&'t Value, &'t Value, &'t Value, &'t Value),
206    Five(&'t Value, &'t Value, &'t Value, &'t Value, &'t Value),
207}
208
209pub fn make_matchable<'t>(value: &'t Value) -> MatchableValue<'t> {
210    use MatchableValue::*;
211    use Value::*;
212
213    match value {
214        #[rustfmt::skip]
215        Tuple(inner) => {
216            match (inner.get(0), inner.get(1), inner.get(2), inner.get(3), inner.get(4)) {
217                (Some(a), Some(b), Some(c), Some(d), Some(e), ..) => Five(a, b, c, d, e),
218                (Some(a), Some(b), Some(c), Some(d), ..) => Four(a, b, c, d),
219                (Some(a), Some(b), Some(c), ..) => Three(a, b, c),
220                (Some(a), Some(b), ..) => Two(a, b),
221                (Some(a), ..) => One(a),
222                _ => Empty,
223            }
224        },
225        x => One(x),
226    }
227}