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; 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)) {
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 mut ms = Vec::new();
1505 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1506 [mpart] => { ms = mpart.to_vec();
1508 },
1509 [mpart, epart] => { ms = mpart.to_vec();
1511 let mut es = epart.to_vec();
1512 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1513 match String::from_utf8(es) {
1514 Ok(es) => {
1515 match es.parse::<i64>() {
1516 Ok(i) => { exp = Some(i); },
1517 Err(e) => {
1518 use std::num::IntErrorKind::*;
1519 match e.kind() {
1520 Empty => { exp = Some(0); },
1521 InvalidDigit => {
1522 valerr!('\'', "Invalid exponent: {}", es);
1523 alt = false;
1524 continue 'cmd;
1525 },
1526 PosOverflow | NegOverflow => {
1527 valerr!('\'', "Exponent {} is unrepresentable", es);
1528 alt = false;
1529 continue 'cmd;
1530 },
1531 _ => { unreachable!() }
1532 }
1533 }
1534 }
1535 },
1536 _ => { unreachable!() }
1537 }
1538 },
1539 ref v => {
1540 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1541 drop(ms);
1542 alt = false;
1543 continue 'cmd;
1544 }
1545 }
1546 let mut is = Vec::new();
1547 let mut frs = Vec::new();
1548 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1549 [ipart] => {
1550 is = ipart.to_vec();
1551 },
1552 [ipart, fpart] => {
1553 is = ipart.to_vec();
1554 frs = fpart.to_vec();
1555 },
1556 ref v => {
1557 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1558 drop(is);
1559 alt = false;
1560 continue 'cmd;
1561 }
1562 }
1563 if is.contains(&b'`') {
1564 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1565 alt = false;
1566 continue 'cmd;
1567 }
1568 let mut fs = Vec::new();
1569 let mut rs = Vec::new();
1570 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1571 [fpart] => {
1572 fs = fpart.to_vec();
1573 },
1574 [fpart, rpart] => {
1575 fs = fpart.to_vec();
1576 rs = rpart.to_vec();
1577 },
1578 ref v => {
1579 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1580 drop(fs);
1581 alt = false;
1582 continue 'cmd;
1583 }
1584 }
1585 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1586 let id = str::from_utf8(id).unwrap();
1587 ipart.push(Natural::from_str(id).unwrap());
1588 }}
1589 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1590 let fd = str::from_utf8(fd).unwrap();
1591 fpart.push(Natural::from_str(fd).unwrap());
1592 }}
1593 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1594 let rd = str::from_utf8(rd).unwrap();
1595 rpart.push(Natural::from_str(rd).unwrap());
1596 }}
1597 for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1598 if *d >= ibase {
1599 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
1600 alt = false;
1601 continue 'cmd;
1602 }
1603 }
1604 }
1605 }
1606
1607 let m_empty = ipart.is_empty() && fpart.is_empty() && rpart.is_empty(); let mut r;
1609 if m_empty {
1610 r = Rational::ZERO;
1611 }
1612 else {
1613 ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1615 if alt {r.neg_assign();} }
1617
1618 if get_epart {
1619 match mac.next() {
1620 Some(b'@') => { let mut es = String::new();
1622 let mut eneg = false; while let Some(eb) = mac.next() {
1624 match eb {
1625 b'`' if !eneg => { es.push('-'); }
1626 b'0'..=b'9' => { es.push(eb as char); }
1627 _ => {
1628 mac.back();
1629 break;
1630 }
1631 }
1632 eneg = true; }
1634 if es.is_empty() { es.push('0'); }
1635 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1637 r *= Rational::from(st.params.get_i()).pow(i); }
1639 else {
1640 valerr!('\'', "Exponent {} is unrepresentable", es);
1641 discard = true;
1642 }
1643 }
1644 Some(_) => { mac.back(); }
1645 None => {}
1646 }
1647 }
1648 else if let Some(i) = exp {
1649 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1652
1653 if !discard {
1654 push!(Value::N(r));
1655 }
1656 },
1657 b'[' => { debug!("String literal");
1659 let mut bytes = Vec::new();
1660 let mut discard = false;
1661 let mut nest = 1usize;
1662 while let Some(b) = mac.next() {
1663 match b {
1664 b'[' => {
1665 nest = unsafe { nest.unchecked_add(1) };
1666 bytes.push(b'[');
1667 },
1668 b']' => {
1669 nest = unsafe { nest.unchecked_sub(1) };
1670 if nest == 0 {
1671 break;
1672 }
1673 else {
1674 bytes.push(b']');
1675 }
1676 },
1677 b'\\' => { match mac.next() {
1679 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() {
1693 if let Some(low) = upper_hex_to_nibble(b1) {
1694 bytes.push(high << 4 | low);
1695 }
1696 else {
1697 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1698 discard = true;
1699 }
1700 }
1701 else {
1702 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1703 discard = true;
1704 }
1705 }
1706 else { mac.back();
1708 match mac.try_next_char() {
1709 Ok(c) => {
1710 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1711 discard = true;
1712 },
1713 Err(e) => {
1714 *count = Natural::ZERO;
1715 synerr!('\0', "Aborting invalid macro: {}", e);
1716 break 'cmd;
1717 }
1718 }
1719 }
1720 },
1721 None => {
1722 synerr!('[', "Incomplete character escape: \\");
1723 discard = true;
1724 }
1725 }
1726 },
1727 _ => {
1728 bytes.push(b);
1729 }
1730 }
1731 }
1732 if !discard {
1733 match String::try_from(Utf8Iter::from(bytes)) {
1734 Ok(s) => {
1735 push!(Value::S(s));
1736 },
1737 Err(e) => {
1738 synerr!('[', "Invalid string: {}", e);
1739 }
1740 }
1741 }
1742 },
1743 _ => unreachable!()
1744 }
1745 },
1746 Space if b == b'#' => { debug!("Line comment");
1748 mac.find(|b| *b == b'\n'); },
1750 Space => {
1751 },
1753 Wrong => {
1754 mac.back();
1755 match mac.try_next_char() {
1756 Ok(c) => {
1757 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1758 },
1759 Err(e) => {
1760 *count = Natural::ZERO;
1761 synerr!('\0', "Aborting invalid macro: {}", e);
1762 break 'cmd;
1763 }
1764 }
1765 }
1766 }
1767
1768 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1773 dest.clear(); }
1775
1776 *count -= Natural::ONE; if *count == Natural::ZERO { call.pop();
1780 }
1781 else { mac.rewind();
1783 }
1784 } Ok(Finished)
1787}