1mod closures;
6mod dicts;
7mod impls;
8mod lists;
9mod structs;
10mod traits;
11
12use std::any::Any;
13use std::borrow::Cow;
14use std::cmp::Ordering;
15use std::fmt;
16use std::fmt::Write;
17use std::ops::Deref;
18
19use crate::bytecode::DispatchTable;
20use crate::common::ErrorKind;
21use crate::gc::GcRaw;
22
23use impls::ValueImpl;
24
25pub use closures::*;
26pub use dicts::*;
27pub use lists::*;
28pub use structs::*;
29pub use traits::*;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum ValueKind {
34 Nil,
35 Boolean,
36 Number,
37 String,
38 Function,
39 Struct,
40 Trait,
41 List,
42 Dict,
43 UserData,
44}
45
46trait ValueCommon: Clone + PartialEq {
48 fn new_nil() -> Self;
49 fn new_boolean(b: bool) -> Self;
50 fn new_number(n: f64) -> Self;
51 fn new_string(s: GcRaw<String>) -> Self;
52 fn new_function(f: GcRaw<Closure>) -> Self;
53 fn new_struct(s: GcRaw<Struct>) -> Self;
54 fn new_trait(s: GcRaw<Trait>) -> Self;
55 fn new_list(s: GcRaw<List>) -> Self;
56 fn new_dict(d: GcRaw<Dict>) -> Self;
57 fn new_user_data(u: GcRaw<Box<dyn UserData>>) -> Self;
58
59 fn kind(&self) -> ValueKind;
60
61 unsafe fn get_boolean_unchecked(&self) -> bool;
62 unsafe fn get_number_unchecked(&self) -> &f64;
64 unsafe fn get_raw_string_unchecked(&self) -> GcRaw<String>;
65 unsafe fn get_raw_function_unchecked(&self) -> GcRaw<Closure>;
66 unsafe fn get_raw_struct_unchecked(&self) -> GcRaw<Struct>;
67 unsafe fn get_raw_trait_unchecked(&self) -> GcRaw<Trait>;
68 unsafe fn get_raw_list_unchecked(&self) -> GcRaw<List>;
69 unsafe fn get_raw_dict_unchecked(&self) -> GcRaw<Dict>;
70 unsafe fn get_raw_user_data_unchecked(&self) -> GcRaw<Box<dyn UserData>>;
71}
72
73fn _check_implementations() {
74 fn check_value<T: ValueCommon>() {}
75 check_value::<ValueImpl>();
76}
77
78#[derive(Clone, Copy, PartialEq)]
80#[repr(transparent)]
81pub struct RawValue(ValueImpl);
82
83impl RawValue {
84 pub fn kind(&self) -> ValueKind {
86 self.0.kind()
87 }
88
89 fn type_name(&self) -> Cow<'static, str> {
90 match self.0.kind() {
91 ValueKind::Nil => "Nil".into(),
92 ValueKind::Boolean => "Boolean".into(),
93 ValueKind::Number => "Number".into(),
94 ValueKind::String => "String".into(),
95 ValueKind::Function => "Function".into(),
96 ValueKind::List => "List".into(),
97 ValueKind::Dict => "Dict".into(),
98 ValueKind::Struct => unsafe { self.0.get_raw_struct_unchecked().get().dtable() }
99 .type_name
100 .deref()
101 .to_owned()
102 .into(),
103 ValueKind::Trait => unsafe { self.0.get_raw_trait_unchecked().get().dtable() }
104 .type_name
105 .deref()
106 .to_owned()
107 .into(),
108 ValueKind::UserData => unsafe { self.0.get_raw_user_data_unchecked().get().dtable() }
109 .type_name
110 .deref()
111 .to_owned()
112 .into(),
113 }
114 }
115
116 fn type_error(&self, expected: &'static str) -> ErrorKind {
117 ErrorKind::TypeError {
118 expected: Cow::from(expected),
119 got: self.type_name(),
120 }
121 }
122
123 pub unsafe fn get_boolean_unchecked(&self) -> bool {
128 self.0.get_boolean_unchecked()
129 }
130
131 pub unsafe fn get_number_unchecked(&self) -> &f64 {
136 self.0.get_number_unchecked()
137 }
138
139 pub unsafe fn get_raw_string_unchecked(&self) -> GcRaw<String> {
144 self.0.get_raw_string_unchecked()
145 }
146
147 pub unsafe fn get_raw_function_unchecked(&self) -> GcRaw<Closure> {
152 self.0.get_raw_function_unchecked()
153 }
154
155 pub unsafe fn get_raw_struct_unchecked(&self) -> GcRaw<Struct> {
160 self.0.get_raw_struct_unchecked()
161 }
162
163 pub unsafe fn get_raw_trait_unchecked(&self) -> GcRaw<Trait> {
168 self.0.get_raw_trait_unchecked()
169 }
170
171 pub unsafe fn get_raw_list_unchecked(&self) -> GcRaw<List> {
176 self.0.get_raw_list_unchecked()
177 }
178
179 pub unsafe fn get_raw_dict_unchecked(&self) -> GcRaw<Dict> {
184 self.0.get_raw_dict_unchecked()
185 }
186
187 pub unsafe fn get_raw_user_data_unchecked(&self) -> GcRaw<Box<dyn UserData>> {
192 self.0.get_raw_user_data_unchecked()
193 }
194
195 pub fn ensure_nil(&self) -> Result<(), ErrorKind> {
197 if self.0.kind() == ValueKind::Nil {
198 Ok(())
199 } else {
200 Err(self.type_error("Nil"))
201 }
202 }
203
204 pub fn ensure_boolean(&self) -> Result<bool, ErrorKind> {
206 if self.0.kind() == ValueKind::Boolean {
207 Ok(unsafe { self.0.get_boolean_unchecked() })
208 } else {
209 Err(self.type_error("Boolean"))
210 }
211 }
212
213 pub fn ensure_number(&self) -> Result<f64, ErrorKind> {
215 if self.0.kind() == ValueKind::Number {
216 Ok(unsafe { *self.0.get_number_unchecked() })
217 } else {
218 Err(self.type_error("Number"))
219 }
220 }
221
222 pub fn ensure_raw_string(&self) -> Result<GcRaw<String>, ErrorKind> {
224 if self.0.kind() == ValueKind::String {
225 Ok(unsafe { self.0.get_raw_string_unchecked() })
226 } else {
227 Err(self.type_error("String"))
228 }
229 }
230
231 pub fn ensure_raw_function(&self) -> Result<GcRaw<Closure>, ErrorKind> {
233 if self.0.kind() == ValueKind::Function {
234 Ok(unsafe { self.0.get_raw_function_unchecked() })
235 } else {
236 Err(self.type_error("Function"))
237 }
238 }
239
240 pub fn ensure_raw_struct(&self) -> Result<GcRaw<Struct>, ErrorKind> {
242 if self.0.kind() == ValueKind::Struct {
243 Ok(unsafe { self.0.get_raw_struct_unchecked() })
244 } else {
245 Err(self.type_error("any struct"))
246 }
247 }
248
249 pub fn ensure_raw_trait(&self) -> Result<GcRaw<Trait>, ErrorKind> {
251 if self.0.kind() == ValueKind::Trait {
252 Ok(unsafe { self.0.get_raw_trait_unchecked() })
253 } else {
254 Err(self.type_error("any trait"))
255 }
256 }
257
258 pub fn get_raw_user_data<T>(&self) -> Option<GcRaw<Box<dyn UserData>>>
261 where
262 T: UserData,
263 {
264 if self.0.kind() == ValueKind::UserData {
265 Some(unsafe { self.0.get_raw_user_data_unchecked() })
266 } else {
267 None
268 }
269 }
270
271 pub fn is_truthy(&self) -> bool {
273 !self.is_falsy()
274 }
275
276 pub fn is_falsy(&self) -> bool {
278 self.0.kind() == ValueKind::Nil
279 || (self.0.kind() == ValueKind::Boolean && unsafe { !self.0.get_boolean_unchecked() })
280 }
281
282 pub fn try_partial_cmp(&self, other: &Self) -> Result<Option<Ordering>, ErrorKind> {
286 if self.0.kind() != other.0.kind() {
287 Err(ErrorKind::TypeError {
288 expected: self.type_name(),
289 got: other.type_name(),
290 })
291 } else {
292 match self.0.kind() {
293 ValueKind::Nil => Ok(Some(Ordering::Equal)),
294 ValueKind::Boolean => {
295 let a = unsafe { self.0.get_boolean_unchecked() };
296 let b = unsafe { other.0.get_boolean_unchecked() };
297 Ok(Some(a.cmp(&b)))
298 }
299 ValueKind::Number => {
300 let a = unsafe { self.0.get_number_unchecked() };
301 let b = unsafe { other.0.get_number_unchecked() };
302 Ok(a.partial_cmp(b))
303 }
304 ValueKind::String => unsafe {
305 let a = self.0.get_raw_string_unchecked();
306 let b = other.0.get_raw_string_unchecked();
307 Ok(Some(a.get().cmp(b.get())))
308 },
309 ValueKind::Function => Ok(None),
310 ValueKind::Struct => Ok(None),
311 ValueKind::Trait => Ok(None),
312 ValueKind::List => unsafe {
313 let a = self.0.get_raw_list_unchecked();
314 let b = other.0.get_raw_list_unchecked();
315 a.get().try_partial_cmp(b.get())
316 },
317 ValueKind::Dict => todo!(),
318 ValueKind::UserData => Ok(None),
319 }
320 }
321 }
322}
323
324impl Default for RawValue {
325 fn default() -> Self {
326 Self(ValueImpl::new_nil())
327 }
328}
329
330impl From<()> for RawValue {
331 fn from(_: ()) -> Self {
332 Self(ValueImpl::new_nil())
333 }
334}
335
336impl From<bool> for RawValue {
337 fn from(b: bool) -> Self {
338 Self(ValueImpl::new_boolean(b))
339 }
340}
341
342impl From<f64> for RawValue {
343 fn from(x: f64) -> Self {
344 Self(ValueImpl::new_number(x))
345 }
346}
347
348impl From<GcRaw<String>> for RawValue {
349 fn from(s: GcRaw<String>) -> Self {
350 Self(ValueImpl::new_string(s))
351 }
352}
353
354impl From<GcRaw<Closure>> for RawValue {
355 fn from(f: GcRaw<Closure>) -> Self {
356 Self(ValueImpl::new_function(f))
357 }
358}
359
360impl From<GcRaw<Struct>> for RawValue {
361 fn from(s: GcRaw<Struct>) -> Self {
362 Self(ValueImpl::new_struct(s))
363 }
364}
365
366impl From<GcRaw<Trait>> for RawValue {
367 fn from(t: GcRaw<Trait>) -> Self {
368 Self(ValueImpl::new_trait(t))
369 }
370}
371
372impl From<GcRaw<List>> for RawValue {
373 fn from(s: GcRaw<List>) -> Self {
374 Self(ValueImpl::new_list(s))
375 }
376}
377
378impl From<GcRaw<Dict>> for RawValue {
379 fn from(s: GcRaw<Dict>) -> Self {
380 Self(ValueImpl::new_dict(s))
381 }
382}
383
384impl From<GcRaw<Box<dyn UserData>>> for RawValue {
385 fn from(u: GcRaw<Box<dyn UserData>>) -> Self {
386 Self(ValueImpl::new_user_data(u))
387 }
388}
389
390impl fmt::Debug for RawValue {
391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392 fn dtable(f: &mut fmt::Formatter, dtable: &DispatchTable) -> fmt::Result {
393 let type_name = &dtable.pretty_name;
394 write!(f, "<[{type_name}]>")
395 }
396
397 unsafe {
398 match self.0.kind() {
399 ValueKind::Nil => f.write_str("nil"),
400 ValueKind::Boolean => write!(f, "{}", self.0.get_boolean_unchecked()),
401 ValueKind::Number => write!(f, "{}", self.0.get_number_unchecked()),
402 ValueKind::String => write!(f, "{:?}", self.0.get_raw_string_unchecked().get().deref()),
403 ValueKind::Function => write!(
404 f,
405 "<func {:?}>",
406 self.0.get_raw_function_unchecked().get_raw()
407 ),
408 ValueKind::List => {
409 f.write_char('[')?;
410 let list = self.0.get_raw_list_unchecked();
411 let elements = list.get().as_slice();
412 for (i, element) in elements.iter().enumerate() {
413 if i != 0 {
414 f.write_str(", ")?;
415 }
416 fmt::Debug::fmt(element, f)?;
417 }
418 f.write_char(']')?;
419 Ok(())
420 }
421 ValueKind::Dict => {
422 let dict = self.0.get_raw_dict_unchecked();
423 let dict = dict.get();
424 if dict.is_empty() {
425 f.write_str("[:]")?;
426 } else {
427 f.write_char('[')?;
428 for (i, (key, value)) in dict.iter().enumerate() {
429 if i != 0 {
430 f.write_str(", ")?;
431 }
432 fmt::Debug::fmt(&key, f)?;
433 f.write_str(": ")?;
434 fmt::Debug::fmt(&value, f)?;
435 }
436 f.write_char(']')?;
437 }
438 Ok(())
439 }
440 ValueKind::Struct => dtable(f, self.0.get_raw_struct_unchecked().get().dtable()),
441 ValueKind::Trait => dtable(f, self.0.get_raw_trait_unchecked().get().dtable()),
442 ValueKind::UserData => dtable(f, self.0.get_raw_user_data_unchecked().get().dtable()),
443 }
444 }
445 }
446}
447
448impl fmt::Display for RawValue {
449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450 unsafe {
451 match self.0.kind() {
452 ValueKind::String => write!(f, "{}", self.0.get_raw_string_unchecked().get()),
453 _ => fmt::Debug::fmt(&self, f),
454 }
455 }
456 }
457}
458
459pub trait UserData: Any {
460 fn dtable_gcraw(&self) -> GcRaw<DispatchTable>;
462
463 unsafe fn dtable(&self) -> &DispatchTable {
469 self.dtable_gcraw().get()
470 }
471
472 fn as_any(&self) -> &dyn Any;
474}