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, 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::{ConvertibleFrom, 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 err = &mut io.lock().unwrap().2;
368 writeln!(err, "! {th_name}{}: {}", $c, $s)?;
369 err.flush()?;
370 }
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 err = &mut io.lock().unwrap().2;
378 writeln!(err, "! {th_name}{}: {}", $c, s)?;
379 err.flush()?;
380 }
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 err = &mut io.lock().unwrap().2;
390 writeln!(err, "? {th_name}{}: {}", $c, $s)?;
391 err.flush()?;
392 }
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 err = &mut io.lock().unwrap().2;
400 writeln!(err, "? {th_name}{}: {}", $c, s)?;
401 err.flush()?;
402 }
404 elatch = Some((Natural::ZERO, $c, s));
405 };
406 }
407
408 macro_rules! debug {
409 ($s:expr) => {
410 if ll == LogLevel::Debug {
411 let err = &mut io.lock().unwrap().2;
412 writeln!(err, "\tDEBUG: {th_name}{}", $s)?;
413 err.flush()?;
414 }
416 };
417 ($f:literal, $($s:expr),*) => {
418 if ll == LogLevel::Debug {
419 let err = &mut io.lock().unwrap().2;
420 writeln!(err, "\tDEBUG: {th_name}{}", format!($f, $($s),*))?;
421 err.flush()?;
422 }
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::const_from(1))];
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 res = {
717 let inp = &mut io.lock().unwrap().0;
718 inp.read_line()
719 };
721 match res {
722 Ok(s) => {
723 push!(Value::S(s));
724 },
725 Err(e) => {
726 match e.kind() {
727 ErrorKind::Interrupted => {
728 valerr!('?', "Interrupted");
729 },
730 ErrorKind::UnexpectedEof => {
731 push!(Value::S(String::new()));
732 },
733 _ => {
734 return Err(e);
735 }
736 }
737 }
738 }
739 },
740 b'p' => { if let Some(va) = st.mstk.pop() {
742 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
743 if let Some(s) = &mut pbuf {
744 s.push_str(&vs);
745 s.push('\n');
746 }
747 else {
748 let out = &mut io.lock().unwrap().1;
749 writeln!(out, "{}", vs)?;
750 out.flush()?;
751 }
753 }
754 else {
755 synerr!('p', "Expected 1 argument, 0 given");
756 }
757 },
758 b'P' => { if let Some(va) = st.mstk.pop() {
760 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
761 if let Some(s) = &mut pbuf {
762 s.push_str(&vs);
763 }
764 else {
765 let out = &mut io.lock().unwrap().1;
766 write!(out, "{}", vs)?;
767 out.flush()?;
768 }
770 }
771 else {
772 synerr!('P', "Expected 1 argument, 0 given");
773 }
774 },
775 b'"' => { if let Some(s) = pbuf.take() { push!(Value::S(s));
778 }
779 else { pbuf = Some(String::new());
781 }
782 },
783 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)
788 }}
789 else {
790 NonNull::from(&mut abuf) };
792 dest.push(nn);
793 },
794 b')' => { if dest.pop().is_some() {
796 if dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf)))); }
799 }
800 else {
801 synerr!(')', "Mismatched closing ')'");
802 }
803 },
804 b'x' => {
805 if let Some(top) = st.mstk.pop() {
806 let sec = st.mstk.pop();
807 match Utf8Iter::try_macros(&top, sec.as_deref()) {
808 Ok((stk, ret)) => {
809 if let Some(sec) = sec && ret { st.mstk.push(sec);
811 }
812
813 if mac.is_finished() && *count == Natural::ZERO { call.pop();
815 }
816
817 call.extend(stk.into_iter().rev());
818 continue 'mac;
819 },
820 Err(e) => {
821 if let Some(sec) = sec {st.mstk.push(sec);}
822 st.mstk.push(top);
823 synerr!('x', "{}", e);
824 }
825 }
826 }
827 else {
828 synerr!('x', "Expected 1 or 2 arguments, 0 given");
829 }
830 },
831 b'q' => {
832 let u = u8::wrapping_from(&Integer::rounding_from(rptr.unwrap_or_default(), RoundingMode::Down).0);
833 return if alt {
834 Ok(HardQuit(u))
835 }
836 else {
837 Ok(SoftQuit(u))
838 };
839 },
840 b'Q' => {
841 if let Some(va) = st.mstk.pop() {
842 match &*va {
843 Value::N(r) => {
844 if let Ok(u) = usize::try_from(r) {
845 call.truncate(call.len().saturating_sub(u));
846 if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
848 dest.clear(); }
850 continue 'mac;
851 }
852 else {
853 let vs = va.to_string();
854 st.mstk.push(va);
855 valerr!('Q', "Cannot possibly break {} macros", vs);
856 }
857 },
858 _ => {
859 let ta = TypeLabel::from(&*va);
860 st.mstk.push(va);
861 synerr!('Q', "Expected a number, {} given", ta);
862 }
863 }
864 }
865 else {
866 synerr!('Q', "Expected 1 argument, 0 given");
867 }
868 },
869 b'a' => { match mac.next() {
871 Some(b) if !matches!(byte_cmd(b), Space) => {
872 match b {
873 b'a' => {
874 todo!()
875 },
876 _ => {
877 synerr!('a', "Invalid array command 'a{}'", b as char);
878 }
879 }
880 },
881 Some(_) | None => {
882 synerr!('a', "Incomplete array command 'a'");
883 }
884 }
885 },
886 b'f' => { match mac.next() {
888 Some(b) if !matches!(byte_cmd(b), Space) => {
889 match b {
890 b'z' => { push!(Value::N(st.mstk.len().into()));
892 },
893 b'r' => { st.mstk.reverse();
895 },
896 b'R' => { if let Some(va) = st.mstk.pop() {
898 if let Value::N(r) = &*va {
899 match usize::try_from(r) {
900 Ok(0) => {}, Ok(u) => {
902 if let Some(from) = st.mstk.len().checked_sub(u) {
903 st.mstk[from..].reverse();
904 }
905 else {
906 st.mstk.push(va);
907 valerr!('f', "Can't reverse {} values, stack depth is {}", u, st.mstk.len() - 1);
908 }
909 }
910 Err(_) => {
911 let vs = va.to_string();
912 st.mstk.push(va);
913 valerr!('f', "Can't possibly reverse {} values", vs);
914 }
915 }
916 }
917 else {
918 let ta = TypeLabel::from(&*va);
919 st.mstk.push(va);
920 synerr!('f', "Expected a number, {} given", ta);
921 }
922 }
923 else {
924 synerr!('f', "Expected 1 argument, 0 given");
925 }
926 },
927 b'f' => { let ri = if let Some(r) = rptr.take() {r}
929 else {
930 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
931 synerr!('f', "No register index");
932 alt = false;
933 continue 'cmd;
934 }
935 Rational::from(
936 match mac.try_next_char() {
937 Ok(c) => {c as u32},
938 Err(e) => {
939 *count = Natural::ZERO;
940 synerr!('\0', "Aborting invalid macro: {}", e);
941 break 'cmd;
942 }
943 }
944 )
945 };
946 let reg = st.regs.get_mut(&ri);
947 std::mem::swap(&mut st.mstk, &mut reg.v);
948 },
949 b'p' => { for v in &st.mstk {
951 let vs = v.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
952 if let Some(s) = &mut pbuf {
953 s.push_str(&vs);
954 s.push('\n');
955 }
956 else {
957 let out = &mut io.lock().unwrap().1;
958 writeln!(out, "{}", vs)?;
959 out.flush()?;
960 }
961 }
962 },
963 _ => {
964 synerr!('f', "Invalid stack command 'f{}'", b as char);
965 }
966 }
967 },
968 Some(_) | None => {
969 synerr!('f', "Incomplete stack command 'f'");
970 }
971 }
972 },
973 b'N' => {
974 match (st.mstk.pop(), alt) {
975 (Some(va), false) => { match &*va {
977 Value::N(r) => {
978 match Natural::try_from(r) {
979 Ok(n) => {
980 push!(Value::N(Rational::from(
981 malachite::natural::random::get_random_natural_less_than(rng.get_or_insert_with(rng_os), &n)
982 )));
983 },
984 _ => {
985 st.mstk.push(va);
986 valerr!('N', "Limit must be a natural number");
987 }
988 }
989 },
990 _ => {
991 let ta = TypeLabel::from(&*va);
992 st.mstk.push(va);
993 synerr!('N', "Expected a number, {} given", ta);
994 }
995 }
996 }
997 (Some(va), true) => { match &*va {
999 Value::N(r) => {
1000 match Integer::try_from(r) {
1001 Ok(Integer::NEGATIVE_ONE) => { rng = None;
1003 },
1004 Ok(i) if Natural::convertible_from(&i) => { let n= unsafe { Natural::try_from(i).unwrap_unchecked() }; let mut bytes: Vec<u8> = PowerOf2DigitIterable::<u8>::power_of_2_digits(&n, 8).take(32).collect();
1007 bytes.resize(32, 0);
1008 rng = Some(rng_preset(
1009 unsafe { <[u8; 32]>::try_from(bytes).unwrap_unchecked() }
1010 ));
1011 },
1012 _ => {
1013 st.mstk.push(va);
1014 valerr!('N', "Seed must be a natural number or `1");
1015 }
1016 }
1017 },
1018 _ => {
1019 let ta = TypeLabel::from(&*va);
1020 st.mstk.push(va);
1021 synerr!('N', "Expected a number, {} given", ta);
1022 }
1023 }
1024 }
1025 (None, _) => {
1026 synerr!('N', "Expected 1 argument, 0 given");
1027 }
1028 }
1029 },
1030 b'w' => { if let Some(va) = st.mstk.pop() {
1032 if let Value::N(r) = &*va {
1033 if let Some(dur) = u128::try_from(r).ok().and_then(|ns| {
1034 (ns <= std::time::Duration::MAX.as_nanos()).then(|| std::time::Duration::from_nanos_u128(ns))
1035 }) {
1036 if let Some(rx) = kill {
1037 match rx.recv_timeout(dur) {
1038 Ok(()) => { #[expect(unused_assignments)]
1040 for s in st.regs.end_threads(true) { valerr!('j', s);
1042 }
1043 return Ok(Killed);
1044 },
1045 Err(RecvTimeoutError::Timeout) => { },
1048 Err(RecvTimeoutError::Disconnected) => { unreachable!()
1050 }
1051 }
1052 }
1053 else {
1054 std::thread::sleep(dur); }
1056 }
1057 else {
1058 let vs = va.to_string();
1059 st.mstk.push(va);
1060 valerr!('w', "Can't possibly wait {} ns", vs);
1061 }
1062 }
1063 else {
1064 let ta = TypeLabel::from(&*va);
1065 st.mstk.push(va);
1066 synerr!('w', "Expected a number, {} given", ta);
1067 }
1068 }
1069 else {
1070 synerr!('w', "Expected 1 argument, 0 given");
1071 }
1072 },
1073 b'W' => {
1074 push!(Value::N(
1075 match std::time::SystemTime::UNIX_EPOCH.elapsed() {
1076 Ok(dur) => {
1077 Rational::from(dur.as_nanos())
1078 },
1079 Err(e) => {
1080 Rational::from(e.duration().as_nanos()).neg()
1081 }
1082 }
1083 ));
1084 },
1085 b'_' => { let mut word = Vec::new();
1087 while let Some(b) = mac.next() {
1088 if matches!(byte_cmd(b), Space) {
1089 mac.back();
1090 break;
1091 }
1092 else {
1093 word.push(b);
1094 }
1095 }
1096
1097 match &word[..] { b"restrict" => {
1099 #[cfg_attr(feature = "no_os", expect(unused_assignments))] { restrict = true; }
1100 },
1101 b"quiet" => {
1102 ll = LogLevel::Quiet;
1103 },
1104 b"error" => {
1105 ll = LogLevel::Normal;
1106 },
1107 b"debug" => {
1108 ll = LogLevel::Debug;
1109 },
1110 b"err" => {
1111 push!(Value::A(
1112 if let Some((n, c, s)) = elatch.take() {
1113 vec![
1114 Value::N(n.into()),
1115 Value::S(c.into()),
1116 Value::S(s)
1117 ]
1118 }
1119 else { vec![] }
1120 ));
1121 },
1122 b"th" => {
1123 push!(Value::S(th_name.clone()));
1124 },
1125 b"joinall" => {
1126 for s in st.regs.end_threads(false) {
1127 valerr!('j', s);
1128 }
1129 },
1130 b"killall" => {
1131 for s in st.regs.end_threads(true) {
1132 valerr!('j', s);
1133 }
1134 },
1135 b"trim" => {
1136 st.trim();
1137 RE_CACHE.clear();
1138 },
1139 b"dedup" => {
1140 st.dedup();
1141 },
1142 b"clhist" => {
1143 io.lock().unwrap().0.clear_history();
1144 },
1145 b"clpar" => {
1146 st.params = ParamStk::default();
1147 },
1148 b"clall" => {
1149 st.clear_vals();
1150 RE_CACHE.clear();
1151 },
1152 _ => {
1153 #[cfg(feature = "no_os")]
1154 {
1155 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1156 }
1157 #[cfg(not(feature = "no_os"))]
1158 {
1159 match os::OS_CMDS.lock() {
1160 Ok(guard) => {
1161 match (restrict, guard.get(&word).copied()) {
1162 (false, Some(oscmd)) => {
1163 let res = oscmd(st);
1164 drop(guard); match res {
1166 Ok(mut v) => {
1167 append!(v);
1168 },
1169 Err(e) => {
1170 if let Some(se) = e.strip_suffix('!') {
1171 synerr!('_', "OS command '{}': {}", string_or_bytes(&word), se);
1172 }
1173 else {
1174 valerr!('_', "OS command '{}': {}", string_or_bytes(&word), e);
1175 }
1176 }
1177 }
1178 },
1179 (true, Some(_)) => {
1180 synerr!('_', "OS command '{}' is disabled (restricted mode)", string_or_bytes(&word));
1181 },
1182 _ => {
1183 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1184 }
1185 }
1186 },
1187 Err(_) => {
1188 panic!("A child thread panicked, terminating!");
1189 }
1190 }
1191 }
1192 }
1193 }
1194 },
1195 _ => unreachable!()
1196 }
1197 },
1198 ExecR => {
1199 let ri = if let Some(r) = rptr.take() {r}
1200 else {
1201 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
1202 synerr!(b as char, "No register index");
1203 alt = false;
1204 continue 'cmd;
1205 }
1206 Rational::from(
1207 match mac.try_next_char() {
1208 Ok(c) => {c as u32},
1209 Err(e) => {
1210 *count = Natural::ZERO;
1211 synerr!('\0', "Aborting invalid macro: {}", e);
1212 break 'cmd;
1213 }
1214 }
1215 )
1216 };
1217 debug!("Register command {}{}", if alt {"alt-"} else {""}, b as char);
1218 match b {
1219 b'Z' => { push!(Value::N(
1221 st.regs.try_get(&ri).map(|reg| reg.v.len().into()).unwrap_or_default()
1222 ));
1223 },
1224 b's' => {
1225 if let Some(va) = st.mstk.pop() {
1226 let reg = st.regs.get_mut(&ri);
1227 if let Some(rv) = reg.v.last_mut() {
1228 *rv = va;
1229 }
1230 else {
1231 reg.v.push(va);
1232 }
1233 }
1234 else {
1235 synerr!('s', "Stack is empty");
1236 }
1237 },
1238 b'S' => {
1239 if let Some(va) = st.mstk.pop() {
1240 st.regs.get_mut(&ri).v.push(va);
1241 }
1242 else {
1243 synerr!('S', "Stack is empty");
1244 }
1245 },
1246 b'l' => {
1247 if let Some(rv) = st.regs.try_get(&ri).and_then(|reg| reg.v.last()) {
1248 if let Some(p) = dest.last_mut() { unsafe {
1250 p.as_mut().push((**rv).clone()); }
1252 }
1253 else {
1254 st.mstk.push(Arc::clone(rv));
1255 }
1256 }
1257 else {
1258 synerr!('l', "Register {} is empty", reg_index_nice(&ri));
1259 }
1260 },
1261 b'L' => {
1262 if let Some(rv) = st.regs.try_get_mut(&ri).and_then(|reg| reg.v.pop()) {
1263 if let Some(p) = dest.last_mut() { unsafe {
1265 p.as_mut().push((*rv).clone()); }
1267 }
1268 else {
1269 st.mstk.push(Arc::clone(&rv));
1270 }
1271 }
1272 else {
1273 synerr!('L', "Register {} is empty", reg_index_nice(&ri));
1274 }
1275 },
1276 b'X' => {
1277 if let Some(true) = st.regs.try_get(&ri).map(|reg| reg.th.is_some()) {
1278 valerr!('X', "Register {} is already running a thread", reg_index_nice(&ri));
1279 }
1280 else if let Some(va) = st.mstk.pop() {
1281 if let Value::S(sa) = &*va {
1282 let th_start = sa.to_owned().into();
1283 let (ktx, krx) = std::sync::mpsc::channel::<()>();
1284 let (jtx, jrx) = std::sync::mpsc::channel::<()>();
1285 let tb = std::thread::Builder::new().name(format!("{th_name}{}: ", reg_index_nice(&ri)));
1286 let mut th_st = if alt { st.clone() } else { State::default() };
1287 let th_io = Arc::clone(&io);
1288
1289 match tb.spawn(move || {
1290 let th_res = unsafe { interpreter(&mut th_st, th_start, th_io, ll, Some(&krx), restrict) };
1292
1293 let _ = jrx.recv(); th_st.regs.end_threads( th_res.is_err() ||
1297 match krx.try_recv() { Ok(()) => { true },
1299 Err(TryRecvError::Empty) => { false },
1300 Err(TryRecvError::Disconnected) => { unreachable!() } }
1302 );
1303
1304 (th_st.mstk, th_res)
1305 }) {
1307 Ok(jh) => {
1308 st.regs.get_mut(&ri).th = Some((jh, ktx, jtx));
1309 },
1310 Err(e) => {
1311 st.mstk.push(va);
1312 valerr!('X', "Can't spawn child thread: {}", e);
1313 }
1314 }
1315 }
1316 else {
1317 let ta = TypeLabel::from(&*va);
1318 st.mstk.push(va);
1319 synerr!('X', "Expected a macro string, {} given", ta);
1320 }
1321 }
1322 else {
1323 synerr!('X', "Expected 1 argument, 0 given");
1324 }
1325 },
1326 b'j' => {
1327 let ri_nice = reg_index_nice(&ri);
1328 if let Some(reg) = st.regs.try_get_mut(&ri) && let Some((jh, ktx, jtx)) = reg.th.take() {
1329 if alt {
1330 ktx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", ri_nice));
1331 }
1332 jtx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", ri_nice));
1333 match jh.join() {
1334 Ok(mut tr) => {
1335 match tr.1 {
1336 Err(e) => {
1337 let s = format!("IO error in thread {}: {}", ri_nice, e);
1338 eprintln!("? {th_name}j: {}", s); elatch = Some((Natural::ZERO, 'j', s));
1340 },
1341 Ok(SoftQuit(c)) if c != 0 => {
1342 valerr!('j', "Thread {} quit with code {}", ri_nice, c);
1343 },
1344 Ok(HardQuit(c)) if c != 0 => {
1345 valerr!('j', "Thread {} hard-quit with code {}", ri_nice, c);
1346 },
1347 Ok(Killed) => {
1348 valerr!('j', "Thread {} was killed", ri_nice);
1349 },
1350 _ => {} }
1352
1353 reg.v.append(&mut tr.0);
1354 },
1355 Err(e) => {
1356 std::panic::resume_unwind(e);
1357 }
1358 }
1359 }
1360 else {
1361 valerr!('j', "Register {} is not running a thread", ri_nice);
1362 }
1363 },
1364 b'J' => {
1365 if let Some(Some((jh, _, _))) = st.regs.try_get(&ri).map(|reg| ®.th) {
1366 let mut bz = BitVec::new();
1367 bz.push(jh.is_finished());
1368 push!(Value::B(bz));
1369 }
1370 else {
1371 valerr!('J', "Register {} is not running a thread", reg_index_nice(&ri));
1372 }
1373 },
1374 _ => unreachable!()
1375 }
1376 },
1377 Lit => {
1378 match b {
1379 b'T' | b'F' => { debug!("Boolean literal");
1381 let mut bits = BitVec::new();
1382 bits.push(b == b'T');
1383 while let Some(b) = mac.next() {
1384 match b {
1385 b'T' => {bits.push(true);},
1386 b'F' => {bits.push(false);},
1387 _ => {
1388 mac.back();
1389 break;
1390 }
1391 }
1392 }
1393 push!(Value::B(bits));
1394 },
1395 b'\'' | b'0'..=b'9' | b'.' | b'@' => { debug!("Number literal");
1397 let mut ipart = Vec::new();
1398 let mut fpart = Vec::new();
1399 let mut rpart = Vec::new();
1400 let mut get_epart = true;
1401 let mut exp = None;
1402 let mut discard = false;
1403 let mut ibase = st.params.get_i().clone();
1404
1405 match (b == b'\'', ibase > Natural::const_from(36) || ibase == Natural::ONE) {
1406 (false, high_base) => { mac.back();
1408 ibase = if high_base {Natural::const_from(10)} else {ibase}; while let Some(ib) = mac.next() { let id = ib.wrapping_sub(0x30);
1411 match id {
1412 0..=9 if id < ibase => {ipart.push(Natural::from(id));},
1413 0..=9 => {
1414 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1415 discard = true;
1416 },
1417 _ => {
1418 mac.back();
1419 break;
1420 }
1421 }
1422 }
1423 match mac.next() {
1424 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1427 let fd = fb.wrapping_sub(0x30);
1428 match fd {
1429 0x30 if !recur => {recur = true;}, 0..=9 if !recur && fd < ibase => {fpart.push(Natural::from(fd));},
1431 0..=9 if recur && fd < ibase => {rpart.push(Natural::from(fd));},
1432 0..=9 => {
1433 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1434 discard = true;
1435 },
1436 _ => {
1437 mac.back();
1438 break;
1439 }
1440 }
1441 }
1442 },
1443 Some(_) => {mac.back();},
1444 None => {}
1445 }
1446 }
1447 (true, false) => { while let Some(ib) = mac.next() { if let Some(id) = mixed_ascii_to_digit(ib) {
1450 if id < ibase {ipart.push(Natural::from(id));}
1451 else {
1452 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1453 discard = true;
1454 }
1455 }
1456 else {
1457 mac.back();
1458 break;
1459 }
1460 }
1461 match mac.next() {
1462 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1465 if let Some(fd) = mixed_ascii_to_digit(fb) {
1466 if fd < ibase {
1467 if !recur {fpart.push(Natural::from(fd));}
1468 else {rpart.push(Natural::from(fd));}
1469 }
1470 else {
1471 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1472 discard = true;
1473 }
1474 }
1475 else if !recur && fb == b'`' {recur = true;}
1476 else {
1477 mac.back();
1478 break;
1479 }
1480 }
1481 },
1482 Some(_) => {mac.back();},
1483 None => {}
1484 }
1485 },
1486 (true, true) => { get_epart = false;
1488 let ns= mac.by_ref().take_while(|b| *b != b'\'').collect::<Vec<u8>>();
1489 if ns.is_empty() {
1490 synerr!('\'', "Empty any-base number");
1491 alt = false;
1492 continue 'cmd;
1493 }
1494 for nc in ns.iter() {
1495 match nc {
1496 b' ' | b'.' | b'0'..=b'9' | b'@' | b'`' => {} wrong => {
1498 synerr!('\'', "Invalid character in any-base number: {}", string_or_bytes(&[*wrong]));
1499 alt = false;
1500 continue 'cmd;
1501 }
1502 }
1503 }
1504 let ms;
1505 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1506 [mpart] => { if let Some((b'`', rest)) = mpart.split_first() { alt = true;
1509 ms = rest.to_vec();
1510 }
1511 else {
1512 ms = mpart.to_vec();
1513 }
1514 },
1515 [mpart, epart] => { ms = mpart.to_vec();
1517 let mut es = epart.to_vec();
1518 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1519 match String::from_utf8(es) {
1520 Ok(es) => {
1521 match es.parse::<i64>() {
1522 Ok(i) => { exp = Some(i); },
1523 Err(e) => {
1524 use std::num::IntErrorKind::*;
1525 match e.kind() {
1526 Empty => { exp = Some(0); },
1527 InvalidDigit => {
1528 valerr!('\'', "Invalid exponent: {}", es);
1529 alt = false;
1530 continue 'cmd;
1531 },
1532 PosOverflow | NegOverflow => {
1533 valerr!('\'', "Exponent {} is unrepresentable", es);
1534 alt = false;
1535 continue 'cmd;
1536 },
1537 _ => { unreachable!() }
1538 }
1539 }
1540 }
1541 },
1542 _ => { unreachable!() }
1543 }
1544 },
1545 ref v => {
1546 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1547 alt = false;
1548 continue 'cmd;
1549 }
1550 }
1551 let is;
1552 let frs;
1553 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1554 [ipart] => {
1555 is = ipart.to_vec();
1556 frs = Vec::new();
1557 },
1558 [ipart, fpart] => {
1559 is = ipart.to_vec();
1560 frs = fpart.to_vec();
1561 },
1562 ref v => {
1563 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1564 alt = false;
1565 continue 'cmd;
1566 }
1567 }
1568 if is.contains(&b'`') {
1569 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1570 alt = false;
1571 continue 'cmd;
1572 }
1573 let fs;
1574 let rs;
1575 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1576 [fpart] => {
1577 fs = fpart.to_vec();
1578 rs = Vec::new();
1579 },
1580 [fpart, rpart] => {
1581 if ibase != Natural::ONE {
1582 fs = fpart.to_vec();
1583 rs = rpart.to_vec();
1584 }
1585 else {
1586 synerr!('\'', "Recurring digits (`) are not allowed in factoradic numbers");
1587 alt = false;
1588 continue 'cmd;
1589 }
1590 },
1591 ref v => {
1592 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1593 alt = false;
1594 continue 'cmd;
1595 }
1596 }
1597 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1598 let id = str::from_utf8(id).unwrap();
1599 ipart.push(Natural::from_str(id).unwrap());
1600 }}
1601 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1602 let fd = str::from_utf8(fd).unwrap();
1603 fpart.push(Natural::from_str(fd).unwrap());
1604 }}
1605 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1606 let rd = str::from_utf8(rd).unwrap();
1607 rpart.push(Natural::from_str(rd).unwrap());
1608 }}
1609 if ibase != Natural::ONE { for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1610 if *d >= ibase {
1611 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
1612 alt = false;
1613 continue 'cmd;
1614 }
1615 }}
1616 else { for (i, d) in ipart.iter().rev().enumerate().chain(fpart.iter().enumerate()) {
1617 if *d >= i+2 { synerr!('\'', "Digit {} is too high for factoradic place {} away from the '.'", d, i);
1619 alt = false;
1620 continue 'cmd;
1621 }
1622 }}
1623 }
1624 }
1625
1626 let m_empty = ipart.is_empty() && fpart.is_empty() && rpart.is_empty(); let mut r;
1628 match (m_empty, ibase != Natural::ONE) {
1629 (true, true) => { r = Rational::ZERO;
1631 },
1632 (true, false) => { if let Some(i) = exp.take() { if let Ok(u) = u64::try_from(i) {
1635 r = Rational::from(Natural::factorial(u+1));
1636 }
1637 else {
1638 r = Rational::from_naturals(Natural::ONE, Natural::factorial(i.unsigned_abs()+1));
1639 }
1640 }
1641 else {
1642 r = Rational::ZERO;
1643 }
1644 },
1645 (false, true) => { ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1648 if alt {r.neg_assign();} },
1650 (false, false) => { if let Some(i) = exp.take() { if let Ok(u) = u64::try_from(i) {
1653 let mut fi = fpart.into_iter();
1654 ipart.extend(fi.by_ref().chain(std::iter::repeat(Natural::ZERO)).take(u as usize));
1655 fpart = fi.collect();
1656 }
1657 else {
1658 let mut temp = ipart.split_off(ipart.len().saturating_sub(i.unsigned_abs() as usize));
1659 temp.append(&mut fpart);
1660 fpart = temp;
1661 }
1662 }
1663
1664 let mut ii = ipart.iter().rev().peekable();
1665 let mut fi = fpart.iter().peekable();
1666 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)) {
1671 if let Some(id) = ii.next() {
1672 r += Rational::from(id * &d);
1673 }
1674 if let Some(fd) = fi.next() {
1675 r += Rational::from_naturals_ref(fd, &d);
1676 }
1677 if ii.peek().or_else(|| fi.peek()).is_none() {break;}
1678 d *= n;
1679 }
1680
1681 if alt {r.neg_assign();} }
1683 }
1684
1685 if get_epart {
1686 match mac.next() {
1687 Some(b'@') => { let mut es = String::new();
1689 let mut eneg = false; while let Some(eb) = mac.next() {
1691 match eb {
1692 b'`' if !eneg => { es.push('-'); }
1693 b'0'..=b'9' => { es.push(eb as char); }
1694 _ => {
1695 mac.back();
1696 break;
1697 }
1698 }
1699 eneg = true; }
1701 if es.is_empty() { es.push('0'); }
1702 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1704 r *= Rational::from(ibase).pow(i); }
1706 else {
1707 valerr!('\'', "Exponent {} is unrepresentable", es);
1708 discard = true;
1709 }
1710 }
1711 Some(_) => { mac.back(); }
1712 None => {}
1713 }
1714 }
1715 else if let Some(i) = exp {
1716 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1719
1720 if !discard {
1721 push!(Value::N(r));
1722 }
1723 },
1724 b'[' => { debug!("String literal");
1726 let mut bytes = Vec::new();
1727 let mut discard = false;
1728 let mut nest = 1usize;
1729 while let Some(b) = mac.next() {
1730 match b {
1731 b'[' => {
1732 nest = unsafe { nest.unchecked_add(1) };
1733 bytes.push(b'[');
1734 },
1735 b']' => {
1736 nest = unsafe { nest.unchecked_sub(1) };
1737 if nest == 0 {
1738 break;
1739 }
1740 else {
1741 bytes.push(b']');
1742 }
1743 },
1744 b'\\' => { match mac.next() {
1746 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() {
1760 if let Some(low) = upper_hex_to_nibble(b1) {
1761 bytes.push(high << 4 | low);
1762 }
1763 else {
1764 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1765 discard = true;
1766 }
1767 }
1768 else {
1769 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1770 discard = true;
1771 }
1772 }
1773 else { mac.back();
1775 match mac.try_next_char() {
1776 Ok(c) => {
1777 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1778 discard = true;
1779 },
1780 Err(e) => {
1781 *count = Natural::ZERO;
1782 synerr!('\0', "Aborting invalid macro: {}", e);
1783 break 'cmd;
1784 }
1785 }
1786 }
1787 },
1788 None => {
1789 synerr!('[', "Incomplete character escape: \\");
1790 discard = true;
1791 }
1792 }
1793 },
1794 _ => {
1795 bytes.push(b);
1796 }
1797 }
1798 }
1799 if !discard {
1800 match String::try_from(Utf8Iter::from(bytes)) {
1801 Ok(s) => {
1802 push!(Value::S(s));
1803 },
1804 Err(e) => {
1805 synerr!('[', "Invalid string: {}", e);
1806 }
1807 }
1808 }
1809 },
1810 _ => unreachable!()
1811 }
1812 },
1813 Space if b == b'#' => { debug!("Line comment");
1815 mac.find(|b| *b == b'\n'); },
1817 Space => {
1818 },
1820 Wrong => {
1821 mac.back();
1822 match mac.try_next_char() {
1823 Ok(c) => {
1824 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1825 },
1826 Err(e) => {
1827 *count = Natural::ZERO;
1828 synerr!('\0', "Aborting invalid macro: {}", e);
1829 break 'cmd;
1830 }
1831 }
1832 }
1833 }
1834
1835 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1840 dest.clear(); }
1842
1843 *count -= Natural::ONE; if *count == Natural::ZERO { call.pop();
1847 }
1848 else { mac.rewind();
1850 }
1851 } Ok(Finished)
1854}