1use core::fmt;
2use core::hash::{Hash, Hasher};
3use static_assertions::const_assert_eq;
4use crate::language::{IntType, FloatType};
5use crate::runtime::types::{Tuple, UserData, UserIterator, Marker};
6use crate::runtime::function::{Function, NativeFunction};
7use crate::runtime::strings::{StringValue, StringSymbol, InlineStr};
8use crate::runtime::gc::{Gc, GcTrace};
9use crate::runtime::errors::{ExecResult, RuntimeError};
10
11
12#[cfg(target_pointer_width = "32")]
14const_assert_eq!(core::mem::size_of::<Variant>(), 8);
15
16#[cfg(target_pointer_width = "64")]
17const_assert_eq!(core::mem::size_of::<Variant>(), 16);
18
19#[derive(Clone, Copy)]
21pub enum Variant {
22 Nil,
23 BoolTrue,
24 BoolFalse,
25
26 Marker(Marker),
27
28 Integer(IntType),
29 Float(FloatType),
30
31 InternStr(StringSymbol),
33 InlineStr(InlineStr),
34 GCStr(Gc<str>),
35
36 Tuple(Tuple),
37 Function(Gc<Function>),
38 NativeFunction(Gc<NativeFunction>),
39
40 Iterator(Gc<dyn UserIterator>),
41
42 Error(Gc<RuntimeError>),
43
44 UserData(Gc<dyn UserData>),
45}
46
47unsafe impl GcTrace for Variant {
48 #[inline]
49 fn trace(&self) {
50 match self {
51 Self::Tuple(tuple) => tuple.trace(),
52 Self::Function(fun) => fun.mark_trace(),
53 Self::NativeFunction(fun) => fun.mark_trace(),
54 Self::Iterator(iter) => iter.mark_trace(),
55 Self::UserData(data) => data.mark_trace(),
56 _ => { },
57 };
58 }
59}
60
61impl Variant {
62 pub fn marker(id: StringSymbol) -> Self {
63 Self::Marker(Marker::new(id))
64 }
65
66 pub fn is_nil(&self) -> bool {
67 matches!(self, Variant::Nil)
68 }
69
70 pub fn as_strval(&self) -> Option<StringValue> {
71 match self {
72 Self::InternStr(symbol) => Some(StringValue::from(*symbol)),
73 Self::InlineStr(inline) => Some(StringValue::from(*inline)),
74 Self::GCStr(gc_str) => Some(StringValue::from(*gc_str)),
75 _ => None,
76 }
77 }
78
79 pub fn display_echo(&self) -> impl fmt::Display + '_ {
80 struct Display<'a>(&'a Variant);
81 impl fmt::Display for Display<'_> {
82 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83 match self.0.fmt_repr() {
84 Ok(strval) => write!(fmt, "{}", strval),
85 Err(error) => write!(fmt, "{}", error),
86 }
87 }
88 }
89
90 Display(self)
91 }
92
93 pub fn fmt_str(&self) -> ExecResult<StringValue> {
94 if let Some(strval) = self.as_strval() {
95 Ok(strval)
96 } else {
97 self.fmt_repr()
98 }
99 }
100}
101
102
103impl From<bool> for Variant {
104 fn from(value: bool) -> Self {
105 match value {
106 true => Self::BoolTrue,
107 false => Self::BoolFalse,
108 }
109 }
110}
111
112impl From<IntType> for Variant {
113 fn from(value: IntType) -> Self { Self::Integer(value) }
114}
115
116impl From<FloatType> for Variant {
117 fn from(value: FloatType) -> Self { Self::Float(value) }
118}
119
120impl From<StringValue> for Variant {
121 fn from(value: StringValue) -> Self {
122 match value {
123 StringValue::Intern(symbol) => Self::InternStr(symbol),
124 StringValue::Inline(inline) => Self::InlineStr(inline),
125 StringValue::Gc(gc_str) => Self::GCStr(gc_str),
126 }
127 }
128}
129
130impl From<StringSymbol> for Variant {
131 fn from(symbol: StringSymbol) -> Self {
132 Self::InternStr(symbol)
133 }
134}
135
136impl From<Box<[Variant]>> for Variant {
137 fn from(items: Box<[Variant]>) -> Self {
138 Self::Tuple(items.into())
139 }
140}
141
142impl From<Function> for Variant {
143 fn from(func: Function) -> Self {
144 Self::Function(Gc::new(func))
145 }
146}
147
148impl From<NativeFunction> for Variant {
149 fn from(func: NativeFunction) -> Self {
150 Self::NativeFunction(Gc::new(func))
151 }
152}
153
154
155impl Variant {
157 pub fn can_hash(&self) -> bool {
158 struct DummyHasher();
159 impl Hasher for DummyHasher {
160 fn finish(&self) -> u64 { 0 }
161 fn write(&mut self, _: &[u8]) { }
162 }
163 self.try_hash(&mut DummyHasher()).is_ok()
164 }
165
166 fn try_hash<H: Hasher>(&self, state: &mut H) -> ExecResult<()> {
167 let discr = core::mem::discriminant(self);
168
169 match self {
170 Self::Nil | Self::BoolTrue | Self::BoolFalse
171 => discr.hash(state),
172
173 Self::Integer(value) => (discr, value).hash(state),
174
175 Self::Function(fun) => (discr, fun).hash(state),
176 Self::NativeFunction(fun) => (discr, fun).hash(state),
177 Self::Tuple(items) => {
178 discr.hash(state); for item in items.as_ref().iter() {
180 item.try_hash(state)?;
181 }
182 },
183
184 Self::InternStr(..) | Self::InlineStr(..) | Self::GCStr(..) =>
185 self.as_strval().unwrap().hash(state),
186
187 _ => return Err(RuntimeError::unhashable_value(self)),
188 }
189 Ok(())
190 }
191
192}
193
194
195#[derive(Clone)]
197pub struct VariantKey<'a>(&'a Variant);
198
199impl<'a> TryFrom<&'a Variant> for VariantKey<'a> {
200 type Error = Box<RuntimeError>;
201 fn try_from(value: &'a Variant) -> ExecResult<Self> {
202 if !value.can_hash() {
203 return Err(RuntimeError::unhashable_value(value));
204 }
205 Ok(Self(value))
206 }
207}
208
209impl Hash for VariantKey<'_> {
210 fn hash<H: Hasher>(&self, state: &mut H) {
211 self.0.try_hash(state).unwrap()
212 }
213}
214
215impl<'s> PartialEq for VariantKey<'_> {
216 fn eq(&self, other: &VariantKey) -> bool {
217 self.0.cmp_eq(other.0).unwrap_or(false)
218 }
219}
220impl Eq for VariantKey<'_> { }
221
222impl fmt::Display for Variant {
223 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
224 match self.fmt_repr() {
225 Ok(strval) => write!(fmt, "{}", strval),
226 Err(error) => write!(fmt, "{}", error),
227 }
228 }
229}
230
231macro_rules! debug_tuple {
232 ( $fmt:expr, $name:expr, $( $debug:expr ),* ) => {
233 $fmt.debug_tuple($name)
234 $( .field($debug) )*
235 .finish()
236 }
237}
238
239impl fmt::Debug for Variant {
240 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
241 match self {
242 Self::Nil => fmt.write_str("Nil"),
243 Self::BoolTrue => fmt.write_str("True"),
244 Self::BoolFalse => fmt.write_str("False"),
245 Self::Marker(marker) => debug_tuple!(fmt, "Marker", marker),
246 Self::Integer(value) => debug_tuple!(fmt, "Integer", value),
247 Self::Float(value) => debug_tuple!(fmt, "Float", value),
248 Self::InternStr(value) => debug_tuple!(fmt, "InternStr", value),
249 Self::InlineStr(value) => debug_tuple!(fmt, "InlineStr", &value.to_string()),
250 Self::GCStr(gc_str) => debug_tuple!(fmt, "GCStr", &gc_str.to_string()),
251 Self::Tuple(tuple) => debug_tuple!(fmt, "Tuple", tuple),
252 Self::Function(fun)
253 => debug_tuple!(fmt, "Function", &fun.signature().fmt_signature().to_string()),
254 Self::NativeFunction(fun)
255 => debug_tuple!(fmt, "NativeFunction", &fun.signature().fmt_signature().to_string()),
256 Self::Iterator(iter) => debug_tuple!(fmt, "Iterator", iter),
257 Self::Error(error) => write!(fmt, "{:?}", &**error),
258 Self::UserData(data) => debug_tuple!(fmt, "UserData", data),
259 }
260 }
261}