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::{NegAssign, Pow};
31use malachite::base::num::basic::traits::{NegativeOne, Zero, One};
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; 256] = {
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 Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,
215 Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,
216 Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,
217 Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong,Wrong
218 ]
219};
220
221fn byte_cmd(b: u8) -> Command {
222 unsafe { *CMDS.get_unchecked(b as usize)
224 }
225}
226
227fn string_or_bytes(v: &[u8]) -> String {
228 str::from_utf8(v).map(|s| s.to_owned()).unwrap_or_else(|_| {
229 let mut res = String::from("(not UTF-8: [");
230 for b in v {
231 res += &format!("\\{b:02X}");
232 }
233 res += "])";
234 res
235 })
236}
237
238const fn upper_hex_to_nibble(b: u8) -> Option<u8> {
239 match b {
240 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'F' => Some(unsafe{b.unchecked_sub(0x37)}),
242 _ => None
243 }
244}
245
246const fn mixed_ascii_to_digit(b: u8) -> Option<u8> {
247 match b {
248 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'Z' => Some(unsafe{b.unchecked_sub(0x37)}),
250 b'a'..=b'z' => Some(unsafe{b.unchecked_sub(0x57)}),
251 _ => None
252 }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
257pub enum LogLevel {
258 Normal,
260 Debug,
262 Quiet
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
268#[must_use] pub enum ExecResult {
269 Finished,
271
272 SoftQuit(u8),
274
275 HardQuit(u8),
277
278 Killed
280}
281
282pub fn interpreter_simple(
286 st: &mut State,
287 start: Utf8Iter,
288 kill: Option<&Receiver<()>>
289) -> std::io::Result<ExecResult>
290{
291 let no_io = Arc::new(Mutex::new(IOStreams::empty()));
292 interpreter_no_os(st, start, no_io, LogLevel::Quiet, kill)
293}
294
295pub fn interpreter_no_os(
299 st: &mut State,
300 start: Utf8Iter,
301 io: Arc<Mutex<IOStreams>>,
302 ll: LogLevel,
303 kill: Option<&Receiver<()>>,
304) -> std::io::Result<ExecResult>
305{
306 unsafe { interpreter(st, start, io, ll, kill, true) }
308}
309
310pub unsafe fn interpreter_no_io(
315 st: &mut State,
316 start: Utf8Iter,
317 kill: Option<&Receiver<()>>,
318 restrict: bool
319) -> std::io::Result<ExecResult>
320{
321 let no_io = Arc::new(Mutex::new(IOStreams::empty()));
322 unsafe { interpreter(st, start, no_io, LogLevel::Quiet, kill, restrict) }
323}
324
325pub unsafe fn interpreter(
353 st: &mut State,
354 start: Utf8Iter,
355 io: Arc<Mutex<IOStreams>>,
356 mut ll: LogLevel,
357 kill: Option<&Receiver<()>>,
358 #[cfg_attr(feature = "no_os", expect(unused_variables))]
359 mut restrict: bool
360) -> std::io::Result<ExecResult>
361{
362 use ExecResult::*;
363
364 let th_name = if kill.is_some() { #[cfg_attr(feature = "no_os", expect(unused_assignments))] { restrict = true; }
366 std::thread::current().name().unwrap().to_owned()
367 }
368 else {
369 String::new()
370 };
371
372 let mut pbuf: Option<String> = None; let mut elatch: Option<(Natural, char, String)> = None;
375
376 macro_rules! synerr {
377 ($c:expr, $s:expr) => {
378 if ll != LogLevel::Quiet {
379 let err = &mut io.lock().unwrap().2;
380 writeln!(err, "! {th_name}{}: {}", $c, $s)?;
381 err.flush()?;
382 }
384 elatch = Some((Natural::ZERO, $c, $s.into()));
385 };
386 ($c:expr, $f:literal, $($s:expr),*) => {
387 let s = format!($f, $($s),*);
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));
395 };
396 }
397
398 macro_rules! valerr {
399 ($c:expr, $s:expr) => {
400 if ll != LogLevel::Quiet {
401 let err = &mut io.lock().unwrap().2;
402 writeln!(err, "? {th_name}{}: {}", $c, $s)?;
403 err.flush()?;
404 }
406 elatch = Some((Natural::ZERO, $c, $s.into()));
407 };
408 ($c:expr, $f:literal, $($s:expr),*) => {
409 let s = format!($f, $($s),*);
410 if ll != LogLevel::Quiet {
411 let err = &mut io.lock().unwrap().2;
412 writeln!(err, "? {th_name}{}: {}", $c, s)?;
413 err.flush()?;
414 }
416 elatch = Some((Natural::ZERO, $c, s));
417 };
418 }
419
420 macro_rules! debug {
421 ($s:expr) => {
422 if ll == LogLevel::Debug {
423 let err = &mut io.lock().unwrap().2;
424 writeln!(err, "\tDEBUG: {th_name}{}", $s)?;
425 err.flush()?;
426 }
428 };
429 ($f:literal, $($s:expr),*) => {
430 if ll == LogLevel::Debug {
431 let err = &mut io.lock().unwrap().2;
432 writeln!(err, "\tDEBUG: {th_name}{}", format!($f, $($s),*))?;
433 err.flush()?;
434 }
436 };
437 }
438
439 let mut rptr: Option<Rational> = None; let mut rng: Option<RandomPrimitiveInts<u64>> = None;
442
443 let mut call: Vec<(Utf8Iter, Natural)> = vec![(start, Natural::const_from(1))];
444
445 'mac: while let Some((mac, count)) = call.last_mut() { *count -= Natural::ONE;
447 let mut alt = false;
448
449 let mut abuf: Vec<Value> = Vec::new(); let mut dest: Vec<NonNull<Vec<Value>>> = Vec::new(); macro_rules! push {
453 ($v:expr) => {
454 if let Some(p) = dest.last_mut() {
455 unsafe {
456 p.as_mut().push($v); }
458 }
459 else {
460 st.mstk.push(Arc::new($v));
461 }
462 };
463 }
464 macro_rules! append {
466 ($v:expr) => {
467 if let Some(p) = dest.last_mut() {
468 unsafe {
469 p.as_mut().append(&mut $v); }
471 }
472 else {
473 for val in $v {
474 st.mstk.push(Arc::new(val));
475 }
476 }
477 };
478 }
479
480 'cmd: while let Some(b) = mac.next() { if let Some(rx) = kill { match rx.try_recv() {
483 Ok(()) => { #[expect(unused_assignments)]
485 for s in st.regs.end_threads(true) { valerr!('j', s);
487 }
488 return Ok(Killed);
489 },
490 Err(TryRecvError::Empty) => { },
493 Err(TryRecvError::Disconnected) => { unreachable!()
495 }
496 }
497 }
498
499 if let Some(e) = &mut elatch { e.0 += Natural::ONE;
501 }
502
503 use Command::*;
504 match byte_cmd(b) {
505 Fn1(mon) => {
506 if let Some(va) = st.mstk.pop() {
507 debug!("Monadic {}{} with {}", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va));
508 match catch_unwind(|| fns::exec1(mon, &va, alt)) {
509 Ok(Ok(vz)) => {
510 push!(vz);
511 },
512 Ok(Err(e)) => {
513 st.mstk.push(va);
514 valerr!(b as char, e.to_string());
515 },
516 Err(cause) => {
517 st.mstk.push(va);
518 valerr!(b as char, "Caught function panic: {:?}", cause);
519 }
520 }
521 }
522 else {
523 synerr!(b as char, "Expected 1 argument, 0 given");
524 }
525 },
526 Fn2(dya) => {
527 if let Some(vb) = st.mstk.pop() {
528 if let Some(va) = st.mstk.pop() {
529 debug!("Dyadic {}{} with ({}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb));
530 match catch_unwind(|| fns::exec2(dya, &va, &vb, alt)) {
531 Ok(Ok(vz)) => {
532 push!(vz);
533 },
534 Ok(Err(e)) => {
535 st.mstk.push(va);
536 st.mstk.push(vb);
537 valerr!(b as char, e.to_string());
538 },
539 Err(cause) => {
540 st.mstk.push(va);
541 st.mstk.push(vb);
542 valerr!(b as char, "Caught function panic: {:?}", cause);
543 }
544 }
545 }
546 else {
547 st.mstk.push(vb);
548 synerr!(b as char, "Expected 2 arguments, 1 given");
549 }
550 }
551 else {
552 synerr!(b as char, "Expected 2 arguments, 0 given");
553 }
554 },
555 Fn3(tri) => {
556 if let Some(vc) = st.mstk.pop() {
557 if let Some(vb) = st.mstk.pop() {
558 if let Some(va) = st.mstk.pop() {
559 debug!("Triadic {}{} with ({}, {}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb), TypeLabel::from(&*vc));
560 match catch_unwind(|| fns::exec3(tri, &va, &vb, &vc, alt)) {
561 Ok(Ok(vz)) => {
562 push!(vz);
563 },
564 Ok(Err(e)) => {
565 st.mstk.push(va);
566 st.mstk.push(vb);
567 st.mstk.push(vc);
568 valerr!(b as char, e.to_string());
569 },
570 Err(cause) => {
571 st.mstk.push(va);
572 st.mstk.push(vb);
573 st.mstk.push(vc);
574 valerr!(b as char, "Caught function panic: {:?}", cause);
575 }
576 }
577 }
578 else {
579 st.mstk.push(vb);
580 st.mstk.push(vc);
581 synerr!(b as char, "Expected 3 arguments, 2 given");
582 }
583 }
584 else {
585 st.mstk.push(vc);
586 synerr!(b as char, "Expected 3 arguments, 1 given");
587 }
588 }
589 else {
590 synerr!(b as char, "Expected 3 arguments, 0 given");
591 }
592 },
593 Cmd(cmd) => {
594 debug!("Impure command {}", b as char);
595 match cmd(st) {
596 Ok(mut v) => {
597 append!(v);
598 }
599 Err(e) => {
600 if let Some(se) = e.strip_suffix('!') {
601 synerr!(b as char, se);
602 }
603 else {
604 valerr!(b as char, e);
605 }
606 }
607 }
608 },
609 Exec => {
610 debug!("Command {}{}", if alt {"alt-"} else {""}, b as char);
611 match b {
612 b'`' => { alt = true;
614 continue 'cmd; },
616 b':' if !alt => { if let Some(va) = st.mstk.pop() {
618 if let Value::N(r) = &*va {
619 rptr = Some(r.clone());
620 }
621 else {
622 let ta = TypeLabel::from(&*va);
623 st.mstk.push(va);
624 synerr!(':', "Expected a number, {} given", ta);
625 }
626 }
627 else {
628 synerr!(':', "Expected 1 argument, 0 given");
629 }
630 },
631 b':' if alt => { push!(
633 if let Some(ri) = rptr.take() {
634 Value::N(ri)
635 }
636 else {
637 Value::A(vec![])
638 }
639 );
640 },
641 b'd' => {
642 if let Some(v) = st.mstk.last() {
643 if let Some(p) = dest.last_mut() { unsafe {
645 p.as_mut().push((**v).clone()); }
647 }
648 else {
649 st.mstk.push(Arc::clone(v));
650 }
651 }
652 else {
653 synerr!('d', "Stack is empty");
654 }
655 },
656 b'D' => {
657 if let Some(va) = st.mstk.pop() {
658 if let Value::N(r) = &*va {
659 match usize::try_from(r) {
660 Ok(0) => {}, Ok(u) => {
662 if let Some(from) = st.mstk.len().checked_sub(u) {
663 if let Some(p) = dest.last_mut() { for v in &st.mstk[from..] {
665 unsafe {
666 p.as_mut().push((**v).clone()); }
668 }
669 }
670 else {
671 st.mstk.extend_from_within(from..);
672 }
673 }
674 else {
675 st.mstk.push(va);
676 valerr!('D', "Can't duplicate {} values, stack depth is {}", u, st.mstk.len() - 1);
677 }
678 }
679 Err(_) => {
680 let vs = va.to_string();
681 st.mstk.push(va);
682 valerr!('D', "Can't possibly duplicate {} values", vs);
683 }
684 }
685 }
686 else {
687 let ta = TypeLabel::from(&*va);
688 st.mstk.push(va);
689 synerr!('D', "Expected a number, {} given", ta);
690 }
691 }
692 else {
693 synerr!('D', "Expected 1 argument, 0 given");
694 }
695 },
696 b'R' => { if let Some(va) = st.mstk.pop() {
698 if let Value::N(r) = &*va {
699 match usize::try_from(r) {
700 Ok(0) => {}, Ok(u) => {
702 if let Some(from) = st.mstk.len().checked_sub(u) {
703 if alt {st.mstk[from..].rotate_left(1);}
704 else {st.mstk[from..].rotate_right(1);}
705 }
706 else {
707 st.mstk.push(va);
708 valerr!('R', "Can't rotate {} values, stack depth is {}", u, st.mstk.len() - 1);
709 }
710 }
711 Err(_) => {
712 let vs = va.to_string();
713 st.mstk.push(va);
714 valerr!('R', "Can't possibly rotate {} values", vs);
715 }
716 }
717 }
718 else {
719 let ta = TypeLabel::from(&*va);
720 st.mstk.push(va);
721 synerr!('R', "Expected a number, {} given", ta);
722 }
723 }
724 else {
725 synerr!('R', "Expected 1 argument, 0 given");
726 }
727 },
728 b'?' => { let res = {
730 let inp = &mut io.lock().unwrap().0;
731 inp.read_line()
732 };
734 match res {
735 Ok(s) => {
736 push!(Value::S(s));
737 },
738 Err(e) => {
739 match e.kind() {
740 ErrorKind::Interrupted => {
741 valerr!('?', "Interrupted");
742 },
743 ErrorKind::UnexpectedEof => {
744 push!(Value::S(String::new()));
745 },
746 _ => {
747 return Err(e);
748 }
749 }
750 }
751 }
752 },
753 b'p' => { if let Some(va) = st.mstk.pop() {
755 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
756 if let Some(s) = &mut pbuf {
757 s.push_str(&vs);
758 s.push('\n');
759 }
760 else {
761 let out = &mut io.lock().unwrap().1;
762 writeln!(out, "{}", vs)?;
763 out.flush()?;
764 }
766 }
767 else {
768 synerr!('p', "Expected 1 argument, 0 given");
769 }
770 },
771 b'P' => { if let Some(va) = st.mstk.pop() {
773 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
774 if let Some(s) = &mut pbuf {
775 s.push_str(&vs);
776 }
777 else {
778 let out = &mut io.lock().unwrap().1;
779 write!(out, "{}", vs)?;
780 out.flush()?;
781 }
783 }
784 else {
785 synerr!('P', "Expected 1 argument, 0 given");
786 }
787 },
788 b'"' => { if let Some(s) = pbuf.take() { push!(Value::S(s));
791 }
792 else { pbuf = Some(String::new());
794 }
795 },
796 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)
801 }}
802 else {
803 NonNull::from(&mut abuf) };
805 dest.push(nn);
806 },
807 b')' => { if dest.pop().is_some() {
809 if dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf)))); }
812 }
813 else {
814 synerr!(')', "Mismatched closing ')'");
815 }
816 },
817 b'x' => {
818 if let Some(top) = st.mstk.pop() {
819 let sec = st.mstk.pop();
820 match Utf8Iter::try_macros(&top, sec.as_deref()) {
821 Ok((stk, ret)) => {
822 if let Some(sec) = sec && ret { st.mstk.push(sec);
824 }
825
826 if mac.is_finished() && *count == Natural::ZERO { call.pop();
828 }
829
830 call.extend(stk.into_iter().rev());
831 continue 'mac;
832 },
833 Err(e) => {
834 if let Some(sec) = sec {st.mstk.push(sec);}
835 st.mstk.push(top);
836 synerr!('x', "{}", e);
837 }
838 }
839 }
840 else {
841 synerr!('x', "Expected 1 or 2 arguments, 0 given");
842 }
843 },
844 b'q' => {
845 let u = u8::wrapping_from(&Integer::rounding_from(rptr.unwrap_or_default(), RoundingMode::Down).0);
846 return if alt {
847 Ok(HardQuit(u))
848 }
849 else {
850 Ok(SoftQuit(u))
851 };
852 },
853 b'Q' => {
854 if let Some(va) = st.mstk.pop() {
855 match &*va {
856 Value::N(r) => {
857 if let Ok(u) = usize::try_from(r) {
858 call.truncate(call.len().saturating_sub(u));
859 if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
861 dest.clear(); }
863 continue 'mac;
864 }
865 else {
866 let vs = va.to_string();
867 st.mstk.push(va);
868 valerr!('Q', "Cannot possibly break {} macros", vs);
869 }
870 },
871 _ => {
872 let ta = TypeLabel::from(&*va);
873 st.mstk.push(va);
874 synerr!('Q', "Expected a number, {} given", ta);
875 }
876 }
877 }
878 else {
879 synerr!('Q', "Expected 1 argument, 0 given");
880 }
881 },
882 b'a' => { match mac.next() {
884 Some(b) if !matches!(byte_cmd(b), Space) => {
885 match b {
886 b'a' => {
887 todo!()
888 },
889 _ => {
890 synerr!('a', "Invalid array command 'a{}'", b as char);
891 }
892 }
893 },
894 Some(_) | None => {
895 synerr!('a', "Incomplete array command 'a'");
896 }
897 }
898 },
899 b'f' => { match mac.next() {
901 Some(b) if !matches!(byte_cmd(b), Space) => {
902 match b {
903 b'z' => { push!(Value::N(st.mstk.len().into()));
905 },
906 b'r' => { st.mstk.reverse();
908 },
909 b'R' => { if let Some(va) = st.mstk.pop() {
911 if let Value::N(r) = &*va {
912 match usize::try_from(r) {
913 Ok(0) => {}, Ok(u) => {
915 if let Some(from) = st.mstk.len().checked_sub(u) {
916 st.mstk[from..].reverse();
917 }
918 else {
919 st.mstk.push(va);
920 valerr!('f', "Can't reverse {} values, stack depth is {}", u, st.mstk.len() - 1);
921 }
922 }
923 Err(_) => {
924 let vs = va.to_string();
925 st.mstk.push(va);
926 valerr!('f', "Can't possibly reverse {} values", vs);
927 }
928 }
929 }
930 else {
931 let ta = TypeLabel::from(&*va);
932 st.mstk.push(va);
933 synerr!('f', "Expected a number, {} given", ta);
934 }
935 }
936 else {
937 synerr!('f', "Expected 1 argument, 0 given");
938 }
939 },
940 b'f' => { let ri = if let Some(r) = rptr.take() {r}
942 else {
943 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
944 synerr!('f', "No register index");
945 alt = false;
946 continue 'cmd;
947 }
948 Rational::from(
949 match mac.try_next_char() {
950 Ok(c) => {c as u32},
951 Err(e) => {
952 *count = Natural::ZERO;
953 synerr!('\0', "Aborting invalid macro: {}", e);
954 break 'cmd;
955 }
956 }
957 )
958 };
959 let reg = st.regs.get_mut(&ri);
960 std::mem::swap(&mut st.mstk, &mut reg.v);
961 },
962 b'p' => { for v in &st.mstk {
964 let vs = v.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
965 if let Some(s) = &mut pbuf {
966 s.push_str(&vs);
967 s.push('\n');
968 }
969 else {
970 let out = &mut io.lock().unwrap().1;
971 writeln!(out, "{}", vs)?;
972 out.flush()?;
973 }
974 }
975 },
976 _ => {
977 synerr!('f', "Invalid stack command 'f{}'", b as char);
978 }
979 }
980 },
981 Some(_) | None => {
982 synerr!('f', "Incomplete stack command 'f'");
983 }
984 }
985 },
986 b'N' => {
987 match (st.mstk.pop(), alt) {
988 (Some(va), false) => { match &*va {
990 Value::N(r) => {
991 match Natural::try_from(r) {
992 Ok(n) => {
993 push!(Value::N(Rational::from(
994 malachite::natural::random::get_random_natural_less_than(rng.get_or_insert_with(rng_os), &n)
995 )));
996 },
997 _ => {
998 st.mstk.push(va);
999 valerr!('N', "Limit must be a natural number");
1000 }
1001 }
1002 },
1003 _ => {
1004 let ta = TypeLabel::from(&*va);
1005 st.mstk.push(va);
1006 synerr!('N', "Expected a number, {} given", ta);
1007 }
1008 }
1009 }
1010 (Some(va), true) => { match &*va {
1012 Value::N(r) => {
1013 match Integer::try_from(r) {
1014 Ok(Integer::NEGATIVE_ONE) => { rng = None;
1016 },
1017 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();
1020 bytes.resize(32, 0);
1021 rng = Some(rng_preset(
1022 unsafe { <[u8; 32]>::try_from(bytes).unwrap_unchecked() }
1023 ));
1024 },
1025 _ => {
1026 st.mstk.push(va);
1027 valerr!('N', "Seed must be a natural number or `1");
1028 }
1029 }
1030 },
1031 _ => {
1032 let ta = TypeLabel::from(&*va);
1033 st.mstk.push(va);
1034 synerr!('N', "Expected a number, {} given", ta);
1035 }
1036 }
1037 }
1038 (None, _) => {
1039 synerr!('N', "Expected 1 argument, 0 given");
1040 }
1041 }
1042 },
1043 b'w' => { if let Some(va) = st.mstk.pop() {
1045 if let Value::N(r) = &*va {
1046 if let Some(dur) = u128::try_from(r).ok().and_then(|ns| {
1047 (ns <= std::time::Duration::MAX.as_nanos()).then(|| std::time::Duration::from_nanos_u128(ns))
1048 }) {
1049 if let Some(rx) = kill {
1050 match rx.recv_timeout(dur) {
1051 Ok(()) => { #[expect(unused_assignments)]
1053 for s in st.regs.end_threads(true) { valerr!('j', s);
1055 }
1056 return Ok(Killed);
1057 },
1058 Err(RecvTimeoutError::Timeout) => { },
1061 Err(RecvTimeoutError::Disconnected) => { unreachable!()
1063 }
1064 }
1065 }
1066 else {
1067 std::thread::sleep(dur); }
1069 }
1070 else {
1071 let vs = va.to_string();
1072 st.mstk.push(va);
1073 valerr!('w', "Can't possibly wait {} ns", vs);
1074 }
1075 }
1076 else {
1077 let ta = TypeLabel::from(&*va);
1078 st.mstk.push(va);
1079 synerr!('w', "Expected a number, {} given", ta);
1080 }
1081 }
1082 else {
1083 synerr!('w', "Expected 1 argument, 0 given");
1084 }
1085 },
1086 b'W' => {
1087 push!(Value::N(
1088 match std::time::SystemTime::UNIX_EPOCH.elapsed() {
1089 Ok(dur) => {
1090 Rational::from(dur.as_nanos())
1091 },
1092 Err(e) => {
1093 Rational::from(e.duration().as_nanos()).neg()
1094 }
1095 }
1096 ));
1097 },
1098 b'_' => { let mut word = Vec::new();
1100 while let Some(b) = mac.next() {
1101 if matches!(byte_cmd(b), Space) {
1102 mac.back();
1103 break;
1104 }
1105 else {
1106 word.push(b);
1107 }
1108 }
1109
1110 match &word[..] { b"restrict" => {
1112 #[cfg_attr(feature = "no_os", expect(unused_assignments))] { restrict = true; }
1113 },
1114 b"quiet" => {
1115 ll = LogLevel::Quiet;
1116 },
1117 b"error" => {
1118 ll = LogLevel::Normal;
1119 },
1120 b"debug" => {
1121 ll = LogLevel::Debug;
1122 },
1123 b"err" => {
1124 push!(Value::A(
1125 if let Some((n, c, s)) = elatch.take() {
1126 vec![
1127 Value::N(n.into()),
1128 Value::S(c.into()),
1129 Value::S(s)
1130 ]
1131 }
1132 else { vec![] }
1133 ));
1134 },
1135 b"th" => {
1136 push!(Value::S(th_name.clone()));
1137 },
1138 b"joinall" => {
1139 for s in st.regs.end_threads(false) {
1140 valerr!('j', s);
1141 }
1142 },
1143 b"killall" => {
1144 for s in st.regs.end_threads(true) {
1145 valerr!('j', s);
1146 }
1147 },
1148 b"trim" => {
1149 st.trim();
1150 RE_CACHE.clear();
1151 },
1152 b"dedup" => {
1153 st.dedup();
1154 },
1155 b"clhist" => {
1156 io.lock().unwrap().0.clear_history();
1157 },
1158 b"clpar" => {
1159 st.params = ParamStk::default();
1160 },
1161 b"clall" => {
1162 st.clear_vals();
1163 RE_CACHE.clear();
1164 },
1165 _ => {
1166 #[cfg(feature = "no_os")]
1167 {
1168 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1169 }
1170 #[cfg(not(feature = "no_os"))]
1171 {
1172 match (restrict, os::OS_CMDS.get(&word).copied()) {
1173 (false, Some(oscmd)) => {
1174 let res;
1175 unsafe {
1176 if os::ACCESS { panic!("Failsafe panic: Attempted to execute multiple OS commands simultaneously. See documentation of `interpreter` function for safe usage.");
1178 }
1179 else {
1180 os::ACCESS = true;
1181 }
1182
1183 res = oscmd(st);
1184
1185 os::ACCESS = false;
1186 }
1187 match res {
1188 Ok(mut v) => {
1189 append!(v);
1190 }
1191 Err(e) => {
1192 if let Some(se) = e.strip_suffix('!') {
1193 synerr!('_', "OS command '{}': {}", string_or_bytes(&word), se);
1194 }
1195 else {
1196 valerr!('_', "OS command '{}': {}", string_or_bytes(&word), e);
1197 }
1198 }
1199 }
1200 }
1201 (true, Some(_)) => {
1202 synerr!('_', "OS command '{}' is disabled (restricted mode)", string_or_bytes(&word));
1203 },
1204 _ => {
1205 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1206 }
1207 }
1208 }
1209 }
1210 }
1211 },
1212 _ => unreachable!()
1213 }
1214 },
1215 ExecR => {
1216 let ri = if let Some(r) = rptr.take() {r}
1217 else {
1218 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
1219 synerr!(b as char, "No register index");
1220 alt = false;
1221 continue 'cmd;
1222 }
1223 Rational::from(
1224 match mac.try_next_char() {
1225 Ok(c) => {c as u32},
1226 Err(e) => {
1227 *count = Natural::ZERO;
1228 synerr!('\0', "Aborting invalid macro: {}", e);
1229 break 'cmd;
1230 }
1231 }
1232 )
1233 };
1234 debug!("Register command {}{}", if alt {"alt-"} else {""}, b as char);
1235 match b {
1236 b'Z' => { push!(Value::N(
1238 st.regs.try_get(&ri).map(|reg| reg.v.len().into()).unwrap_or_default()
1239 ));
1240 },
1241 b's' => {
1242 if let Some(va) = st.mstk.pop() {
1243 let reg = st.regs.get_mut(&ri);
1244 if let Some(rv) = reg.v.last_mut() {
1245 *rv = va;
1246 }
1247 else {
1248 reg.v.push(va);
1249 }
1250 }
1251 else {
1252 synerr!('s', "Stack is empty");
1253 }
1254 },
1255 b'S' => {
1256 if let Some(va) = st.mstk.pop() {
1257 st.regs.get_mut(&ri).v.push(va);
1258 }
1259 else {
1260 synerr!('S', "Stack is empty");
1261 }
1262 },
1263 b'l' => {
1264 if let Some(rv) = st.regs.try_get(&ri).and_then(|reg| reg.v.last()) {
1265 if let Some(p) = dest.last_mut() { unsafe {
1267 p.as_mut().push((**rv).clone()); }
1269 }
1270 else {
1271 st.mstk.push(Arc::clone(rv));
1272 }
1273 }
1274 else {
1275 synerr!('l', "Register {} is empty", reg_index_nice(&ri));
1276 }
1277 },
1278 b'L' => {
1279 if let Some(rv) = st.regs.try_get_mut(&ri).and_then(|reg| reg.v.pop()) {
1280 if let Some(p) = dest.last_mut() { unsafe {
1282 p.as_mut().push((*rv).clone()); }
1284 }
1285 else {
1286 st.mstk.push(Arc::clone(&rv));
1287 }
1288 }
1289 else {
1290 synerr!('L', "Register {} is empty", reg_index_nice(&ri));
1291 }
1292 },
1293 b'X' => {
1294 if let Some(true) = st.regs.try_get(&ri).map(|reg| reg.th.is_some()) {
1295 valerr!('X', "Register {} is already running a thread", reg_index_nice(&ri));
1296 }
1297 else if let Some(va) = st.mstk.pop() {
1298 if let Value::S(sa) = &*va {
1299 let th_start = sa.to_owned().into();
1300 let (ktx, krx) = std::sync::mpsc::channel::<()>();
1301 let (jtx, jrx) = std::sync::mpsc::channel::<()>();
1302 let tb = std::thread::Builder::new().name(format!("{th_name}{}: ", reg_index_nice(&ri)));
1303 let mut th_st = if alt { st.clone() } else { State::default() };
1304 let th_io = Arc::clone(&io);
1305
1306 match tb.spawn(move || {
1307 let th_res = interpreter_no_os(&mut th_st, th_start, th_io, ll, Some(&krx));
1309
1310 let _ = jrx.recv(); th_st.regs.end_threads( th_res.is_err() ||
1314 match krx.try_recv() { Ok(()) => { true },
1316 Err(TryRecvError::Empty) => { false },
1317 Err(TryRecvError::Disconnected) => { unreachable!() } }
1319 );
1320
1321 (th_st.mstk, th_res)
1322 }) {
1324 Ok(jh) => {
1325 st.regs.get_mut(&ri).th = Some((jh, ktx, jtx));
1326 },
1327 Err(e) => {
1328 st.mstk.push(va);
1329 valerr!('X', "Can't spawn child thread: {}", e);
1330 }
1331 }
1332 }
1333 else {
1334 let ta = TypeLabel::from(&*va);
1335 st.mstk.push(va);
1336 synerr!('X', "Expected a string, {} given", ta);
1337 }
1338 }
1339 else {
1340 synerr!('X', "Expected 1 argument, 0 given");
1341 }
1342 },
1343 b'j' => {
1344 let ri_nice = reg_index_nice(&ri);
1345 if let Some(reg) = st.regs.try_get_mut(&ri) && let Some((jh, ktx, jtx)) = reg.th.take() {
1346 if alt {
1347 ktx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", ri_nice));
1348 }
1349 jtx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", ri_nice));
1350 match jh.join() {
1351 Ok(mut tr) => {
1352 match tr.1 {
1353 Err(e) => {
1354 let s = format!("IO error in thread {}: {}", ri_nice, e);
1355 eprintln!("? {th_name}j: {}", s); elatch = Some((Natural::ZERO, 'j', s));
1357 },
1358 Ok(SoftQuit(c)) if c != 0 => {
1359 valerr!('j', "Thread {} quit with code {}", ri_nice, c);
1360 },
1361 Ok(HardQuit(c)) if c != 0 => {
1362 valerr!('j', "Thread {} hard-quit with code {}", ri_nice, c);
1363 },
1364 Ok(Killed) => {
1365 valerr!('j', "Thread {} was killed", ri_nice);
1366 },
1367 _ => {} }
1369
1370 reg.v.append(&mut tr.0);
1371 },
1372 Err(e) => {
1373 std::panic::resume_unwind(e);
1374 }
1375 }
1376 }
1377 else {
1378 valerr!('j', "Register {} is not running a thread", ri_nice);
1379 }
1380 },
1381 b'J' => {
1382 if let Some(Some((jh, _, _))) = st.regs.try_get(&ri).map(|reg| ®.th) {
1383 let mut bz = BitVec::new();
1384 bz.push(jh.is_finished());
1385 push!(Value::B(bz));
1386 }
1387 else {
1388 valerr!('J', "Register {} is not running a thread", reg_index_nice(&ri));
1389 }
1390 },
1391 _ => unreachable!()
1392 }
1393 },
1394 Lit => {
1395 match b {
1396 b'T' | b'F' => { debug!("Boolean literal");
1398 let mut bits = BitVec::new();
1399 bits.push(b == b'T');
1400 while let Some(b) = mac.next() {
1401 match b {
1402 b'T' => {bits.push(true);},
1403 b'F' => {bits.push(false);},
1404 _ => {
1405 mac.back();
1406 break;
1407 }
1408 }
1409 }
1410 push!(Value::B(bits));
1411 },
1412 b'\'' | b'0'..=b'9' | b'.' | b'@' => { debug!("Number literal");
1414 let mut ipart = Vec::new();
1415 let mut fpart = Vec::new();
1416 let mut rpart = Vec::new();
1417 let mut get_epart = true;
1418 let mut exp = None;
1419 let mut discard = false;
1420 let mut ibase = st.params.get_i().clone();
1421
1422 match (b == b'\'', ibase > Natural::const_from(36)) {
1423 (false, high_base) => { mac.back();
1425 ibase = if high_base {Natural::const_from(10)} else {ibase}; while let Some(ib) = mac.next() { let id = ib.wrapping_sub(0x30);
1428 match id {
1429 0..=9 if id < ibase => {ipart.push(Natural::from(id));},
1430 0..=9 => {
1431 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1432 discard = true;
1433 },
1434 _ => {
1435 mac.back();
1436 break;
1437 }
1438 }
1439 }
1440 match mac.next() {
1441 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1444 let fd = fb.wrapping_sub(0x30);
1445 match fd {
1446 0x30 if !recur => {recur = true;}, 0..=9 if !recur && fd < ibase => {fpart.push(Natural::from(fd));},
1448 0..=9 if recur && fd < ibase => {rpart.push(Natural::from(fd));},
1449 0..=9 => {
1450 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1451 discard = true;
1452 },
1453 _ => {
1454 mac.back();
1455 break;
1456 }
1457 }
1458 }
1459 },
1460 Some(_) => {mac.back();},
1461 None => {}
1462 }
1463 }
1464 (true, false) => { while let Some(ib) = mac.next() { if let Some(id) = mixed_ascii_to_digit(ib) {
1467 if id < ibase {ipart.push(Natural::from(id));}
1468 else {
1469 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1470 discard = true;
1471 }
1472 }
1473 else {
1474 mac.back();
1475 break;
1476 }
1477 }
1478 match mac.next() {
1479 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1482 if let Some(fd) = mixed_ascii_to_digit(fb) {
1483 if fd < ibase {
1484 if !recur {fpart.push(Natural::from(fd));}
1485 else {rpart.push(Natural::from(fd));}
1486 }
1487 else {
1488 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1489 discard = true;
1490 }
1491 }
1492 else if !recur && fb == b'`' {recur = true;}
1493 else {
1494 mac.back();
1495 break;
1496 }
1497 }
1498 },
1499 Some(_) => {mac.back();},
1500 None => {}
1501 }
1502 },
1503 (true, true) => { get_epart = false;
1505 let ns= mac.by_ref().take_while(|b| *b != b'\'').collect::<Vec<u8>>();
1506 if ns.is_empty() {
1507 synerr!('\'', "Empty any-base number");
1508 alt = false;
1509 continue 'cmd;
1510 }
1511 for nc in ns.iter() {
1512 match nc {
1513 b' ' | b'.' | b'0'..=b'9' | b'@' | b'`' => {} wrong => {
1515 synerr!('\'', "Invalid character in any-base number: {}", string_or_bytes(&[*wrong]));
1516 alt = false;
1517 continue 'cmd;
1518 }
1519 }
1520 }
1521 let mut ms = Vec::new();
1522 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1523 [mpart] => { ms = mpart.to_vec();
1525 },
1526 [mpart, epart] => { ms = mpart.to_vec();
1528 let mut es = epart.to_vec();
1529 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1530 match String::from_utf8(es) {
1531 Ok(es) => {
1532 match es.parse::<i64>() {
1533 Ok(i) => { exp = Some(i); },
1534 Err(e) => {
1535 use std::num::IntErrorKind::*;
1536 match e.kind() {
1537 Empty => { exp = Some(0); },
1538 InvalidDigit => {
1539 valerr!('\'', "Invalid exponent: {}", es);
1540 alt = false;
1541 continue 'cmd;
1542 },
1543 PosOverflow | NegOverflow => {
1544 valerr!('\'', "Exponent {} is unrepresentable", es);
1545 alt = false;
1546 continue 'cmd;
1547 },
1548 _ => { unreachable!() }
1549 }
1550 }
1551 }
1552 },
1553 _ => { unreachable!() }
1554 }
1555 },
1556 ref v => {
1557 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1558 drop(ms);
1559 alt = false;
1560 continue 'cmd;
1561 }
1562 }
1563 let mut is = Vec::new();
1564 let mut frs = Vec::new();
1565 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1566 [ipart] => {
1567 is = ipart.to_vec();
1568 },
1569 [ipart, fpart] => {
1570 is = ipart.to_vec();
1571 frs = fpart.to_vec();
1572 },
1573 ref v => {
1574 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1575 drop(is);
1576 alt = false;
1577 continue 'cmd;
1578 }
1579 }
1580 if is.contains(&b'`') {
1581 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1582 alt = false;
1583 continue 'cmd;
1584 }
1585 let mut fs = Vec::new();
1586 let mut rs = Vec::new();
1587 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1588 [fpart] => {
1589 fs = fpart.to_vec();
1590 },
1591 [fpart, rpart] => {
1592 fs = fpart.to_vec();
1593 rs = rpart.to_vec();
1594 },
1595 ref v => {
1596 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1597 drop(fs);
1598 alt = false;
1599 continue 'cmd;
1600 }
1601 }
1602 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1603 let id = str::from_utf8(id).unwrap();
1604 ipart.push(Natural::from_str(id).unwrap());
1605 }}
1606 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1607 let fd = str::from_utf8(fd).unwrap();
1608 fpart.push(Natural::from_str(fd).unwrap());
1609 }}
1610 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1611 let rd = str::from_utf8(rd).unwrap();
1612 rpart.push(Natural::from_str(rd).unwrap());
1613 }}
1614 for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1615 if *d >= ibase {
1616 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
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 if m_empty {
1627 r = Rational::ZERO;
1628 }
1629 else {
1630 ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1632 if alt {r.neg_assign();} }
1634
1635 if get_epart {
1636 match mac.next() {
1637 Some(b'@') => { let mut es = String::new();
1639 let mut eneg = false; while let Some(eb) = mac.next() {
1641 match eb {
1642 b'`' if !eneg => { es.push('-'); }
1643 b'0'..=b'9' => { es.push(eb as char); }
1644 _ => {
1645 mac.back();
1646 break;
1647 }
1648 }
1649 eneg = true; }
1651 if es.is_empty() { es.push('0'); }
1652 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1654 r *= Rational::from(st.params.get_i()).pow(i); }
1656 else {
1657 valerr!('\'', "Exponent {} is unrepresentable", es);
1658 discard = true;
1659 }
1660 }
1661 Some(_) => { mac.back(); }
1662 None => {}
1663 }
1664 }
1665 else if let Some(i) = exp {
1666 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1669
1670 if !discard {
1671 push!(Value::N(r));
1672 }
1673 },
1674 b'[' => { debug!("String literal");
1676 let mut bytes = Vec::new();
1677 let mut discard = false;
1678 let mut nest = 1usize;
1679 while let Some(b) = mac.next() {
1680 match b {
1681 b'[' => {
1682 nest = unsafe { nest.unchecked_add(1) };
1683 bytes.push(b'[');
1684 },
1685 b']' => {
1686 nest = unsafe { nest.unchecked_sub(1) };
1687 if nest == 0 {
1688 break;
1689 }
1690 else {
1691 bytes.push(b']');
1692 }
1693 },
1694 b'\\' => { match mac.next() {
1696 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() {
1710 if let Some(low) = upper_hex_to_nibble(b1) {
1711 bytes.push(high << 4 | low);
1712 }
1713 else {
1714 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1715 discard = true;
1716 }
1717 }
1718 else {
1719 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1720 discard = true;
1721 }
1722 }
1723 else { mac.back();
1725 match mac.try_next_char() {
1726 Ok(c) => {
1727 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1728 discard = true;
1729 },
1730 Err(e) => {
1731 *count = Natural::ZERO;
1732 synerr!('\0', "Aborting invalid macro: {}", e);
1733 break 'cmd;
1734 }
1735 }
1736 }
1737 },
1738 None => {
1739 synerr!('[', "Incomplete character escape: \\");
1740 discard = true;
1741 }
1742 }
1743 },
1744 _ => {
1745 bytes.push(b);
1746 }
1747 }
1748 }
1749 if !discard {
1750 match String::try_from(Utf8Iter::from(bytes)) {
1751 Ok(s) => {
1752 push!(Value::S(s));
1753 },
1754 Err(e) => {
1755 synerr!('[', "Invalid string: {}", e);
1756 }
1757 }
1758 }
1759 },
1760 _ => unreachable!()
1761 }
1762 },
1763 Space if b == b'#' => { debug!("Line comment");
1765 mac.find(|b| *b == b'\n');
1766 },
1767 Space => {
1768 },
1770 Wrong => {
1771 mac.back();
1772 match mac.try_next_char() {
1773 Ok(c) => {
1774 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1775 },
1776 Err(e) => {
1777 *count = Natural::ZERO;
1778 synerr!('\0', "Aborting invalid macro: {}", e);
1779 break 'cmd;
1780 }
1781 }
1782 }
1783 }
1784
1785 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1790 dest.clear(); }
1792
1793 if *count == Natural::ZERO { call.pop();
1795 }
1796 else { mac.rewind();
1798 }
1799 } Ok(Finished)
1802}