1use crate::vm::GVm;
2use crate::{FxHasher, Handle, Heap, Interned, VMError, VMResult, float};
3use bridge_types::BridgedType;
4use std::collections::{BTreeSet, HashMap};
5use std::fmt;
6use std::fmt::{Display, Formatter};
7use std::hash::{Hash, Hasher};
8use std::iter;
9use std::ops::Deref;
10use std::sync::Arc;
11
12pub type CallFuncSig<ENV> = fn(vm: &mut GVm<ENV>, registers: &[Value]) -> VMResult<Value>;
13#[derive(Copy, Clone)]
14pub struct CallFunc<ENV> {
15 pub func: CallFuncSig<ENV>,
16}
17
18impl<ENV> PartialEq for CallFunc<ENV> {
19 fn eq(&self, other: &CallFunc<ENV>) -> bool {
20 std::ptr::eq(
21 self.func as *const CallFuncSig<ENV>,
22 other.func as *const CallFuncSig<ENV>,
23 )
24 }
25}
26
27impl<ENV> Eq for CallFunc<ENV> {}
28
29impl<ENV> Hash for CallFunc<ENV> {
30 fn hash<H: Hasher>(&self, state: &mut H) {
31 state.write_usize(self.func as usize);
32 }
33}
34
35impl<ENV> fmt::Debug for CallFunc<ENV> {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "...")
38 }
39}
40
41pub struct PairIter<'vm, ENV> {
42 vm: &'vm GVm<ENV>,
43 current: Option<Value>,
44 dotted: bool,
45}
46
47impl<'vm, ENV> PairIter<'vm, ENV> {
48 pub fn new(vm: &'vm GVm<ENV>, exp: Value) -> Self {
49 Self {
50 vm,
51 current: Some(exp),
52 dotted: false,
53 }
54 }
55
56 pub fn is_dotted(&self) -> bool {
57 self.dotted
58 }
59}
60
61impl<ENV> Iterator for PairIter<'_, ENV> {
62 type Item = Value;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 if let Some(current) = self.current {
66 match current {
67 Value::Pair(h) => {
68 let (car, cdr) = self.vm.get_pair(h);
69 self.current = Some(cdr);
70 Some(car)
71 }
72 Value::Nil => None,
74 _ => {
75 let cur = Some(current);
76 self.current = None;
77 self.dotted = true;
78 cur
79 }
80 }
81 } else {
82 None
83 }
84 }
85}
86
87pub const INT_BITS: u8 = 56;
88pub const INT_MAX: i64 = 2_i64.pow(INT_BITS as u32 - 1) - 1;
89pub const INT_MIN: i64 = -(2_i64.pow(INT_BITS as u32 - 1));
90
91#[derive(Copy, Clone)]
92pub struct I56(pub [u8; 7]);
93
94impl I56 {
95 pub fn max() -> i64 {
96 INT_MAX
97 }
98
99 pub fn max_i56() -> Self {
100 I56(Self::into_inner(Self::max()))
101 }
102
103 pub fn min() -> i64 {
104 INT_MIN
105 }
106
107 pub fn min_i56() -> Self {
108 I56(Self::into_inner(Self::min()))
109 }
110
111 pub fn from_inner(arr: &[u8; 7]) -> i64 {
113 from_i56(arr)
114 }
115
116 pub fn into_inner(i: i64) -> [u8; 7] {
118 to_i56_raw(i)
119 }
120
121 pub fn into_i56_fallible(f: f64) -> VMResult<i64> {
122 if !f.is_finite() {
123 Err(VMError::new_conversion(
124 "Can not represent NaN or infinity as int.",
125 ))
126 } else if f > i64::MAX as f64 || f > I56::max() as f64 {
127 Err(VMError::new_conversion(
128 "Can not represent number greater than max i56.",
129 ))
130 } else if f < i64::MIN as f64 || f < I56::min() as f64 {
131 Err(VMError::new_conversion(
132 "Can not represent number less than max i56.",
133 ))
134 } else {
135 Ok(f.round() as i64)
136 }
137 }
138
139 pub fn from_byte(byte: u8) -> Self {
140 Self(Self::into_inner(byte as i64))
141 }
142}
143
144pub fn from_i56(arr: &[u8; 7]) -> i64 {
145 let mut bytes = [0x00, arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6]];
146 if (arr[0] & 0x80) > 0 {
147 bytes[0] = 0xff;
148 i64::from_be_bytes(bytes)
149 } else {
150 i64::from_be_bytes(bytes)
151 }
152}
153
154pub fn to_i56_raw(i: i64) -> [u8; 7] {
155 let bytes = i.to_be_bytes();
156 [
157 bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
158 ]
159}
160
161pub fn to_i56(i: i64) -> Value {
162 Value::Int(to_i56_raw(i))
163}
164
165#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
166pub enum Value {
167 Byte(u8),
168 Int([u8; 7]),
170 Float(float::F56),
172 CodePoint(char),
173 CharCluster(u8, [u8; 6]),
174 CharClusterLong(Handle),
176 Symbol(Interned),
177 Keyword(Interned),
178 StringConst(Interned),
179 Special(Interned),
181 Builtin(u32),
182 True,
183 False,
184 Nil,
185 Undefined,
188 String(Handle),
189 Vector(Handle),
190 Map(Handle),
191 Bytes(Handle),
192 Pair(Handle),
193 List(Handle, u16),
194 Lambda(Handle),
195 Closure(Handle),
196 Continuation(Handle),
197 CallFrame(Handle),
198 Value(Handle),
199 Error(Handle),
200 Io(Handle),
201}
202
203impl Default for Value {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209impl From<f32> for Value {
210 fn from(value: f32) -> Self {
211 Self::Float(value.into())
212 }
213}
214
215impl From<f64> for Value {
216 fn from(value: f64) -> Self {
217 Self::Float(value.into())
218 }
219}
220
221impl From<i64> for Value {
222 fn from(value: i64) -> Self {
223 to_i56(value)
224 }
225}
226
227impl From<i32> for Value {
228 fn from(value: i32) -> Self {
229 to_i56(value as i64)
230 }
231}
232
233impl From<u32> for Value {
234 fn from(value: u32) -> Self {
235 to_i56(value as i64)
236 }
237}
238
239impl BridgedType for Value {}
240impl BridgedType for &Value {}
241impl BridgedType for &mut Value {}
242
243impl Value {
244 pub fn new() -> Self {
245 Value::Undefined
246 }
247
248 #[inline(always)]
249 pub fn unref<ENV>(self, vm: &GVm<ENV>) -> Value {
250 match &self {
251 Value::Value(handle) => vm.get_value(*handle),
252 _ => self,
253 }
254 }
255
256 pub fn get_symbol(&self) -> Option<Interned> {
257 if let Value::Symbol(i) = self {
258 Some(*i)
259 } else {
260 None
261 }
262 }
263
264 pub fn is_symbol(&self, sym: Interned) -> bool {
265 if let Value::Symbol(i) = self {
266 *i == sym
267 } else {
268 false
269 }
270 }
271
272 pub fn is_indirect(&self) -> bool {
273 matches!(self, Value::Value(_))
274 }
275
276 pub fn is_nil(&self) -> bool {
277 matches!(self, Value::Nil)
278 }
279
280 pub fn is_undef(&self) -> bool {
281 matches!(self, Value::Undefined)
282 }
283
284 pub fn is_true(&self) -> bool {
285 matches!(self, Value::True)
286 }
287
288 pub fn is_truthy(&self) -> bool {
289 !matches!(self, Value::False | Value::Nil)
290 }
291
292 pub fn is_false(&self) -> bool {
293 matches!(self, Value::False)
294 }
295
296 pub fn is_falsey(&self) -> bool {
297 matches!(self, Value::False | Value::Nil)
298 }
299
300 pub fn is_int(&self) -> bool {
301 matches!(&self, Value::Byte(_) | Value::Int(_))
302 }
303
304 pub fn is_number(&self) -> bool {
305 matches!(&self, Value::Byte(_) | Value::Int(_) | Value::Float(_))
306 }
307
308 pub fn is_float(&self) -> bool {
309 matches!(self, Value::Float(_))
310 }
311
312 pub fn not(&self) -> Value {
313 match self {
314 Value::False | Value::Nil => Value::True,
315 _ => Value::False,
316 }
317 }
318
319 pub fn get_int<ENV>(&self, vm: &GVm<ENV>) -> VMResult<i64> {
320 match &self {
321 Value::Byte(b) => Ok(*b as i64),
322 Value::Int(i) => Ok(from_i56(i)),
323 _ => Err(VMError::new_value(format!(
324 "Not an integer: {}",
325 self.display_value(vm)
326 ))),
327 }
328 }
329
330 pub fn get_float<ENV>(&self, _vm: &GVm<ENV>) -> VMResult<f64> {
331 match &self {
332 Value::Byte(b) => Ok(*b as f64),
333 Value::Int(i) => Ok(from_i56(i) as f64),
334 Value::Float(f) => Ok(f64::from(*f)),
335 _ => Err(VMError::new_value(format!("Not a float: {self:?}"))),
336 }
337 }
338
339 pub fn get_string<'vm, ENV>(&self, vm: &'vm GVm<ENV>) -> VMResult<&'vm str> {
340 match &self {
341 Value::String(h) => Ok(vm.get_string(*h)),
342 Value::StringConst(i) => Ok(vm.get_interned(*i)),
343 _ => Err(VMError::new_value(format!("Not a string: {self:?}"))),
345 }
346 }
347
348 pub fn get_handle(&self) -> Option<Handle> {
349 match &self {
350 Value::CharClusterLong(handle) => Some(*handle),
351 Value::String(handle) => Some(*handle),
352 Value::Vector(handle) => Some(*handle),
353 Value::Map(handle) => Some(*handle),
354 Value::Bytes(handle) => Some(*handle),
355 Value::Pair(handle) => Some(*handle),
356 Value::List(handle, _) => Some(*handle),
357 Value::Lambda(handle) => Some(*handle),
358 Value::Closure(handle) => Some(*handle),
359 Value::Continuation(handle) => Some(*handle),
360 Value::CallFrame(handle) => Some(*handle),
361 Value::Value(handle) => Some(*handle),
362 Value::Error(handle) => Some(*handle),
363 Value::Io(handle) => Some(*handle),
364
365 Value::Byte(_) => None,
366 Value::Int(_) => None,
367 Value::Float(_) => None,
368 Value::CodePoint(_) => None,
369 Value::CharCluster(_, _) => None,
370 Value::Symbol(_) => None,
371 Value::Keyword(_) => None,
372 Value::Special(_) => None,
373 Value::StringConst(_) => None,
374 Value::Builtin(_) => None,
375 Value::True => None,
376 Value::False => None,
377 Value::Nil => None,
378 Value::Undefined => None,
379 }
380 }
381
382 pub fn get_pair<ENV>(&self, vm: &GVm<ENV>) -> Option<(Value, Value)> {
383 match &self {
384 Value::Pair(handle) => {
385 let (car, cdr) = vm.get_pair(*handle);
386 Some((car, cdr))
387 }
388 Value::List(handle, start_u32) => {
389 let start = *start_u32 as usize;
390 let v = vm.get_vector(*handle);
391 let car = if start < v.len() {
392 v[start]
393 } else {
394 Value::Nil
395 };
396 let cdr = if start + 1 < v.len() {
397 Value::List(*handle, start_u32 + 1)
398 } else {
399 Value::Nil
400 };
401 Some((car, cdr))
402 }
403 _ => None,
404 }
405 }
406
407 pub fn iter<'vm, ENV>(&self, vm: &'vm GVm<ENV>) -> Box<dyn Iterator<Item = Value> + 'vm> {
410 match &self.unref(vm) {
411 Value::Pair(_) => Box::new(PairIter::new(vm, *self)),
412 Value::List(handle, start) => {
413 Box::new(vm.get_vector(*handle)[*start as usize..].iter().copied())
414 }
415 Value::Vector(handle) => Box::new(vm.get_vector(*handle).iter().copied()),
416 _ => Box::new(iter::empty()),
417 }
418 }
419
420 pub fn iter_all<'vm, ENV>(&self, vm: &'vm GVm<ENV>) -> Box<dyn Iterator<Item = Value> + 'vm> {
429 match &self.unref(vm) {
430 Value::Pair(_) => Box::new(PairIter::new(vm, *self)),
431 Value::List(handle, start) => {
432 Box::new(vm.get_vector(*handle)[*start as usize..].iter().copied())
433 }
434 Value::Vector(handle) => Box::new(vm.get_vector(*handle).iter().copied()),
435 Value::Nil => Box::new(iter::empty()),
436 v => Box::new(iter::once(*v)),
437 }
438 }
439
440 pub fn display_value<ENV>(&self, vm: &GVm<ENV>) -> String {
441 fn list_out_iter<ENV>(
442 vm: &GVm<ENV>,
443 res: &mut String,
444 itr: &mut dyn Iterator<Item = Value>,
445 ) {
446 let mut first = true;
447 for p in itr {
448 if !first {
449 res.push(' ');
450 } else {
451 first = false;
452 }
453 res.push_str(&p.display_value(vm));
454 }
455 }
456 fn list_out<ENV>(vm: &GVm<ENV>, res: &mut String, lst: Value) {
457 let mut first = true;
458 let mut cdr = lst;
459 loop {
460 if let Value::Nil = cdr {
461 break;
462 }
463 if !first {
464 res.push(' ');
465 } else {
466 first = false;
467 }
468 match cdr {
469 Value::Pair(handle) => {
470 let (car, ncdr) = vm.get_pair(handle);
471 res.push_str(&car.display_value(vm));
472 cdr = ncdr;
473 }
474 _ => {
475 res.push_str(". ");
476 res.push_str(&cdr.display_value(vm));
477 break;
478 }
479 }
480 }
481 }
482 match self {
483 Value::True => "true".to_string(),
484 Value::False => "false".to_string(),
485 Value::Int(i) => format!("{}", from_i56(i)),
486 Value::Float(f) => format!("{}", f),
487 Value::Byte(b) => format!("{b}"),
488 Value::Symbol(i) => vm.get_interned(*i).to_string(),
489 Value::Keyword(i) => format!(":{}", vm.get_interned(*i)),
490 Value::StringConst(i) => format!("\"{}\"", vm.get_interned(*i)),
491 Value::Special(i) => format!("#<SpecialFn({})>", vm.get_interned(*i)),
492 Value::CodePoint(ch) => format!("\\{ch}"),
493 Value::CharCluster(l, c) => {
494 format!("\\{}", String::from_utf8_lossy(&c[0..*l as usize]))
495 }
496 Value::CharClusterLong(h) => format!("\\{}", vm.get_string(*h)),
497 Value::Builtin(_) => "#<Function>".to_string(),
498 Value::Nil => "nil".to_string(),
499 Value::Undefined => "#<Undefined>".to_string(), Value::Lambda(_) => "#<Lambda>".to_string(),
501 Value::Closure(_) => "#<Lambda>".to_string(),
502 Value::Continuation(_) => "#<Continuation>".to_string(),
503 Value::CallFrame(_) => "#<CallFrame>".to_string(),
504 Value::Vector(handle) => {
505 let v = vm.get_vector(*handle);
506 let mut res = String::new();
507 res.push('[');
508 list_out_iter(vm, &mut res, &mut v.iter().copied());
509 res.push(']');
510 res
511 }
512 Value::Map(handle) => {
513 let mut res = String::new();
514 res.push('{');
515 for (key, val) in vm.get_map(*handle).iter() {
516 res.push_str(&format!(
517 "{} {}\n",
518 key.display_value(vm),
519 val.display_value(vm)
520 ));
521 }
522 res.push('}');
523 res
524 }
525 Value::Pair(_) => {
526 let mut res = String::new();
527 res.push('(');
528 list_out(vm, &mut res, *self);
529 res.push(')');
530 res
531 }
532 Value::List(handle, start) => {
533 let v = vm.get_vector(*handle);
534 let mut res = String::new();
535 res.push('(');
536 list_out_iter(vm, &mut res, &mut v[*start as usize..].iter().copied());
537 res.push(')');
538 res
539 }
540 Value::String(handle) => format!("\"{}\"", vm.get_string(*handle)),
541 Value::Bytes(_) => "Bytes".to_string(), Value::Value(handle) => vm.get_value(*handle).display_value(vm),
543 Value::Error(handle) => {
544 let err = vm.get_error(*handle);
545 let key = vm.get_interned(err.keyword);
546 format!("error [{key}]: {}", err.data.display_value(vm))
547 }
548 Value::Io(_) => "#<IO>".to_string(),
549 }
550 }
551
552 pub fn pretty_value<ENV>(&self, vm: &GVm<ENV>) -> String {
553 match self {
554 Value::StringConst(i) => vm.get_interned(*i).to_string(),
555 Value::CodePoint(ch) => format!("{ch}"),
556 Value::CharCluster(l, c) => {
557 format!("{}", String::from_utf8_lossy(&c[0..*l as usize]))
558 }
559 Value::CharClusterLong(h) => vm.get_string(*h).to_string(),
560 Value::String(handle) => vm.get_string(*handle).to_string(),
561 _ => self.display_value(vm),
562 }
563 }
564
565 pub fn value_type<ENV>(&self, vm: &GVm<ENV>) -> ValueType {
568 match self {
569 Value::Byte(_) => ValueType::Byte,
570 Value::Int(_) => ValueType::Int,
571 Value::Float(_) => ValueType::Float,
572 Value::CodePoint(_) => ValueType::CodePoint,
573 Value::CharCluster(_, _) => ValueType::CharCluster,
574 Value::CharClusterLong(_) => ValueType::CharClusterLong,
575 Value::Symbol(_) => ValueType::Symbol,
576 Value::Keyword(_) => ValueType::Keyword,
577 Value::StringConst(_) => ValueType::StringConst,
578 Value::Special(_) => ValueType::Special,
579 Value::Builtin(_) => ValueType::Builtin,
580 Value::True => ValueType::True,
581 Value::False => ValueType::False,
582 Value::Nil => ValueType::Nil,
583 Value::Undefined => ValueType::Undefined,
584 Value::String(_) => ValueType::String,
585 Value::Vector(_) => ValueType::Vector,
586 Value::Map(_) => ValueType::Map,
587 Value::Bytes(_) => ValueType::Bytes,
588 Value::Pair(_) => ValueType::Pair,
589 Value::List(_, _) => ValueType::List,
590 Value::Lambda(_) => ValueType::Lambda,
591 Value::Closure(_) => ValueType::Closure,
592 Value::Continuation(_) => ValueType::Continuation,
593 Value::CallFrame(_) => ValueType::CallFrame,
594 Value::Error(_) => ValueType::Error,
595 Value::Io(_) => ValueType::Io,
596 Value::Value(handle) => vm.get_value(*handle).value_type(vm),
597 }
598 }
599
600 pub fn display_type<ENV>(&self, vm: &GVm<ENV>) -> &'static str {
601 self.value_type(vm).into()
602 }
603
604 pub fn is_proper_list<ENV>(&self, vm: &GVm<ENV>) -> bool {
605 if let Value::Pair(handle) = self {
607 let (_car, cdr) = vm.get_pair(*handle);
608 if cdr.is_nil() {
609 true
610 } else {
611 cdr.is_proper_list(vm)
612 }
613 } else {
614 matches!(self, Value::List(_, _))
615 }
616 }
617
618 pub fn get_hash<ENV>(&self, vm: &GVm<ENV>) -> u64 {
625 let mut hasher = FxHasher::default();
626 match self {
627 Value::StringConst(i) => {
628 let s = vm.get_interned(*i);
629 hasher.write_u8(0xFF);
630 hasher.write(s.as_bytes());
631 }
632 Value::String(h) => {
633 let s = vm.get_string(*h);
634 hasher.write_u8(0xFF);
635 hasher.write(s.as_bytes());
636 }
637
638 Value::Byte(_)
639 | Value::Int(_)
640 | Value::Float(_)
641 | Value::CodePoint(_)
642 | Value::CharCluster(_, _)
643 | Value::CharClusterLong(_)
644 | Value::Symbol(_)
645 | Value::Keyword(_)
646 | Value::Builtin(_)
647 | Value::True
648 | Value::False
649 | Value::Nil
650 | Value::Undefined
651 | Value::Special(_)
652 | Value::Vector(_)
653 | Value::Map(_)
654 | Value::Bytes(_)
655 | Value::Pair(_)
656 | Value::List(_, _)
657 | Value::Lambda(_)
658 | Value::Closure(_)
659 | Value::Continuation(_)
660 | Value::CallFrame(_)
661 | Value::Value(_)
662 | Value::Error(_)
663 | Value::Io(_) => self.hash(&mut hasher),
664 }
665 hasher.finish()
666 }
667}
668
669#[derive(Clone, Debug)]
670pub struct Globals {
671 objects: Vec<Value>,
672 props: HashMap<u32, Arc<HashMap<Interned, Value>>>,
673}
674
675impl Default for Globals {
676 fn default() -> Self {
677 Self::new()
678 }
679}
680
681impl Globals {
682 pub fn new() -> Self {
683 Globals {
684 objects: Vec::new(),
685 props: HashMap::new(),
686 }
687 }
688
689 pub fn reserve(&mut self) -> u32 {
690 let index = self.objects.len();
691 self.objects.push(Value::Undefined);
692 index as u32
693 }
694
695 pub fn set(&mut self, idx: u32, val: Value) {
698 self.objects[idx as usize] = val;
699 }
700
701 pub fn get(&self, idx: u32) -> Value {
702 self.objects
703 .get(idx as usize)
704 .map_or_else(|| Value::Undefined, |v| *v)
705 }
706
707 pub fn mark(&self, heap: &mut Heap) {
708 self.objects.iter().for_each(|obj| {
709 heap.mark(*obj);
710 });
711 self.props.iter().for_each(|(_, map)| {
712 for val in map.values() {
713 heap.mark(*val);
714 }
715 });
716 }
717
718 pub fn get_property(&self, global: u32, prop: Interned) -> Option<Value> {
719 if let Some(map) = self.props.get(&global) {
720 if let Some(val) = map.get(&prop) {
721 return Some(*val);
722 }
723 }
724 None
725 }
726
727 pub fn set_property(&mut self, global: u32, prop: Interned, value: Value) {
728 if let Some(map) = self.props.get_mut(&global) {
729 let map = Arc::make_mut(map);
730 map.insert(prop, value);
731 } else {
732 let mut map = HashMap::new();
733 map.insert(prop, value);
734 self.props.insert(global, Arc::new(map));
735 }
736 }
737}
738
739pub const SLOSH_CHAR: &str = "Char";
740pub const SLOSH_STRING: &str = "String";
741pub const SLOSH_INT: &str = "Int";
742pub const SLOSH_FLOAT: &str = "Float";
743pub const SLOSH_BOOL_TRUE: &str = "True";
744pub const SLOSH_BOOL_FALSE: &str = "False";
745pub const SLOSH_SYMBOL: &str = "Symbol";
746pub const SLOSH_KEYWORD: &str = "Keyword";
747pub const SLOSH_SPECIAL: &str = "Special";
748pub const SLOSH_BUILTIN: &str = "Builtin";
749pub const SLOSH_BYTE: &str = "Byte";
750pub const SLOSH_BYTES: &str = "Bytes";
751pub const SLOSH_NIL: &str = "Nil";
752pub const SLOSH_UNDEFINED: &str = "Undefined";
753pub const SLOSH_LAMBDA: &str = "Lambda";
754pub const SLOSH_CLOSURE: &str = "Lambda";
755pub const SLOSH_CONTINUATION: &str = "Continuation";
756pub const SLOSH_CALLFRAME: &str = "CallFrame";
757pub const SLOSH_VECTOR: &str = "Vector";
758pub const SLOSH_MAP: &str = "Map";
759pub const SLOSH_PAIR: &str = "Pair";
760pub const SLOSH_ERROR: &str = "Error";
761pub const SLOSH_IO: &str = "Io";
762
763#[derive(Copy, Clone, PartialEq, Eq, Hash)]
765pub enum ValueType {
766 Byte,
767 Int,
768 Float,
769 CodePoint,
770 CharCluster,
771 CharClusterLong,
772 Symbol,
773 Keyword,
774 StringConst,
775 Special,
776 Builtin,
777 True,
778 False,
779 Nil,
780 Undefined,
781 String,
782 Vector,
783 Map,
784 Bytes,
785 Pair,
786 List,
787 Lambda,
788 Closure,
789 Continuation,
790 CallFrame,
791 Error,
792 Io,
793}
794
795impl Display for ValueType {
796 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
797 write!(f, "{}", <ValueType as Into<&'static str>>::into(*self))
798 }
799}
800
801impl From<ValueType> for &'static str {
802 fn from(value: ValueType) -> Self {
803 match value {
804 ValueType::True => SLOSH_BOOL_TRUE,
805 ValueType::False => SLOSH_BOOL_FALSE,
806 ValueType::Int => SLOSH_INT,
807 ValueType::Float => SLOSH_FLOAT,
808 ValueType::Symbol => SLOSH_SYMBOL,
809 ValueType::Keyword => SLOSH_KEYWORD,
810 ValueType::StringConst => SLOSH_STRING,
811 ValueType::Special => SLOSH_SPECIAL,
812 ValueType::CodePoint => SLOSH_CHAR,
813 ValueType::CharCluster => SLOSH_CHAR,
814 ValueType::CharClusterLong => SLOSH_CHAR,
815 ValueType::Builtin => SLOSH_BUILTIN,
816 ValueType::Byte => SLOSH_BYTE,
817 ValueType::Bytes => SLOSH_BYTES,
818 ValueType::Nil => SLOSH_NIL,
819 ValueType::Undefined => SLOSH_UNDEFINED,
820 ValueType::Lambda => SLOSH_LAMBDA,
821 ValueType::Closure => SLOSH_LAMBDA,
822 ValueType::Continuation => SLOSH_CONTINUATION,
823 ValueType::CallFrame => SLOSH_CALLFRAME,
824 ValueType::Vector => SLOSH_VECTOR,
825 ValueType::Map => SLOSH_MAP,
826 ValueType::Pair => SLOSH_PAIR,
827 ValueType::List => SLOSH_PAIR,
828 ValueType::String => SLOSH_STRING,
829 ValueType::Error => SLOSH_ERROR,
830 ValueType::Io => SLOSH_IO,
831 }
832 }
833}
834
835pub struct ValueTypes<const N: usize> {
836 values: [ValueType; N],
837}
838
839impl<const N: usize> From<[ValueType; N]> for ValueTypes<N> {
840 fn from(values: [ValueType; N]) -> Self {
841 Self { values }
842 }
843}
844
845impl<const N: usize> Deref for ValueTypes<N> {
846 type Target = [ValueType];
847
848 fn deref(&self) -> &Self::Target {
849 &self.values
850 }
851}
852
853impl<const N: usize> From<ValueTypes<N>> for String {
854 fn from(value: ValueTypes<N>) -> Self {
855 let mut res = String::new();
856 let set: BTreeSet<&str> = BTreeSet::from_iter(
857 value
858 .deref()
859 .iter()
860 .map(|v| <ValueType as Into<&'static str>>::into(*v)),
861 );
862 for (i, v) in set.iter().enumerate() {
863 if i > 0 {
864 res.push_str(", ");
865 }
866 res.push_str(v);
867 }
868 res
869 }
870}