1pub mod structs;
4use structs::*;
5
6pub(crate) mod fns;
7
8pub(crate) mod cmds;
9
10pub(crate) mod errors;
11
12pub(crate) mod conv;
13
14pub(crate) mod num;
15
16#[cfg(not(feature = "no_os"))]
17mod os;
18
19use std::io::{Write, BufRead, ErrorKind};
20use std::panic::catch_unwind;
21use std::ptr::NonNull;
22use std::str::FromStr;
23use std::sync::{Arc, Mutex, mpsc::{Receiver, TryRecvError, RecvTimeoutError}};
24use linefeed::{DefaultTerminal, Interface};
25use bitvec::prelude::*;
26use malachite::{Natural, Integer, Rational};
27use malachite::base::num::arithmetic::traits::{DivRem, NegAssign, Pow};
28use malachite::base::num::basic::traits::{NegativeOne, Zero, One};
29use malachite::base::num::conversion::traits::{ConvertibleFrom, PowerOf2DigitIterable, PowerOf2Digits, RoundingFrom, WrappingFrom};
30use malachite::base::num::random::RandomPrimitiveInts;
31use malachite::base::rational_sequences::RationalSequence;
32use malachite::base::rounding_modes::RoundingMode;
33use crate::errors::TypeLabel;
34
35
36pub const STATE_FILE_HEADER: [u8;20] = *b"# ADC state file v1\n";
38
39struct LineEditor(Interface<DefaultTerminal>);
40impl Default for LineEditor {
41 fn default() -> Self {
42 use linefeed::Signal::*;
43 let iface = Interface::new("").unwrap();
44 iface.set_report_signal(Break, true);
46 iface.set_report_signal(Interrupt, true);
47 iface.set_report_signal(Quit, true);
48 Self(iface)
49 }
50}
51
52pub trait ReadLine {
56 fn read_line(&mut self) -> std::io::Result<String>;
60
61 fn clear_history(&mut self);
63}
64impl<T: BufRead> ReadLine for T {
65 fn read_line(&mut self) -> std::io::Result<String> {
66 let mut buf = String::new();
67 self.read_line(&mut buf)?;
68 Ok(buf)
69 }
70
71 fn clear_history(&mut self) {
72 }
74}
75impl ReadLine for LineEditor {
76 fn read_line(&mut self) -> std::io::Result<String> {
77 use linefeed::{ReadResult, Signal};
78 match self.0.read_line() {
79 Ok(ReadResult::Input(s)) => {
80 self.0.add_history_unique(s.clone());
81 Ok(s)
82 },
83 Ok(ReadResult::Eof) => {Err(ErrorKind::UnexpectedEof.into())},
84 Ok(ReadResult::Signal(sig)) => {
85 self.0.cancel_read_line()?;
86 match sig {
87 Signal::Break | Signal::Interrupt | Signal::Quit => {Err(ErrorKind::Interrupted.into())},
88 Signal::Continue => {Err(std::io::Error::other("Unhandled SIGCONT"))},
89 Signal::Suspend => {Err(std::io::Error::other("Unhandled SIGTSTP"))},
90 Signal::Resize => {Err(std::io::Error::other("Unhandled window resize"))},
91 }
92 },
93 Err(e) => {Err(e)}
94 }
95 }
96
97 fn clear_history(&mut self) {
98 self.0.clear_history();
99 }
100}
101
102pub struct IOStreams (
104 pub Box<dyn ReadLine + Send>,
106 pub Box<dyn Write + Send>,
108 pub Box<dyn Write + Send>
110);
111impl IOStreams {
112 pub fn empty() -> Self {
114 Self (
115 Box::new(std::io::empty()),
116 Box::new(std::io::empty()),
117 Box::new(std::io::empty())
118 )
119 }
120
121 pub fn process() -> Self {
123 Self (
124 Box::new(LineEditor::default()),
125 Box::new(std::io::stdout()),
126 Box::new(std::io::stderr())
127 )
128 }
129}
130
131#[derive(Debug, PartialEq, Eq, Clone, Copy)]
133pub enum LogLevel {
134 Normal,
136 Debug,
138 Quiet
140}
141
142lazy_static::lazy_static! {
143 pub(crate) static ref RE_CACHE: RegexCache = RegexCache::default();
144}
145
146fn rng_preset(bytes: [u8; 32]) -> RandomPrimitiveInts<u64> {
147 malachite::base::num::random::random_primitive_ints(malachite::base::random::Seed::from_bytes(bytes))
148}
149
150fn rng_os() -> RandomPrimitiveInts<u64> {
151 let mut bytes = [0u8; 32];
152 getrandom::fill(&mut bytes).unwrap();
153 rng_preset(bytes)
154}
155
156#[derive(Default, Clone, Copy)]
157enum Command {
158 Fn1(fns::Mon),
160
161 Fn2(fns::Dya),
163
164 Fn3(fns::Tri),
166
167 Cmd(cmds::Cmd),
169
170 Exec,
172
173 ExecR,
175
176 Lit,
178
179 Space,
181
182 #[default] Wrong,
184}
185
186const CMDS: [Command; 256] = {
188 use Command::*;
189 use fns::*;
190 use cmds::*;
191 [
192 Space, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Space, Space, Space, Space, Space, Wrong, Wrong,
194
195 Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong, Wrong,
197
198 Space, Fn1(neg), Exec, Space, Wrong, Fn2(modu), Wrong, Lit, Exec, Exec, Fn2(mul), Fn2(add), Wrong, Fn2(sub), Lit, Fn2(div),
200
201 Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Lit, Exec, Wrong, Fn2(lt), Fn2(eq), Fn2(gt), Exec,
203
204 Lit, Wrong, Wrong, Cmd(cln), Exec, Wrong, Lit, Fn2(logb), Wrong, Cmd(gi), ExecR, Cmd(gk), ExecR, Cmd(gm), Exec, Cmd(go),
206
207 Exec, Exec, Exec, ExecR, Lit, Wrong, Fn2(root), Wrong, ExecR, Wrong, ExecR, Lit, Wrong, Wrong, Fn2(pow), Exec,
209
210 Exec, Exec, Wrong, Cmd(cls), Exec, Wrong, Exec, Fn1(log), Wrong, Cmd(si), ExecR, Cmd(sk), ExecR, Cmd(sm), Fn1(fac), Cmd(so),
212
213 Exec, Exec, Cmd(rev), ExecR, Wrong, Wrong, Fn1(sqrt), Exec, Exec, Wrong, Fn1(disc), Cmd(cbo), Fn3(bar), Cmd(cbc), Fn2(euc), Wrong,
215
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,
218 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,
219 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,
220 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
221 ]
222};
223
224fn byte_cmd(b: u8) -> Command {
225 unsafe { *CMDS.get_unchecked(b as usize)
227 }
228}
229
230fn string_or_bytes(v: &[u8]) -> String {
231 str::from_utf8(v).map(|s| s.to_owned()).unwrap_or_else(|_| {
232 let mut res = String::from("(not UTF-8: [");
233 for b in v {
234 res += &format!("\\{b:02X}");
235 }
236 res += "])";
237 res
238 })
239}
240
241fn upper_hex_to_nibble(b: u8) -> Option<u8> {
242 match b {
243 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'F' => Some(unsafe{b.unchecked_sub(0x37)}),
245 _ => None
246 }
247}
248
249fn mixed_ascii_to_digit(b: u8) -> Option<u8> {
250 match b {
251 b'0'..=b'9' => Some(unsafe{b.unchecked_sub(0x30)}), b'A'..=b'Z' => Some(unsafe{b.unchecked_sub(0x37)}),
253 b'a'..=b'z' => Some(unsafe{b.unchecked_sub(0x57)}),
254 _ => None
255 }
256}
257
258fn reg_index_nice(ri: &Rational) -> String {
259 Natural::try_from(ri).ok().and_then(|n| { let bytes: Vec<u8> = n.to_power_of_2_digits_desc(8); str::from_utf8(&bytes).ok().map(|s| String::from("[") + s + "]") })
263 .unwrap_or_else(|| {
264 num::nauto(ri, DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2) })
266}
267
268#[derive(Clone, Copy, Debug, PartialEq)]
270#[must_use] pub enum ExecResult {
271 Finished,
273
274 SoftQuit(u8),
276
277 HardQuit(u8)
279}
280
281pub fn interpreter_no_os(
283 st: &mut State,
284 start: Utf8Iter,
285 io: Arc<Mutex<IOStreams>>,
286 ll: LogLevel,
287 kill: Option<&Receiver<()>>,
288) -> std::io::Result<ExecResult>
289{
290 unsafe { interpreter(st, start, io, ll, kill, true) }
292}
293
294pub unsafe fn interpreter(
319 st: &mut State,
320 start: Utf8Iter,
321 io: Arc<Mutex<IOStreams>>,
322 mut ll: LogLevel,
323 kill: Option<&Receiver<()>>,
324 #[cfg_attr(feature = "no_os", allow(unused_variables))]
325 mut restrict: bool
326) -> std::io::Result<ExecResult>
327{
328 use ExecResult::*;
329
330 let th_name = if kill.is_some() { #[cfg_attr(feature = "no_os", allow(unused_assignments))] { restrict = true; } std::thread::current().name().unwrap().to_owned()
333 }
334 else {
335 String::new()
336 };
337
338 let mut pbuf: Option<String> = None; let mut elatch: Option<(Natural, char, String)> = None;
341
342 macro_rules! synerr {
343 ($c:expr, $s:expr) => {
344 if ll != LogLevel::Quiet {
345 let err = &mut io.lock().unwrap().2;
346 writeln!(err, "! {th_name}{}: {}", $c, $s)?;
347 err.flush()?;
348 }
350 elatch = Some((Natural::ZERO, $c, $s.into()));
351 };
352 ($c:expr, $f:literal, $($s:expr),*) => {
353 let s = format!($f, $($s),*);
354 if ll != LogLevel::Quiet {
355 let err = &mut io.lock().unwrap().2;
356 writeln!(err, "! {th_name}{}: {}", $c, s)?;
357 err.flush()?;
358 }
360 elatch = Some((Natural::ZERO, $c, s));
361 };
362 }
363
364 macro_rules! valerr {
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! debug {
387 ($s:expr) => {
388 if ll == LogLevel::Debug {
389 let err = &mut io.lock().unwrap().2;
390 writeln!(err, "\tDEBUG: {th_name}{}", $s)?;
391 err.flush()?;
392 }
394 };
395 ($f:literal, $($s:expr),*) => {
396 if ll == LogLevel::Debug {
397 let err = &mut io.lock().unwrap().2;
398 writeln!(err, "\tDEBUG: {th_name}{}", format!($f, $($s),*))?;
399 err.flush()?;
400 }
402 };
403 }
404
405 let mut rptr: Option<Rational> = None; let mut rng: Option<RandomPrimitiveInts<u64>> = None;
408
409 let mut call: Vec<(Utf8Iter, Natural)> = vec![(start, Natural::const_from(1))];
410
411 'mac: while let Some((mac, count)) = call.last_mut() { *count -= Natural::ONE;
413 let mut alt = false;
414
415 let mut abuf: Vec<Value> = Vec::new(); let mut dest: Vec<NonNull<Vec<Value>>> = Vec::new(); macro_rules! push {
419 ($v:expr) => {
420 if let Some(p) = dest.last_mut() {
421 unsafe {
422 p.as_mut().push($v); }
424 }
425 else {
426 st.mstk.push(Arc::new($v));
427 }
428 };
429 }
430 macro_rules! append {
432 ($v:expr) => {
433 if let Some(p) = dest.last_mut() {
434 unsafe {
435 p.as_mut().append(&mut $v); }
437 }
438 else {
439 for val in $v {
440 st.mstk.push(Arc::new(val));
441 }
442 }
443 };
444 }
445
446 'cmd: while let Some(b) = mac.next() { if let Some(rx) = kill { match rx.try_recv() {
449 Ok(()) => { return Ok(Finished);
451 },
452 Err(TryRecvError::Empty) => { },
455 Err(TryRecvError::Disconnected) => { unreachable!()
457 }
458 }
459 }
460
461 if let Some(e) = &mut elatch { e.0 += Natural::ONE;
463 }
464
465 use Command::*;
466 match byte_cmd(b) {
467 Fn1(mon) => {
468 if let Some(va) = st.mstk.pop() {
469 debug!("Monadic {}{} with {}", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va));
470 match catch_unwind(|| fns::exec1(mon, &va, alt)) {
471 Ok(Ok(vz)) => {
472 push!(vz);
473 },
474 Ok(Err(e)) => {
475 st.mstk.push(va);
476 valerr!(b as char, e.to_string());
477 },
478 Err(cause) => {
479 st.mstk.push(va);
480 valerr!(b as char, "Caught function panic: {:?}", cause);
481 }
482 }
483 }
484 else {
485 synerr!(b as char, "Expected 1 argument, 0 given");
486 }
487 },
488 Fn2(dya) => {
489 if let Some(vb) = st.mstk.pop() {
490 if let Some(va) = st.mstk.pop() {
491 debug!("Dyadic {}{} with ({}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb));
492 match catch_unwind(|| fns::exec2(dya, &va, &vb, alt)) {
493 Ok(Ok(vz)) => {
494 push!(vz);
495 },
496 Ok(Err(e)) => {
497 st.mstk.push(va);
498 st.mstk.push(vb);
499 valerr!(b as char, e.to_string());
500 },
501 Err(cause) => {
502 st.mstk.push(va);
503 st.mstk.push(vb);
504 valerr!(b as char, "Caught function panic: {:?}", cause);
505 }
506 }
507 }
508 else {
509 st.mstk.push(vb);
510 synerr!(b as char, "Expected 2 arguments, 1 given");
511 }
512 }
513 else {
514 synerr!(b as char, "Expected 2 arguments, 0 given");
515 }
516 },
517 Fn3(tri) => {
518 if let Some(vc) = st.mstk.pop() {
519 if let Some(vb) = st.mstk.pop() {
520 if let Some(va) = st.mstk.pop() {
521 debug!("Triadic {}{} with ({}, {}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb), TypeLabel::from(&*vc));
522 match catch_unwind(|| fns::exec3(tri, &va, &vb, &vc, alt)) {
523 Ok(Ok(vz)) => {
524 push!(vz);
525 },
526 Ok(Err(e)) => {
527 st.mstk.push(va);
528 st.mstk.push(vb);
529 st.mstk.push(vc);
530 valerr!(b as char, e.to_string());
531 },
532 Err(cause) => {
533 st.mstk.push(va);
534 st.mstk.push(vb);
535 st.mstk.push(vc);
536 valerr!(b as char, "Caught function panic: {:?}", cause);
537 }
538 }
539 }
540 else {
541 st.mstk.push(vb);
542 st.mstk.push(vc);
543 synerr!(b as char, "Expected 3 arguments, 2 given");
544 }
545 }
546 else {
547 st.mstk.push(vc);
548 synerr!(b as char, "Expected 3 arguments, 1 given");
549 }
550 }
551 else {
552 synerr!(b as char, "Expected 3 arguments, 0 given");
553 }
554 },
555 Cmd(cmd) => {
556 debug!("Impure command {}", b as char);
557 match cmd(st) {
558 Ok(mut v) => {
559 append!(v);
560 }
561 Err(e) => {
562 if let Some(se) = e.strip_suffix('!') {
563 synerr!(b as char, se);
564 }
565 else {
566 valerr!(b as char, e);
567 }
568 }
569 }
570 },
571 Exec => {
572 debug!("Special command {}{}", if alt {"alt-"} else {""}, b as char);
573 match b {
574 b'`' => { alt = true;
576 continue 'cmd; },
578 b':' if !alt => { if let Some(va) = st.mstk.pop() {
580 if let Value::N(r) = &*va {
581 rptr = Some(r.clone());
582 }
583 else {
584 let ta = TypeLabel::from(&*va);
585 st.mstk.push(va);
586 synerr!(':', "Expected a number, {} given", ta);
587 }
588 }
589 else {
590 synerr!(':', "Expected 1 argument, 0 given");
591 }
592 },
593 b':' if alt => { push!(
595 if let Some(ri) = rptr.take() {
596 Value::N(ri)
597 }
598 else {
599 Value::A(vec![])
600 }
601 );
602 },
603 b'd' => {
604 if let Some(v) = st.mstk.last() {
605 if let Some(p) = dest.last_mut() { unsafe {
607 p.as_mut().push((**v).clone()); }
609 }
610 else {
611 st.mstk.push(Arc::clone(v));
612 }
613 }
614 else {
615 synerr!('d', "Stack is empty");
616 }
617 },
618 b'D' => {
619 if let Some(va) = st.mstk.pop() {
620 if let Value::N(r) = &*va {
621 match usize::try_from(r) {
622 Ok(0) => {}, Ok(u) => {
624 if let Some(from) = st.mstk.len().checked_sub(u) {
625 if let Some(p) = dest.last_mut() { for v in &st.mstk[from..] {
627 unsafe {
628 p.as_mut().push((**v).clone()); }
630 }
631 }
632 else {
633 st.mstk.extend_from_within(from..);
634 }
635 }
636 else {
637 st.mstk.push(va);
638 valerr!('D', "Can't duplicate {} values, stack depth is {}", u, st.mstk.len() - 1);
639 }
640 }
641 Err(_) => {
642 let vs = va.to_string();
643 st.mstk.push(va);
644 valerr!('D', "Can't possibly duplicate {} values", vs);
645 }
646 }
647 }
648 else {
649 let ta = TypeLabel::from(&*va);
650 st.mstk.push(va);
651 synerr!('D', "Expected a number, {} given", ta);
652 }
653 }
654 else {
655 synerr!('D', "Expected 1 argument, 0 given");
656 }
657 },
658 b'R' => { if let Some(va) = st.mstk.pop() {
660 if let Value::N(r) = &*va {
661 match usize::try_from(r) {
662 Ok(0) => {}, Ok(u) => {
664 if let Some(from) = st.mstk.len().checked_sub(u) {
665 if alt {st.mstk[from..].rotate_left(1);}
666 else {st.mstk[from..].rotate_right(1);}
667 }
668 else {
669 st.mstk.push(va);
670 valerr!('R', "Can't rotate {} values, stack depth is {}", u, st.mstk.len() - 1);
671 }
672 }
673 Err(_) => {
674 let vs = va.to_string();
675 st.mstk.push(va);
676 valerr!('R', "Can't possibly rotate {} values", vs);
677 }
678 }
679 }
680 else {
681 let ta = TypeLabel::from(&*va);
682 st.mstk.push(va);
683 synerr!('R', "Expected a number, {} given", ta);
684 }
685 }
686 else {
687 synerr!('R', "Expected 1 argument, 0 given");
688 }
689 },
690 b'?' => { let res = {
692 let inp = &mut io.lock().unwrap().0;
693 inp.read_line()
694 };
696 match res {
697 Ok(s) => {
698 push!(Value::S(s));
699 },
700 Err(e) => {
701 match e.kind() {
702 ErrorKind::Interrupted => {
703 valerr!('?', "Interrupted");
704 },
705 ErrorKind::UnexpectedEof => {
706 push!(Value::S(String::new()));
707 },
708 _ => {
709 return Err(e);
710 }
711 }
712 }
713 }
714 },
715 b'p' => { if let Some(va) = st.mstk.pop() {
717 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
718 if let Some(s) = &mut pbuf {
719 s.push_str(&vs);
720 s.push('\n');
721 }
722 else {
723 let out = &mut io.lock().unwrap().1;
724 writeln!(out, "{}", vs)?;
725 out.flush()?;
726 }
728 }
729 else {
730 synerr!('p', "Expected 1 argument, 0 given");
731 }
732 },
733 b'P' => { if let Some(va) = st.mstk.pop() {
735 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
736 if let Some(s) = &mut pbuf {
737 s.push_str(&vs);
738 }
739 else {
740 let out = &mut io.lock().unwrap().1;
741 write!(out, "{}", vs)?;
742 out.flush()?;
743 }
745 }
746 else {
747 synerr!('P', "Expected 1 argument, 0 given");
748 }
749 },
750 b'"' => { if let Some(s) = pbuf.take() { push!(Value::S(s));
753 }
754 else { pbuf = Some(String::new());
756 }
757 },
758 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)
763 }}
764 else {
765 NonNull::from(&mut abuf) };
767 dest.push(nn);
768 },
769 b')' => { if dest.pop().is_some() {
771 if dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf)))); }
774 }
775 else {
776 synerr!(')', "Mismatched closing ')'");
777 }
778 },
779 b'x' => {
780 if let Some(top) = st.mstk.pop() {
781 let sec = st.mstk.pop();
782 match Utf8Iter::from_vals(&top, sec.as_deref()) {
783 Ok((mut stk, ret)) => {
784 if let Some(sec) = sec && ret { st.mstk.push(sec);
786 }
787
788 if mac.is_finished() && *count == Natural::ZERO { call.pop();
790 }
791
792 call.append(&mut stk);
793 continue 'mac;
794 },
795 Err(e) => {
796 if let Some(sec) = sec {st.mstk.push(sec);}
797 st.mstk.push(top);
798 synerr!('x', "{}", e);
799 }
800 }
801 }
802 else {
803 synerr!('x', "Expected 1 or 2 arguments, 0 given");
804 }
805 },
806 b'q' => {
807 let u = u8::wrapping_from(&Integer::rounding_from(rptr.unwrap_or_default(), RoundingMode::Down).0);
808 return if alt {
809 Ok(HardQuit(u))
810 }
811 else {
812 Ok(SoftQuit(u))
813 };
814 },
815 b'Q' => {
816 if let Some(va) = st.mstk.pop() {
817 match &*va {
818 Value::N(r) => {
819 if let Ok(u) = usize::try_from(r) {
820 call.truncate(call.len().saturating_sub(u));
821 if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
823 dest.clear(); }
825 continue 'mac;
826 }
827 else {
828 let vs = va.to_string();
829 st.mstk.push(va);
830 valerr!('Q', "Cannot possibly break {} macros", vs);
831 }
832 },
833 _ => {
834 let ta = TypeLabel::from(&*va);
835 st.mstk.push(va);
836 synerr!('Q', "Expected a number, {} given", ta);
837 }
838 }
839 }
840 else {
841 synerr!('Q', "Expected 1 argument, 0 given");
842 }
843 },
844 b'a' => { match mac.next() {
846 Some(b) if !matches!(byte_cmd(b), Space) => {
847 match b {
848 b'a' => {
849 todo!()
850 },
851 _ => {
852 synerr!('a', "Invalid array command 'a{}'", b as char);
853 }
854 }
855 },
856 Some(_) | None => {
857 synerr!('a', "Incomplete array command 'a'");
858 }
859 }
860 },
861 b'f' => { match mac.next() {
863 Some(b) if !matches!(byte_cmd(b), Space) => {
864 match b {
865 b'z' => { push!(Value::N(st.mstk.len().into()));
867 },
868 b'r' => { st.mstk.reverse();
870 },
871 b'R' => { if let Some(va) = st.mstk.pop() {
873 if let Value::N(r) = &*va {
874 match usize::try_from(r) {
875 Ok(0) => {}, Ok(u) => {
877 if let Some(from) = st.mstk.len().checked_sub(u) {
878 st.mstk[from..].reverse();
879 }
880 else {
881 st.mstk.push(va);
882 valerr!('f', "Can't reverse {} values, stack depth is {}", u, st.mstk.len() - 1);
883 }
884 }
885 Err(_) => {
886 let vs = va.to_string();
887 st.mstk.push(va);
888 valerr!('f', "Can't possibly reverse {} values", vs);
889 }
890 }
891 }
892 else {
893 let ta = TypeLabel::from(&*va);
894 st.mstk.push(va);
895 synerr!('f', "Expected a number, {} given", ta);
896 }
897 }
898 else {
899 synerr!('f', "Expected 1 argument, 0 given");
900 }
901 },
902 b'f' => { let ri = if let Some(r) = rptr.take() {r}
904 else {
905 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
906 synerr!('f', "No register index");
907 alt = false;
908 continue 'cmd;
909 }
910 Rational::from(
911 match mac.try_next_char() {
912 Ok(c) => {c as u32},
913 Err(e) => {
914 *count = Natural::ZERO;
915 synerr!('\0', "Aborting invalid macro: {}", e);
916 break 'cmd;
917 }
918 }
919 )
920 };
921 let reg = st.regs.get_mut(&ri);
922 std::mem::swap(&mut st.mstk, &mut reg.v);
923 },
924 b'p' => { for v in &st.mstk {
926 let vs = v.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
927 if let Some(s) = &mut pbuf {
928 s.push_str(&vs);
929 s.push('\n');
930 }
931 else {
932 let out = &mut io.lock().unwrap().1;
933 writeln!(out, "{}", vs)?;
934 out.flush()?;
935 }
936 }
937 },
938 _ => {
939 synerr!('f', "Invalid stack command 'f{}'", b as char);
940 }
941 }
942 },
943 Some(_) | None => {
944 synerr!('f', "Incomplete stack command 'f'");
945 }
946 }
947 },
948 b'N' => {
949 match (st.mstk.pop(), alt) {
950 (Some(va), false) => { match &*va {
952 Value::N(r) => {
953 match Natural::try_from(r) {
954 Ok(n) => {
955 push!(Value::N(Rational::from(
956 malachite::natural::random::get_random_natural_less_than(rng.get_or_insert_with(rng_os), &n)
957 )));
958 },
959 _ => {
960 st.mstk.push(va);
961 valerr!('N', "Limit must be a natural number");
962 }
963 }
964 },
965 _ => {
966 let ta = TypeLabel::from(&*va);
967 st.mstk.push(va);
968 synerr!('N', "Expected a number, {} given", ta);
969 }
970 }
971 }
972 (Some(va), true) => { match &*va {
974 Value::N(r) => {
975 match Integer::try_from(r) {
976 Ok(Integer::NEGATIVE_ONE) => { rng = None;
978 },
979 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();
982 bytes.resize(32, 0);
983 rng = Some(rng_preset( unsafe { <[u8; 32]>::try_from(bytes).unwrap_unchecked() } ));
984 },
985 _ => {
986 st.mstk.push(va);
987 valerr!('N', "Seed must be a natural number or `1");
988 }
989 }
990 },
991 _ => {
992 let ta = TypeLabel::from(&*va);
993 st.mstk.push(va);
994 synerr!('N', "Expected a number, {} given", ta);
995 }
996 }
997 }
998 (None, _) => {
999 synerr!('N', "Expected 1 argument, 0 given");
1000 }
1001 }
1002 },
1003 b'w' => { if let Some(va) = st.mstk.pop() {
1005 if let Value::N(r) = &*va {
1006 if let Some(dur) = Natural::try_from(r).ok().and_then(|n| {
1007 let (s, ns) = n.div_rem(Natural::const_from(1_000_000_000));
1008 u64::try_from(&s).ok().map(|s| {
1009 let ns = unsafe { u32::try_from(&ns).unwrap_unchecked() }; std::time::Duration::new(s, ns)
1011 })
1012 }) {
1013 if let Some(rx) = kill {
1014 match rx.recv_timeout(dur) {
1015 Ok(()) => { return Ok(Finished);
1017 },
1018 Err(RecvTimeoutError::Timeout) => { },
1021 Err(RecvTimeoutError::Disconnected) => { unreachable!()
1023 }
1024 }
1025 }
1026 else {
1027 std::thread::sleep(dur); }
1029 }
1030 else {
1031 let vs = va.to_string();
1032 st.mstk.push(va);
1033 valerr!('w', "Can't possibly wait {} ns", vs);
1034 }
1035 }
1036 else {
1037 let ta = TypeLabel::from(&*va);
1038 st.mstk.push(va);
1039 synerr!('w', "Expected a number, {} given", ta);
1040 }
1041 }
1042 else {
1043 synerr!('w', "Expected 1 argument, 0 given");
1044 }
1045 },
1046 b'_' => { let mut word = Vec::new();
1048 while let Some(b) = mac.next() {
1049 if matches!(byte_cmd(b), Space) {
1050 mac.back();
1051 break;
1052 }
1053 else {
1054 word.push(b);
1055 }
1056 }
1057
1058 match &word[..] { b"restrict" => {
1060 #[cfg_attr(feature = "no_os", allow(unused_assignments))] { restrict = true; }
1061 },
1062 b"quiet" => {
1063 ll = LogLevel::Quiet;
1064 },
1065 b"error" => {
1066 ll = LogLevel::Normal;
1067 },
1068 b"debug" => {
1069 ll = LogLevel::Debug;
1070 },
1071 b"err" => {
1072 push!(Value::A(
1073 if let Some((n, c, s)) = elatch.take() {
1074 vec![
1075 Value::N(n.into()),
1076 Value::S(c.into()),
1077 Value::S(s)
1078 ]
1079 }
1080 else { vec![] }
1081 ));
1082 },
1083 b"th" => {
1084 push!(Value::S(th_name.clone()));
1085 },
1086 b"trim" => {
1087 st.trim();
1088 RE_CACHE.clear();
1089 },
1090 b"clhist" => {
1091 io.lock().unwrap().0.clear_history();
1092 },
1093 b"clpar" => {
1094 st.params = ParamStk::default();
1095 },
1096 b"clall" => {
1097 st.clear_vals();
1098 RE_CACHE.clear();
1099 },
1100 _ => {
1101 #[cfg(feature = "no_os")]
1102 {
1103 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1104 }
1105 #[cfg(not(feature = "no_os"))]
1106 {
1107 match (restrict, os::OS_CMDS.get(&word).copied()) {
1108 (false, Some(oscmd)) => {
1109 match unsafe { oscmd(st) } { Ok(mut v) => {
1111 append!(v);
1112 }
1113 Err(e) => {
1114 if let Some(se) = e.strip_suffix('!') {
1115 synerr!('_', "OS command '{}': {}", string_or_bytes(&word), se);
1116 }
1117 else {
1118 valerr!('_', "OS command '{}': {}", string_or_bytes(&word), e);
1119 }
1120 }
1121 }
1122 }
1123 (true, Some(_)) => {
1124 synerr!('_', "OS command '{}' is disabled (restricted mode)", string_or_bytes(&word));
1125 },
1126 _ => {
1127 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1128 }
1129 }
1130 }
1131 }
1132 }
1133 },
1134 _ => unreachable!()
1135 }
1136 },
1137 ExecR => {
1138 let ri = if let Some(r) = rptr.take() {r}
1139 else {
1140 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
1141 synerr!(b as char, "No register index");
1142 alt = false;
1143 continue 'cmd;
1144 }
1145 Rational::from(
1146 match mac.try_next_char() {
1147 Ok(c) => {c as u32},
1148 Err(e) => {
1149 *count = Natural::ZERO;
1150 synerr!('\0', "Aborting invalid macro: {}", e);
1151 break 'cmd;
1152 }
1153 }
1154 )
1155 };
1156 debug!("Special register command {}{}", if alt {"alt-"} else {""}, b as char);
1157 match b {
1158 b'Z' => { push!(Value::N(
1160 st.regs.try_get(&ri).map(|reg| reg.v.len().into()).unwrap_or_default()
1161 ));
1162 },
1163 b's' => {
1164 if let Some(va) = st.mstk.pop() {
1165 let reg = st.regs.get_mut(&ri);
1166 if let Some(rv) = reg.v.last_mut() {
1167 *rv = va;
1168 }
1169 else {
1170 reg.v.push(va);
1171 }
1172 }
1173 else {
1174 synerr!('s', "Stack is empty");
1175 }
1176 },
1177 b'S' => {
1178 if let Some(va) = st.mstk.pop() {
1179 st.regs.get_mut(&ri).v.push(va);
1180 }
1181 else {
1182 synerr!('S', "Stack is empty");
1183 }
1184 },
1185 b'l' => {
1186 if let Some(rv) = st.regs.try_get(&ri).and_then(|reg| reg.v.last()) {
1187 if let Some(p) = dest.last_mut() { unsafe {
1189 p.as_mut().push((**rv).clone()); }
1191 }
1192 else {
1193 st.mstk.push(Arc::clone(rv));
1194 }
1195 }
1196 else {
1197 synerr!('l', "Register {} is empty", reg_index_nice(&ri));
1198 }
1199 },
1200 b'L' => {
1201 if let Some(rv) = st.regs.try_get_mut(&ri).and_then(|reg| reg.v.pop()) {
1202 if let Some(p) = dest.last_mut() { unsafe {
1204 p.as_mut().push((*rv).clone()); }
1206 }
1207 else {
1208 st.mstk.push(Arc::clone(&rv));
1209 }
1210 }
1211 else {
1212 synerr!('L', "Register {} is empty", reg_index_nice(&ri));
1213 }
1214 },
1215 b'X' => {
1216 if let Some(true) = st.regs.try_get(&ri).map(|reg| reg.th.is_some()) {
1217 valerr!('X', "Register {} is already running a thread", reg_index_nice(&ri));
1218 }
1219 else if let Some(top) = st.mstk.pop() {
1220 let sec = st.mstk.pop();
1221 match Utf8Iter::from_vals(&top, sec.as_deref()) {
1222 Ok((stk, ret)) => {
1223 if let Some(sec) = sec && ret { st.mstk.push(sec);
1225 }
1226
1227 let (tx, rx) = std::sync::mpsc::channel::<()>();
1228 let tb = std::thread::Builder::new().name(format!("{th_name}{}: ", reg_index_nice(&ri)));
1229 let mut th_st = if alt { st.clone() } else { State::default() };
1230 let th_io = Arc::clone(&io);
1231
1232 match tb.spawn(move || {
1233 let mut th_res = (Vec::new(), Ok(Finished));
1234
1235 'all: for (th_start, th_count) in stk {
1236 for _ in malachite::natural::exhaustive::exhaustive_natural_range(Natural::ZERO, th_count) {
1237 match interpreter_no_os(&mut th_st, th_start.clone(), Arc::clone(&th_io), ll, Some(&rx)) {
1238 Ok(Finished) => {continue;},
1239 Ok(er) => {
1240 th_res.1 = Ok(er);
1241 break 'all;
1242 },
1243 Err(e) => {
1244 th_res.1 = Err(e);
1245 break 'all;
1246 }
1247 }
1248 }
1249 }
1250
1251 th_res.0 = th_st.mstk;
1252 th_res
1253 }) {
1254 Ok(jh) => {
1255 st.regs.get_mut(&ri).th = Some((jh, tx));
1256 },
1257 Err(e) => {
1258 valerr!('X', "Can't spawn child thread: {}", e);
1259 }
1260 }
1261 },
1262 Err(e) => {
1263 if let Some(sec) = sec {st.mstk.push(sec);}
1264 st.mstk.push(top);
1265 synerr!('X', "{}", e);
1266 }
1267 }
1268 }
1269 else {
1270 synerr!('X', "Expected 1 or 2 arguments, 0 given");
1271 }
1272 },
1273 b'j' => {
1274 if let Some(reg) = st.regs.try_get_mut(&ri) && let Some((jh, tx)) = reg.th.take() {
1275 if alt {
1276 tx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", reg_index_nice(&ri)));
1277 }
1278 match jh.join() {
1279 Ok(mut res) => {
1280 match res.1 {
1281 Err(e) => {
1282 valerr!('j', "IO error in thread {}: {}", reg_index_nice(&ri), e);
1283 },
1284 Ok(SoftQuit(c)) | Ok(HardQuit(c)) if c != 0 => {
1285 valerr!('j', "Thread {} exited with code {}", reg_index_nice(&ri), c);
1286 },
1287 _ => {}
1288 }
1289
1290 reg.v.append(&mut res.0);
1291 },
1292 Err(e) => {
1293 std::panic::resume_unwind(e);
1294 }
1295 }
1296 }
1297 else {
1298 valerr!('j', "Register {} is not running a thread", reg_index_nice(&ri));
1299 }
1300 },
1301 b'J' => {
1302 if let Some(Some((jh, _))) = st.regs.try_get(&ri).map(|reg| ®.th) {
1303 let mut bz = BitVec::new();
1304 bz.push(jh.is_finished());
1305 push!(Value::B(bz));
1306 }
1307 else {
1308 valerr!('J', "Register {} is not running a thread", reg_index_nice(&ri));
1309 }
1310 },
1311 _ => unreachable!()
1312 }
1313 },
1314 Lit => {
1315 match b {
1316 b'T' | b'F' => { debug!("Boolean literal");
1318 let mut bits = BitVec::new();
1319 bits.push(b == b'T');
1320 while let Some(b) = mac.next() {
1321 match b {
1322 b'T' => {bits.push(true);},
1323 b'F' => {bits.push(false);},
1324 _ => {
1325 mac.back();
1326 break;
1327 }
1328 }
1329 }
1330 push!(Value::B(bits));
1331 },
1332 b'\'' | b'0'..=b'9' | b'.' | b'@' => { debug!("Number literal");
1334 let mut ipart = Vec::new();
1335 let mut fpart = Vec::new();
1336 let mut rpart = Vec::new();
1337 let mut get_epart = true;
1338 let mut exp = None;
1339 let mut discard = false;
1340 let mut ibase = st.params.get_i().clone();
1341
1342 match (b == b'\'', ibase > Natural::const_from(36)) {
1343 (false, high_base) => { mac.back();
1345 ibase = if high_base {Natural::const_from(10)} else {ibase}; while let Some(ib) = mac.next() { let id = ib.wrapping_sub(0x30);
1348 match id {
1349 0..=9 if id < ibase => {ipart.push(Natural::from(id));},
1350 0..=9 => {
1351 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1352 discard = true;
1353 },
1354 _ => {
1355 mac.back();
1356 break;
1357 }
1358 }
1359 }
1360 match mac.next() {
1361 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1364 let fd = fb.wrapping_sub(0x30);
1365 match fd {
1366 0x30 if !recur => {recur = true;}, 0..=9 if !recur && fd < ibase => {fpart.push(Natural::from(fd));},
1368 0..=9 if recur && fd < ibase => {rpart.push(Natural::from(fd));},
1369 0..=9 => {
1370 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1371 discard = true;
1372 },
1373 _ => {
1374 mac.back();
1375 break;
1376 }
1377 }
1378 }
1379 },
1380 Some(_) => {mac.back();},
1381 None => {}
1382 }
1383 }
1384 (true, false) => { while let Some(ib) = mac.next() { if let Some(id) = mixed_ascii_to_digit(ib) {
1387 if id < ibase {ipart.push(Natural::from(id));}
1388 else {
1389 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1390 discard = true;
1391 }
1392 }
1393 else {
1394 mac.back();
1395 break;
1396 }
1397 }
1398 match mac.next() {
1399 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1402 if let Some(fd) = mixed_ascii_to_digit(fb) {
1403 if fd < ibase {
1404 if !recur {fpart.push(Natural::from(fd));}
1405 else {rpart.push(Natural::from(fd));}
1406 }
1407 else {
1408 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1409 discard = true;
1410 }
1411 }
1412 else if !recur && fb == b'`' {recur = true;}
1413 else {
1414 mac.back();
1415 break;
1416 }
1417 }
1418 },
1419 Some(_) => {mac.back();},
1420 None => {}
1421 }
1422 },
1423 (true, true) => { get_epart = false;
1425 let ns= mac.by_ref().take_while(|b| *b != b'\'').collect::<Vec<u8>>();
1426 if ns.is_empty() {
1427 synerr!('\'', "Empty any-base number");
1428 alt = false;
1429 continue 'cmd;
1430 }
1431 for nc in ns.iter() {
1432 match nc {
1433 b' ' | b'.' | b'0'..=b'9' | b'@' | b'`' => {} wrong => {
1435 synerr!('\'', "Invalid character in any-base number: {}", string_or_bytes(&[*wrong]));
1436 alt = false;
1437 continue 'cmd;
1438 }
1439 }
1440 }
1441 let mut ms = Vec::new();
1442 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1443 [mpart] => { ms = mpart.to_vec();
1445 },
1446 [mpart, epart] => { ms = mpart.to_vec();
1448 let mut es = epart.to_vec();
1449 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1450 match String::from_utf8(es) {
1451 Ok(es) => {
1452 match es.parse::<i64>() {
1453 Ok(i) => { exp = Some(i); },
1454 Err(e) => {
1455 use std::num::IntErrorKind::*;
1456 match e.kind() {
1457 Empty => { exp = Some(0); },
1458 InvalidDigit => {
1459 valerr!('\'', "Invalid exponent: {}", es);
1460 alt = false;
1461 continue 'cmd;
1462 },
1463 PosOverflow | NegOverflow => {
1464 valerr!('\'', "Exponent {} is unrepresentable", es);
1465 alt = false;
1466 continue 'cmd;
1467 },
1468 _ => { unreachable!() }
1469 }
1470 }
1471 }
1472 },
1473 _ => { unreachable!() }
1474 }
1475 },
1476 ref v => {
1477 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1478 drop(ms);
1479 alt = false;
1480 continue 'cmd;
1481 }
1482 }
1483 let mut is = Vec::new();
1484 let mut frs = Vec::new();
1485 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1486 [ipart] => {
1487 is = ipart.to_vec();
1488 },
1489 [ipart, fpart] => {
1490 is = ipart.to_vec();
1491 frs = fpart.to_vec();
1492 },
1493 ref v => {
1494 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1495 drop(is);
1496 alt = false;
1497 continue 'cmd;
1498 }
1499 }
1500 if is.contains(&b'`') {
1501 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1502 alt = false;
1503 continue 'cmd;
1504 }
1505 let mut fs = Vec::new();
1506 let mut rs = Vec::new();
1507 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1508 [fpart] => {
1509 fs = fpart.to_vec();
1510 },
1511 [fpart, rpart] => {
1512 fs = fpart.to_vec();
1513 rs = rpart.to_vec();
1514 },
1515 ref v => {
1516 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1517 drop(fs);
1518 alt = false;
1519 continue 'cmd;
1520 }
1521 }
1522 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1523 let id = str::from_utf8(id).unwrap();
1524 ipart.push(Natural::from_str(id).unwrap());
1525 }}
1526 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1527 let fd = str::from_utf8(fd).unwrap();
1528 fpart.push(Natural::from_str(fd).unwrap());
1529 }}
1530 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1531 let rd = str::from_utf8(rd).unwrap();
1532 rpart.push(Natural::from_str(rd).unwrap());
1533 }}
1534 for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1535 if *d >= ibase {
1536 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
1537 alt = false;
1538 continue 'cmd;
1539 }
1540 }
1541 }
1542 }
1543
1544 let m_empty = ipart.is_empty() && fpart.is_empty() && rpart.is_empty(); let mut r;
1546 if m_empty {
1547 r = Rational::ZERO;
1548 }
1549 else {
1550 ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1552 if alt {r.neg_assign();} }
1554
1555 if get_epart {
1556 match mac.next() {
1557 Some(b'@') => { let mut es = String::new();
1559 let mut eneg = false; while let Some(eb) = mac.next() {
1561 match eb {
1562 b'`' if !eneg => { es.push('-'); }
1563 b'0'..=b'9' => { es.push(eb as char); }
1564 _ => {
1565 mac.back();
1566 break;
1567 }
1568 }
1569 eneg = true; }
1571 if es.is_empty() { es.push('0'); }
1572 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1574 r *= Rational::from(st.params.get_i()).pow(i); }
1576 else {
1577 valerr!('\'', "Exponent {} is unrepresentable", es);
1578 discard = true;
1579 }
1580 }
1581 Some(_) => { mac.back(); }
1582 None => {}
1583 }
1584 }
1585 else if let Some(i) = exp {
1586 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1589
1590 if !discard {
1591 push!(Value::N(r));
1592 }
1593 },
1594 b'[' => { debug!("String literal");
1596 let mut bytes = Vec::new();
1597 let mut discard = false;
1598 let mut nest = 1usize;
1599 while let Some(b) = mac.next() {
1600 match b {
1601 b'[' => {
1602 nest = unsafe { nest.unchecked_add(1) };
1603 bytes.push(b'[');
1604 },
1605 b']' => {
1606 nest = unsafe { nest.unchecked_sub(1) };
1607 if nest == 0 {
1608 break;
1609 }
1610 else {
1611 bytes.push(b']');
1612 }
1613 },
1614 b'\\' => { match mac.next() {
1616 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() {
1630 if let Some(low) = upper_hex_to_nibble(b1) {
1631 bytes.push(high << 4 | low);
1632 }
1633 else {
1634 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1635 discard = true;
1636 }
1637 }
1638 else {
1639 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1640 discard = true;
1641 }
1642 }
1643 else { mac.back();
1645 match mac.try_next_char() {
1646 Ok(c) => {
1647 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1648 discard = true;
1649 },
1650 Err(e) => {
1651 *count = Natural::ZERO;
1652 synerr!('\0', "Aborting invalid macro: {}", e);
1653 break 'cmd;
1654 }
1655 }
1656 }
1657 },
1658 None => {
1659 synerr!('[', "Incomplete character escape: \\");
1660 discard = true;
1661 }
1662 }
1663 },
1664 _ => {
1665 bytes.push(b);
1666 }
1667 }
1668 }
1669 if !discard {
1670 match String::try_from(Utf8Iter::from(bytes)) {
1671 Ok(s) => {
1672 push!(Value::S(s));
1673 },
1674 Err(e) => {
1675 synerr!('[', "Invalid string: {}", e);
1676 }
1677 }
1678 }
1679 },
1680 _ => unreachable!()
1681 }
1682 },
1683 Space if b == b'#' => { debug!("Line comment");
1685 mac.find(|b| *b == b'\n');
1686 },
1687 Space => {
1688 },
1690 Wrong => {
1691 mac.back();
1692 match mac.try_next_char() {
1693 Ok(c) => {
1694 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1695 },
1696 Err(e) => {
1697 *count = Natural::ZERO;
1698 synerr!('\0', "Aborting invalid macro: {}", e);
1699 break 'cmd;
1700 }
1701 }
1702 }
1703 }
1704
1705 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1710 dest.clear(); }
1712
1713 if *count == Natural::ZERO { call.pop();
1715 }
1716 else { mac.rewind();
1718 }
1719 } Ok(Finished)
1722}