1pub mod structs;
6use structs::*;
7
8pub(crate) mod fns;
9
10pub(crate) mod cmds;
11
12pub(crate) mod errors;
13
14pub(crate) mod conv;
15
16pub(crate) mod num;
17
18#[cfg(not(feature = "no_os"))]
19mod os;
20
21use std::io::{Write, BufRead, ErrorKind};
22use std::ops::Neg;
23use std::panic::catch_unwind;
24use std::ptr::NonNull;
25use std::str::FromStr;
26use std::sync::{Arc, LazyLock, Mutex, mpsc::{Receiver, TryRecvError, RecvTimeoutError}};
27use linefeed::{DefaultTerminal, Interface};
28use bitvec::prelude::*;
29use malachite::{Natural, Integer, Rational};
30use malachite::base::num::arithmetic::traits::{Factorial, NegAssign, Pow};
31use malachite::base::num::basic::traits::{NegativeOne, Zero, One, Two};
32use malachite::base::num::conversion::traits::{PowerOf2DigitIterable, RoundingFrom, WrappingFrom};
33use malachite::base::num::random::RandomPrimitiveInts;
34use malachite::base::rational_sequences::RationalSequence;
35use malachite::base::rounding_modes::RoundingMode;
36use crate::errors::TypeLabel;
37
38
39pub const STATE_FILE_HEADER: [u8;20] = *b"# ADC state file v1\n";
41
42struct LineEditor(Interface<DefaultTerminal>);
43
44pub trait ReadLine {
48 fn read_line(&mut self) -> std::io::Result<String>;
52
53 fn clear_history(&mut self);
55}
56impl<T: BufRead> ReadLine for T {
57 fn read_line(&mut self) -> std::io::Result<String> {
58 let mut buf = String::new();
59 self.read_line(&mut buf)?;
60 Ok(buf)
61 }
62
63 fn clear_history(&mut self) {
64 }
66}
67impl ReadLine for LineEditor {
68 fn read_line(&mut self) -> std::io::Result<String> {
69 use linefeed::{ReadResult, Signal};
70 match self.0.read_line() {
71 Ok(ReadResult::Input(s)) => {
72 self.0.add_history_unique(s.clone());
73 Ok(s)
74 },
75 Ok(ReadResult::Eof) => {Err(ErrorKind::UnexpectedEof.into())},
76 Ok(ReadResult::Signal(sig)) => {
77 self.0.cancel_read_line()?;
78 match sig {
79 Signal::Break | Signal::Interrupt | Signal::Quit => {Err(ErrorKind::Interrupted.into())},
80 Signal::Continue => {Err(std::io::Error::other("Unhandled SIGCONT"))},
81 Signal::Suspend => {Err(std::io::Error::other("Unhandled SIGTSTP"))},
82 Signal::Resize => {Err(std::io::Error::other("Unhandled window resize"))},
83 }
84 },
85 Err(e) => {Err(e)}
86 }
87 }
88
89 fn clear_history(&mut self) {
90 self.0.clear_history();
91 }
92}
93
94fn input_stream() -> Box<dyn ReadLine + Send> {
95 use linefeed::Signal::*;
96 match Interface::new("") { Ok(iface) => {
98 iface.set_report_signal(Break, true);
100 iface.set_report_signal(Interrupt, true);
101 iface.set_report_signal(Quit, true);
102 Box::new(LineEditor(iface))
103 },
104 Err(_) => { Box::new(std::io::BufReader::new(std::io::stdin()))
106 }
107 }
108}
109
110pub struct IOStreams (
112 pub Box<dyn ReadLine + Send>,
114 pub Box<dyn Write + Send>,
116 pub Box<dyn Write + Send>
118);
119impl IOStreams {
120 pub fn empty() -> Self {
122 Self (
123 Box::new(std::io::empty()),
124 Box::new(std::io::empty()),
125 Box::new(std::io::empty())
126 )
127 }
128
129 pub fn process() -> Self {
131 Self (
132 input_stream(),
133 Box::new(std::io::stdout()),
134 Box::new(std::io::stderr())
135 )
136 }
137}
138
139lazy_static::lazy_static! {
140 pub(crate) static ref RE_CACHE: RegexCache = RegexCache::default();
141}
142
143fn rng_preset(bytes: [u8; 32]) -> RandomPrimitiveInts<u64> {
144 malachite::base::num::random::random_primitive_ints(malachite::base::random::Seed::from_bytes(bytes))
145}
146
147fn rng_os() -> RandomPrimitiveInts<u64> {
148 let mut bytes = [0u8; 32];
149 getrandom::fill(&mut bytes).unwrap();
150 rng_preset(bytes)
151}
152
153#[derive(Default, Debug, Clone, Copy, Hash)]
154enum Command {
155 Fn1(fns::Mon),
157
158 Fn2(fns::Dya),
160
161 Fn3(fns::Tri),
163
164 Cmd(cmds::Cmd),
166
167 Exec,
169
170 ExecR,
172
173 Lit,
175
176 Space,
178
179 #[default] Wrong
181}
182
183const CMDS: [Command; 128] = {
185 use Command::*;
186 use fns::*;
187 use cmds::*;
188 [
189 Space, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Space, Space, Space, Space, Space, Wrong, Wrong,
191
192 Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong,
194
195 Space, Fn1(neg), Exec, Space, Wrong, Fn2(modu), Wrong, Lit, Exec, Exec, Fn2(mul), Fn2(add), Wrong, Fn2(sub), Lit, Fn2(div),
197
198 Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Exec, Wrong, Fn2(lt), Fn2(eq), Fn2(gt), Exec,
200
201 Lit, Wrong, Wrong, Cmd(cln), Exec, Wrong, Lit, Fn2(logb), Wrong, Cmd(gi), ExecR, Cmd(gk), ExecR, Cmd(gm), Exec, Cmd(go),
203
204 Exec, Exec, Exec, ExecR, Lit, Wrong, Fn2(root), Exec, ExecR, Wrong, ExecR, Lit, Wrong, Wrong, Fn2(pow), Exec,
206
207 Exec, Exec, Wrong, Cmd(cls), Exec, Wrong, Exec, Fn1(log), Wrong, Cmd(si), ExecR, Cmd(sk), ExecR, Cmd(sm), Fn1(fac), Cmd(so),
209
210 Exec, Exec, Cmd(rev), ExecR, Fn2(trig), Wrong, Fn1(sqrt), Exec, Exec, Wrong, Fn1(disc), Cmd(cbo), Fn3(bar), Cmd(cbc), Fn2(euc), Wrong
212 ]
213};
214
215fn byte_cmd(b: u8) -> Command {
216 CMDS.get(b as usize).copied().unwrap_or_default()
217}
218
219fn string_or_bytes(v: &[u8]) -> String {
220 str::from_utf8(v).map(|s| s.to_owned()).unwrap_or_else(|_| {
221 let mut res = String::from("(not UTF-8: [");
222 for b in v {
223 res += &format!("\\{b:02X}");
224 }
225 res += "])";
226 res
227 })
228}
229
230const fn upper_hex_to_nibble(b: u8) -> Option<u8> {
231 match b {
232 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'F' => Some(unsafe{b.unchecked_sub(0x37)}),
234 _ => None
235 }
236}
237
238const fn mixed_ascii_to_digit(b: u8) -> Option<u8> {
239 match b {
240 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'Z' => Some(unsafe{b.unchecked_sub(0x37)}),
242 b'a'..=b'z' => Some(unsafe{b.unchecked_sub(0x57)}),
243 _ => None
244 }
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
249pub enum LogLevel {
250 Normal,
252 Debug,
254 Quiet
256}
257
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
260#[must_use] pub enum ExecResult {
261 Finished,
263
264 SoftQuit(u8),
266
267 HardQuit(u8),
269
270 Killed
272}
273
274pub fn interpreter_simple(
278 st: &mut State,
279 start: Utf8Iter,
280 kill: Option<&Receiver<()>>
281) -> std::io::Result<ExecResult>
282{
283 let no_io = Arc::new(Mutex::new(IOStreams::empty()));
284 interpreter_no_os(st, start, no_io, LogLevel::Quiet, kill)
285}
286
287pub fn interpreter_no_os(
291 st: &mut State,
292 start: Utf8Iter,
293 io: Arc<Mutex<IOStreams>>,
294 ll: LogLevel,
295 kill: Option<&Receiver<()>>,
296) -> std::io::Result<ExecResult>
297{
298 unsafe { interpreter(st, start, io, ll, kill, true) }
300}
301
302pub unsafe fn interpreter_no_io(
307 st: &mut State,
308 start: Utf8Iter,
309 kill: Option<&Receiver<()>>,
310 restrict: bool
311) -> std::io::Result<ExecResult>
312{
313 let no_io = Arc::new(Mutex::new(IOStreams::empty()));
314 unsafe { interpreter(st, start, no_io, LogLevel::Quiet, kill, restrict) }
315}
316
317pub unsafe fn interpreter(
342 st: &mut State,
343 start: Utf8Iter,
344 io: Arc<Mutex<IOStreams>>,
345 mut ll: LogLevel,
346 kill: Option<&Receiver<()>>,
347 #[cfg_attr(feature = "no_os", expect(unused_variables))]
348 mut restrict: bool
349) -> std::io::Result<ExecResult>
350{
351 use ExecResult::*;
352
353 let th_name = if kill.is_some() { std::thread::current().name().unwrap().to_owned()
355 }
356 else {
357 String::new()
358 };
359
360 let mut pbuf: Option<String> = None; let mut elatch: Option<(Natural, char, String)> = None;
363
364 macro_rules! synerr {
365 ($c:expr, $s:expr) => {
366 if ll != LogLevel::Quiet {
367 let mut lock = io.lock().unwrap();
368 writeln!(lock.2, "! {th_name}{}: {}", $c, $s)?;
369 lock.2.flush()?;
370 drop(lock);
371 }
372 elatch = Some((Natural::ZERO, $c, $s.into()));
373 };
374 ($c:expr, $f:literal, $($s:expr),*) => {
375 let s = format!($f, $($s),*);
376 if ll != LogLevel::Quiet {
377 let mut lock = io.lock().unwrap();
378 writeln!(lock.2, "! {th_name}{}: {}", $c, s)?;
379 lock.2.flush()?;
380 drop(lock);
381 }
382 elatch = Some((Natural::ZERO, $c, s));
383 };
384 }
385
386 macro_rules! valerr {
387 ($c:expr, $s:expr) => {
388 if ll != LogLevel::Quiet {
389 let mut lock = io.lock().unwrap();
390 writeln!(lock.2, "? {th_name}{}: {}", $c, $s)?;
391 lock.2.flush()?;
392 drop(lock);
393 }
394 elatch = Some((Natural::ZERO, $c, $s.into()));
395 };
396 ($c:expr, $f:literal, $($s:expr),*) => {
397 let s = format!($f, $($s),*);
398 if ll != LogLevel::Quiet {
399 let mut lock = io.lock().unwrap();
400 writeln!(lock.2, "? {th_name}{}: {}", $c, s)?;
401 lock.2.flush()?;
402 drop(lock);
403 }
404 elatch = Some((Natural::ZERO, $c, s));
405 };
406 }
407
408 macro_rules! debug {
409 ($s:expr) => {
410 if ll == LogLevel::Debug {
411 let mut lock = io.lock().unwrap();
412 writeln!(lock.2, "\tDEBUG: {th_name}{}", $s)?;
413 lock.2.flush()?;
414 drop(lock);
415 }
416 };
417 ($f:literal, $($s:expr),*) => {
418 if ll == LogLevel::Debug {
419 let mut lock = io.lock().unwrap();
420 writeln!(lock.2, "\tDEBUG: {th_name}{}", format!($f, $($s),*))?;
421 lock.2.flush()?;
422 drop(lock);
423 }
424 };
425 }
426
427 let mut rptr: Option<Rational> = None; let mut rng: Option<RandomPrimitiveInts<u64>> = None;
430
431 let mut call: Vec<(Utf8Iter, Natural)> = vec![(start, Natural::ONE)];
432
433 'mac: while let Some((mac, count)) = call.last_mut() { let mut alt = false;
435
436 let mut abuf: Vec<Value> = Vec::new(); let mut dest: Vec<NonNull<Vec<Value>>> = Vec::new(); macro_rules! push {
440 ($v:expr) => {
441 if let Some(p) = dest.last_mut() {
442 unsafe {
443 p.as_mut().push($v); }
445 }
446 else {
447 st.mstk.push(Arc::new($v));
448 }
449 };
450 }
451 macro_rules! append {
453 ($v:expr) => {
454 if let Some(p) = dest.last_mut() {
455 unsafe {
456 p.as_mut().append(&mut $v); }
458 }
459 else {
460 for val in $v {
461 st.mstk.push(Arc::new(val));
462 }
463 }
464 };
465 }
466
467 'cmd: while let Some(b) = mac.next() { if let Some(rx) = kill { match rx.try_recv() {
470 Ok(()) => { #[expect(unused_assignments)]
472 for s in st.regs.end_threads(true) { valerr!('j', s);
474 }
475 return Ok(Killed);
476 },
477 Err(TryRecvError::Empty) => { },
480 Err(TryRecvError::Disconnected) => { unreachable!()
482 }
483 }
484 }
485
486 if let Some(e) = &mut elatch { e.0 += Natural::ONE;
488 }
489
490 use Command::*;
491 match byte_cmd(b) {
492 Fn1(mon) => {
493 if let Some(va) = st.mstk.pop() {
494 debug!("Monadic {}{} with {}", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va));
495 match catch_unwind(|| fns::exec1(mon, &va, alt)) {
496 Ok(Ok(vz)) => {
497 push!(vz);
498 },
499 Ok(Err(e)) => {
500 st.mstk.push(va);
501 valerr!(b as char, e.to_string());
502 },
503 Err(cause) => {
504 st.mstk.push(va);
505 valerr!(b as char, "Caught function panic: {:?}", cause);
506 }
507 }
508 }
509 else {
510 synerr!(b as char, "Expected 1 argument, 0 given");
511 }
512 },
513 Fn2(dya) => {
514 if let Some(vb) = st.mstk.pop() {
515 if let Some(va) = st.mstk.pop() {
516 debug!("Dyadic {}{} with ({}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb));
517 match catch_unwind(|| fns::exec2(dya, &va, &vb, alt)) {
518 Ok(Ok(vz)) => {
519 push!(vz);
520 },
521 Ok(Err(e)) => {
522 st.mstk.push(va);
523 st.mstk.push(vb);
524 valerr!(b as char, e.to_string());
525 },
526 Err(cause) => {
527 st.mstk.push(va);
528 st.mstk.push(vb);
529 valerr!(b as char, "Caught function panic: {:?}", cause);
530 }
531 }
532 }
533 else {
534 st.mstk.push(vb);
535 synerr!(b as char, "Expected 2 arguments, 1 given");
536 }
537 }
538 else {
539 synerr!(b as char, "Expected 2 arguments, 0 given");
540 }
541 },
542 Fn3(tri) => {
543 if let Some(vc) = st.mstk.pop() {
544 if let Some(vb) = st.mstk.pop() {
545 if let Some(va) = st.mstk.pop() {
546 debug!("Triadic {}{} with ({}, {}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb), TypeLabel::from(&*vc));
547 match catch_unwind(|| fns::exec3(tri, &va, &vb, &vc, alt)) {
548 Ok(Ok(vz)) => {
549 push!(vz);
550 },
551 Ok(Err(e)) => {
552 st.mstk.push(va);
553 st.mstk.push(vb);
554 st.mstk.push(vc);
555 valerr!(b as char, e.to_string());
556 },
557 Err(cause) => {
558 st.mstk.push(va);
559 st.mstk.push(vb);
560 st.mstk.push(vc);
561 valerr!(b as char, "Caught function panic: {:?}", cause);
562 }
563 }
564 }
565 else {
566 st.mstk.push(vb);
567 st.mstk.push(vc);
568 synerr!(b as char, "Expected 3 arguments, 2 given");
569 }
570 }
571 else {
572 st.mstk.push(vc);
573 synerr!(b as char, "Expected 3 arguments, 1 given");
574 }
575 }
576 else {
577 synerr!(b as char, "Expected 3 arguments, 0 given");
578 }
579 },
580 Cmd(cmd) => {
581 debug!("Impure command {}", b as char);
582 match cmd(st) {
583 Ok(mut v) => {
584 append!(v);
585 }
586 Err(e) => {
587 if let Some(se) = e.strip_suffix('!') {
588 synerr!(b as char, se);
589 }
590 else {
591 valerr!(b as char, e);
592 }
593 }
594 }
595 },
596 Exec => {
597 debug!("Command {}{}", if alt {"alt-"} else {""}, b as char);
598 match b {
599 b'`' => { alt = true;
601 continue 'cmd; },
603 b':' if !alt => { if let Some(va) = st.mstk.pop() {
605 if let Value::N(r) = &*va {
606 rptr = Some(r.clone());
607 }
608 else {
609 let ta = TypeLabel::from(&*va);
610 st.mstk.push(va);
611 synerr!(':', "Expected a number, {} given", ta);
612 }
613 }
614 else {
615 synerr!(':', "Expected 1 argument, 0 given");
616 }
617 },
618 b':' if alt => { push!(
620 if let Some(ri) = rptr.take() {
621 Value::N(ri)
622 }
623 else {
624 Value::A(vec![])
625 }
626 );
627 },
628 b'd' => {
629 if let Some(v) = st.mstk.last() {
630 if let Some(p) = dest.last_mut() { unsafe {
632 p.as_mut().push((**v).clone()); }
634 }
635 else {
636 st.mstk.push(Arc::clone(v));
637 }
638 }
639 else {
640 synerr!('d', "Stack is empty");
641 }
642 },
643 b'D' => {
644 if let Some(va) = st.mstk.pop() {
645 if let Value::N(r) = &*va {
646 match usize::try_from(r) {
647 Ok(0) => {}, Ok(u) => {
649 if let Some(from) = st.mstk.len().checked_sub(u) {
650 if let Some(p) = dest.last_mut() { for v in &st.mstk[from..] {
652 unsafe {
653 p.as_mut().push((**v).clone()); }
655 }
656 }
657 else {
658 st.mstk.extend_from_within(from..);
659 }
660 }
661 else {
662 st.mstk.push(va);
663 valerr!('D', "Can't duplicate {} values, stack depth is {}", u, st.mstk.len() - 1);
664 }
665 }
666 Err(_) => {
667 let vs = va.to_string();
668 st.mstk.push(va);
669 valerr!('D', "Can't possibly duplicate {} values", vs);
670 }
671 }
672 }
673 else {
674 let ta = TypeLabel::from(&*va);
675 st.mstk.push(va);
676 synerr!('D', "Expected a number, {} given", ta);
677 }
678 }
679 else {
680 synerr!('D', "Expected 1 argument, 0 given");
681 }
682 },
683 b'R' => { if let Some(va) = st.mstk.pop() {
685 if let Value::N(r) = &*va {
686 match usize::try_from(r) {
687 Ok(0) => {}, Ok(u) => {
689 if let Some(from) = st.mstk.len().checked_sub(u) {
690 if alt {st.mstk[from..].rotate_left(1);}
691 else {st.mstk[from..].rotate_right(1);}
692 }
693 else {
694 st.mstk.push(va);
695 valerr!('R', "Can't rotate {} values, stack depth is {}", u, st.mstk.len() - 1);
696 }
697 }
698 Err(_) => {
699 let vs = va.to_string();
700 st.mstk.push(va);
701 valerr!('R', "Can't possibly rotate {} values", vs);
702 }
703 }
704 }
705 else {
706 let ta = TypeLabel::from(&*va);
707 st.mstk.push(va);
708 synerr!('R', "Expected a number, {} given", ta);
709 }
710 }
711 else {
712 synerr!('R', "Expected 1 argument, 0 given");
713 }
714 },
715 b'?' => { let mut lock = io.lock().unwrap();
717 let res = lock.0.read_line();
718 drop(lock);
719 match res {
720 Ok(s) => {
721 push!(Value::S(s));
722 },
723 Err(e) => {
724 match e.kind() {
725 ErrorKind::Interrupted => {
726 valerr!('?', "Interrupted");
727 },
728 ErrorKind::UnexpectedEof => {
729 push!(Value::S(String::new()));
730 },
731 _ => {
732 return Err(e);
733 }
734 }
735 }
736 }
737 },
738 b'p' => { if let Some(va) = st.mstk.pop() {
740 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
741 if let Some(s) = &mut pbuf {
742 s.push_str(&vs);
743 s.push('\n');
744 }
745 else {
746 let mut lock = io.lock().unwrap();
747 writeln!(lock.1, "{}", vs)?;
748 lock.1.flush()?;
749 drop(lock);
750 }
751 }
752 else {
753 synerr!('p', "Expected 1 argument, 0 given");
754 }
755 },
756 b'P' => { if let Some(va) = st.mstk.pop() {
758 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
759 if let Some(s) = &mut pbuf {
760 s.push_str(&vs);
761 }
762 else {
763 let mut lock = io.lock().unwrap();
764 write!(lock.1, "{}", vs)?;
765 lock.1.flush()?;
766 drop(lock);
767 }
768 }
769 else {
770 synerr!('P', "Expected 1 argument, 0 given");
771 }
772 },
773 b'"' => { if let Some(s) = pbuf.take() { push!(Value::S(s));
776 }
777 else { pbuf = Some(String::new());
779 }
780 },
781 b'(' => { let nn = if let Some(p) = dest.last_mut() { unsafe { p.as_mut().push(Value::A(Vec::new())); let Value::A(new) = &mut p.as_mut().last_mut().unwrap_unchecked() else { std::hint::unreachable_unchecked() }; NonNull::from(new)
786 }}
787 else {
788 NonNull::from(&mut abuf) };
790 dest.push(nn);
791 },
792 b')' => { if dest.pop().is_some() {
794 if dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf)))); }
797 }
798 else {
799 synerr!(')', "Mismatched closing ')'");
800 }
801 },
802 b'x' => {
803 if let Some(top) = st.mstk.pop() {
804 let sec = st.mstk.pop();
805 match Utf8Iter::try_macros(&top, sec.as_deref()) {
806 Ok((stk, ret)) => {
807 if let Some(sec) = sec && ret { st.mstk.push(sec);
809 }
810
811 if mac.is_finished() && *count == Natural::ZERO { call.pop();
813 }
814
815 call.extend(stk.into_iter().rev());
816 continue 'mac;
817 },
818 Err(e) => {
819 if let Some(sec) = sec {st.mstk.push(sec);}
820 st.mstk.push(top);
821 synerr!('x', "{}", e);
822 }
823 }
824 }
825 else {
826 synerr!('x', "Expected 1 or 2 arguments, 0 given");
827 }
828 },
829 b'q' => {
830 let u = u8::wrapping_from(&Integer::rounding_from(rptr.unwrap_or_default(), RoundingMode::Down).0);
831 return if alt {
832 Ok(HardQuit(u))
833 }
834 else {
835 Ok(SoftQuit(u))
836 };
837 },
838 b'Q' => {
839 if let Some(va) = st.mstk.pop() {
840 match &*va {
841 Value::N(r) => {
842 if let Ok(u) = usize::try_from(r) {
843 call.truncate(call.len().saturating_sub(u));
844 if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
846 dest.clear(); }
848 continue 'mac;
849 }
850 else {
851 let vs = va.to_string();
852 st.mstk.push(va);
853 valerr!('Q', "Cannot possibly break {} macros", vs);
854 }
855 },
856 _ => {
857 let ta = TypeLabel::from(&*va);
858 st.mstk.push(va);
859 synerr!('Q', "Expected a number, {} given", ta);
860 }
861 }
862 }
863 else {
864 synerr!('Q', "Expected 1 argument, 0 given");
865 }
866 },
867 b'a' => { match mac.next() {
869 Some(b) if !matches!(byte_cmd(b), Space) => {
870 match b {
871 b'a' => {
872 todo!()
873 },
874 _ => {
875 synerr!('a', "Invalid array command 'a{}'", b as char);
876 }
877 }
878 },
879 Some(_) | None => {
880 synerr!('a', "Incomplete array command 'a'");
881 }
882 }
883 },
884 b'f' => { match mac.next() {
886 Some(b) if !matches!(byte_cmd(b), Space) => {
887 match b {
888 b'z' => { push!(Value::N(st.mstk.len().into()));
890 },
891 b'r' => { st.mstk.reverse();
893 },
894 b'R' => { if let Some(va) = st.mstk.pop() {
896 if let Value::N(r) = &*va {
897 match usize::try_from(r) {
898 Ok(0) => {}, Ok(u) => {
900 if let Some(from) = st.mstk.len().checked_sub(u) {
901 st.mstk[from..].reverse();
902 }
903 else {
904 st.mstk.push(va);
905 valerr!('f', "Can't reverse {} values, stack depth is {}", u, st.mstk.len() - 1);
906 }
907 }
908 Err(_) => {
909 let vs = va.to_string();
910 st.mstk.push(va);
911 valerr!('f', "Can't possibly reverse {} values", vs);
912 }
913 }
914 }
915 else {
916 let ta = TypeLabel::from(&*va);
917 st.mstk.push(va);
918 synerr!('f', "Expected a number, {} given", ta);
919 }
920 }
921 else {
922 synerr!('f', "Expected 1 argument, 0 given");
923 }
924 },
925 b'f' => { let ri = if let Some(r) = rptr.take() {r}
927 else {
928 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
929 synerr!('f', "No register index");
930 alt = false;
931 continue 'cmd;
932 }
933 Rational::from(
934 match mac.try_next_char() {
935 Ok(c) => {c as u32},
936 Err(e) => {
937 *count = Natural::ZERO;
938 synerr!('\0', "Aborting invalid macro: {}", e);
939 break 'cmd;
940 }
941 }
942 )
943 };
944 let reg = st.regs.get_mut(&ri);
945 std::mem::swap(&mut st.mstk, &mut reg.v);
946 },
947 b'p' => { for v in &st.mstk {
949 let vs = v.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
950 if let Some(s) = &mut pbuf {
951 s.push_str(&vs);
952 s.push('\n');
953 }
954 else {
955 let mut lock = io.lock().unwrap();
956 writeln!(lock.1, "{}", vs)?;
957 lock.1.flush()?;
958 drop(lock);
959 }
960 }
961 },
962 _ => {
963 synerr!('f', "Invalid stack command 'f{}'", b as char);
964 }
965 }
966 },
967 Some(_) | None => {
968 synerr!('f', "Incomplete stack command 'f'");
969 }
970 }
971 },
972 b'N' => {
973 match (st.mstk.pop(), alt) {
974 (Some(va), false) => { match &*va {
976 Value::N(r) => {
977 match Natural::try_from(r) {
978 Ok(n) => {
979 push!(Value::N(Rational::from(
980 malachite::natural::random::get_random_natural_less_than(rng.get_or_insert_with(rng_os), &n)
981 )));
982 },
983 _ => {
984 st.mstk.push(va);
985 valerr!('N', "Limit must be a natural number");
986 }
987 }
988 },
989 _ => {
990 let ta = TypeLabel::from(&*va);
991 st.mstk.push(va);
992 synerr!('N', "Expected a number, {} given", ta);
993 }
994 }
995 }
996 (Some(va), true) => { match &*va {
998 Value::N(r) => {
999 match Integer::try_from(r) {
1000 Ok(Integer::NEGATIVE_ONE) => { rng = None;
1002 },
1003 Ok(i) if let Ok(n) = Natural::try_from(&i) => { let mut bytes: Vec<u8> = PowerOf2DigitIterable::<u8>::power_of_2_digits(&n, 8).take(32).collect();
1005 bytes.resize(32, 0);
1006 rng = Some(rng_preset(
1007 unsafe { <[u8; 32]>::try_from(bytes).unwrap_unchecked() }
1008 ));
1009 },
1010 _ => {
1011 st.mstk.push(va);
1012 valerr!('N', "Seed must be a natural number or `1");
1013 }
1014 }
1015 },
1016 _ => {
1017 let ta = TypeLabel::from(&*va);
1018 st.mstk.push(va);
1019 synerr!('N', "Expected a number, {} given", ta);
1020 }
1021 }
1022 }
1023 (None, _) => {
1024 synerr!('N', "Expected 1 argument, 0 given");
1025 }
1026 }
1027 },
1028 b'w' => { if let Some(va) = st.mstk.pop() {
1030 if let Value::N(r) = &*va {
1031 if let Some(dur) = u128::try_from(r).ok().and_then(|ns| {
1032 (ns <= std::time::Duration::MAX.as_nanos()).then(|| std::time::Duration::from_nanos_u128(ns))
1033 }) {
1034 if let Some(rx) = kill {
1035 match rx.recv_timeout(dur) {
1036 Ok(()) => { #[expect(unused_assignments)]
1038 for s in st.regs.end_threads(true) { valerr!('j', s);
1040 }
1041 return Ok(Killed);
1042 },
1043 Err(RecvTimeoutError::Timeout) => { },
1046 Err(RecvTimeoutError::Disconnected) => { unreachable!()
1048 }
1049 }
1050 }
1051 else {
1052 std::thread::sleep(dur); }
1054 }
1055 else {
1056 let vs = va.to_string();
1057 st.mstk.push(va);
1058 valerr!('w', "Can't possibly wait {} ns", vs);
1059 }
1060 }
1061 else {
1062 let ta = TypeLabel::from(&*va);
1063 st.mstk.push(va);
1064 synerr!('w', "Expected a number, {} given", ta);
1065 }
1066 }
1067 else {
1068 synerr!('w', "Expected 1 argument, 0 given");
1069 }
1070 },
1071 b'W' => {
1072 push!(Value::N(
1073 match std::time::SystemTime::UNIX_EPOCH.elapsed() {
1074 Ok(dur) => {
1075 Rational::from(dur.as_nanos())
1076 },
1077 Err(e) => {
1078 Rational::from(e.duration().as_nanos()).neg()
1079 }
1080 }
1081 ));
1082 },
1083 b'_' => { let mut word = Vec::new();
1085 while let Some(b) = mac.next() {
1086 if matches!(byte_cmd(b), Space) {
1087 mac.back();
1088 break;
1089 }
1090 else {
1091 word.push(b);
1092 }
1093 }
1094
1095 match &word[..] { b"restrict" => {
1097 #[cfg_attr(feature = "no_os", expect(unused_assignments))] { restrict = true; }
1098 },
1099 b"quiet" => {
1100 ll = LogLevel::Quiet;
1101 },
1102 b"error" => {
1103 ll = LogLevel::Normal;
1104 },
1105 b"debug" => {
1106 ll = LogLevel::Debug;
1107 },
1108 b"err" => {
1109 push!(Value::A(
1110 if let Some((n, c, s)) = elatch.take() {
1111 vec![
1112 Value::N(n.into()),
1113 Value::S(c.into()),
1114 Value::S(s)
1115 ]
1116 }
1117 else { vec![] }
1118 ));
1119 },
1120 b"th" => {
1121 push!(Value::S(th_name.clone()));
1122 },
1123 b"joinall" => {
1124 for s in st.regs.end_threads(false) {
1125 valerr!('j', s);
1126 }
1127 },
1128 b"killall" => {
1129 for s in st.regs.end_threads(true) {
1130 valerr!('j', s);
1131 }
1132 },
1133 b"thlist" => {
1134 push!(Value::A(st.regs.list_threads().into_iter().map(Value::N).collect()));
1135 },
1136 b"trim" => {
1137 st.trim();
1138 RE_CACHE.clear();
1139 },
1140 b"dedup" => {
1141 st.dedup();
1142 },
1143 b"clhist" => {
1144 io.lock().unwrap().0.clear_history();
1145 },
1146 b"clpar" => {
1147 st.params = ParamStk::default();
1148 },
1149 b"clall" => {
1150 st.clear_vals();
1151 RE_CACHE.clear();
1152 },
1153 _ => {
1154 #[cfg(feature = "no_os")]
1155 {
1156 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1157 }
1158 #[cfg(not(feature = "no_os"))]
1159 {
1160 match os::OS_CMDS.lock() {
1161 Ok(guard) => {
1162 match (restrict, guard.get(&word).copied()) {
1163 (false, Some(oscmd)) => {
1164 let res = oscmd(st);
1165 drop(guard); match res {
1167 Ok(mut v) => {
1168 append!(v);
1169 },
1170 Err(e) => {
1171 if let Some(se) = e.strip_suffix('!') {
1172 synerr!('_', "OS command '{}': {}", string_or_bytes(&word), se);
1173 }
1174 else {
1175 valerr!('_', "OS command '{}': {}", string_or_bytes(&word), e);
1176 }
1177 }
1178 }
1179 },
1180 (true, Some(_)) => {
1181 synerr!('_', "OS command '{}' is disabled (restricted mode)", string_or_bytes(&word));
1182 },
1183 _ => {
1184 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1185 }
1186 }
1187 },
1188 Err(_) => {
1189 panic!("A child thread panicked, terminating!");
1190 }
1191 }
1192 }
1193 }
1194 }
1195 },
1196 _ => unreachable!()
1197 }
1198 },
1199 ExecR => {
1200 let ri = if let Some(r) = rptr.take() {r}
1201 else {
1202 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
1203 synerr!(b as char, "No register index");
1204 alt = false;
1205 continue 'cmd;
1206 }
1207 Rational::from(
1208 match mac.try_next_char() {
1209 Ok(c) => {c as u32},
1210 Err(e) => {
1211 *count = Natural::ZERO;
1212 synerr!('\0', "Aborting invalid macro: {}", e);
1213 break 'cmd;
1214 }
1215 }
1216 )
1217 };
1218 debug!("Register command {}{}", if alt {"alt-"} else {""}, b as char);
1219 match b {
1220 b'Z' => { push!(Value::N(
1222 st.regs.try_get(&ri).map(|reg| reg.v.len().into()).unwrap_or_default()
1223 ));
1224 },
1225 b's' => {
1226 if let Some(va) = st.mstk.pop() {
1227 let reg = st.regs.get_mut(&ri);
1228 if let Some(rv) = reg.v.last_mut() {
1229 *rv = va;
1230 }
1231 else {
1232 reg.v.push(va);
1233 }
1234 }
1235 else {
1236 synerr!('s', "Stack is empty");
1237 }
1238 },
1239 b'S' => {
1240 if let Some(va) = st.mstk.pop() {
1241 st.regs.get_mut(&ri).v.push(va);
1242 }
1243 else {
1244 synerr!('S', "Stack is empty");
1245 }
1246 },
1247 b'l' => {
1248 if let Some(rv) = st.regs.try_get(&ri).and_then(|reg| reg.v.last()) {
1249 if let Some(p) = dest.last_mut() { unsafe {
1251 p.as_mut().push((**rv).clone()); }
1253 }
1254 else {
1255 st.mstk.push(Arc::clone(rv));
1256 }
1257 }
1258 else {
1259 synerr!('l', "Register {} is empty", reg_index_nice(&ri));
1260 }
1261 },
1262 b'L' => {
1263 if let Some(rv) = st.regs.try_get_mut(&ri).and_then(|reg| reg.v.pop()) {
1264 if let Some(p) = dest.last_mut() { unsafe {
1266 p.as_mut().push((*rv).clone()); }
1268 }
1269 else {
1270 st.mstk.push(Arc::clone(&rv));
1271 }
1272 }
1273 else {
1274 synerr!('L', "Register {} is empty", reg_index_nice(&ri));
1275 }
1276 },
1277 b'X' => {
1278 if let Some(true) = st.regs.try_get(&ri).map(|reg| reg.th.is_some()) {
1279 valerr!('X', "Register {} is already running a thread", reg_index_nice(&ri));
1280 }
1281 else if let Some(va) = st.mstk.pop() {
1282 if let Value::S(sa) = &*va {
1283 let th_start = sa.to_owned().into();
1284 let (ktx, krx) = std::sync::mpsc::channel::<()>();
1285 let fin: Arc<LazyLock<_>> = Arc::new(LazyLock::new(|| ()));
1286 let th_fin = Arc::clone(&fin);
1287 let jbar = Arc::new(std::sync::Barrier::new(2));
1288 let th_jbar = Arc::clone(&jbar);
1289 let tb = std::thread::Builder::new().name(format!("{th_name}{}: ", reg_index_nice(&ri)));
1290 let mut th_st = if alt { st.clone() } else { State::default() };
1291 let th_io = Arc::clone(&io);
1292
1293 match tb.spawn(move || {
1294 let th_res = unsafe { interpreter(&mut th_st, th_start, th_io, ll, Some(&krx), restrict) };
1296 LazyLock::force(&th_fin); th_jbar.wait(); th_st.regs.end_threads( th_res.is_err() ||
1302 match krx.try_recv() { Ok(()) => { true },
1304 Err(TryRecvError::Empty) => { false },
1305 Err(TryRecvError::Disconnected) => { unreachable!() } }
1307 );
1308
1309 (th_st.mstk, th_res)
1310 }) {
1312 Ok(jh) => {
1313 st.regs.get_mut(&ri).th = Some(ThreadHandle{fin, ktx, jbar, jh});
1314 },
1315 Err(e) => {
1316 st.mstk.push(va);
1317 valerr!('X', "Can't spawn child thread: {}", e);
1318 }
1319 }
1320 }
1321 else {
1322 let ta = TypeLabel::from(&*va);
1323 st.mstk.push(va);
1324 synerr!('X', "Expected a macro string, {} given", ta);
1325 }
1326 }
1327 else {
1328 synerr!('X', "Expected 1 argument, 0 given");
1329 }
1330 },
1331 b'j' => {
1332 let ri_nice = reg_index_nice(&ri);
1333 if let Some(reg) = st.regs.try_get_mut(&ri) && let Some(th) = reg.th.take() {
1334 if alt {
1335 th.ktx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", ri_nice));
1336 }
1337 let (mut vals, th_res) = th.join();
1338 match th_res {
1339 Err(e) => {
1340 let s = format!("IO error in thread {}: {}", ri_nice, e);
1341 eprintln!("? {th_name}j: {}", s); elatch = Some((Natural::ZERO, 'j', s));
1343 },
1344 Ok(SoftQuit(c)) if c != 0 => {
1345 valerr!('j', "Thread {} quit with code {}", ri_nice, c);
1346 },
1347 Ok(HardQuit(c)) if c != 0 => {
1348 valerr!('j', "Thread {} hard-quit with code {}", ri_nice, c);
1349 },
1350 Ok(Killed) => {
1351 valerr!('j', "Thread {} was killed", ri_nice);
1352 },
1353 _ => {} }
1355
1356 reg.v.append(&mut vals);
1357 }
1358 else {
1359 valerr!('j', "Register {} is not running a thread", ri_nice);
1360 }
1361 },
1362 b'J' => {
1363 if let Some(th) = st.regs.try_get(&ri).and_then(|reg| reg.th.as_ref()) {
1364 let mut bz = BitVec::new();
1365 bz.push(th.is_finished());
1366 push!(Value::B(bz));
1367 }
1368 else {
1369 valerr!('J', "Register {} is not running a thread", reg_index_nice(&ri));
1370 }
1371 },
1372 _ => unreachable!()
1373 }
1374 },
1375 Lit => {
1376 match b {
1377 b'T' | b'F' => { debug!("Boolean literal");
1379 let mut bits = BitVec::new();
1380 bits.push(b == b'T');
1381 while let Some(b) = mac.next() {
1382 match b {
1383 b'T' => {bits.push(true);},
1384 b'F' => {bits.push(false);},
1385 _ => {
1386 mac.back();
1387 break;
1388 }
1389 }
1390 }
1391 push!(Value::B(bits));
1392 },
1393 b'\'' | b'0'..=b'9' | b'.' | b'@' => { debug!("Number literal");
1395 let mut ipart = Vec::new();
1396 let mut fpart = Vec::new();
1397 let mut rpart = Vec::new();
1398 let mut get_epart = true;
1399 let mut exp = None;
1400 let mut discard = false;
1401 let mut ibase = st.params.get_i().clone();
1402
1403 match (b == b'\'', ibase > Natural::const_from(36) || ibase == Natural::ONE) {
1404 (false, high_base) => { mac.back();
1406 ibase = if high_base {Natural::const_from(10)} else {ibase}; while let Some(ib) = mac.next() { let id = ib.wrapping_sub(0x30);
1409 match id {
1410 0..=9 if id < ibase => {ipart.push(Natural::from(id));},
1411 0..=9 => {
1412 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1413 discard = true;
1414 },
1415 _ => {
1416 mac.back();
1417 break;
1418 }
1419 }
1420 }
1421 match mac.next() {
1422 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1425 let fd = fb.wrapping_sub(0x30);
1426 match fd {
1427 0x30 if !recur => {recur = true;}, 0..=9 if !recur && fd < ibase => {fpart.push(Natural::from(fd));},
1429 0..=9 if recur && fd < ibase => {rpart.push(Natural::from(fd));},
1430 0..=9 => {
1431 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1432 discard = true;
1433 },
1434 _ => {
1435 mac.back();
1436 break;
1437 }
1438 }
1439 }
1440 },
1441 Some(_) => {mac.back();},
1442 None => {}
1443 }
1444 }
1445 (true, false) => { while let Some(ib) = mac.next() { if let Some(id) = mixed_ascii_to_digit(ib) {
1448 if id < ibase {ipart.push(Natural::from(id));}
1449 else {
1450 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1451 discard = true;
1452 }
1453 }
1454 else {
1455 mac.back();
1456 break;
1457 }
1458 }
1459 match mac.next() {
1460 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1463 if let Some(fd) = mixed_ascii_to_digit(fb) {
1464 if fd < ibase {
1465 if !recur {fpart.push(Natural::from(fd));}
1466 else {rpart.push(Natural::from(fd));}
1467 }
1468 else {
1469 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1470 discard = true;
1471 }
1472 }
1473 else if !recur && fb == b'`' {recur = true;}
1474 else {
1475 mac.back();
1476 break;
1477 }
1478 }
1479 },
1480 Some(_) => {mac.back();},
1481 None => {}
1482 }
1483 },
1484 (true, true) => { get_epart = false;
1486 let ns= mac.by_ref().take_while(|b| *b != b'\'').collect::<Vec<u8>>();
1487 if ns.is_empty() {
1488 synerr!('\'', "Empty any-base number");
1489 alt = false;
1490 continue 'cmd;
1491 }
1492 for nc in ns.iter() {
1493 match nc {
1494 b' ' | b'.' | b'0'..=b'9' | b'@' | b'`' => {} wrong => {
1496 synerr!('\'', "Invalid character in any-base number: {}", string_or_bytes(&[*wrong]));
1497 alt = false;
1498 continue 'cmd;
1499 }
1500 }
1501 }
1502 let ms;
1503 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1504 [mpart] => { if let Some((b'`', rest)) = mpart.split_first() { alt = true;
1507 ms = rest.to_vec();
1508 }
1509 else {
1510 ms = mpart.to_vec();
1511 }
1512 },
1513 [mpart, epart] => { ms = mpart.to_vec();
1515 let mut es = epart.to_vec();
1516 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1517 match String::from_utf8(es) {
1518 Ok(es) => {
1519 match es.parse::<i64>() {
1520 Ok(i) => { exp = Some(i); },
1521 Err(e) => {
1522 use std::num::IntErrorKind::*;
1523 match e.kind() {
1524 Empty => { exp = Some(0); },
1525 InvalidDigit => {
1526 valerr!('\'', "Invalid exponent: {}", es);
1527 alt = false;
1528 continue 'cmd;
1529 },
1530 PosOverflow | NegOverflow => {
1531 valerr!('\'', "Exponent {} is unrepresentable", es);
1532 alt = false;
1533 continue 'cmd;
1534 },
1535 _ => { unreachable!() }
1536 }
1537 }
1538 }
1539 },
1540 _ => { unreachable!() }
1541 }
1542 },
1543 ref v => {
1544 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1545 alt = false;
1546 continue 'cmd;
1547 }
1548 }
1549 let is;
1550 let frs;
1551 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1552 [ipart] => {
1553 is = ipart.to_vec();
1554 frs = Vec::new();
1555 },
1556 [ipart, fpart] => {
1557 is = ipart.to_vec();
1558 frs = fpart.to_vec();
1559 },
1560 ref v => {
1561 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1562 alt = false;
1563 continue 'cmd;
1564 }
1565 }
1566 if is.contains(&b'`') {
1567 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1568 alt = false;
1569 continue 'cmd;
1570 }
1571 let fs;
1572 let rs;
1573 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1574 [fpart] => {
1575 fs = fpart.to_vec();
1576 rs = Vec::new();
1577 },
1578 [fpart, rpart] => {
1579 if ibase != Natural::ONE {
1580 fs = fpart.to_vec();
1581 rs = rpart.to_vec();
1582 }
1583 else {
1584 synerr!('\'', "Recurring digits (`) are not allowed in factoradic numbers");
1585 alt = false;
1586 continue 'cmd;
1587 }
1588 },
1589 ref v => {
1590 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1591 alt = false;
1592 continue 'cmd;
1593 }
1594 }
1595 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1596 let id = str::from_utf8(id).unwrap();
1597 ipart.push(Natural::from_str(id).unwrap());
1598 }}
1599 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1600 let fd = str::from_utf8(fd).unwrap();
1601 fpart.push(Natural::from_str(fd).unwrap());
1602 }}
1603 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1604 let rd = str::from_utf8(rd).unwrap();
1605 rpart.push(Natural::from_str(rd).unwrap());
1606 }}
1607 if ibase != Natural::ONE { for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1608 if *d >= ibase {
1609 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
1610 alt = false;
1611 continue 'cmd;
1612 }
1613 }}
1614 else { for (i, d) in ipart.iter().rev().enumerate().chain(fpart.iter().enumerate()) {
1615 if *d >= i+2 { synerr!('\'', "Digit {} is too high for factoradic place {} away from the '.'", d, i);
1617 alt = false;
1618 continue 'cmd;
1619 }
1620 }}
1621 }
1622 }
1623
1624 let m_empty = ipart.is_empty() && fpart.is_empty() && rpart.is_empty(); let mut r;
1626 match (m_empty, ibase != Natural::ONE) {
1627 (true, true) => { r = Rational::ZERO;
1629 },
1630 (true, false) => { if let Some(i) = exp.take() { if let Ok(u) = u64::try_from(i) {
1633 r = Rational::from(Natural::factorial(u+1));
1634 }
1635 else {
1636 r = Rational::from_naturals(Natural::ONE, Natural::factorial(i.unsigned_abs()+1));
1637 }
1638 }
1639 else {
1640 r = Rational::ZERO;
1641 }
1642 },
1643 (false, true) => { ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1646 if alt {r.neg_assign();} },
1648 (false, false) => { if let Some(i) = exp.take() { if let Ok(u) = u64::try_from(i) {
1651 let mut fi = fpart.into_iter();
1652 ipart.extend(fi.by_ref().chain(std::iter::repeat(Natural::ZERO)).take(u as usize));
1653 fpart = fi.collect();
1654 }
1655 else {
1656 let mut temp = ipart.split_off(ipart.len().saturating_sub(i.unsigned_abs() as usize));
1657 temp.append(&mut fpart);
1658 fpart = temp;
1659 }
1660 }
1661
1662 let mut ii = ipart.iter().rev().peekable();
1663 let mut fi = fpart.iter().peekable();
1664 let mut d = Natural::TWO; r = if let Some(n) = ii.next() {n.into()} else {Rational::ZERO}; for n in malachite::natural::exhaustive::exhaustive_natural_range_to_infinity(Natural::const_from(3)) {
1669 if let Some(id) = ii.next() {
1670 r += Rational::from(id * &d);
1671 }
1672 if let Some(fd) = fi.next() {
1673 r += Rational::from_naturals_ref(fd, &d);
1674 }
1675 if ii.peek().or_else(|| fi.peek()).is_none() {break;}
1676 d *= n;
1677 }
1678
1679 if alt {r.neg_assign();} }
1681 }
1682
1683 if get_epart {
1684 match mac.next() {
1685 Some(b'@') => { let mut es = String::new();
1687 let mut eneg = false; while let Some(eb) = mac.next() {
1689 match eb {
1690 b'`' if !eneg => { es.push('-'); }
1691 b'0'..=b'9' => { es.push(eb as char); }
1692 _ => {
1693 mac.back();
1694 break;
1695 }
1696 }
1697 eneg = true; }
1699 if es.is_empty() { es.push('0'); }
1700 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1702 r *= Rational::from(ibase).pow(i); }
1704 else {
1705 valerr!('\'', "Exponent {} is unrepresentable", es);
1706 discard = true;
1707 }
1708 }
1709 Some(_) => { mac.back(); }
1710 None => {}
1711 }
1712 }
1713 else if let Some(i) = exp {
1714 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1717
1718 if !discard {
1719 push!(Value::N(r));
1720 }
1721 },
1722 b'[' => { debug!("String literal");
1724 let mut bytes = Vec::new();
1725 let mut discard = false;
1726 let mut nest = 1usize;
1727 while let Some(b) = mac.next() {
1728 match b {
1729 b'[' => {
1730 nest = unsafe { nest.unchecked_add(1) };
1731 bytes.push(b'[');
1732 },
1733 b']' => {
1734 nest = unsafe { nest.unchecked_sub(1) };
1735 if nest == 0 {
1736 break;
1737 }
1738 else {
1739 bytes.push(b']');
1740 }
1741 },
1742 b'\\' => { match mac.next() {
1744 Some(b'a') => {bytes.push(0x07);}, Some(b'b') => {bytes.push(0x08);}, Some(b't') => {bytes.push(0x09);}, Some(b'n') => {bytes.push(0x0A);}, Some(b'v') => {bytes.push(0x0B);}, Some(b'f') => {bytes.push(0x0C);}, Some(b'r') => {bytes.push(0x0D);}, Some(b'e') => {bytes.push(0x1B);}, Some(b'[') => {bytes.push(b'[');}, Some(b']') => {bytes.push(b']');}, Some(b'\\') => {bytes.push(b'\\');}, Some(b0) => { if let Some(high) = upper_hex_to_nibble(b0) { if let Some(b1) = mac.next() {
1758 if let Some(low) = upper_hex_to_nibble(b1) {
1759 bytes.push(high << 4 | low);
1760 }
1761 else {
1762 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1763 discard = true;
1764 }
1765 }
1766 else {
1767 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1768 discard = true;
1769 }
1770 }
1771 else { mac.back();
1773 match mac.try_next_char() {
1774 Ok(c) => {
1775 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1776 discard = true;
1777 },
1778 Err(e) => {
1779 *count = Natural::ZERO;
1780 synerr!('\0', "Aborting invalid macro: {}", e);
1781 break 'cmd;
1782 }
1783 }
1784 }
1785 },
1786 None => {
1787 synerr!('[', "Incomplete character escape: \\");
1788 discard = true;
1789 }
1790 }
1791 },
1792 _ => {
1793 bytes.push(b);
1794 }
1795 }
1796 }
1797 if !discard {
1798 match String::try_from(Utf8Iter::from(bytes)) {
1799 Ok(s) => {
1800 push!(Value::S(s));
1801 },
1802 Err(e) => {
1803 synerr!('[', "Invalid string: {}", e);
1804 }
1805 }
1806 }
1807 },
1808 _ => unreachable!()
1809 }
1810 },
1811 Space if b == b'#' => { debug!("Line comment");
1813 mac.find(|b| *b == b'\n'); },
1815 Space => {
1816 },
1818 Wrong => {
1819 mac.back();
1820 match mac.try_next_char() {
1821 Ok(c) => {
1822 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1823 },
1824 Err(e) => {
1825 *count = Natural::ZERO;
1826 synerr!('\0', "Aborting invalid macro: {}", e);
1827 break 'cmd;
1828 }
1829 }
1830 }
1831 }
1832
1833 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1838 dest.clear(); }
1840
1841 *count -= Natural::ONE; if *count == Natural::ZERO { call.pop();
1845 }
1846 else { mac.rewind();
1848 }
1849 } Ok(Finished)
1852}