1use crate::{
2 continuation::Continuation,
3 error::RuntimeError,
4 gc::{Gc, Trace},
5 value::Value,
6};
7use num::{complex::Complex64, FromPrimitive, ToPrimitive, Zero};
8use scheme_rs_macros::builtin;
9use rug::{Complete, Integer, Rational};
10use std::{
11 cmp::Ordering,
12 fmt,
13 ops::{Add, Div, Mul, Neg, Sub},
14 sync::Arc,
15};
16
17#[derive(Debug, Clone)]
18pub enum Number {
19 FixedInteger(i64),
20 BigInteger(Integer),
21 Rational(Rational),
22 Real(f64),
23 Complex(Complex64),
24}
25
26impl Number {
27 fn is_zero(&self) -> bool {
28 match self {
29 Self::FixedInteger(i) => i.is_zero(),
30 Self::BigInteger(i) => i.is_zero(),
31 Self::Rational(r) => r.is_zero(),
32 Self::Real(r) => r.is_zero(),
33 Self::Complex(c) => c.is_zero(),
34 }
35 }
36
37 fn is_even(&self) -> bool {
38 use num::Integer;
39 match self {
40 Self::FixedInteger(i) => i.is_even(),
41 Self::BigInteger(i) => i.is_even(),
42 Self::Rational(_) => false,
43 Self::Real(_) => false,
44 Self::Complex(_) => false,
45 }
46 }
47
48 fn is_odd(&self) -> bool {
49 use num::Integer;
50 match self {
51 Self::FixedInteger(i) => i.is_odd(),
52 Self::BigInteger(i) => i.is_odd(),
53 Self::Rational(_) => false,
54 Self::Real(_) => false,
55 Self::Complex(_) => false,
56 }
57 }
58
59 fn is_complex(&self) -> bool {
60 matches!(self, Self::Complex(_))
61 }
62
63 pub fn to_u64(&self) -> u64 {
64 match self {
65 Self::FixedInteger(i) => i.to_u64().unwrap_or(0),
66 Self::BigInteger(i) => i.to_u64().unwrap_or(0),
67 Self::Rational(r) => r.to_u64().unwrap_or(0),
68 Self::Real(r) => r.to_u64().unwrap_or(0),
69 Self::Complex(c) => c.to_u64().unwrap_or(0),
70 }
71 }
72}
73
74impl From<i64> for Number {
75 fn from(i: i64) -> Self {
76 Self::FixedInteger(i)
77 }
78}
79
80impl From<Integer> for Number {
81 fn from(i: Integer) -> Self {
82 Self::BigInteger(i)
83 }
84}
85
86impl From<Rational> for Number {
87 fn from(r: Rational) -> Self {
88 Self::Rational(r)
89 }
90}
91
92impl From<f64> for Number {
93 fn from(r: f64) -> Self {
94 Self::Real(r)
95 }
96}
97
98impl From<Complex64> for Number {
99 fn from(c: Complex64) -> Self {
100 Self::Complex(c)
101 }
102}
103
104impl fmt::Display for Number {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 match self {
107 Self::FixedInteger(i) => write!(f, "{}", i),
108 Self::BigInteger(i) => write!(f, "{}", i),
109 Self::Rational(r) => write!(f, "{}", r),
110 Self::Real(r) => write!(f, "{}", r),
111 Self::Complex(c) => write!(f, "{}", c),
112 }
113 }
114}
115
116impl Neg for Number {
117 type Output = Number;
118
119 fn neg(self) -> Self {
120 match self {
121 Self::FixedInteger(i) => Self::FixedInteger(-i),
122 Self::BigInteger(i) => Self::BigInteger(-i),
123 Self::Rational(r) => Self::Rational(-r),
124 Self::Real(r) => Self::Real(-r),
125 Self::Complex(c) => Self::Complex(-c),
126 }
127 }
128}
129
130impl PartialEq for Number {
131 fn eq(&self, rhs: &Self) -> bool {
132 match (self, rhs) {
134 (Self::FixedInteger(l), Self::FixedInteger(r)) => l == r,
135 (Self::FixedInteger(l), Self::BigInteger(r)) => l == r,
136 (Self::FixedInteger(l), Self::Rational(r)) => l == r,
137 (Self::FixedInteger(l), Self::Real(r)) => Some(*l) == r.to_i64(),
138 (Self::FixedInteger(l), Self::Complex(r)) => Complex64::from_i64(*l) == Some(*r),
139 (Self::BigInteger(l), Self::FixedInteger(r)) => l == r,
140 (Self::BigInteger(l), Self::BigInteger(r)) => l == r,
141 (Self::BigInteger(l), Self::Rational(r)) => l == r,
142 (Self::BigInteger(l), Self::Real(r)) => l == r,
143 (Self::BigInteger(l), Self::Complex(r)) => {
144 <Integer as ToPrimitive>::to_f64(l).map(|l| Complex64::new(l, 0.0)) == Some(*r)
145 }
146 (Self::Rational(l), Self::FixedInteger(r)) => l == r,
147 (Self::Rational(l), Self::BigInteger(r)) => l == r,
148 (Self::Rational(l), Self::Rational(r)) => l == r,
149 (Self::Rational(l), Self::Real(r)) => <Rational as ToPrimitive>::to_f64(l) == Some(*r),
150 (Self::Rational(l), Self::Complex(r)) => {
151 <Rational as ToPrimitive>::to_f64(l).map(|l| Complex64::new(l, 0.0)) == Some(*r)
152 }
153 (Self::Real(l), Self::FixedInteger(r)) => l.to_i64() == Some(*r),
154 (Self::Real(l), Self::BigInteger(r)) => l == r,
155 (Self::Real(l), Self::Rational(r)) => l == r,
156 (Self::Real(l), Self::Real(r)) => l == r,
157 (Self::Real(l), Self::Complex(r)) => Complex64::new(*l, 0.0) == *r,
158 (Self::Complex(l), Self::FixedInteger(r)) => Some(*l) == Complex64::from_i64(*r),
159 (Self::Complex(l), Self::BigInteger(r)) => {
160 Some(*l) == <Integer as ToPrimitive>::to_f64(r).map(|r| Complex64::new(r, 0.0))
161 }
162 (Self::Complex(l), Self::Rational(r)) => {
163 Some(*l) == <Rational as ToPrimitive>::to_f64(r).map(|r| Complex64::new(r, 0.0))
164 }
165 (Self::Complex(l), Self::Real(r)) => *l == Complex64::new(*r, 0.0),
166 (Self::Complex(l), Self::Complex(r)) => l == r,
167 }
168 }
169}
170
171impl PartialOrd for Number {
172 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
173 match (self, rhs) {
174 (Self::FixedInteger(l), Self::FixedInteger(r)) => l.partial_cmp(r),
175 (Self::FixedInteger(l), Self::BigInteger(r)) => l.partial_cmp(r),
176 (Self::FixedInteger(l), Self::Rational(r)) => l.partial_cmp(r),
177 (Self::BigInteger(l), Self::FixedInteger(r)) => l.partial_cmp(r),
178 (Self::BigInteger(l), Self::BigInteger(r)) => l.partial_cmp(r),
179 (Self::BigInteger(l), Self::Rational(r)) => l.partial_cmp(r),
180 (Self::BigInteger(l), Self::Real(r)) => l.partial_cmp(r),
181 (Self::Rational(l), Self::FixedInteger(r)) => l.partial_cmp(r),
182 (Self::Rational(l), Self::BigInteger(r)) => l.partial_cmp(r),
183 (Self::Rational(l), Self::Rational(r)) => l.partial_cmp(r),
184 (Self::Rational(l), Self::Real(r)) => l.partial_cmp(r),
185 (Self::Real(l), Self::BigInteger(r)) => l.partial_cmp(r),
186 (Self::Real(l), Self::Rational(r)) => l.partial_cmp(r),
187 (Self::Real(l), Self::Real(r)) => l.partial_cmp(r),
188 (Self::Complex(_), _) | (_, Self::Complex(_)) => None,
189 (Self::FixedInteger(l), Self::Real(r)) => Integer::from(*l).partial_cmp(r),
191 (Self::Real(l), Self::FixedInteger(r)) => l.partial_cmp(&Integer::from(*r)),
192 }
193 }
194}
195
196macro_rules! impl_op {
197 ( $trait:ident, $op:ident, $checked_op:ident ) => {
198 impl<'a> $trait<&'a Number> for &'a Number {
199 type Output = Number;
200
201 fn $op(self, rhs: &'a Number) -> Number {
202 match (self, rhs) {
204 (Number::FixedInteger(l), Number::FixedInteger(r)) => match l.$checked_op(*r) {
205 Some(fixed) => Number::FixedInteger(fixed),
206 None => Number::BigInteger(Integer::from(*l).$op(r)),
207 },
208 (Number::FixedInteger(l), Number::BigInteger(r)) => {
209 Number::BigInteger(Integer::from(*l).$op(r))
210 }
211 (Number::FixedInteger(l), Number::Rational(r)) => {
212 Number::Rational(Rational::from((*l, 1)).$op(r))
213 }
214 (Number::FixedInteger(l), Number::Real(r)) => Number::Real((*l as f64).$op(*r)),
215 (Number::FixedInteger(l), Number::Complex(r)) => {
216 Number::Complex(Complex64::new(*l as f64, 0.0).$op(*r))
217 }
218 (Number::BigInteger(l), Number::FixedInteger(r)) => {
219 Number::BigInteger(l.$op(r).complete())
220 }
221 (Number::BigInteger(l), Number::BigInteger(r)) => {
222 Number::BigInteger(l.$op(r).complete())
223 }
224 (Number::BigInteger(l), Number::Rational(r)) => {
225 Number::Rational(Rational::from(l).$op(r))
226 }
227 (Number::BigInteger(l), Number::Real(r)) => Number::Real(l.to_f64().$op(r)),
228 (Number::BigInteger(l), Number::Complex(r)) => {
229 Number::Complex(Complex64::new(l.to_f64(), 0.0).$op(r))
230 }
231 (Number::Rational(l), Number::FixedInteger(r)) => {
232 Number::Rational(l.$op(Rational::from((*r, 1))))
233 }
234 (Number::Rational(l), Number::BigInteger(r)) => {
235 Number::Rational(l.$op(Rational::from(r)))
236 }
237 (Number::Rational(l), Number::Rational(r)) => {
238 Number::Rational(l.$op(r).complete())
239 }
240 (Number::Rational(l), Number::Real(r)) => Number::Real(l.to_f64().$op(r)),
241 (Number::Rational(l), Number::Complex(r)) => {
242 Number::Complex(Complex64::new(l.to_f64(), 0.0).$op(r))
243 }
244 (Number::Real(l), Number::FixedInteger(r)) => Number::Real(l.$op(*r as f64)),
245 (Number::Real(l), Number::BigInteger(r)) => Number::Real(l.$op(r.to_f64())),
246 (Number::Real(l), Number::Rational(r)) => Number::Real(l.$op(r.to_f64())),
247 (Number::Real(l), Number::Real(r)) => Number::Real(l.$op(r)),
248 (Number::Real(l), Number::Complex(r)) => {
249 Number::Complex(Complex64::new(*l, 0.0).$op(r))
250 }
251 (Number::Complex(l), Number::FixedInteger(r)) => {
252 Number::Complex(l.$op(Complex64::new(*r as f64, 0.0)))
253 }
254 (Number::Complex(l), Number::BigInteger(r)) => {
255 Number::Complex(l.$op(Complex64::new(r.to_f64(), 0.0)))
256 }
257 (Number::Complex(l), Number::Rational(r)) => {
258 Number::Complex(l.$op(Complex64::new(r.to_f64(), 0.0)))
259 }
260 (Number::Complex(l), Number::Real(r)) => {
261 Number::Complex(l.$op(Complex64::new(*r, 0.0)))
262 }
263 (Number::Complex(l), Number::Complex(r)) => Number::Complex(l.$op(r)),
264 }
265 }
266 }
267 };
268}
269
270impl_op!(Add, add, checked_add);
271impl_op!(Sub, sub, checked_sub);
272impl_op!(Mul, mul, checked_mul);
273
274impl<'a> Div<&'a Number> for &'a Number {
275 type Output = Number;
276
277 fn div(self, rhs: &'a Number) -> Number {
278 match (self, rhs) {
280 (Number::FixedInteger(l), Number::FixedInteger(r)) => {
281 Number::Rational(Rational::from((*l, *r)))
282 }
283 (Number::FixedInteger(l), Number::BigInteger(r)) => {
284 Number::Rational(Rational::from((*l, r)))
285 }
286 (Number::FixedInteger(l), Number::Rational(r)) => {
287 Number::Rational(Rational::from((*l, 1)) / r)
288 }
289 (Number::FixedInteger(l), Number::Real(r)) => Number::Real((*l as f64) / *r),
290 (Number::FixedInteger(l), Number::Complex(r)) => {
291 Number::Complex(Complex64::new(*l as f64, 0.0) / *r)
292 }
293 (Number::BigInteger(l), Number::FixedInteger(r)) => {
294 Number::Rational(Rational::from((l, *r)))
295 }
296 (Number::BigInteger(l), Number::BigInteger(r)) => {
297 Number::Rational(Rational::from((l, r)))
298 }
299 (Number::BigInteger(l), Number::Rational(r)) => Number::Rational(Rational::from(l) / r),
300 (Number::BigInteger(l), Number::Real(r)) => Number::Real(l.to_f64() / r),
301 (Number::BigInteger(l), Number::Complex(r)) => {
302 Number::Complex(Complex64::new(l.to_f64(), 0.0) / r)
303 }
304 (Number::Rational(l), Number::FixedInteger(r)) => {
305 Number::Rational(l / Rational::from((*r, 1)))
306 }
307 (Number::Rational(l), Number::BigInteger(r)) => Number::Rational((l / r).complete()),
308
309 (Number::Rational(l), Number::Rational(r)) => Number::Rational((l / r).complete()),
310 (Number::Rational(l), Number::Real(r)) => Number::Real(l.to_f64() / r),
311 (Number::Rational(l), Number::Complex(r)) => {
312 Number::Complex(Complex64::new(l.to_f64(), 0.0) / r)
313 }
314 (Number::Real(l), Number::FixedInteger(r)) => Number::Real(l / *r as f64),
315 (Number::Real(l), Number::BigInteger(r)) => Number::Real(l / r.to_f64()),
316 (Number::Real(l), Number::Rational(r)) => Number::Real(l / r.to_f64()),
317 (Number::Real(l), Number::Real(r)) => Number::Real(l / r),
318 (Number::Real(l), Number::Complex(r)) => Number::Complex(Complex64::new(*l, 0.0) / r),
319 (Number::Complex(l), Number::FixedInteger(r)) => {
320 Number::Complex(l / Complex64::new(*r as f64, 0.0))
321 }
322 (Number::Complex(l), Number::BigInteger(r)) => {
323 Number::Complex(l / Complex64::new(r.to_f64(), 0.0))
324 }
325 (Number::Complex(l), Number::Rational(r)) => {
326 Number::Complex(l / Complex64::new(r.to_f64(), 0.0))
327 }
328 (Number::Complex(l), Number::Real(r)) => Number::Complex(l / Complex64::new(*r, 0.0)),
329 (Number::Complex(l), Number::Complex(r)) => Number::Complex(l / r),
330 }
331 }
332}
333
334unsafe impl Trace for Number {
335 unsafe fn visit_children(&self, _visitor: fn(crate::gc::OpaqueGcPtr)) {}
336}
337
338#[builtin("zero?")]
339pub async fn zero(
340 _cont: &Option<Arc<Continuation>>,
341 arg: &Gc<Value>,
342) -> Result<Vec<Gc<Value>>, RuntimeError> {
343 let arg = arg.read().await;
344 let num: &Number = arg.as_ref().try_into()?;
345 Ok(vec![Gc::new(Value::Boolean(num.is_zero()))])
346}
347
348#[builtin("even?")]
349pub async fn even(
350 _cont: &Option<Arc<Continuation>>,
351 arg: &Gc<Value>,
352) -> Result<Vec<Gc<Value>>, RuntimeError> {
353 let arg = arg.read().await;
354 let num: &Number = arg.as_ref().try_into()?;
355 Ok(vec![Gc::new(Value::Boolean(num.is_even()))])
356}
357
358#[builtin("odd?")]
359pub async fn odd(
360 _cont: &Option<Arc<Continuation>>,
361 arg: &Gc<Value>,
362) -> Result<Vec<Gc<Value>>, RuntimeError> {
363 let arg = arg.read().await;
364 let num: &Number = arg.as_ref().try_into()?;
365 Ok(vec![Gc::new(Value::Boolean(num.is_odd()))])
366}
367
368#[builtin("+")]
369pub async fn add(
370 _cont: &Option<Arc<Continuation>>,
371 args: Vec<Gc<Value>>,
372) -> Result<Vec<Gc<Value>>, RuntimeError> {
373 let mut result = Number::FixedInteger(0);
374 for arg in args {
375 let arg = arg.read().await;
376 let num: &Number = arg.as_ref().try_into()?;
377 result = &result + num;
378 }
379 Ok(vec![Gc::new(Value::Number(result))])
380}
381
382#[builtin("-")]
383pub async fn sub(
384 _cont: &Option<Arc<Continuation>>,
385 arg1: &Gc<Value>,
386 args: Vec<Gc<Value>>,
387) -> Result<Vec<Gc<Value>>, RuntimeError> {
388 let arg1 = arg1.read().await;
389 let arg1: &Number = arg1.as_ref().try_into()?;
390 if args.is_empty() {
391 Ok(vec![Gc::new(Value::Number(-arg1.clone()))])
392 } else {
393 let mut result = arg1.clone();
394 for arg in args {
395 let arg = arg.read().await;
396 let num: &Number = arg.as_ref().try_into()?;
397 result = &result - num;
398 }
399 Ok(vec![Gc::new(Value::Number(result))])
400 }
401}
402
403#[builtin("*")]
404pub async fn mul(
405 _cont: &Option<Arc<Continuation>>,
406 args: Vec<Gc<Value>>,
407) -> Result<Vec<Gc<Value>>, RuntimeError> {
408 let mut result = Number::FixedInteger(1);
409 for arg in args {
410 let arg = arg.read().await;
411 let num: &Number = arg.as_ref().try_into()?;
412 result = &result * num;
413 }
414 Ok(vec![Gc::new(Value::Number(result))])
415}
416
417#[builtin("/")]
418pub async fn div(
419 _cont: &Option<Arc<Continuation>>,
420 arg1: &Gc<Value>,
421 args: Vec<Gc<Value>>,
422) -> Result<Vec<Gc<Value>>, RuntimeError> {
423 let arg1 = arg1.read().await;
424 let arg1: &Number = arg1.as_ref().try_into()?;
425 if arg1.is_zero() {
426 return Err(RuntimeError::division_by_zero());
427 }
428 let mut result = &Number::FixedInteger(1) / arg1;
429 for arg in args {
430 let arg = arg.read().await;
431 let num: &Number = arg.as_ref().try_into()?;
432 if num.is_zero() {
433 return Err(RuntimeError::division_by_zero());
434 }
435 result = &result / num;
436 }
437 Ok(vec![Gc::new(Value::Number(result))])
438}
439
440#[builtin("=")]
441pub async fn equals(
442 _cont: &Option<Arc<Continuation>>,
443 args: Vec<Gc<Value>>,
444) -> Result<Vec<Gc<Value>>, RuntimeError> {
445 if let Some((first, rest)) = args.split_first() {
446 let first = first.read().await;
447 let first: &Number = first.as_ref().try_into()?;
448 for next in rest {
449 let next = next.read().await;
450 let next: &Number = next.as_ref().try_into()?;
451 if first != next {
452 return Ok(vec![Gc::new(Value::Boolean(false))]);
453 }
454 }
455 }
456 Ok(vec![Gc::new(Value::Boolean(true))])
457}
458
459#[builtin(">")]
460pub async fn greater(
461 _cont: &Option<Arc<Continuation>>,
462 args: Vec<Gc<Value>>,
463) -> Result<Vec<Gc<Value>>, RuntimeError> {
464 if let Some((head, rest)) = args.split_first() {
465 let mut prev = head.clone();
466 for next in rest {
467 {
468 let prev = prev.read().await;
469 let next = next.read().await;
470 let prev: &Number = prev.as_ref().try_into()?;
471 let next: &Number = next.as_ref().try_into()?;
472 if prev.is_complex() {
475 return Err(RuntimeError::invalid_type("number", "complex"));
476 }
477 if next.is_complex() {
478 return Err(RuntimeError::invalid_type("number", "complex"));
479 }
480 if prev <= next {
481 return Ok(vec![Gc::new(Value::Boolean(false))]);
482 }
483 }
484 prev = next.clone();
485 }
486 }
487 Ok(vec![Gc::new(Value::Boolean(true))])
488}
489
490#[builtin(">=")]
491pub async fn greater_equal(
492 _cont: &Option<Arc<Continuation>>,
493 args: Vec<Gc<Value>>,
494) -> Result<Vec<Gc<Value>>, RuntimeError> {
495 if let Some((head, rest)) = args.split_first() {
496 let mut prev = head.clone();
497 for next in rest {
498 {
499 let prev = prev.read().await;
500 let next = next.read().await;
501 let prev: &Number = prev.as_ref().try_into()?;
502 let next: &Number = next.as_ref().try_into()?;
503 if prev.is_complex() {
504 return Err(RuntimeError::invalid_type("number", "complex"));
505 }
506 if next.is_complex() {
507 return Err(RuntimeError::invalid_type("number", "complex"));
508 }
509 if prev < next {
510 return Ok(vec![Gc::new(Value::Boolean(false))]);
511 }
512 }
513 prev = next.clone();
514 }
515 }
516 Ok(vec![Gc::new(Value::Boolean(true))])
517}
518
519#[builtin("<")]
520pub async fn lesser(
521 _cont: &Option<Arc<Continuation>>,
522 args: Vec<Gc<Value>>,
523) -> Result<Vec<Gc<Value>>, RuntimeError> {
524 if let Some((head, rest)) = args.split_first() {
525 let mut prev = head.clone();
526 for next in rest {
527 {
528 let prev = prev.read().await;
529 let next = next.read().await;
530 let prev: &Number = prev.as_ref().try_into()?;
531 let next: &Number = next.as_ref().try_into()?;
532 if prev.is_complex() {
533 return Err(RuntimeError::invalid_type("number", "complex"));
534 }
535 if next.is_complex() {
536 return Err(RuntimeError::invalid_type("number", "complex"));
537 }
538 if prev >= next {
539 return Ok(vec![Gc::new(Value::Boolean(false))]);
540 }
541 }
542 prev = next.clone();
543 }
544 }
545 Ok(vec![Gc::new(Value::Boolean(true))])
546}
547
548#[builtin("<=")]
549pub async fn lesser_equal(
550 _cont: &Option<Arc<Continuation>>,
551 args: Vec<Gc<Value>>,
552) -> Result<Vec<Gc<Value>>, RuntimeError> {
553 if let Some((head, rest)) = args.split_first() {
554 let mut prev = head.clone();
555 for next in rest {
556 {
557 let prev = prev.read().await;
558 let next = next.read().await;
559 let prev: &Number = prev.as_ref().try_into()?;
560 let next: &Number = next.as_ref().try_into()?;
561 if prev.is_complex() {
562 return Err(RuntimeError::invalid_type("number", "complex"));
563 }
564 if next.is_complex() {
565 return Err(RuntimeError::invalid_type("number", "complex"));
566 }
567 if prev > next {
568 return Ok(vec![Gc::new(Value::Boolean(false))]);
569 }
570 }
571 prev = next.clone();
572 }
573 }
574 Ok(vec![Gc::new(Value::Boolean(true))])
575}
576
577#[builtin("number?")]
578pub async fn is_number(
579 _cont: &Option<Arc<Continuation>>,
580 arg: &Gc<Value>,
581) -> Result<Vec<Gc<Value>>, RuntimeError> {
582 let arg = arg.read().await;
583 Ok(vec![Gc::new(Value::Boolean(matches!(
584 &*arg,
585 Value::Number(_)
586 )))])
587}
588
589#[builtin("integer?")]
590pub async fn is_integer(
591 _cont: &Option<Arc<Continuation>>,
592 arg: &Gc<Value>,
593) -> Result<Vec<Gc<Value>>, RuntimeError> {
594 let arg = arg.read().await;
595 Ok(vec![Gc::new(Value::Boolean(matches!(
596 &*arg,
597 Value::Number(Number::FixedInteger(_)) | Value::Number(Number::BigInteger(_))
598 )))])
599}
600
601#[builtin("rational?")]
602pub async fn is_rational(
603 _cont: &Option<Arc<Continuation>>,
604 arg: &Gc<Value>,
605) -> Result<Vec<Gc<Value>>, RuntimeError> {
606 let arg = arg.read().await;
607 Ok(vec![Gc::new(Value::Boolean(matches!(
608 &*arg,
609 Value::Number(Number::Rational(_))
610 )))])
611}
612
613#[builtin("real?")]
614pub async fn is_real(
615 _cont: &Option<Arc<Continuation>>,
616 arg: &Gc<Value>,
617) -> Result<Vec<Gc<Value>>, RuntimeError> {
618 let arg = arg.read().await;
619 Ok(vec![Gc::new(Value::Boolean(matches!(
620 &*arg,
621 Value::Number(Number::Real(_))
622 )))])
623}
624
625#[builtin("complex?")]
626pub async fn is_complex(
627 _cont: &Option<Arc<Continuation>>,
628 arg: &Gc<Value>,
629) -> Result<Vec<Gc<Value>>, RuntimeError> {
630 let arg = arg.read().await;
631 Ok(vec![Gc::new(Value::Boolean(matches!(
632 &*arg,
633 Value::Number(Number::Complex(_))
634 )))])
635}