1pub mod cycles;
2
3use crate::{
4 gc::{
5 shared::{
6 MappedScopedReadContainer, MappedScopedWriteContainer, ScopedReadContainer,
7 ScopedWriteContainer, ShareableMut, StandardShared,
8 },
9 unsafe_erased_pointers::{OpaqueReference, TemporaryMutableView, TemporaryReadonlyView},
10 Gc, GcMut,
11 },
12 parser::{
13 ast::{self, Atom, ExprKind},
14 parser::SyntaxObject,
15 span::Span,
16 tokens::TokenType,
17 },
18 primitives::numbers::realp,
19 rerrs::{ErrorKind, SteelErr},
20 steel_vm::vm::{
21 threads::closure_into_serializable, BuiltInSignature, Continuation, ContinuationMark,
22 },
23 values::{
24 closed::{Heap, HeapRef, MarkAndSweepContext},
25 functions::{BoxedDynFunction, ByteCodeLambda},
26 lazy_stream::LazyStream,
27 lists::Pair,
28 port::{SendablePort, SteelPort},
29 structs::{SerializableUserDefinedStruct, UserDefinedStruct},
30 transducers::{Reducer, Transducer},
31 HashMapConsumingIter, HashSetConsumingIter, SteelPortRepr, VectorConsumingIter,
32 },
33};
34use alloc::vec::IntoIter;
35use std::{
36 any::{Any, TypeId},
37 cell::RefCell,
38 cmp::Ordering,
39 convert::TryInto,
40 fmt,
41 future::Future,
42 hash::{Hash, Hasher},
43 io::Write,
44 ops::Deref,
45 pin::Pin,
46 rc::Rc,
47 result,
48 sync::{Arc, Mutex},
49 task::Context,
50};
51use thin_vec::ThinVec;
52
53#[macro_export]
55macro_rules! list {
56 () => { $crate::rvals::SteelVal::ListV(
57 im_lists::list![]
58 ) };
59
60 ( $($x:expr),* ) => {{
61 $crate::rvals::SteelVal::ListV(vec![$(
62 $crate::rvals::IntoSteelVal::into_steelval($x).unwrap()
63 ), *].into())
64 }};
65
66 ( $($x:expr ,)* ) => {{
67 $crate::rvals::SteelVal::ListV(im_lists::list![$(
68 $crate::rvals::IntoSteelVal::into_steelval($x).unwrap()
69 )*])
70 }};
71}
72
73use bigdecimal::BigDecimal;
74use parking_lot::RwLock;
75use smallvec::SmallVec;
76use SteelVal::*;
77
78use crate::values::{HashMap, HashSet, Vector};
79
80use futures_task::noop_waker_ref;
81use futures_util::future::Shared;
82use futures_util::FutureExt;
83
84use crate::values::lists::List;
85use num_bigint::{BigInt, ToBigInt};
86use num_rational::{BigRational, Rational32};
87use num_traits::{FromPrimitive, Signed, ToPrimitive, Zero};
88use steel_parser::tokens::{IntLiteral, RealLiteral};
89
90use self::cycles::{CycleDetector, IterativeDropHandler};
91
92pub type RcRefSteelVal = Rc<RefCell<SteelVal>>;
93pub fn new_rc_ref_cell(x: SteelVal) -> RcRefSteelVal {
94 Rc::new(RefCell::new(x))
95}
96
97pub type Result<T> = result::Result<T, SteelErr>;
98pub type FunctionSignature = fn(&[SteelVal]) -> Result<SteelVal>;
99pub type MutFunctionSignature = fn(&mut [SteelVal]) -> Result<SteelVal>;
100
101#[cfg(not(feature = "sync"))]
102pub type BoxedAsyncFunctionSignature =
103 crate::gc::Shared<Box<dyn Fn(&[SteelVal]) -> Result<FutureResult>>>;
104
105#[cfg(feature = "sync")]
106pub type BoxedAsyncFunctionSignature =
107 crate::gc::Shared<Box<dyn Fn(&[SteelVal]) -> Result<FutureResult> + Send + Sync + 'static>>;
108
109pub type AsyncSignature = fn(&[SteelVal]) -> FutureResult;
110
111#[cfg(not(feature = "sync"))]
112pub type BoxedFutureResult = Pin<Box<dyn Future<Output = Result<SteelVal>>>>;
113
114#[cfg(feature = "sync")]
115pub type BoxedFutureResult = Pin<Box<dyn Future<Output = Result<SteelVal>> + Send + 'static>>;
116
117#[derive(Clone)]
122pub struct FutureResult(Shared<BoxedFutureResult>);
123
124impl FutureResult {
125 pub fn new(fut: BoxedFutureResult) -> Self {
126 FutureResult(fut.shared())
127 }
128
129 pub fn into_shared(self) -> Shared<BoxedFutureResult> {
130 self.0
131 }
132}
133
134pub(crate) fn poll_future(mut fut: Shared<BoxedFutureResult>) -> Option<Result<SteelVal>> {
138 if let Some(output) = fut.peek() {
140 return Some(output.clone());
141 }
142
143 let waker = noop_waker_ref();
146 let context = &mut Context::from_waker(waker);
147
148 let mut_fut = Pin::new(&mut fut);
150
151 match Future::poll(mut_fut, context) {
152 core::task::Poll::Ready(r) => Some(r),
153 core::task::Poll::Pending => None,
154 }
155}
156
157pub fn as_underlying_type<T: 'static>(value: &dyn CustomType) -> Option<&T> {
159 value.as_any_ref().downcast_ref::<T>()
160}
161
162pub fn as_underlying_type_mut<T: 'static>(value: &mut dyn CustomType) -> Option<&mut T> {
163 value.as_any_ref_mut().downcast_mut::<T>()
164}
165
166pub trait Custom: private::Sealed {
167 fn fmt(&self) -> Option<core::result::Result<String, core::fmt::Error>> {
168 None
169 }
170
171 #[cfg(feature = "dylibs")]
172 fn fmt_ffi(&self) -> Option<abi_stable::std_types::RString> {
173 None
174 }
175
176 fn into_serializable_steelval(&mut self) -> Option<SerializableSteelVal> {
177 None
178 }
179
180 fn as_iterator(&self) -> Option<Box<dyn Iterator<Item = SteelVal>>> {
181 None
182 }
183
184 fn gc_drop_mut(&mut self, _drop_handler: &mut IterativeDropHandler) {}
185
186 fn gc_visit_children(&self, _context: &mut MarkAndSweepContext) {}
187
188 fn visit_equality(&self, _visitor: &mut cycles::EqualityVisitor) {}
189
190 fn equality_hint(&self, _other: &dyn CustomType) -> bool {
191 true
192 }
193
194 fn equality_hint_general(&self, _other: &SteelVal) -> bool {
195 false
196 }
197
198 #[cfg(feature = "custom-hash")]
199 fn try_as_dyn_hash(&self) -> Option<&dyn DynHash> {
200 None
201 }
202
203 #[doc(hidden)]
204 fn into_error(self) -> core::result::Result<SteelErr, Self>
205 where
206 Self: Sized,
207 {
208 Err(self)
209 }
210}
211
212#[cfg(not(feature = "sync"))]
213pub trait MaybeSendSyncStatic: 'static {}
214
215#[cfg(not(feature = "sync"))]
216impl<T: 'static> MaybeSendSyncStatic for T {}
217
218#[cfg(feature = "sync")]
219pub trait MaybeSendSyncStatic: Send + Sync + 'static {}
220
221#[cfg(feature = "sync")]
222impl<T: Send + Sync + 'static> MaybeSendSyncStatic for T {}
223
224#[cfg(feature = "custom-hash")]
226pub trait DynHash {
227 fn dyn_hash(&self, h: &mut dyn ::core::hash::Hasher);
228}
229
230#[cfg(feature = "custom-hash")]
231impl<T: ::core::hash::Hash> DynHash for T {
232 fn dyn_hash(&self, h: &mut dyn ::core::hash::Hasher) {
233 self.hash(&mut Box::new(h))
234 }
235}
236
237#[cfg(feature = "sync")]
238pub trait CustomType: MaybeSendSyncStatic {
239 fn as_any_ref(&self) -> &dyn Any;
240 fn as_any_ref_mut(&mut self) -> &mut dyn Any;
241 fn name(&self) -> &str {
242 core::any::type_name::<Self>()
243 }
244 fn inner_type_id(&self) -> TypeId;
245 fn display(&self) -> core::result::Result<String, core::fmt::Error> {
246 Ok(format!("#<{}>", self.name()))
247 }
248 fn as_serializable_steelval(&mut self) -> Option<SerializableSteelVal> {
249 None
250 }
251 fn drop_mut(&mut self, _drop_handler: &mut IterativeDropHandler) {}
252 fn visit_children(&self, _context: &mut MarkAndSweepContext) {}
253 fn visit_children_for_equality(&self, _visitor: &mut cycles::EqualityVisitor) {}
256 fn check_equality_hint(&self, _other: &dyn CustomType) -> bool {
257 true
258 }
259 fn check_equality_hint_general(&self, _other: &SteelVal) -> bool {
260 false
261 }
262
263 #[cfg(feature = "custom-hash")]
264 fn try_as_dyn_hash(&self) -> Option<&dyn DynHash> {
265 None
266 }
267
268 #[doc(hidden)]
269 fn into_error_(self) -> core::result::Result<SteelErr, Self>
270 where
271 Self: Sized,
272 {
273 Err(self)
274 }
275}
276
277#[cfg(not(feature = "sync"))]
278pub trait CustomType {
279 fn as_any_ref(&self) -> &dyn Any;
280 fn as_any_ref_mut(&mut self) -> &mut dyn Any;
281 fn name(&self) -> &str {
282 core::any::type_name::<Self>()
283 }
284 fn inner_type_id(&self) -> TypeId;
285 fn display(&self) -> core::result::Result<String, core::fmt::Error> {
286 Ok(format!("#<{}>", self.name()))
287 }
288 fn as_serializable_steelval(&mut self) -> Option<SerializableSteelVal> {
289 None
290 }
291 fn drop_mut(&mut self, _drop_handler: &mut IterativeDropHandler) {}
292 fn visit_children(&self, _context: &mut MarkAndSweepContext) {}
293 fn visit_children_for_equality(&self, _visitor: &mut cycles::EqualityVisitor) {}
294 fn check_equality_hint(&self, _other: &dyn CustomType) -> bool {
295 true
296 }
297 fn check_equality_hint_general(&self, _other: &SteelVal) -> bool {
298 false
299 }
300
301 #[cfg(feature = "custom-hash")]
302 fn try_as_dyn_hash(&self) -> Option<&dyn DynHash> {
303 None
304 }
305
306 #[doc(hidden)]
307 fn into_error_(self) -> core::result::Result<SteelErr, Self>
308 where
309 Self: Sized,
310 {
311 Err(self)
312 }
313}
314
315impl<T: Custom + MaybeSendSyncStatic> CustomType for T {
316 fn as_any_ref(&self) -> &dyn Any {
317 self as &dyn Any
318 }
319 fn as_any_ref_mut(&mut self) -> &mut dyn Any {
320 self as &mut dyn Any
321 }
322 fn inner_type_id(&self) -> TypeId {
323 core::any::TypeId::of::<Self>()
324 }
325 fn display(&self) -> core::result::Result<String, core::fmt::Error> {
326 if let Some(formatted) = self.fmt() {
327 formatted
328 } else {
329 Ok(format!("#<{}>", self.name()))
330 }
331 }
332
333 fn as_serializable_steelval(&mut self) -> Option<SerializableSteelVal> {
334 <T as Custom>::into_serializable_steelval(self)
335 }
336
337 fn drop_mut(&mut self, drop_handler: &mut IterativeDropHandler) {
338 self.gc_drop_mut(drop_handler)
339 }
340
341 fn visit_children(&self, context: &mut MarkAndSweepContext) {
342 self.gc_visit_children(context)
343 }
344
345 fn visit_children_for_equality(&self, visitor: &mut cycles::EqualityVisitor) {
347 self.visit_equality(visitor)
348 }
349
350 fn check_equality_hint(&self, other: &dyn CustomType) -> bool {
351 self.equality_hint(other)
352 }
353
354 fn check_equality_hint_general(&self, other: &SteelVal) -> bool {
355 self.equality_hint_general(other)
356 }
357
358 fn into_error_(self) -> core::result::Result<SteelErr, Self>
359 where
360 Self: Sized,
361 {
362 self.into_error()
363 }
364
365 #[cfg(feature = "custom-hash")]
366 fn try_as_dyn_hash(&self) -> Option<&dyn DynHash> {
367 Custom::try_as_dyn_hash(self)
368 }
369}
370
371impl<T: CustomType + 'static> IntoSteelVal for T {
372 fn into_steelval(self) -> Result<SteelVal> {
373 Ok(SteelVal::Custom(Gc::new_mut(Box::new(self))))
374 }
375
376 fn as_error(self) -> core::result::Result<SteelErr, Self> {
377 T::into_error_(self)
378 }
379}
380
381pub trait IntoSerializableSteelVal {
382 fn into_serializable_steelval(val: &SteelVal) -> Result<SerializableSteelVal>;
383}
384
385impl<T: CustomType + Clone + Send + Sync + 'static> IntoSerializableSteelVal for T {
386 fn into_serializable_steelval(val: &SteelVal) -> Result<SerializableSteelVal> {
387 if let SteelVal::Custom(v) = val {
388 let left = v.read().as_any_ref().downcast_ref::<T>().cloned();
389 let _lifted = left.ok_or_else(|| {
390 let error_message = format!(
391 "Type Mismatch: Type of SteelVal: {:?}, did not match the given type: {}",
392 val,
393 core::any::type_name::<Self>()
394 );
395 SteelErr::new(ErrorKind::ConversionError, error_message)
396 });
397
398 todo!()
399 } else {
400 let error_message = format!(
401 "Type Mismatch: Type of SteelVal: {:?} did not match the given type, expecting opaque struct: {}",
402 val,
403 core::any::type_name::<Self>()
404 );
405
406 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
407 }
408 }
409}
410
411impl<T: CustomType + Clone + 'static> FromSteelVal for T {
414 fn from_steelval(val: &SteelVal) -> Result<Self> {
415 if let SteelVal::Custom(v) = val {
416 let left = v.read().as_any_ref().downcast_ref::<T>().cloned();
420 left.ok_or_else(|| {
421 let error_message = format!(
422 "Type Mismatch: Type of SteelVal: {:?}, did not match the given type: {}",
423 val,
424 core::any::type_name::<Self>()
425 );
426 SteelErr::new(ErrorKind::ConversionError, error_message)
427 })
428 } else {
429 let error_message = format!(
430 "Type Mismatch: Type of SteelVal: {:?} did not match the given type, expecting opaque struct: {}",
431 val,
432 core::any::type_name::<Self>()
433 );
434
435 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
436 }
437 }
438}
439
440pub trait IntoSteelVal: Sized {
446 fn into_steelval(self) -> Result<SteelVal>;
447
448 #[doc(hidden)]
449 fn as_error(self) -> core::result::Result<SteelErr, Self> {
450 Err(self)
451 }
452}
453
454pub trait FromSteelVal: Sized {
460 fn from_steelval(val: &SteelVal) -> Result<Self>;
461}
462
463pub trait PrimitiveAsRef<'a>: Sized {
464 fn primitive_as_ref(val: &'a SteelVal) -> Result<Self>;
465 fn maybe_primitive_as_ref(val: &'a SteelVal) -> Option<Self>;
466}
467
468pub trait PrimitiveAsRefMut<'a>: Sized {
469 fn primitive_as_ref(val: &'a mut SteelVal) -> Result<Self>;
470 fn maybe_primitive_as_ref(val: &'a mut SteelVal) -> Option<Self>;
471}
472
473pub struct RestArgsIter<'a, T>(
474 pub core::iter::Map<core::slice::Iter<'a, SteelVal>, fn(&'a SteelVal) -> Result<T>>,
475);
476
477impl<'a, T: PrimitiveAsRef<'a> + 'a> RestArgsIter<'a, T> {
478 pub fn new(
479 args: core::iter::Map<core::slice::Iter<'a, SteelVal>, fn(&'a SteelVal) -> Result<T>>,
480 ) -> Self {
481 RestArgsIter(args)
482 }
483
484 pub fn from_slice(args: &'a [SteelVal]) -> Result<Self> {
485 Ok(RestArgsIter(args.iter().map(T::primitive_as_ref)))
486 }
487}
488
489impl<'a, T> Iterator for RestArgsIter<'a, T> {
490 type Item = Result<T>;
491
492 fn next(&mut self) -> Option<Self::Item> {
493 self.0.next()
494 }
495
496 fn size_hint(&self) -> (usize, Option<usize>) {
497 self.0.size_hint()
498 }
499}
500
501impl<'a, T> ExactSizeIterator for RestArgsIter<'a, T> {}
502
503pub struct RestArgs<T: FromSteelVal>(pub Vec<T>);
504
505impl<T: FromSteelVal> RestArgs<T> {
506 pub fn new(args: Vec<T>) -> Self {
507 RestArgs(args)
508 }
509
510 pub fn from_slice(args: &[SteelVal]) -> Result<Self> {
511 args.iter()
512 .map(|x| T::from_steelval(x))
513 .collect::<Result<Vec<_>>>()
514 .map(RestArgs)
515 }
516}
517
518impl<T: FromSteelVal> core::ops::Deref for RestArgs<T> {
519 type Target = [T];
520
521 fn deref(&self) -> &Self::Target {
522 &self.0
523 }
524}
525
526mod private {
527
528 use core::any::Any;
529
530 pub trait Sealed {}
531
532 impl<T: Any> Sealed for T {}
533}
534
535pub enum SRef<'b, T: ?Sized + 'b> {
536 Temporary(&'b T),
537 Owned(MappedScopedReadContainer<'b, T>),
538}
539
540impl<'b, T: ?Sized + 'b> Deref for SRef<'b, T> {
541 type Target = T;
542
543 #[inline]
544 fn deref(&self) -> &T {
545 match self {
546 SRef::Temporary(inner) => inner,
547 SRef::Owned(inner) => inner,
548 }
549 }
550}
551
552pub trait AsRefSteelVal: Sized {
554 type Nursery: Default;
555
556 fn as_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<SRef<'b, Self>>;
557}
558
559pub trait AsSlice<T> {
560 fn as_slice_repr(&self) -> &[T];
561}
562
563impl<T> AsSlice<T> for Vec<T> {
564 fn as_slice_repr(&self) -> &[T] {
565 self.as_slice()
566 }
567}
568
569pub trait AsRefSteelValFromUnsized<T>: Sized {
571 type Output: AsSlice<T>;
572
573 fn as_ref_from_unsized(val: &SteelVal) -> Result<Self::Output>;
574}
575
576pub trait AsRefMutSteelVal: Sized {
577 fn as_mut_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<MappedScopedWriteContainer<'b, Self>>;
578}
579
580pub(crate) trait AsRefMutSteelValFromRef: Sized {
581 fn as_mut_ref_from_ref(val: &SteelVal) -> crate::rvals::Result<TemporaryMutableView<Self>>;
582}
583
584pub(crate) trait AsRefSteelValFromRef: Sized {
585 fn as_ref_from_ref(val: &SteelVal) -> crate::rvals::Result<TemporaryReadonlyView<Self>>;
586}
587
588impl AsRefSteelVal for UserDefinedStruct {
589 type Nursery = ();
590
591 fn as_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<SRef<'b, Self>> {
592 if let SteelVal::CustomStruct(l) = val {
593 Ok(SRef::Temporary(l))
594 } else {
595 stop!(TypeMismatch => "Value cannot be referenced as a list")
596 }
597 }
598}
599
600impl<T: CustomType + MaybeSendSyncStatic> AsRefSteelVal for T {
601 type Nursery = ();
602
603 fn as_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<SRef<'b, Self>> {
604 if let SteelVal::Custom(v) = val {
605 let res = ScopedReadContainer::map(v.read(), |x| x.as_any_ref());
606
607 if res.is::<T>() {
608 Ok(SRef::Owned(MappedScopedReadContainer::map(res, |x| {
609 x.downcast_ref::<T>().unwrap()
610 })))
611 } else {
612 let error_message = format!(
613 "Type Mismatch: Type of SteelVal: {} did not match the given type: {}",
614 val,
615 core::any::type_name::<Self>()
616 );
617 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
618 }
619 } else {
621 let error_message = format!(
622 "Type Mismatch: Type of SteelVal: {} did not match the given type: {}",
623 val,
624 core::any::type_name::<Self>()
625 );
626
627 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
628 }
629 }
630}
631
632impl<T: CustomType + MaybeSendSyncStatic> AsRefMutSteelVal for T {
633 fn as_mut_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<MappedScopedWriteContainer<'b, Self>> {
634 if let SteelVal::Custom(v) = val {
635 let res = ScopedWriteContainer::map(v.write(), |x| x.as_any_ref_mut());
636
637 if res.is::<T>() {
638 Ok(MappedScopedWriteContainer::map(res, |x| {
639 x.downcast_mut::<T>().unwrap()
640 }))
641 } else {
642 let error_message = format!(
643 "Type Mismatch: Type of SteelVal: {} did not match the given type: {}",
644 val,
645 core::any::type_name::<Self>()
646 );
647 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
648 }
649 } else {
651 let error_message = format!(
652 "Type Mismatch: Type of SteelVal: {} did not match the given type: {}",
653 val,
654 core::any::type_name::<Self>()
655 );
656
657 Err(SteelErr::new(ErrorKind::ConversionError, error_message))
658 }
659 }
660}
661
662impl ast::TryFromSteelValVisitorForExprKind {
663 pub fn visit_syntax_object(&mut self, value: &Syntax) -> Result<ExprKind> {
664 let span = value.span;
665
666 match &value.syntax {
669 SyntaxObject(s) => self.visit_syntax_object(s),
671 BoolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
672 TokenType::BooleanLiteral(*x),
673 span,
674 )))),
675 NumV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
676 RealLiteral::Float((*x).into()).into(),
677 span,
678 )))),
679 IntV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
680 RealLiteral::Int(IntLiteral::Small(*x)).into(),
681 span,
682 )))),
683 VectorV(lst) => {
684 let items: Result<ThinVec<ExprKind>> = lst.iter().map(|x| self.visit(x)).collect();
685 Ok(ExprKind::List(crate::parser::ast::List::new(items?)))
686 }
687 StringV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
688 TokenType::StringLiteral(x.as_str().into()),
689 span,
690 )))),
691
692 SymbolV(x) if x.starts_with("#:") => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
693 TokenType::Keyword(x.as_str().into()),
694 span,
695 )))),
696
697 SymbolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
698 TokenType::Identifier(x.as_str().into()),
699 span,
700 )))),
701
702 ListV(l) => {
703 if self.qq_depth == 0 {
705 let maybe_special_form = l.first().and_then(|x| {
706 x.as_symbol()
707 .or_else(|| x.as_syntax_object().and_then(|x| x.syntax.as_symbol()))
708 });
709
710 match maybe_special_form {
711 Some(x) if x.as_str() == "quote" => {
712 if self.quoted {
713 let items: core::result::Result<ThinVec<ExprKind>, _> =
714 l.iter().map(|x| self.visit(x)).collect();
715
716 return Ok(ExprKind::List(ast::List::new(items?)));
717 }
718
719 self.quoted = true;
720
721 let return_value = l
722 .into_iter()
723 .map(|x| self.visit(x))
724 .collect::<core::result::Result<ThinVec<_>, _>>()?
725 .try_into()?;
726
727 self.quoted = false;
728
729 return Ok(return_value);
730 } _ => {}
737 }
738 }
739
740 Ok(l.into_iter()
741 .map(|x| self.visit(x))
742 .collect::<core::result::Result<ThinVec<_>, _>>()?
743 .try_into()?)
744 }
745
746 CharV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
747 TokenType::CharacterLiteral(*x),
748 span,
749 )))),
750 _ => stop!(ConversionError => "unable to convert {:?} to expression", &value.syntax),
751 }
752 }
753}
754
755#[derive(Debug, Clone)]
756pub struct Syntax {
757 pub(crate) raw: Option<SteelVal>,
758 pub(crate) syntax: SteelVal,
759 span: Span,
760}
761
762impl Syntax {
763 pub fn new(syntax: SteelVal, span: Span) -> Syntax {
764 Self {
765 raw: None,
766 syntax,
767 span,
768 }
769 }
770
771 pub fn proto(raw: SteelVal, syntax: SteelVal, span: Span) -> Syntax {
772 Self {
773 raw: Some(raw),
774 syntax,
775 span,
776 }
777 }
778
779 pub fn syntax_e(&self) -> SteelVal {
780 self.syntax.clone()
781 }
782
783 pub fn new_with_source(syntax: SteelVal, span: Span) -> Syntax {
784 Self {
785 raw: None,
786 syntax,
787 span,
788 }
789 }
790
791 pub fn syntax_loc(&self) -> Span {
792 self.span
793 }
794
795 pub fn syntax_datum(&self) -> SteelVal {
796 self.raw.clone().unwrap()
797 }
798
799 pub(crate) fn steelval_to_exprkind(value: &SteelVal) -> Result<ExprKind> {
800 match value {
801 SyntaxObject(s) => s.to_exprkind(),
803 BoolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
804 TokenType::BooleanLiteral(*x),
805 )))),
806 NumV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
807 RealLiteral::Float((*x).into()).into(),
808 )))),
809 IntV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
810 RealLiteral::Int(IntLiteral::Small(*x)).into(),
811 )))),
812 VectorV(lst) => {
813 let items: Result<ThinVec<ExprKind>> =
814 lst.iter().map(Self::steelval_to_exprkind).collect();
815 Ok(ExprKind::List(crate::parser::ast::List::new(items?)))
816 }
817 StringV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
818 TokenType::StringLiteral(x.as_str().into()),
819 )))),
820 SymbolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
823 TokenType::Identifier(x.as_str().into()),
824 )))),
825 ListV(l) => {
826 let items: Result<ThinVec<ExprKind>> =
827 l.iter().map(Self::steelval_to_exprkind).collect();
828
829 Ok(ExprKind::List(crate::parser::ast::List::new(items?)))
830 }
831 CharV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::default(
832 TokenType::CharacterLiteral(*x),
833 )))),
834 _ => stop!(ConversionError => "unable to convert {:?} to expression", value),
835 }
836 }
837
838 pub fn to_exprkind(&self) -> Result<ExprKind> {
841 let span = self.span;
842 match &self.syntax {
844 SyntaxObject(s) => s.to_exprkind(),
846 BoolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
847 TokenType::BooleanLiteral(*x),
848 span,
849 )))),
850 NumV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
851 RealLiteral::Float((*x).into()).into(),
852 span,
853 )))),
854 IntV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
855 RealLiteral::Int(IntLiteral::Small(*x)).into(),
856 span,
857 )))),
858 VectorV(lst) => {
859 let items: Result<ThinVec<ExprKind>> =
860 lst.iter().map(Self::steelval_to_exprkind).collect();
861 Ok(ExprKind::List(crate::parser::ast::List::new(items?)))
862 }
863 StringV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
864 TokenType::StringLiteral(x.as_str().into()),
865 span,
866 )))),
867 SymbolV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
870 TokenType::Identifier(x.as_str().into()),
871 span,
872 )))),
873 ListV(l) => {
874 let items: Result<ThinVec<ExprKind>> =
875 l.iter().map(Self::steelval_to_exprkind).collect();
876
877 Ok(ExprKind::List(crate::parser::ast::List::new(items?)))
878 }
879 CharV(x) => Ok(ExprKind::Atom(Atom::new(SyntaxObject::new(
880 TokenType::CharacterLiteral(*x),
881 span,
882 )))),
883 _ => stop!(ConversionError => "unable to convert {:?} to expression", &self.syntax),
884 }
885 }
886}
887
888impl IntoSteelVal for Syntax {
889 fn into_steelval(self) -> Result<SteelVal> {
890 Ok(SteelVal::SyntaxObject(Gc::new(self)))
891 }
892}
893
894impl AsRefSteelVal for Syntax {
895 type Nursery = ();
896
897 fn as_ref<'b, 'a: 'b>(val: &'a SteelVal) -> Result<SRef<'b, Self>> {
898 if let SteelVal::SyntaxObject(s) = val {
899 Ok(SRef::Temporary(s))
900 } else {
901 stop!(TypeMismatch => "Value cannot be referenced as a syntax object: {}", val)
902 }
903 }
904}
905
906impl From<Syntax> for SteelVal {
907 fn from(val: Syntax) -> Self {
908 SteelVal::SyntaxObject(Gc::new(val))
909 }
910}
911
912pub enum SerializableSteelVal {
922 Closure(crate::values::functions::SerializedLambda),
923 BoolV(bool),
924 NumV(f64),
925 IntV(isize),
926 CharV(char),
927 Void,
928 StringV(String),
929 FuncV(FunctionSignature),
930 MutFunc(MutFunctionSignature),
931 HashMapV(Vec<(SerializableSteelVal, SerializableSteelVal)>),
932 ListV(Vec<SerializableSteelVal>),
933 Pair(Box<(SerializableSteelVal, SerializableSteelVal)>),
934 VectorV(Vec<SerializableSteelVal>),
935 ByteVectorV(Vec<u8>),
936 BoxedDynFunction(BoxedDynFunction),
937 BuiltIn(BuiltInSignature),
938 SymbolV(String),
939 Custom(Box<dyn CustomType + Send>),
940 CustomStruct(SerializableUserDefinedStruct),
941 HeapAllocated(usize),
943 Port(SendablePort),
944 Rational(Rational32),
945}
946
947pub enum SerializedHeapRef {
948 Serialized(Option<SerializableSteelVal>),
949 Closed(HeapRef<SteelVal>),
950}
951
952pub struct HeapSerializer<'a> {
953 pub heap: &'a mut Heap,
954 pub fake_heap: &'a mut std::collections::HashMap<usize, SerializedHeapRef>,
955 pub values_to_fill_in: &'a mut std::collections::HashMap<usize, HeapRef<SteelVal>>,
958
959 pub built_functions: &'a mut std::collections::HashMap<u32, Gc<ByteCodeLambda>>,
961}
962
963pub fn from_serializable_value(ctx: &mut HeapSerializer, val: SerializableSteelVal) -> SteelVal {
966 match val {
967 SerializableSteelVal::Closure(c) => {
968 if c.captures.is_empty() {
969 if let Some(already_made) = ctx.built_functions.get(&c.id) {
970 SteelVal::Closure(already_made.clone())
971 } else {
972 let id = c.id;
973 let value = Gc::new(ByteCodeLambda::from_serialized(ctx, c));
974
975 ctx.built_functions.insert(id, value.clone());
978 SteelVal::Closure(value)
979 }
980 } else {
981 SteelVal::Closure(Gc::new(ByteCodeLambda::from_serialized(ctx, c)))
982 }
983 }
984 SerializableSteelVal::BoolV(b) => SteelVal::BoolV(b),
985 SerializableSteelVal::NumV(n) => SteelVal::NumV(n),
986 SerializableSteelVal::IntV(i) => SteelVal::IntV(i),
987 SerializableSteelVal::CharV(c) => SteelVal::CharV(c),
988 SerializableSteelVal::Void => SteelVal::Void,
989 SerializableSteelVal::Rational(r) => SteelVal::Rational(r),
990 SerializableSteelVal::StringV(s) => SteelVal::StringV(s.into()),
991 SerializableSteelVal::FuncV(f) => SteelVal::FuncV(f),
992 SerializableSteelVal::MutFunc(f) => SteelVal::MutFunc(f),
993 SerializableSteelVal::HashMapV(h) => SteelVal::HashMapV(
994 Gc::new(
995 h.into_iter()
996 .map(|(k, v)| {
997 (
998 from_serializable_value(ctx, k),
999 from_serializable_value(ctx, v),
1000 )
1001 })
1002 .collect::<HashMap<_, _>>(),
1003 )
1004 .into(),
1005 ),
1006 SerializableSteelVal::ListV(v) => SteelVal::ListV(
1007 v.into_iter()
1008 .map(|x| from_serializable_value(ctx, x))
1009 .collect(),
1010 ),
1011 SerializableSteelVal::VectorV(v) => SteelVal::VectorV(SteelVector(Gc::new(
1012 v.into_iter()
1013 .map(|x| from_serializable_value(ctx, x))
1014 .collect(),
1015 ))),
1016 SerializableSteelVal::BoxedDynFunction(f) => SteelVal::BoxedFunction(Gc::new(f)),
1017 SerializableSteelVal::BuiltIn(f) => SteelVal::BuiltIn(f),
1018 SerializableSteelVal::SymbolV(s) => SteelVal::SymbolV(s.into()),
1019 SerializableSteelVal::Custom(b) => SteelVal::Custom(Gc::new_mut(b)),
1020 SerializableSteelVal::CustomStruct(s) => {
1021 SteelVal::CustomStruct(Gc::new(UserDefinedStruct {
1022 fields: {
1023 let fields = s
1024 .fields
1025 .into_iter()
1026 .map(|x| from_serializable_value(ctx, x));
1027
1028 let mut recycle: crate::values::recycler::Recycle<SmallVec<_>> =
1034 crate::values::recycler::Recycle::new();
1035
1036 recycle.extend(fields);
1037
1038 recycle
1039 },
1040 type_descriptor: s.type_descriptor,
1041 }))
1042 }
1043 SerializableSteelVal::Port(p) => SteelVal::PortV(SteelPort::from_sendable_port(p)),
1044 SerializableSteelVal::HeapAllocated(v) => {
1045 if let Some(mut guard) = ctx.fake_heap.get_mut(&v) {
1048 match &mut guard {
1049 SerializedHeapRef::Serialized(value) => {
1050 let value = core::mem::take(value);
1051
1052 if let Some(value) = value {
1053 let _ = from_serializable_value(ctx, value);
1054
1055 todo!()
1056 } else {
1063 todo!()
1067
1068 }
1075 }
1076
1077 SerializedHeapRef::Closed(c) => SteelVal::HeapAllocated(c.clone()),
1078 }
1079 } else {
1080 todo!()
1090 }
1091 }
1092 SerializableSteelVal::Pair(pair) => {
1093 let (car, cdr) = *pair;
1094
1095 crate::values::lists::Pair::cons(
1096 from_serializable_value(ctx, car),
1097 from_serializable_value(ctx, cdr),
1098 )
1099 .into()
1100 }
1101 SerializableSteelVal::ByteVectorV(bytes) => {
1102 SteelVal::ByteVector(SteelByteVector::new(bytes))
1103 }
1104 }
1105}
1106
1107pub fn into_serializable_value(
1112 val: SteelVal,
1113 serialized_heap: &mut std::collections::HashMap<usize, SerializableSteelVal>,
1114 visited: &mut std::collections::HashSet<usize>,
1115) -> Result<SerializableSteelVal> {
1116 match val {
1119 SteelVal::Closure(c) => closure_into_serializable(&c, serialized_heap, visited)
1120 .map(SerializableSteelVal::Closure),
1121 SteelVal::BoolV(b) => Ok(SerializableSteelVal::BoolV(b)),
1122 SteelVal::NumV(n) => Ok(SerializableSteelVal::NumV(n)),
1123 SteelVal::IntV(n) => Ok(SerializableSteelVal::IntV(n)),
1124 SteelVal::CharV(c) => Ok(SerializableSteelVal::CharV(c)),
1125 SteelVal::Void => Ok(SerializableSteelVal::Void),
1126 SteelVal::StringV(s) => Ok(SerializableSteelVal::StringV(s.to_string())),
1127 SteelVal::FuncV(f) => Ok(SerializableSteelVal::FuncV(f)),
1128 SteelVal::ListV(l) => Ok(SerializableSteelVal::ListV(
1129 l.into_iter()
1130 .map(|x| into_serializable_value(x, serialized_heap, visited))
1131 .collect::<Result<_>>()?,
1132 )),
1133 SteelVal::Pair(pair) => Ok(SerializableSteelVal::Pair(Box::new((
1134 into_serializable_value(pair.car.clone(), serialized_heap, visited)?,
1135 into_serializable_value(pair.cdr.clone(), serialized_heap, visited)?,
1136 )))),
1137 SteelVal::BoxedFunction(f) => Ok(SerializableSteelVal::BoxedDynFunction((*f).clone())),
1138 SteelVal::BuiltIn(f) => Ok(SerializableSteelVal::BuiltIn(f)),
1139 SteelVal::SymbolV(s) => Ok(SerializableSteelVal::SymbolV(s.to_string())),
1140 SteelVal::MutFunc(f) => Ok(SerializableSteelVal::MutFunc(f)),
1141 SteelVal::HashMapV(v) => Ok(SerializableSteelVal::HashMapV(
1142 v.0.unwrap()
1143 .into_iter()
1144 .map(|(k, v)| {
1145 let kprime = into_serializable_value(k, serialized_heap, visited)?;
1146 let vprime = into_serializable_value(v, serialized_heap, visited)?;
1147
1148 Ok((kprime, vprime))
1149 })
1150 .collect::<Result<_>>()?,
1151 )),
1152
1153 SteelVal::Custom(c) => {
1154 if let Some(output) = c.write().as_serializable_steelval() {
1155 Ok(output)
1156 } else {
1157 stop!(Generic => "Custom type not allowed to be moved across threads!")
1158 }
1159 }
1160
1161 SteelVal::CustomStruct(s) => Ok(SerializableSteelVal::CustomStruct(
1162 SerializableUserDefinedStruct {
1163 fields: s
1164 .fields
1165 .iter()
1166 .cloned()
1167 .map(|x| into_serializable_value(x, serialized_heap, visited))
1168 .collect::<Result<Vec<_>>>()?,
1169 type_descriptor: s.type_descriptor,
1170 },
1171 )),
1172
1173 SteelVal::PortV(p) => SendablePort::from_port(p).map(SerializableSteelVal::Port),
1174
1175 SteelVal::HeapAllocated(h) => {
1177 if visited.contains(&h.as_ptr_usize())
1179 && !serialized_heap.contains_key(&h.as_ptr_usize())
1180 {
1181 Ok(SerializableSteelVal::HeapAllocated(h.as_ptr_usize()))
1184 } else {
1185 visited.insert(h.as_ptr_usize());
1186
1187 if serialized_heap.contains_key(&h.as_ptr_usize()) {
1188 Ok(SerializableSteelVal::HeapAllocated(h.as_ptr_usize()))
1191 } else {
1192 let value = into_serializable_value(h.get(), serialized_heap, visited);
1195
1196 let value = match value {
1197 Ok(v) => v,
1198 Err(e) => {
1199 return Err(e);
1201 }
1202 };
1203
1204 serialized_heap.insert(h.as_ptr_usize(), value);
1205
1206 Ok(SerializableSteelVal::HeapAllocated(h.as_ptr_usize()))
1209 }
1210 }
1211 }
1212
1213 SteelVal::VectorV(vector) => Ok(SerializableSteelVal::VectorV(
1214 vector
1215 .iter()
1216 .cloned()
1217 .map(|val| into_serializable_value(val, serialized_heap, visited))
1218 .collect::<Result<_>>()?,
1219 )),
1220
1221 SteelVal::ByteVector(bytes) => {
1222 Ok(SerializableSteelVal::ByteVectorV(bytes.vec.read().clone()))
1223 }
1224
1225 SteelVal::Rational(r) => Ok(SerializableSteelVal::Rational(r)),
1226
1227 illegal => stop!(Generic => "Type not allowed to be moved across threads!: {}", illegal),
1228 }
1229}
1230
1231#[derive(Clone, Debug, PartialEq, Eq)]
1232pub struct SteelMutableVector(pub(crate) Gc<RefCell<Vec<SteelVal>>>);
1233
1234#[derive(Clone, Debug, PartialEq, Eq)]
1235pub struct SteelVector(pub(crate) Gc<Vector<SteelVal>>);
1236
1237impl FromIterator<SteelVal> for SteelVector {
1238 fn from_iter<T: IntoIterator<Item = SteelVal>>(iter: T) -> Self {
1239 let vec = Vector::from_iter(iter);
1240 SteelVector(Gc::new(vec))
1241 }
1242}
1243
1244impl Deref for SteelVector {
1245 type Target = Vector<SteelVal>;
1246
1247 fn deref(&self) -> &Self::Target {
1248 &self.0
1249 }
1250}
1251
1252impl From<Gc<Vector<SteelVal>>> for SteelVector {
1253 fn from(value: Gc<Vector<SteelVal>>) -> Self {
1254 SteelVector(value)
1255 }
1256}
1257
1258#[derive(Clone, Debug, PartialEq)]
1259pub struct SteelHashMap(pub(crate) Gc<HashMap<SteelVal, SteelVal>>);
1260
1261#[cfg(feature = "imbl")]
1262impl Hash for SteelHashMap {
1263 fn hash<H>(&self, state: &mut H)
1264 where
1265 H: Hasher,
1266 {
1267 for i in self.iter() {
1268 i.hash(state);
1269 }
1270 }
1271}
1272
1273impl Deref for SteelHashMap {
1274 type Target = HashMap<SteelVal, SteelVal>;
1275
1276 fn deref(&self) -> &Self::Target {
1277 &self.0
1278 }
1279}
1280
1281impl From<Gc<HashMap<SteelVal, SteelVal>>> for SteelHashMap {
1282 fn from(value: Gc<HashMap<SteelVal, SteelVal>>) -> Self {
1283 SteelHashMap(value)
1284 }
1285}
1286
1287#[derive(Clone, Debug, PartialEq)]
1288pub struct SteelHashSet(pub(crate) Gc<HashSet<SteelVal>>);
1289
1290#[cfg(feature = "imbl")]
1291impl Hash for SteelHashSet {
1292 fn hash<H>(&self, state: &mut H)
1293 where
1294 H: Hasher,
1295 {
1296 for i in self.iter() {
1297 i.hash(state);
1298 }
1299 }
1300}
1301
1302impl Deref for SteelHashSet {
1303 type Target = HashSet<SteelVal>;
1304
1305 fn deref(&self) -> &Self::Target {
1306 &self.0
1307 }
1308}
1309
1310impl From<Gc<HashSet<SteelVal>>> for SteelHashSet {
1311 fn from(value: Gc<HashSet<SteelVal>>) -> Self {
1312 SteelHashSet(value)
1313 }
1314}
1315
1316pub enum TypeKind {
1317 Any,
1318 Bool,
1319 Num,
1320 Int,
1321 Char,
1322 Vector(Box<TypeKind>),
1323 Void,
1324 String,
1325 Function,
1326 HashMap(Box<TypeKind>, Box<TypeKind>),
1327 HashSet(Box<TypeKind>),
1328 List(Box<TypeKind>),
1329}
1330
1331#[repr(C, u8)]
1333pub enum SteelVal {
1334 Closure(Gc<ByteCodeLambda>),
1336 BoolV(bool),
1338 NumV(f64),
1340 IntV(isize),
1342 Rational(Rational32),
1344 CharV(char),
1346 VectorV(SteelVector),
1349 Void,
1351 StringV(SteelString),
1353 FuncV(FunctionSignature),
1355 SymbolV(SteelString),
1357 Custom(GcMut<Box<dyn CustomType>>), HashMapV(SteelHashMap),
1361 HashSetV(SteelHashSet),
1363 CustomStruct(Gc<UserDefinedStruct>),
1365 PortV(SteelPort),
1367 IterV(Gc<Transducer>),
1369 ReducerV(Gc<Reducer>),
1371 FutureFunc(BoxedAsyncFunctionSignature),
1373 FutureV(Gc<FutureResult>),
1375 StreamV(Gc<LazyStream>),
1377 BoxedFunction(Gc<BoxedDynFunction>),
1379 ContinuationFunction(Continuation),
1381 ListV(crate::values::lists::List<SteelVal>),
1386 Pair(Gc<crate::values::lists::Pair>),
1388 MutFunc(MutFunctionSignature),
1390 BuiltIn(BuiltInSignature),
1392 MutableVector(HeapRef<Vec<SteelVal>>),
1394 BoxedIterator(GcMut<OpaqueIterator>),
1397 SyntaxObject(Gc<Syntax>),
1399 Boxed(GcMut<SteelVal>),
1402 HeapAllocated(HeapRef<SteelVal>),
1404 Reference(Gc<OpaqueReference<'static>>),
1406 BigNum(Gc<BigInt>),
1408 BigRational(Gc<BigRational>),
1410 Complex(Gc<SteelComplex>),
1412 ByteVector(SteelByteVector),
1414}
1415
1416impl Clone for SteelVal {
1417 #[inline(always)]
1418 fn clone(&self) -> Self {
1419 match self {
1420 Closure(gc) => Self::Closure(Gc::clone(gc)),
1421 BoolV(b) => Self::BoolV(*b),
1422 NumV(n) => Self::NumV(*n),
1423 IntV(i) => Self::IntV(*i),
1424 Rational(ratio) => Self::Rational(*ratio),
1425 CharV(c) => Self::CharV(*c),
1426 VectorV(steel_vector) => Self::VectorV(steel_vector.clone()),
1427 Void => Self::Void,
1428 StringV(steel_string) => Self::StringV(steel_string.clone()),
1429 FuncV(f) => Self::FuncV(*f),
1430 SymbolV(steel_string) => Self::SymbolV(steel_string.clone()),
1431 SteelVal::Custom(gc) => SteelVal::Custom(gc.clone()),
1432 HashMapV(steel_hash_map) => SteelVal::HashMapV(steel_hash_map.clone()),
1433 HashSetV(steel_hash_set) => SteelVal::HashSetV(steel_hash_set.clone()),
1434 CustomStruct(gc) => SteelVal::CustomStruct(gc.clone()),
1435 PortV(steel_port) => SteelVal::PortV(steel_port.clone()),
1436 IterV(gc) => SteelVal::IterV(gc.clone()),
1437 ReducerV(gc) => SteelVal::ReducerV(gc.clone()),
1438 FutureFunc(f) => SteelVal::FutureFunc(f.clone()),
1439 FutureV(gc) => SteelVal::FutureV(gc.clone()),
1440 StreamV(gc) => SteelVal::StreamV(gc.clone()),
1441 BoxedFunction(gc) => SteelVal::BoxedFunction(gc.clone()),
1442 ContinuationFunction(continuation) => {
1443 SteelVal::ContinuationFunction(continuation.clone())
1444 }
1445 ListV(generic_list) => SteelVal::ListV(generic_list.clone()),
1446 SteelVal::Pair(gc) => SteelVal::Pair(gc.clone()),
1447 MutFunc(f) => SteelVal::MutFunc(*f),
1448 BuiltIn(f) => SteelVal::BuiltIn(*f),
1449 MutableVector(heap_ref) => SteelVal::MutableVector(heap_ref.clone()),
1450 BoxedIterator(gc) => SteelVal::BoxedIterator(gc.clone()),
1451 SteelVal::SyntaxObject(gc) => SteelVal::SyntaxObject(gc.clone()),
1452 Boxed(gc) => SteelVal::Boxed(gc.clone()),
1453 HeapAllocated(heap_ref) => SteelVal::HeapAllocated(heap_ref.clone()),
1454 Reference(gc) => SteelVal::Reference(gc.clone()),
1455 BigNum(gc) => SteelVal::BigNum(gc.clone()),
1456 SteelVal::BigRational(gc) => SteelVal::BigRational(gc.clone()),
1457 Complex(gc) => SteelVal::Complex(gc.clone()),
1458 ByteVector(steel_byte_vector) => SteelVal::ByteVector(steel_byte_vector.clone()),
1459 }
1460 }
1461}
1462
1463impl Default for SteelVal {
1464 fn default() -> Self {
1465 SteelVal::Void
1466 }
1467}
1468
1469#[cfg(feature = "sync")]
1472pub(crate) enum SteelValPointer {
1473 Closure(*const ByteCodeLambda),
1475 VectorV(*const Vector<SteelVal>),
1476 Custom(*const RwLock<Box<dyn CustomType>>),
1477 HashMapV(*const HashMap<SteelVal, SteelVal>),
1478 HashSetV(*const HashSet<SteelVal>),
1479 CustomStruct(*const UserDefinedStruct),
1480 IterV(*const Transducer),
1481 ReducerV(*const Reducer),
1482 StreamV(*const LazyStream),
1483 ContinuationFunction(*const RwLock<ContinuationMark>),
1484 ListV(crate::values::lists::CellPointer<SteelVal>),
1485 Pair(*const crate::values::lists::Pair),
1486 MutableVector(HeapRef<Vec<SteelVal>>),
1487 SyntaxObject(*const Syntax),
1488 BoxedIterator(*const RwLock<OpaqueIterator>),
1489 Boxed(*const RwLock<SteelVal>),
1490 HeapAllocated(HeapRef<SteelVal>),
1491}
1492
1493#[cfg(feature = "sync")]
1494unsafe impl Sync for SteelValPointer {}
1495#[cfg(feature = "sync")]
1496unsafe impl Send for SteelValPointer {}
1497
1498#[cfg(feature = "sync")]
1499impl SteelValPointer {
1500 pub(crate) fn from_value(value: &SteelVal) -> Option<Self> {
1501 match value {
1502 Closure(gc) => Some(Self::Closure(gc.as_ptr())),
1503 VectorV(steel_vector) => Some(Self::VectorV(steel_vector.0.as_ptr())),
1504 SteelVal::Custom(gc) => Some(Self::Custom(gc.as_ptr())),
1505 HashMapV(steel_hash_map) => Some(Self::HashMapV(steel_hash_map.0.as_ptr())),
1506 HashSetV(steel_hash_set) => Some(Self::HashSetV(steel_hash_set.0.as_ptr())),
1507 CustomStruct(gc) => Some(Self::CustomStruct(gc.as_ptr())),
1508 IterV(gc) => Some(Self::IterV(gc.as_ptr())),
1509 ReducerV(gc) => Some(Self::ReducerV(gc.as_ptr())),
1510 StreamV(gc) => Some(Self::StreamV(gc.as_ptr())),
1511 ListV(generic_list) => Some(Self::ListV(generic_list.as_ptr())),
1512 Pair(gc) => Some(Self::Pair(gc.as_ptr())),
1513 SteelVal::ContinuationFunction(continuation) => Some(Self::ContinuationFunction(
1514 crate::gc::shared::StandardShared::as_ptr(&continuation.inner),
1515 )),
1516 MutableVector(heap_ref) => Some(Self::MutableVector(heap_ref.clone())),
1518 BoxedIterator(gc) => Some(Self::BoxedIterator(gc.as_ptr())),
1519 SteelVal::SyntaxObject(gc) => Some(Self::SyntaxObject(gc.as_ptr())),
1520 Boxed(gc) => Some(Self::Boxed(gc.as_ptr())),
1521 HeapAllocated(heap_ref) => Some(Self::HeapAllocated(heap_ref.clone())),
1523 _ => None,
1524 }
1525 }
1526}
1527
1528#[cfg(feature = "sync")]
1529#[test]
1530fn check_send_sync() {
1531 let value = SteelVal::IntV(10);
1532
1533 let handle = std::thread::spawn(move || value);
1534
1535 handle.join().unwrap();
1536}
1537
1538#[derive(Clone, Debug)]
1539pub struct SteelByteVector {
1540 pub(crate) vec: GcMut<Vec<u8>>,
1541}
1542
1543impl SteelByteVector {
1544 pub fn new(vec: Vec<u8>) -> Self {
1545 Self {
1546 vec: Gc::new_mut(vec),
1547 }
1548 }
1549}
1550
1551impl PartialEq for SteelByteVector {
1552 fn eq(&self, other: &Self) -> bool {
1553 *(self.vec.read()) == *(other.vec.read())
1554 }
1555}
1556
1557impl Eq for SteelByteVector {}
1558
1559impl Hash for SteelByteVector {
1560 fn hash<H: Hasher>(&self, state: &mut H) {
1561 self.vec.read().hash(state);
1562 }
1563}
1564
1565#[derive(Clone, Debug, Hash, PartialEq)]
1570pub struct SteelComplex {
1571 pub re: SteelVal,
1573 pub im: SteelVal,
1575}
1576
1577impl SteelComplex {
1578 pub fn new(real: SteelVal, imaginary: SteelVal) -> SteelComplex {
1579 SteelComplex {
1580 re: real,
1581 im: imaginary,
1582 }
1583 }
1584
1585 pub(crate) fn imaginary_is_negative(&self) -> bool {
1587 match &self.im {
1588 NumV(x) => x.is_negative(),
1589 IntV(x) => x.is_negative(),
1590 Rational(x) => x.is_negative(),
1591 BigNum(x) => x.is_negative(),
1592 SteelVal::BigRational(x) => x.is_negative(),
1593 _ => unreachable!(),
1594 }
1595 }
1596
1597 pub(crate) fn imaginary_is_finite(&self) -> bool {
1598 match &self.im {
1599 NumV(x) => x.is_finite(),
1600 IntV(_) | Rational(_) | BigNum(_) | SteelVal::BigRational(_) => true,
1601 _ => unreachable!(),
1602 }
1603 }
1604}
1605
1606impl IntoSteelVal for SteelComplex {
1607 #[inline(always)]
1608 fn into_steelval(self) -> Result<SteelVal> {
1609 Ok(match self.im {
1610 NumV(n) if n.is_zero() => self.re,
1611 IntV(0) => self.re,
1612 _ => SteelVal::Complex(Gc::new(self)),
1613 })
1614 }
1615}
1616
1617impl fmt::Display for SteelComplex {
1618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1619 if self.imaginary_is_negative() || !self.imaginary_is_finite() {
1620 write!(f, "{re}{im}i", re = self.re, im = self.im)
1621 } else {
1622 write!(f, "{re}+{im}i", re = self.re, im = self.im)
1623 }
1624 }
1625}
1626
1627impl SteelVal {
1628 pub fn new_dyn_writer_port(port: impl Write + Send + Sync + 'static) -> SteelVal {
1630 SteelVal::PortV(SteelPort {
1631 port: Gc::new_lock(SteelPortRepr::DynWriter(Arc::new(Mutex::new(port)))),
1632 })
1633 }
1634
1635 pub fn anonymous_boxed_function(
1636 function: alloc::sync::Arc<
1637 dyn Fn(&[SteelVal]) -> crate::rvals::Result<SteelVal> + Send + Sync + 'static,
1638 >,
1639 ) -> SteelVal {
1640 SteelVal::BoxedFunction(Gc::new(BoxedDynFunction {
1641 function,
1642 name: None,
1643 arity: None,
1644 }))
1645 }
1646
1647 pub fn as_box(&self) -> Option<HeapRef<SteelVal>> {
1648 if let SteelVal::HeapAllocated(heap_ref) = self {
1649 Some(heap_ref.clone())
1650 } else {
1651 None
1652 }
1653 }
1654
1655 pub fn as_box_to_inner(&self) -> Option<SteelVal> {
1656 self.as_box().map(|x| x.get())
1657 }
1658
1659 pub fn as_ptr_usize(&self) -> Option<usize> {
1660 match self {
1661 Closure(l) => Some(l.as_ptr() as usize),
1662 VectorV(v) => Some(v.0.as_ptr() as usize),
1663 StringV(s) => Some(s.0.as_ptr() as usize),
1665 FuncV(_) => todo!(),
1666 HashMapV(h) => Some(h.0.as_ptr() as usize),
1669 HashSetV(h) => Some(h.0.as_ptr() as usize),
1670 CustomStruct(c) => Some(c.as_ptr() as usize),
1671 ListV(l) => Some(l.as_ptr_usize()),
1680 MutableVector(v) => Some(v.as_ptr_usize()),
1681 Custom(c) => Some(c.as_ptr() as usize),
1682 Boxed(b) => Some(b.as_ptr() as usize),
1685 HeapAllocated(h) => Some(h.as_ptr_usize()),
1686 Pair(p) => Some(p.as_ptr() as usize),
1687 SyntaxObject(s) => Some(s.as_ptr() as usize),
1688 BigNum(b) => Some(b.as_ptr() as usize),
1690 _ => None,
1691 }
1692 }
1693
1694 }
1707
1708#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1791#[repr(C)]
1792pub struct SteelString(pub(crate) Gc<String>);
1793
1794impl Deref for SteelString {
1795 type Target = crate::gc::Shared<String>;
1796
1797 fn deref(&self) -> &Self::Target {
1798 &self.0 .0
1799 }
1800}
1801
1802#[cfg(not(feature = "sync"))]
1803impl From<Arc<String>> for SteelString {
1804 fn from(value: Arc<String>) -> Self {
1805 SteelString(Gc(Rc::new((*value).clone())))
1806 }
1807}
1808
1809#[cfg(all(feature = "sync", feature = "triomphe", not(feature = "biased")))]
1810impl From<Arc<String>> for SteelString {
1811 fn from(value: Arc<String>) -> Self {
1812 SteelString(Gc(triomphe::Arc::new((*value).clone())))
1813 }
1814}
1815
1816#[cfg(all(feature = "sync", feature = "biased", not(feature = "triomphe")))]
1817impl From<Arc<String>> for SteelString {
1818 fn from(value: Arc<String>) -> Self {
1819 SteelString(Gc(steel_rc::BiasedRc::new((*value).clone())))
1820 }
1821}
1822
1823impl From<&str> for SteelString {
1824 fn from(val: &str) -> Self {
1825 SteelString(Gc::new(val.to_string()))
1826 }
1827}
1828
1829impl From<&String> for SteelString {
1830 fn from(val: &String) -> Self {
1831 SteelString(Gc::new(val.to_owned()))
1832 }
1833}
1834
1835impl From<String> for SteelString {
1836 fn from(val: String) -> Self {
1837 SteelString(Gc::new(val))
1838 }
1839}
1840
1841impl From<crate::gc::Shared<String>> for SteelString {
1842 fn from(val: crate::gc::Shared<String>) -> Self {
1843 SteelString(Gc(val))
1844 }
1845}
1846
1847impl From<Gc<String>> for SteelString {
1848 fn from(val: Gc<String>) -> Self {
1849 SteelString(val)
1850 }
1851}
1852
1853impl From<SteelString> for crate::gc::Shared<String> {
1854 fn from(value: SteelString) -> Self {
1855 value.0 .0
1856 }
1857}
1858
1859impl From<SteelString> for Gc<String> {
1860 fn from(value: SteelString) -> Self {
1861 value.0
1862 }
1863}
1864
1865impl core::fmt::Display for SteelString {
1866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1867 write!(f, "{}", self.0.as_str())
1868 }
1869}
1870
1871impl core::fmt::Debug for SteelString {
1872 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1873 write!(f, "{:?}", self.0.as_str())
1874 }
1875}
1876
1877const _ASSERT_SMALL: () = assert!(core::mem::size_of::<SteelVal>() <= 16);
1879
1880#[test]
1881fn check_size_of_steelval() {
1882 assert_eq!(core::mem::size_of::<SteelVal>(), 16);
1883}
1884
1885pub struct Chunks {
1886 remaining: IntoIter<char>,
1887}
1888
1889impl Chunks {
1890 fn new(s: SteelString) -> Self {
1891 Chunks {
1892 remaining: s.chars().collect::<Vec<_>>().into_iter(),
1893 }
1894 }
1895}
1896
1897pub struct OpaqueIterator {
1898 pub(crate) root: SteelVal,
1899 iterator: BuiltInDataStructureIterator,
1900}
1901
1902impl Custom for OpaqueIterator {
1903 fn fmt(&self) -> Option<core::result::Result<String, core::fmt::Error>> {
1904 Some(Ok("#<iterator>".to_owned()))
1905 }
1906}
1907
1908pub enum BuiltInDataStructureIterator {
1911 List(crate::values::lists::ConsumingIterator<SteelVal>),
1912 Vector(VectorConsumingIter<SteelVal>),
1913 Set(HashSetConsumingIter<SteelVal>),
1914 Map(HashMapConsumingIter<SteelVal, SteelVal>),
1915 String(Chunks),
1916 #[cfg(not(feature = "sync"))]
1917 Opaque(Box<dyn Iterator<Item = SteelVal>>),
1918 #[cfg(feature = "sync")]
1919 Opaque(Box<dyn Iterator<Item = SteelVal> + Send + Sync + 'static>),
1920}
1921
1922impl BuiltInDataStructureIterator {
1923 pub fn into_boxed_iterator(self, value: SteelVal) -> SteelVal {
1924 SteelVal::BoxedIterator(Gc::new_mut(OpaqueIterator {
1925 root: value,
1926 iterator: self,
1927 }))
1928 }
1929}
1930
1931impl BuiltInDataStructureIterator {
1932 pub fn from_iterator<
1933 T: IntoSteelVal + MaybeSendSyncStatic,
1934 I: Iterator<Item = T> + MaybeSendSyncStatic,
1935 S: IntoIterator<Item = T, IntoIter = I> + MaybeSendSyncStatic,
1936 >(
1937 value: S,
1938 ) -> Self {
1939 Self::Opaque(Box::new(
1940 value
1941 .into_iter()
1942 .map(|x| x.into_steelval().expect("This shouldn't fail!")),
1943 ))
1944 }
1945}
1946
1947impl Iterator for BuiltInDataStructureIterator {
1948 type Item = SteelVal;
1949
1950 fn next(&mut self) -> Option<SteelVal> {
1951 match self {
1952 Self::List(l) => l.next(),
1953 Self::Vector(v) => v.next(),
1954 Self::String(s) => s.remaining.next().map(SteelVal::CharV),
1955 Self::Set(s) => s.next(),
1956 Self::Map(s) => s
1957 .next()
1958 .map(|x| SteelVal::Pair(Gc::new(Pair::cons(x.0, x.1)))),
1959 Self::Opaque(s) => s.next(),
1960 }
1961 }
1962}
1963
1964pub fn value_into_iterator(val: SteelVal) -> Option<SteelVal> {
1965 let root = val.clone();
1966 match val {
1967 SteelVal::ListV(l) => Some(BuiltInDataStructureIterator::List(l.into_iter())),
1968 SteelVal::VectorV(v) => Some(BuiltInDataStructureIterator::Vector(
1969 (*v).clone().into_iter(),
1970 )),
1971 SteelVal::StringV(s) => Some(BuiltInDataStructureIterator::String(Chunks::new(s))),
1972 SteelVal::HashSetV(s) => Some(BuiltInDataStructureIterator::Set((*s).clone().into_iter())),
1973 SteelVal::HashMapV(m) => Some(BuiltInDataStructureIterator::Map((*m).clone().into_iter())),
1974 _ => None,
1976 }
1977 .map(|iterator| BuiltInDataStructureIterator::into_boxed_iterator(iterator, root))
1978}
1979
1980thread_local! {
1981 pub static ITERATOR_FINISHED: SteelVal = SteelVal::SymbolV("done".into());
1982}
1983
1984pub fn iterator_next(args: &[SteelVal]) -> Result<SteelVal> {
1985 match &args[0] {
1986 SteelVal::BoxedIterator(b) => match b.write().iterator.next() {
1987 Some(v) => Ok(v),
1988 None => Ok(ITERATOR_FINISHED.with(|x| x.clone())),
1989 },
1990 _ => stop!(TypeMismatch => "Unexpected argument"),
1991 }
1992}
1993
1994impl SteelVal {
1995 pub fn boxed(value: SteelVal) -> SteelVal {
1996 SteelVal::Boxed(Gc::new_mut(value))
1997 }
1998
1999 pub(crate) fn ptr_eq(&self, other: &SteelVal) -> bool {
2000 match (self, other) {
2001 (IntV(l), IntV(r)) => l == r,
2003 (NumV(l), NumV(r)) => l == r,
2004 (BoolV(l), BoolV(r)) => l == r,
2005 (CharV(l), CharV(r)) => l == r,
2006 (VectorV(l), VectorV(r)) => Gc::ptr_eq(&l.0, &r.0),
2007 (Void, Void) => true,
2008 (StringV(l), StringV(r)) => crate::gc::Shared::ptr_eq(l, r),
2009 (FuncV(l), FuncV(r)) => *l as usize == *r as usize,
2010 (SymbolV(l), SymbolV(r)) => crate::gc::Shared::ptr_eq(l, r),
2011 (SteelVal::Custom(l), SteelVal::Custom(r)) => Gc::ptr_eq(l, r),
2012 (HashMapV(l), HashMapV(r)) => Gc::ptr_eq(&l.0, &r.0),
2013 (HashSetV(l), HashSetV(r)) => Gc::ptr_eq(&l.0, &r.0),
2014 (PortV(l), PortV(r)) => Gc::ptr_eq(&l.port, &r.port),
2015 (Closure(l), Closure(r)) => Gc::ptr_eq(l, r),
2016 (IterV(l), IterV(r)) => Gc::ptr_eq(l, r),
2017 (ReducerV(l), ReducerV(r)) => Gc::ptr_eq(l, r),
2018 (FutureFunc(l), FutureFunc(r)) => crate::gc::Shared::ptr_eq(l, r),
2019 (FutureV(l), FutureV(r)) => Gc::ptr_eq(l, r),
2020 (StreamV(l), StreamV(r)) => Gc::ptr_eq(l, r),
2021 (BoxedFunction(l), BoxedFunction(r)) => Gc::ptr_eq(l, r),
2022 (ContinuationFunction(l), ContinuationFunction(r)) => Continuation::ptr_eq(l, r),
2023 (ListV(l), ListV(r)) => {
2024 l.ptr_eq(r) || l.storage_ptr_eq(r) || (l.is_empty() && r.is_empty()) || {
2026 slow_path_eq_lists(l, r)
2027 }
2028 }
2029 (MutFunc(l), MutFunc(r)) => *l as usize == *r as usize,
2030 (BuiltIn(l), BuiltIn(r)) => *l as usize == *r as usize,
2031 (MutableVector(l), MutableVector(r)) => HeapRef::ptr_eq(l, r),
2032 (BigNum(l), BigNum(r)) => Gc::ptr_eq(l, r),
2033 (ByteVector(l), ByteVector(r)) => Gc::ptr_eq(&l.vec, &r.vec),
2034 (Pair(l), Pair(r)) => Gc::ptr_eq(l, r),
2035 (_, _) => {
2036 false
2038 }
2039 }
2040 }
2041}
2042
2043#[inline]
2046fn slow_path_eq_lists(
2047 _l: &crate::values::lists::List<SteelVal>,
2048 _r: &crate::values::lists::List<SteelVal>,
2049) -> bool {
2050 false
2051
2052 }
2084
2085impl Hash for SteelVal {
2086 fn hash<H: Hasher>(&self, state: &mut H) {
2087 core::mem::discriminant(self).hash(state);
2088 match self {
2089 Closure(b) => b.hash(state),
2090 BoolV(b) => b.hash(state),
2091 NumV(n) => n.to_string().hash(state),
2092 IntV(i) => i.hash(state),
2093 Rational(f) => f.hash(state),
2094 CharV(c) => c.hash(state),
2095 VectorV(v) => v.hash(state),
2096 Void => {}
2097 StringV(s) => s.hash(state),
2098 FuncV(s) => s.hash(state),
2099 SymbolV(sym) => sym.hash(state),
2100 #[cfg(feature = "custom-hash")]
2101 Custom(v) => match v.read().try_as_dyn_hash() {
2102 Some(x) => x.dyn_hash(state),
2103 _ => Gc::as_ptr(v).hash(state),
2104 },
2105 #[cfg(not(feature = "custom-hash"))]
2106 Custom(v) => Gc::as_ptr(v).hash(state),
2107 HashMapV(hm) => hm.hash(state),
2108 HashSetV(hs) => hs.hash(state),
2109 CustomStruct(s) => s.hash(state),
2110 PortV(port) => port.hash(state),
2111 IterV(s) => s.hash(state),
2112 ReducerV(r) => r.hash(state),
2113 FutureFunc(fun) => crate::gc::Shared::as_ptr(fun).hash(state),
2114 FutureV(f) => Gc::as_ptr(f).hash(state),
2115 StreamV(s) => Gc::as_ptr(s).hash(state),
2116 BoxedFunction(fun) => Gc::as_ptr(fun).hash(state),
2117 ContinuationFunction(cont) => StandardShared::as_ptr(&cont.inner).hash(state),
2118 ListV(l) => l.hash(state),
2119 Pair(p) => (**p).hash(state),
2120 MutFunc(fun) => fun.hash(state),
2121 BuiltIn(fun) => fun.hash(state),
2122 MutableVector(vec) => vec.get().hash(state),
2123 BoxedIterator(iter) => Gc::as_ptr(iter).hash(state),
2124 SyntaxObject(s) => s.raw.hash(state),
2125 Boxed(val) => val.read().hash(state),
2126 HeapAllocated(v) => v.get().hash(state),
2127 Reference(v) => Gc::as_ptr(v).hash(state),
2128 BigNum(n) => n.hash(state),
2129 BigRational(f) => f.hash(state),
2130 Complex(x) => x.hash(state),
2131 ByteVector(v) => (*v).hash(state),
2132 }
2133 }
2134}
2135
2136impl SteelVal {
2137 #[inline(always)]
2138 pub fn is_truthy(&self) -> bool {
2139 match &self {
2140 SteelVal::BoolV(false) => false,
2141 _ => true,
2142 }
2143 }
2144
2145 #[inline(always)]
2146 pub fn is_future(&self) -> bool {
2147 matches!(self, SteelVal::FutureV(_))
2148 }
2149
2150 pub fn is_function(&self) -> bool {
2151 matches!(
2152 self,
2153 BoxedFunction(_)
2154 | Closure(_)
2155 | FuncV(_)
2156 | BuiltIn(_)
2158 | MutFunc(_)
2159 )
2160 }
2161
2162 pub fn empty_hashmap() -> SteelVal {
2167 SteelVal::HashMapV(Gc::new(HashMap::new()).into())
2168 }
2169}
2170
2171impl SteelVal {
2172 pub fn list_or_else<E, F: FnOnce() -> E>(
2175 &self,
2176 err: F,
2177 ) -> core::result::Result<&List<SteelVal>, E> {
2178 match self {
2179 Self::ListV(v) => Ok(v),
2180 _ => Err(err()),
2181 }
2182 }
2183
2184 pub fn list(&self) -> Option<&List<SteelVal>> {
2185 match self {
2186 Self::ListV(l) => Some(l),
2187 _ => None,
2188 }
2189 }
2190
2191 pub fn pair(&self) -> Option<&Gc<crate::values::lists::Pair>> {
2192 match self {
2193 Self::Pair(p) => Some(p),
2194 _ => None,
2195 }
2196 }
2197
2198 pub fn bool_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<bool, E> {
2199 match self {
2200 Self::BoolV(v) => Ok(*v),
2201 _ => Err(err()),
2202 }
2203 }
2204
2205 pub fn int_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<isize, E> {
2206 match self {
2207 Self::IntV(v) => Ok(*v),
2208 _ => Err(err()),
2209 }
2210 }
2211
2212 pub fn num_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<f64, E> {
2213 match self {
2214 Self::NumV(v) => Ok(*v),
2215 _ => Err(err()),
2216 }
2217 }
2218
2219 pub fn char_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<char, E> {
2220 match self {
2221 Self::CharV(v) => Ok(*v),
2222 _ => Err(err()),
2223 }
2224 }
2225
2226 pub fn vector_or_else<E, F: FnOnce() -> E>(
2228 &self,
2229 err: F,
2230 ) -> core::result::Result<Vector<SteelVal>, E> {
2231 match self {
2232 Self::VectorV(v) => Ok(v.0.unwrap()),
2233 _ => Err(err()),
2234 }
2235 }
2236
2237 pub fn void_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<(), E> {
2238 match self {
2239 Self::Void => Ok(()),
2240 _ => Err(err()),
2241 }
2242 }
2243
2244 pub fn string_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<&str, E> {
2245 match self {
2246 Self::StringV(v) => Ok(v),
2247 _ => Err(err()),
2248 }
2249 }
2250
2251 pub fn func_or_else<E, F: FnOnce() -> E>(
2252 &self,
2253 err: F,
2254 ) -> core::result::Result<&FunctionSignature, E> {
2255 match self {
2256 Self::FuncV(v) => Ok(v),
2257 _ => Err(err()),
2258 }
2259 }
2260
2261 pub fn boxed_func_or_else<E, F: FnOnce() -> E>(
2262 &self,
2263 err: F,
2264 ) -> core::result::Result<&BoxedDynFunction, E> {
2265 match self {
2266 Self::BoxedFunction(v) => Ok(v),
2267 _ => Err(err()),
2268 }
2269 }
2270
2271 pub fn closure_or_else<E, F: FnOnce() -> E>(
2282 &self,
2283 err: F,
2284 ) -> core::result::Result<Gc<ByteCodeLambda>, E> {
2285 match self {
2286 Self::Closure(c) => Ok(c.clone()),
2287 _ => Err(err()),
2288 }
2289 }
2290
2291 pub fn symbol_or_else<E, F: FnOnce() -> E>(&self, err: F) -> core::result::Result<&str, E> {
2292 match self {
2293 Self::SymbolV(v) => Ok(v),
2294 _ => Err(err()),
2295 }
2296 }
2297
2298 pub fn clone_symbol_or_else<E, F: FnOnce() -> E>(
2299 &self,
2300 err: F,
2301 ) -> core::result::Result<String, E> {
2302 match self {
2303 Self::SymbolV(v) => Ok(v.to_string()),
2304 _ => Err(err()),
2305 }
2306 }
2307
2308 pub fn as_isize(&self) -> Option<isize> {
2309 match self {
2310 Self::IntV(i) => Some(*i),
2311 _ => None,
2312 }
2313 }
2314
2315 pub fn as_usize(&self) -> Option<usize> {
2316 self.as_isize()
2317 .and_then(|x| if x >= 0 { Some(x as usize) } else { None })
2318 }
2319
2320 pub fn as_bool(&self) -> Option<bool> {
2321 match self {
2322 Self::BoolV(b) => Some(*b),
2323 _ => None,
2324 }
2325 }
2326
2327 pub fn as_future(&self) -> Option<Shared<BoxedFutureResult>> {
2328 match self {
2329 Self::FutureV(v) => Some(v.clone().unwrap().into_shared()),
2330 _ => None,
2331 }
2332 }
2333
2334 pub fn as_string(&self) -> Option<&SteelString> {
2335 match self {
2336 Self::StringV(s) => Some(s),
2337 _ => None,
2338 }
2339 }
2340
2341 pub fn as_symbol(&self) -> Option<&SteelString> {
2342 match self {
2343 Self::SymbolV(s) => Some(s),
2344 _ => None,
2345 }
2346 }
2347
2348 pub fn as_syntax_object(&self) -> Option<&Syntax> {
2349 match self {
2350 Self::SyntaxObject(s) => Some(s),
2351 _ => None,
2352 }
2353 }
2354
2355 pub fn closure_arity(&self) -> Option<usize> {
2376 if let SteelVal::Closure(c) = self {
2377 Some(c.arity())
2378 } else {
2379 None
2380 }
2381 }
2382}
2383
2384impl SteelVal {
2385 pub const INT_ZERO: SteelVal = SteelVal::IntV(0);
2386 pub const INT_ONE: SteelVal = SteelVal::IntV(1);
2387 pub const INT_TWO: SteelVal = SteelVal::IntV(2);
2388}
2389
2390impl Eq for SteelVal {}
2391
2392fn integer_float_equality(int: isize, float: f64) -> bool {
2393 let converted = float as isize;
2394
2395 if float == converted as f64 {
2396 int == converted
2397 } else {
2398 false
2399 }
2400}
2401
2402fn bignum_float_equality(bigint: &Gc<BigInt>, float: f64) -> bool {
2403 if float.fract() == 0.0 {
2404 if let Some(promoted) = bigint.to_f64() {
2405 promoted == float
2406 } else {
2407 false
2408 }
2409 } else {
2410 false
2411 }
2412}
2413
2414#[inline(always)]
2415#[steel_derive::function(name = "=", constant = true)]
2416pub fn number_equality(left: &SteelVal, right: &SteelVal) -> Result<SteelVal> {
2417 let result = match (left, right) {
2418 (IntV(l), IntV(r)) => l == r,
2419 (NumV(l), NumV(r)) => l == r,
2420 (IntV(l), NumV(r)) | (NumV(r), IntV(l)) => integer_float_equality(*l, *r),
2421 (Rational(l), Rational(r)) => l == r,
2422 (Rational(l), NumV(r)) | (NumV(r), Rational(l)) => l.to_f64().unwrap() == *r,
2423 (BigNum(l), BigNum(r)) => l == r,
2424 (BigNum(l), NumV(r)) | (NumV(r), BigNum(l)) => bignum_float_equality(l, *r),
2425 (BigRational(l), BigRational(r)) => l == r,
2426 (BigRational(l), NumV(r)) | (NumV(r), BigRational(l)) => l.to_f64().unwrap() == *r,
2427 (Rational(_), IntV(_))
2430 | (IntV(_), Rational(_))
2431 | (Rational(_), BigNum(_))
2432 | (BigNum(_), Rational(_))
2433 | (Rational(_), BigRational(_))
2434 | (BigRational(_), Rational(_)) => false,
2435 (BigRational(_), IntV(_))
2436 | (IntV(_), BigRational(_))
2437 | (BigRational(_), BigNum(_))
2438 | (BigNum(_), BigRational(_)) => false,
2439 (IntV(_), BigNum(_)) | (BigNum(_), IntV(_)) => false,
2440 (Complex(x), Complex(y)) => {
2441 number_equality(&x.re, &y.re)? == BoolV(true)
2442 && number_equality(&x.im, &y.re)? == BoolV(true)
2443 }
2444 (Complex(_), _) | (_, Complex(_)) => false,
2445 _ => stop!(TypeMismatch => "= expects two numbers, found: {:?} and {:?}", left, right),
2446 };
2447 Ok(BoolV(result))
2448}
2449
2450impl PartialOrd for SteelVal {
2451 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2452 match (self, other) {
2455 (IntV(x), IntV(y)) => x.partial_cmp(y),
2457 (BigNum(x), BigNum(y)) => x.partial_cmp(y),
2458 (Rational(x), Rational(y)) => x.partial_cmp(y),
2459 (BigRational(x), BigRational(y)) => x.partial_cmp(y),
2460 (NumV(x), NumV(y)) => x.partial_cmp(y),
2461 (StringV(s), StringV(o)) => s.partial_cmp(o),
2462 (CharV(l), CharV(r)) => l.partial_cmp(r),
2463
2464 (IntV(x), BigNum(y)) => x
2466 .to_bigint()
2467 .expect("integers are representable by bigint")
2468 .partial_cmp(y),
2469 (IntV(x), Rational(y)) => {
2470 #[cfg(target_pointer_width = "32")]
2473 {
2474 let x_rational = num_rational::Rational32::new_raw(*x as i32, 1);
2475 x_rational.partial_cmp(y)
2476 }
2477 #[cfg(target_pointer_width = "64")]
2478 {
2479 let x_rational = num_rational::Rational64::new_raw(*x as i64, 1);
2480 x_rational.partial_cmp(&num_rational::Rational64::new_raw(
2481 *y.numer() as i64,
2482 *y.denom() as i64,
2483 ))
2484 }
2485 }
2486 (IntV(x), BigRational(y)) => {
2487 let x_rational = BigRational::from_integer(
2488 x.to_bigint().expect("integers are representable by bigint"),
2489 );
2490 x_rational.partial_cmp(y)
2491 }
2492 (IntV(x), NumV(y)) => (*x as f64).partial_cmp(y),
2493
2494 (BigNum(x), IntV(y)) => x
2497 .as_ref()
2498 .partial_cmp(&y.to_bigint().expect("integers are representable by bigint")),
2499 (BigNum(x), Rational(y)) => {
2500 let x_big_rational = BigRational::from_integer(x.unwrap());
2501 let y_big_rational = BigRational::new_raw(
2502 y.numer()
2503 .to_bigint()
2504 .expect("integers are representable by bigint"),
2505 y.denom()
2506 .to_bigint()
2507 .expect("integers are representable by bigint"),
2508 );
2509 x_big_rational.partial_cmp(&y_big_rational)
2510 }
2511 (BigNum(x), BigRational(y)) => {
2512 let x_big_rational = BigRational::from_integer(x.unwrap());
2513 x_big_rational.partial_cmp(y)
2514 }
2515 (BigNum(x), NumV(y)) => {
2516 let x_decimal = BigDecimal::new(x.unwrap(), 0);
2517 let y_decimal_opt = BigDecimal::from_f64(*y);
2518 y_decimal_opt.and_then(|y_decimal| x_decimal.partial_cmp(&y_decimal))
2519 }
2520
2521 (Rational(x), IntV(y)) => {
2523 #[cfg(target_pointer_width = "32")]
2525 {
2526 let y_rational = num_rational::Rational32::new_raw(*y as i32, 1);
2527 x.partial_cmp(&y_rational)
2528 }
2529 #[cfg(target_pointer_width = "64")]
2530 {
2531 let y_rational = num_rational::Rational64::new_raw(*y as i64, 1);
2532 num_rational::Rational64::new_raw(*x.numer() as i64, *x.denom() as i64)
2533 .partial_cmp(&y_rational)
2534 }
2535 }
2536 (Rational(x), BigNum(y)) => {
2537 let x_big_rational = BigRational::new_raw(
2538 x.numer()
2539 .to_bigint()
2540 .expect("integers are representable by bigint"),
2541 x.denom()
2542 .to_bigint()
2543 .expect("integers are representable by bigint"),
2544 );
2545 let y_big_rational = BigRational::from_integer(y.unwrap());
2546 x_big_rational.partial_cmp(&y_big_rational)
2547 }
2548 (Rational(x), BigRational(y)) => {
2549 let x_big_rational = BigRational::new_raw(
2550 x.numer()
2551 .to_bigint()
2552 .expect("integers are representable by bigint"),
2553 x.denom()
2554 .to_bigint()
2555 .expect("integers are representable by bigint"),
2556 );
2557 x_big_rational.partial_cmp(y)
2558 }
2559 (Rational(x), NumV(y)) => (*x.numer() as f64 / *x.denom() as f64).partial_cmp(y),
2560
2561 (BigRational(x), IntV(y)) => {
2563 let y_rational = BigRational::from_integer(
2564 y.to_bigint().expect("integers are representable by bigint"),
2565 );
2566 x.as_ref().partial_cmp(&y_rational)
2567 }
2568 (BigRational(x), BigNum(y)) => {
2569 let y_big_rational = BigRational::from_integer(y.unwrap());
2570 x.as_ref().partial_cmp(&y_big_rational)
2571 }
2572 (BigRational(x), Rational(y)) => {
2573 let y_big_rational = BigRational::new_raw(
2574 y.numer()
2575 .to_bigint()
2576 .expect("integers are representable by bigint"),
2577 y.denom()
2578 .to_bigint()
2579 .expect("integers are representable by bigint"),
2580 );
2581 x.as_ref().partial_cmp(&y_big_rational)
2582 }
2583 (BigRational(x), NumV(y)) => {
2584 let x_decimal =
2585 BigDecimal::new(x.numer().clone(), 0) / BigDecimal::new(x.denom().clone(), 0);
2586 let y_decimal_opt = BigDecimal::from_f64(*y);
2587 y_decimal_opt.and_then(|y_decimal| x_decimal.partial_cmp(&y_decimal))
2588 }
2589
2590 (NumV(x), IntV(y)) => x.partial_cmp(&(*y as f64)),
2592 (NumV(x), BigNum(y)) => {
2593 let x_decimal_opt = BigDecimal::from_f64(*x);
2594 let y_decimal = BigDecimal::new(y.unwrap(), 0);
2595 x_decimal_opt.and_then(|x_decimal| x_decimal.partial_cmp(&y_decimal))
2596 }
2597 (NumV(x), Rational(y)) => x.partial_cmp(&(*y.numer() as f64 / *y.denom() as f64)),
2598 (NumV(x), BigRational(y)) => {
2599 let x_decimal_opt = BigDecimal::from_f64(*x);
2600 let y_decimal =
2601 BigDecimal::new(y.numer().clone(), 0) / BigDecimal::new(y.denom().clone(), 0);
2602 x_decimal_opt.and_then(|x_decimal| x_decimal.partial_cmp(&y_decimal))
2603 }
2604
2605 (l, r) => {
2606 debug_assert!(
2608 !(realp(l) && realp(r)),
2609 "Numbers {l:?} and {r:?} should implement partial_cmp"
2610 );
2611 None
2613 }
2614 }
2615 }
2616}
2617
2618pub(crate) struct SteelValDisplay<'a>(pub(crate) &'a SteelVal);
2619
2620impl<'a> fmt::Display for SteelValDisplay<'a> {
2621 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2622 CycleDetector::detect_and_display_cycles(self.0, f, false)
2623 }
2624}
2625
2626impl fmt::Display for SteelVal {
2627 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2628 CycleDetector::detect_and_display_cycles(self, f, true)
2629 }
2630}
2631
2632impl fmt::Debug for SteelVal {
2633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2634 match self {
2637 SymbolV(_) | ListV(_) | VectorV(_) => write!(f, "'")?,
2638 _ => (),
2639 };
2640 CycleDetector::detect_and_display_cycles(self, f, true)
2643 }
2644}
2645
2646#[cfg(test)]
2647mod or_else_tests {
2648
2649 use super::*;
2650
2651 #[cfg(all(feature = "sync", not(feature = "imbl")))]
2652 use im::vector;
2653
2654 #[cfg(all(feature = "sync", feature = "imbl"))]
2655 use steel_imbl::generic_vector as vector;
2656
2657 #[cfg(not(feature = "sync"))]
2658 use im_rc::vector;
2659
2660 #[test]
2661 fn bool_or_else_test_good() {
2662 let input = SteelVal::BoolV(true);
2663 assert_eq!(input.bool_or_else(throw!(Generic => "test")).unwrap(), true);
2664 }
2665
2666 #[test]
2667 fn bool_or_else_test_bad() {
2668 let input = SteelVal::CharV('f');
2669 assert!(input.bool_or_else(throw!(Generic => "test")).is_err());
2670 }
2671
2672 #[test]
2673 fn num_or_else_test_good() {
2674 let input = SteelVal::NumV(10.0);
2675 assert_eq!(input.num_or_else(throw!(Generic => "test")).unwrap(), 10.0);
2676 }
2677
2678 #[test]
2679 fn num_or_else_test_bad() {
2680 let input = SteelVal::CharV('f');
2681 assert!(input.num_or_else(throw!(Generic => "test")).is_err());
2682 }
2683
2684 #[test]
2685 fn char_or_else_test_good() {
2686 let input = SteelVal::CharV('f');
2687 assert_eq!(input.char_or_else(throw!(Generic => "test")).unwrap(), 'f');
2688 }
2689
2690 #[test]
2691 fn char_or_else_test_bad() {
2692 let input = SteelVal::NumV(10.0);
2693 assert!(input.char_or_else(throw!(Generic => "test")).is_err());
2694 }
2695
2696 #[test]
2697 fn vector_or_else_test_good() {
2698 let input: SteelVal = vector![SteelVal::IntV(1)].into();
2699 assert_eq!(
2700 input.vector_or_else(throw!(Generic => "test")).unwrap(),
2701 vector![SteelVal::IntV(1)]
2702 );
2703 }
2704
2705 #[test]
2706 fn vector_or_else_bad() {
2707 let input = SteelVal::CharV('f');
2708 assert!(input.vector_or_else(throw!(Generic => "test")).is_err());
2709 }
2710
2711 #[test]
2712 fn void_or_else_test_good() {
2713 let input = SteelVal::Void;
2714 assert_eq!(input.void_or_else(throw!(Generic => "test")).unwrap(), ())
2715 }
2716
2717 #[test]
2718 fn void_or_else_test_bad() {
2719 let input = SteelVal::StringV("foo".into());
2720 assert!(input.void_or_else(throw!(Generic => "test")).is_err());
2721 }
2722
2723 #[test]
2724 fn string_or_else_test_good() {
2725 let input = SteelVal::StringV("foo".into());
2726 assert_eq!(
2727 input.string_or_else(throw!(Generic => "test")).unwrap(),
2728 "foo".to_string()
2729 );
2730 }
2731
2732 #[test]
2733 fn string_or_else_test_bad() {
2734 let input = SteelVal::Void;
2735 assert!(input.string_or_else(throw!(Generic => "test")).is_err())
2736 }
2737
2738 #[test]
2739 fn symbol_or_else_test_good() {
2740 let input = SteelVal::SymbolV("foo".into());
2741 assert_eq!(
2742 input.symbol_or_else(throw!(Generic => "test")).unwrap(),
2743 "foo".to_string()
2744 );
2745 }
2746
2747 #[test]
2748 fn symbol_or_else_test_bad() {
2749 let input = SteelVal::Void;
2750 assert!(input.symbol_or_else(throw!(Generic => "test")).is_err())
2751 }
2752
2753 #[test]
2754 fn num_and_char_are_not_ordered() {
2755 assert_eq!(SteelVal::IntV(0).partial_cmp(&SteelVal::CharV('0')), None);
2756 assert_eq!(SteelVal::NumV(0.0).partial_cmp(&SteelVal::CharV('0')), None);
2757 assert_eq!(
2758 SteelVal::BigNum(Gc::new(BigInt::default())).partial_cmp(&SteelVal::CharV('0')),
2759 None
2760 );
2761 }
2762
2763 #[test]
2764 fn number_cmp() {
2765 let less_cases = [
2766 (SteelVal::IntV(-10), SteelVal::IntV(1)),
2767 (
2768 SteelVal::IntV(-10),
2769 SteelVal::BigNum(Gc::new(BigInt::from(1))),
2770 ),
2771 (SteelVal::NumV(-10.0), SteelVal::IntV(1)),
2772 (SteelVal::IntV(-10), SteelVal::NumV(1.0)),
2773 (
2774 SteelVal::BigNum(Gc::new(BigInt::from(-10))),
2775 SteelVal::BigNum(Gc::new(BigInt::from(1))),
2776 ),
2777 (
2778 SteelVal::NumV(-10.0),
2779 SteelVal::BigNum(Gc::new(BigInt::from(1))),
2780 ),
2781 ];
2782 for (l, r) in less_cases {
2783 assert_eq!(l.partial_cmp(&r), Some(Ordering::Less));
2784 assert_eq!(r.partial_cmp(&l), Some(Ordering::Greater));
2785 }
2786 let equal_cases = [
2787 SteelVal::IntV(-10),
2788 SteelVal::NumV(-10.0),
2789 SteelVal::BigNum(Gc::new(BigInt::from(-10))),
2790 SteelVal::BigNum(Gc::new(BigInt::from(-10))),
2792 ]
2793 .into_iter();
2794 for (l, r) in equal_cases.clone().zip(equal_cases.clone()) {
2795 assert_eq!(l.partial_cmp(&r), Some(Ordering::Equal));
2796 }
2797 }
2798}