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, 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, Fn2(trig), 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
258#[derive(Clone, Copy, Debug, PartialEq)]
260#[must_use] pub enum ExecResult {
261 Finished,
263
264 SoftQuit(u8),
266
267 HardQuit(u8),
269
270 Killed
272}
273
274pub fn interpreter_no_os(
276 st: &mut State,
277 start: Utf8Iter,
278 io: Arc<Mutex<IOStreams>>,
279 ll: LogLevel,
280 kill: Option<&Receiver<()>>,
281) -> std::io::Result<ExecResult>
282{
283 unsafe { interpreter(st, start, io, ll, kill, true) }
285}
286
287pub unsafe fn interpreter(
312 st: &mut State,
313 start: Utf8Iter,
314 io: Arc<Mutex<IOStreams>>,
315 mut ll: LogLevel,
316 kill: Option<&Receiver<()>>,
317 #[cfg_attr(feature = "no_os", allow(unused_variables))]
318 mut restrict: bool
319) -> std::io::Result<ExecResult>
320{
321 use ExecResult::*;
322
323 let th_name = if kill.is_some() { #[cfg_attr(feature = "no_os", allow(unused_assignments))] { restrict = true; } std::thread::current().name().unwrap().to_owned()
326 }
327 else {
328 String::new()
329 };
330
331 let mut pbuf: Option<String> = None; let mut elatch: Option<(Natural, char, String)> = None;
334
335 macro_rules! synerr {
336 ($c:expr, $s:expr) => {
337 if ll != LogLevel::Quiet {
338 let err = &mut io.lock().unwrap().2;
339 writeln!(err, "! {th_name}{}: {}", $c, $s)?;
340 err.flush()?;
341 }
343 elatch = Some((Natural::ZERO, $c, $s.into()));
344 };
345 ($c:expr, $f:literal, $($s:expr),*) => {
346 let s = format!($f, $($s),*);
347 if ll != LogLevel::Quiet {
348 let err = &mut io.lock().unwrap().2;
349 writeln!(err, "! {th_name}{}: {}", $c, s)?;
350 err.flush()?;
351 }
353 elatch = Some((Natural::ZERO, $c, s));
354 };
355 }
356
357 macro_rules! valerr {
358 ($c:expr, $s:expr) => {
359 if ll != LogLevel::Quiet {
360 let err = &mut io.lock().unwrap().2;
361 writeln!(err, "? {th_name}{}: {}", $c, $s)?;
362 err.flush()?;
363 }
365 elatch = Some((Natural::ZERO, $c, $s.into()));
366 };
367 ($c:expr, $f:literal, $($s:expr),*) => {
368 let s = format!($f, $($s),*);
369 if ll != LogLevel::Quiet {
370 let err = &mut io.lock().unwrap().2;
371 writeln!(err, "? {th_name}{}: {}", $c, s)?;
372 err.flush()?;
373 }
375 elatch = Some((Natural::ZERO, $c, s));
376 };
377 }
378
379 macro_rules! debug {
380 ($s:expr) => {
381 if ll == LogLevel::Debug {
382 let err = &mut io.lock().unwrap().2;
383 writeln!(err, "\tDEBUG: {th_name}{}", $s)?;
384 err.flush()?;
385 }
387 };
388 ($f:literal, $($s:expr),*) => {
389 if ll == LogLevel::Debug {
390 let err = &mut io.lock().unwrap().2;
391 writeln!(err, "\tDEBUG: {th_name}{}", format!($f, $($s),*))?;
392 err.flush()?;
393 }
395 };
396 }
397
398 let mut rptr: Option<Rational> = None; let mut rng: Option<RandomPrimitiveInts<u64>> = None;
401
402 let mut call: Vec<(Utf8Iter, Natural)> = vec![(start, Natural::const_from(1))];
403
404 'mac: while let Some((mac, count)) = call.last_mut() { *count -= Natural::ONE;
406 let mut alt = false;
407
408 let mut abuf: Vec<Value> = Vec::new(); let mut dest: Vec<NonNull<Vec<Value>>> = Vec::new(); macro_rules! push {
412 ($v:expr) => {
413 if let Some(p) = dest.last_mut() {
414 unsafe {
415 p.as_mut().push($v); }
417 }
418 else {
419 st.mstk.push(Arc::new($v));
420 }
421 };
422 }
423 macro_rules! append {
425 ($v:expr) => {
426 if let Some(p) = dest.last_mut() {
427 unsafe {
428 p.as_mut().append(&mut $v); }
430 }
431 else {
432 for val in $v {
433 st.mstk.push(Arc::new(val));
434 }
435 }
436 };
437 }
438
439 'cmd: while let Some(b) = mac.next() { if let Some(rx) = kill { match rx.try_recv() {
442 Ok(()) => { #[expect(unused_assignments)]
444 for s in st.regs.end_threads(true) {
445 valerr!('j', s);
446 }
447 return Ok(Killed);
448 },
449 Err(TryRecvError::Empty) => { },
452 Err(TryRecvError::Disconnected) => { unreachable!()
454 }
455 }
456 }
457
458 if let Some(e) = &mut elatch { e.0 += Natural::ONE;
460 }
461
462 use Command::*;
463 match byte_cmd(b) {
464 Fn1(mon) => {
465 if let Some(va) = st.mstk.pop() {
466 debug!("Monadic {}{} with {}", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va));
467 match catch_unwind(|| fns::exec1(mon, &va, alt)) {
468 Ok(Ok(vz)) => {
469 push!(vz);
470 },
471 Ok(Err(e)) => {
472 st.mstk.push(va);
473 valerr!(b as char, e.to_string());
474 },
475 Err(cause) => {
476 st.mstk.push(va);
477 valerr!(b as char, "Caught function panic: {:?}", cause);
478 }
479 }
480 }
481 else {
482 synerr!(b as char, "Expected 1 argument, 0 given");
483 }
484 },
485 Fn2(dya) => {
486 if let Some(vb) = st.mstk.pop() {
487 if let Some(va) = st.mstk.pop() {
488 debug!("Dyadic {}{} with ({}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb));
489 match catch_unwind(|| fns::exec2(dya, &va, &vb, alt)) {
490 Ok(Ok(vz)) => {
491 push!(vz);
492 },
493 Ok(Err(e)) => {
494 st.mstk.push(va);
495 st.mstk.push(vb);
496 valerr!(b as char, e.to_string());
497 },
498 Err(cause) => {
499 st.mstk.push(va);
500 st.mstk.push(vb);
501 valerr!(b as char, "Caught function panic: {:?}", cause);
502 }
503 }
504 }
505 else {
506 st.mstk.push(vb);
507 synerr!(b as char, "Expected 2 arguments, 1 given");
508 }
509 }
510 else {
511 synerr!(b as char, "Expected 2 arguments, 0 given");
512 }
513 },
514 Fn3(tri) => {
515 if let Some(vc) = st.mstk.pop() {
516 if let Some(vb) = st.mstk.pop() {
517 if let Some(va) = st.mstk.pop() {
518 debug!("Triadic {}{} with ({}, {}, {})", if alt {"alt-"} else {""}, b as char, TypeLabel::from(&*va), TypeLabel::from(&*vb), TypeLabel::from(&*vc));
519 match catch_unwind(|| fns::exec3(tri, &va, &vb, &vc, alt)) {
520 Ok(Ok(vz)) => {
521 push!(vz);
522 },
523 Ok(Err(e)) => {
524 st.mstk.push(va);
525 st.mstk.push(vb);
526 st.mstk.push(vc);
527 valerr!(b as char, e.to_string());
528 },
529 Err(cause) => {
530 st.mstk.push(va);
531 st.mstk.push(vb);
532 st.mstk.push(vc);
533 valerr!(b as char, "Caught function panic: {:?}", cause);
534 }
535 }
536 }
537 else {
538 st.mstk.push(vb);
539 st.mstk.push(vc);
540 synerr!(b as char, "Expected 3 arguments, 2 given");
541 }
542 }
543 else {
544 st.mstk.push(vc);
545 synerr!(b as char, "Expected 3 arguments, 1 given");
546 }
547 }
548 else {
549 synerr!(b as char, "Expected 3 arguments, 0 given");
550 }
551 },
552 Cmd(cmd) => {
553 debug!("Impure command {}", b as char);
554 match cmd(st) {
555 Ok(mut v) => {
556 append!(v);
557 }
558 Err(e) => {
559 if let Some(se) = e.strip_suffix('!') {
560 synerr!(b as char, se);
561 }
562 else {
563 valerr!(b as char, e);
564 }
565 }
566 }
567 },
568 Exec => {
569 debug!("Command {}{}", if alt {"alt-"} else {""}, b as char);
570 match b {
571 b'`' => { alt = true;
573 continue 'cmd; },
575 b':' if !alt => { if let Some(va) = st.mstk.pop() {
577 if let Value::N(r) = &*va {
578 rptr = Some(r.clone());
579 }
580 else {
581 let ta = TypeLabel::from(&*va);
582 st.mstk.push(va);
583 synerr!(':', "Expected a number, {} given", ta);
584 }
585 }
586 else {
587 synerr!(':', "Expected 1 argument, 0 given");
588 }
589 },
590 b':' if alt => { push!(
592 if let Some(ri) = rptr.take() {
593 Value::N(ri)
594 }
595 else {
596 Value::A(vec![])
597 }
598 );
599 },
600 b'd' => {
601 if let Some(v) = st.mstk.last() {
602 if let Some(p) = dest.last_mut() { unsafe {
604 p.as_mut().push((**v).clone()); }
606 }
607 else {
608 st.mstk.push(Arc::clone(v));
609 }
610 }
611 else {
612 synerr!('d', "Stack is empty");
613 }
614 },
615 b'D' => {
616 if let Some(va) = st.mstk.pop() {
617 if let Value::N(r) = &*va {
618 match usize::try_from(r) {
619 Ok(0) => {}, Ok(u) => {
621 if let Some(from) = st.mstk.len().checked_sub(u) {
622 if let Some(p) = dest.last_mut() { for v in &st.mstk[from..] {
624 unsafe {
625 p.as_mut().push((**v).clone()); }
627 }
628 }
629 else {
630 st.mstk.extend_from_within(from..);
631 }
632 }
633 else {
634 st.mstk.push(va);
635 valerr!('D', "Can't duplicate {} values, stack depth is {}", u, st.mstk.len() - 1);
636 }
637 }
638 Err(_) => {
639 let vs = va.to_string();
640 st.mstk.push(va);
641 valerr!('D', "Can't possibly duplicate {} values", vs);
642 }
643 }
644 }
645 else {
646 let ta = TypeLabel::from(&*va);
647 st.mstk.push(va);
648 synerr!('D', "Expected a number, {} given", ta);
649 }
650 }
651 else {
652 synerr!('D', "Expected 1 argument, 0 given");
653 }
654 },
655 b'R' => { if let Some(va) = st.mstk.pop() {
657 if let Value::N(r) = &*va {
658 match usize::try_from(r) {
659 Ok(0) => {}, Ok(u) => {
661 if let Some(from) = st.mstk.len().checked_sub(u) {
662 if alt {st.mstk[from..].rotate_left(1);}
663 else {st.mstk[from..].rotate_right(1);}
664 }
665 else {
666 st.mstk.push(va);
667 valerr!('R', "Can't rotate {} values, stack depth is {}", u, st.mstk.len() - 1);
668 }
669 }
670 Err(_) => {
671 let vs = va.to_string();
672 st.mstk.push(va);
673 valerr!('R', "Can't possibly rotate {} values", vs);
674 }
675 }
676 }
677 else {
678 let ta = TypeLabel::from(&*va);
679 st.mstk.push(va);
680 synerr!('R', "Expected a number, {} given", ta);
681 }
682 }
683 else {
684 synerr!('R', "Expected 1 argument, 0 given");
685 }
686 },
687 b'?' => { let res = {
689 let inp = &mut io.lock().unwrap().0;
690 inp.read_line()
691 };
693 match res {
694 Ok(s) => {
695 push!(Value::S(s));
696 },
697 Err(e) => {
698 match e.kind() {
699 ErrorKind::Interrupted => {
700 valerr!('?', "Interrupted");
701 },
702 ErrorKind::UnexpectedEof => {
703 push!(Value::S(String::new()));
704 },
705 _ => {
706 return Err(e);
707 }
708 }
709 }
710 }
711 },
712 b'p' => { if let Some(va) = st.mstk.pop() {
714 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
715 if let Some(s) = &mut pbuf {
716 s.push_str(&vs);
717 s.push('\n');
718 }
719 else {
720 let out = &mut io.lock().unwrap().1;
721 writeln!(out, "{}", vs)?;
722 out.flush()?;
723 }
725 }
726 else {
727 synerr!('p', "Expected 1 argument, 0 given");
728 }
729 },
730 b'P' => { if let Some(va) = st.mstk.pop() {
732 let vs = va.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
733 if let Some(s) = &mut pbuf {
734 s.push_str(&vs);
735 }
736 else {
737 let out = &mut io.lock().unwrap().1;
738 write!(out, "{}", vs)?;
739 out.flush()?;
740 }
742 }
743 else {
744 synerr!('P', "Expected 1 argument, 0 given");
745 }
746 },
747 b'"' => { if let Some(s) = pbuf.take() { push!(Value::S(s));
750 }
751 else { pbuf = Some(String::new());
753 }
754 },
755 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)
760 }}
761 else {
762 NonNull::from(&mut abuf) };
764 dest.push(nn);
765 },
766 b')' => { if dest.pop().is_some() {
768 if dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf)))); }
771 }
772 else {
773 synerr!(')', "Mismatched closing ')'");
774 }
775 },
776 b'x' => {
777 if let Some(top) = st.mstk.pop() {
778 let sec = st.mstk.pop();
779 match Utf8Iter::from_vals(&top, sec.as_deref()) {
780 Ok((mut stk, ret)) => {
781 if let Some(sec) = sec && ret { st.mstk.push(sec);
783 }
784
785 if mac.is_finished() && *count == Natural::ZERO { call.pop();
787 }
788
789 call.append(&mut stk);
790 continue 'mac;
791 },
792 Err(e) => {
793 if let Some(sec) = sec {st.mstk.push(sec);}
794 st.mstk.push(top);
795 synerr!('x', "{}", e);
796 }
797 }
798 }
799 else {
800 synerr!('x', "Expected 1 or 2 arguments, 0 given");
801 }
802 },
803 b'q' => {
804 let u = u8::wrapping_from(&Integer::rounding_from(rptr.unwrap_or_default(), RoundingMode::Down).0);
805 return if alt {
806 Ok(HardQuit(u))
807 }
808 else {
809 Ok(SoftQuit(u))
810 };
811 },
812 b'Q' => {
813 if let Some(va) = st.mstk.pop() {
814 match &*va {
815 Value::N(r) => {
816 if let Ok(u) = usize::try_from(r) {
817 call.truncate(call.len().saturating_sub(u));
818 if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
820 dest.clear(); }
822 continue 'mac;
823 }
824 else {
825 let vs = va.to_string();
826 st.mstk.push(va);
827 valerr!('Q', "Cannot possibly break {} macros", vs);
828 }
829 },
830 _ => {
831 let ta = TypeLabel::from(&*va);
832 st.mstk.push(va);
833 synerr!('Q', "Expected a number, {} given", ta);
834 }
835 }
836 }
837 else {
838 synerr!('Q', "Expected 1 argument, 0 given");
839 }
840 },
841 b'a' => { match mac.next() {
843 Some(b) if !matches!(byte_cmd(b), Space) => {
844 match b {
845 b'a' => {
846 todo!()
847 },
848 _ => {
849 synerr!('a', "Invalid array command 'a{}'", b as char);
850 }
851 }
852 },
853 Some(_) | None => {
854 synerr!('a', "Incomplete array command 'a'");
855 }
856 }
857 },
858 b'f' => { match mac.next() {
860 Some(b) if !matches!(byte_cmd(b), Space) => {
861 match b {
862 b'z' => { push!(Value::N(st.mstk.len().into()));
864 },
865 b'r' => { st.mstk.reverse();
867 },
868 b'R' => { if let Some(va) = st.mstk.pop() {
870 if let Value::N(r) = &*va {
871 match usize::try_from(r) {
872 Ok(0) => {}, Ok(u) => {
874 if let Some(from) = st.mstk.len().checked_sub(u) {
875 st.mstk[from..].reverse();
876 }
877 else {
878 st.mstk.push(va);
879 valerr!('f', "Can't reverse {} values, stack depth is {}", u, st.mstk.len() - 1);
880 }
881 }
882 Err(_) => {
883 let vs = va.to_string();
884 st.mstk.push(va);
885 valerr!('f', "Can't possibly reverse {} values", vs);
886 }
887 }
888 }
889 else {
890 let ta = TypeLabel::from(&*va);
891 st.mstk.push(va);
892 synerr!('f', "Expected a number, {} given", ta);
893 }
894 }
895 else {
896 synerr!('f', "Expected 1 argument, 0 given");
897 }
898 },
899 b'f' => { let ri = if let Some(r) = rptr.take() {r}
901 else {
902 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
903 synerr!('f', "No register index");
904 alt = false;
905 continue 'cmd;
906 }
907 Rational::from(
908 match mac.try_next_char() {
909 Ok(c) => {c as u32},
910 Err(e) => {
911 *count = Natural::ZERO;
912 synerr!('\0', "Aborting invalid macro: {}", e);
913 break 'cmd;
914 }
915 }
916 )
917 };
918 let reg = st.regs.get_mut(&ri);
919 std::mem::swap(&mut st.mstk, &mut reg.v);
920 },
921 b'p' => { for v in &st.mstk {
923 let vs = v.display(st.params.get_k(), st.params.get_o(), st.params.get_m(), alt);
924 if let Some(s) = &mut pbuf {
925 s.push_str(&vs);
926 s.push('\n');
927 }
928 else {
929 let out = &mut io.lock().unwrap().1;
930 writeln!(out, "{}", vs)?;
931 out.flush()?;
932 }
933 }
934 },
935 _ => {
936 synerr!('f', "Invalid stack command 'f{}'", b as char);
937 }
938 }
939 },
940 Some(_) | None => {
941 synerr!('f', "Incomplete stack command 'f'");
942 }
943 }
944 },
945 b'N' => {
946 match (st.mstk.pop(), alt) {
947 (Some(va), false) => { match &*va {
949 Value::N(r) => {
950 match Natural::try_from(r) {
951 Ok(n) => {
952 push!(Value::N(Rational::from(
953 malachite::natural::random::get_random_natural_less_than(rng.get_or_insert_with(rng_os), &n)
954 )));
955 },
956 _ => {
957 st.mstk.push(va);
958 valerr!('N', "Limit must be a natural number");
959 }
960 }
961 },
962 _ => {
963 let ta = TypeLabel::from(&*va);
964 st.mstk.push(va);
965 synerr!('N', "Expected a number, {} given", ta);
966 }
967 }
968 }
969 (Some(va), true) => { match &*va {
971 Value::N(r) => {
972 match Integer::try_from(r) {
973 Ok(Integer::NEGATIVE_ONE) => { rng = None;
975 },
976 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();
979 bytes.resize(32, 0);
980 rng = Some(rng_preset( unsafe { <[u8; 32]>::try_from(bytes).unwrap_unchecked() } ));
981 },
982 _ => {
983 st.mstk.push(va);
984 valerr!('N', "Seed must be a natural number or `1");
985 }
986 }
987 },
988 _ => {
989 let ta = TypeLabel::from(&*va);
990 st.mstk.push(va);
991 synerr!('N', "Expected a number, {} given", ta);
992 }
993 }
994 }
995 (None, _) => {
996 synerr!('N', "Expected 1 argument, 0 given");
997 }
998 }
999 },
1000 b'w' => { if let Some(va) = st.mstk.pop() {
1002 if let Value::N(r) = &*va {
1003 if let Some(dur) = Natural::try_from(r).ok().and_then(|n| {
1004 let (s, ns) = n.div_rem(Natural::const_from(1_000_000_000));
1005 u64::try_from(&s).ok().map(|s| {
1006 let ns = unsafe { u32::try_from(&ns).unwrap_unchecked() }; std::time::Duration::new(s, ns)
1008 })
1009 }) {
1010 if let Some(rx) = kill {
1011 match rx.recv_timeout(dur) {
1012 Ok(()) => { #[expect(unused_assignments)]
1014 for s in st.regs.end_threads(true) {
1015 valerr!('j', s);
1016 }
1017 return Ok(Killed);
1018 },
1019 Err(RecvTimeoutError::Timeout) => { },
1022 Err(RecvTimeoutError::Disconnected) => { unreachable!()
1024 }
1025 }
1026 }
1027 else {
1028 std::thread::sleep(dur); }
1030 }
1031 else {
1032 let vs = va.to_string();
1033 st.mstk.push(va);
1034 valerr!('w', "Can't possibly wait {} ns", vs);
1035 }
1036 }
1037 else {
1038 let ta = TypeLabel::from(&*va);
1039 st.mstk.push(va);
1040 synerr!('w', "Expected a number, {} given", ta);
1041 }
1042 }
1043 else {
1044 synerr!('w', "Expected 1 argument, 0 given");
1045 }
1046 },
1047 b'_' => { let mut word = Vec::new();
1049 while let Some(b) = mac.next() {
1050 if matches!(byte_cmd(b), Space) {
1051 mac.back();
1052 break;
1053 }
1054 else {
1055 word.push(b);
1056 }
1057 }
1058
1059 match &word[..] { b"restrict" => {
1061 #[cfg_attr(feature = "no_os", allow(unused_assignments))] { restrict = true; }
1062 },
1063 b"quiet" => {
1064 ll = LogLevel::Quiet;
1065 },
1066 b"error" => {
1067 ll = LogLevel::Normal;
1068 },
1069 b"debug" => {
1070 ll = LogLevel::Debug;
1071 },
1072 b"err" => {
1073 push!(Value::A(
1074 if let Some((n, c, s)) = elatch.take() {
1075 vec![
1076 Value::N(n.into()),
1077 Value::S(c.into()),
1078 Value::S(s)
1079 ]
1080 }
1081 else { vec![] }
1082 ));
1083 },
1084 b"th" => {
1085 push!(Value::S(th_name.clone()));
1086 },
1087 b"joinall" => {
1088 for s in st.regs.end_threads(false) {
1089 valerr!('j', s);
1090 }
1091 },
1092 b"killall" => {
1093 for s in st.regs.end_threads(true) {
1094 valerr!('j', s);
1095 }
1096 },
1097 b"trim" => {
1098 st.trim();
1099 RE_CACHE.clear();
1100 },
1101 b"clhist" => {
1102 io.lock().unwrap().0.clear_history();
1103 },
1104 b"clpar" => {
1105 st.params = ParamStk::default();
1106 },
1107 b"clall" => {
1108 st.clear_vals();
1109 RE_CACHE.clear();
1110 },
1111 _ => {
1112 #[cfg(feature = "no_os")]
1113 {
1114 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1115 }
1116 #[cfg(not(feature = "no_os"))]
1117 {
1118 match (restrict, os::OS_CMDS.get(&word).copied()) {
1119 (false, Some(oscmd)) => {
1120 match unsafe { oscmd(st) } { Ok(mut v) => {
1122 append!(v);
1123 }
1124 Err(e) => {
1125 if let Some(se) = e.strip_suffix('!') {
1126 synerr!('_', "OS command '{}': {}", string_or_bytes(&word), se);
1127 }
1128 else {
1129 valerr!('_', "OS command '{}': {}", string_or_bytes(&word), e);
1130 }
1131 }
1132 }
1133 }
1134 (true, Some(_)) => {
1135 synerr!('_', "OS command '{}' is disabled (restricted mode)", string_or_bytes(&word));
1136 },
1137 _ => {
1138 synerr!('_', "Invalid word command '{}'", string_or_bytes(&word));
1139 }
1140 }
1141 }
1142 }
1143 }
1144 },
1145 _ => unreachable!()
1146 }
1147 },
1148 ExecR => {
1149 let ri = if let Some(r) = rptr.take() {r}
1150 else {
1151 if matches!(mac.next().map(|b| {mac.back(); byte_cmd(b)}), None | Some(Space)) {
1152 synerr!(b as char, "No register index");
1153 alt = false;
1154 continue 'cmd;
1155 }
1156 Rational::from(
1157 match mac.try_next_char() {
1158 Ok(c) => {c as u32},
1159 Err(e) => {
1160 *count = Natural::ZERO;
1161 synerr!('\0', "Aborting invalid macro: {}", e);
1162 break 'cmd;
1163 }
1164 }
1165 )
1166 };
1167 debug!("Register command {}{}", if alt {"alt-"} else {""}, b as char);
1168 match b {
1169 b'Z' => { push!(Value::N(
1171 st.regs.try_get(&ri).map(|reg| reg.v.len().into()).unwrap_or_default()
1172 ));
1173 },
1174 b's' => {
1175 if let Some(va) = st.mstk.pop() {
1176 let reg = st.regs.get_mut(&ri);
1177 if let Some(rv) = reg.v.last_mut() {
1178 *rv = va;
1179 }
1180 else {
1181 reg.v.push(va);
1182 }
1183 }
1184 else {
1185 synerr!('s', "Stack is empty");
1186 }
1187 },
1188 b'S' => {
1189 if let Some(va) = st.mstk.pop() {
1190 st.regs.get_mut(&ri).v.push(va);
1191 }
1192 else {
1193 synerr!('S', "Stack is empty");
1194 }
1195 },
1196 b'l' => {
1197 if let Some(rv) = st.regs.try_get(&ri).and_then(|reg| reg.v.last()) {
1198 if let Some(p) = dest.last_mut() { unsafe {
1200 p.as_mut().push((**rv).clone()); }
1202 }
1203 else {
1204 st.mstk.push(Arc::clone(rv));
1205 }
1206 }
1207 else {
1208 synerr!('l', "Register {} is empty", reg_index_nice(&ri));
1209 }
1210 },
1211 b'L' => {
1212 if let Some(rv) = st.regs.try_get_mut(&ri).and_then(|reg| reg.v.pop()) {
1213 if let Some(p) = dest.last_mut() { unsafe {
1215 p.as_mut().push((*rv).clone()); }
1217 }
1218 else {
1219 st.mstk.push(Arc::clone(&rv));
1220 }
1221 }
1222 else {
1223 synerr!('L', "Register {} is empty", reg_index_nice(&ri));
1224 }
1225 },
1226 b'X' => {
1227 if let Some(true) = st.regs.try_get(&ri).map(|reg| reg.th.is_some()) {
1228 valerr!('X', "Register {} is already running a thread", reg_index_nice(&ri));
1229 }
1230 else if let Some(top) = st.mstk.pop() {
1231 let sec = st.mstk.pop();
1232 match Utf8Iter::from_vals(&top, sec.as_deref()) {
1233 Ok((stk, ret)) => {
1234 if let Some(sec) = sec && ret { st.mstk.push(sec);
1236 }
1237
1238 let (tx, rx) = std::sync::mpsc::channel::<()>();
1239 let tb = std::thread::Builder::new().name(format!("{th_name}{}: ", reg_index_nice(&ri)));
1240 let mut th_st = if alt { st.clone() } else { State::default() };
1241 let th_io = Arc::clone(&io);
1242
1243 match tb.spawn(move || {
1244 let mut th_res = (Vec::new(), Ok(Finished));
1245
1246 'all: for (th_start, th_count) in stk {
1247 for _ in malachite::natural::exhaustive::exhaustive_natural_range(Natural::ZERO, th_count) {
1248 match interpreter_no_os(&mut th_st, th_start.clone(), Arc::clone(&th_io), ll, Some(&rx)) {
1249 Ok(Finished) => {continue;},
1250 Ok(er) => {
1251 th_res.1 = Ok(er);
1252 break 'all;
1253 },
1254 Err(e) => {
1255 th_res.1 = Err(e);
1256 break 'all;
1257 }
1258 }
1259 }
1260 }
1261
1262 th_res.0 = th_st.mstk;
1263 th_res
1264 }) {
1265 Ok(jh) => {
1266 st.regs.get_mut(&ri).th = Some((jh, tx));
1267 },
1268 Err(e) => {
1269 valerr!('X', "Can't spawn child thread: {}", e);
1270 }
1271 }
1272 },
1273 Err(e) => {
1274 if let Some(sec) = sec {st.mstk.push(sec);}
1275 st.mstk.push(top);
1276 synerr!('X', "{}", e);
1277 }
1278 }
1279 }
1280 else {
1281 synerr!('X', "Expected 1 or 2 arguments, 0 given");
1282 }
1283 },
1284 b'j' => {
1285 if let Some(reg) = st.regs.try_get_mut(&ri) && let Some((jh, tx)) = reg.th.take() {
1286 if alt {
1287 tx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", reg_index_nice(&ri)));
1288 }
1289 match jh.join() {
1290 Ok(mut res) => {
1291 match res.1 {
1292 Err(e) => {
1293 valerr!('j', "IO error in thread {}: {}", reg_index_nice(&ri), e);
1294 },
1295 Ok(SoftQuit(c)) if c != 0 => {
1296 valerr!('j', "Thread {} quit with code {}", reg_index_nice(&ri), c);
1297 },
1298 Ok(HardQuit(c)) if c != 0 => {
1299 valerr!('j', "Thread {} hard-quit with code {}", reg_index_nice(&ri), c);
1300 },
1301 Ok(Killed) => {
1302 valerr!('j', "Thread {} was killed", reg_index_nice(&ri));
1303 },
1304 _ => {}
1305 }
1306
1307 reg.v.append(&mut res.0);
1308 },
1309 Err(e) => {
1310 std::panic::resume_unwind(e);
1311 }
1312 }
1313 }
1314 else {
1315 valerr!('j', "Register {} is not running a thread", reg_index_nice(&ri));
1316 }
1317 },
1318 b'J' => {
1319 if let Some(Some((jh, _))) = st.regs.try_get(&ri).map(|reg| ®.th) {
1320 let mut bz = BitVec::new();
1321 bz.push(jh.is_finished());
1322 push!(Value::B(bz));
1323 }
1324 else {
1325 valerr!('J', "Register {} is not running a thread", reg_index_nice(&ri));
1326 }
1327 },
1328 _ => unreachable!()
1329 }
1330 },
1331 Lit => {
1332 match b {
1333 b'T' | b'F' => { debug!("Boolean literal");
1335 let mut bits = BitVec::new();
1336 bits.push(b == b'T');
1337 while let Some(b) = mac.next() {
1338 match b {
1339 b'T' => {bits.push(true);},
1340 b'F' => {bits.push(false);},
1341 _ => {
1342 mac.back();
1343 break;
1344 }
1345 }
1346 }
1347 push!(Value::B(bits));
1348 },
1349 b'\'' | b'0'..=b'9' | b'.' | b'@' => { debug!("Number literal");
1351 let mut ipart = Vec::new();
1352 let mut fpart = Vec::new();
1353 let mut rpart = Vec::new();
1354 let mut get_epart = true;
1355 let mut exp = None;
1356 let mut discard = false;
1357 let mut ibase = st.params.get_i().clone();
1358
1359 match (b == b'\'', ibase > Natural::const_from(36)) {
1360 (false, high_base) => { mac.back();
1362 ibase = if high_base {Natural::const_from(10)} else {ibase}; while let Some(ib) = mac.next() { let id = ib.wrapping_sub(0x30);
1365 match id {
1366 0..=9 if id < ibase => {ipart.push(Natural::from(id));},
1367 0..=9 => {
1368 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1369 discard = true;
1370 },
1371 _ => {
1372 mac.back();
1373 break;
1374 }
1375 }
1376 }
1377 match mac.next() {
1378 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1381 let fd = fb.wrapping_sub(0x30);
1382 match fd {
1383 0x30 if !recur => {recur = true;}, 0..=9 if !recur && fd < ibase => {fpart.push(Natural::from(fd));},
1385 0..=9 if recur && fd < ibase => {rpart.push(Natural::from(fd));},
1386 0..=9 => {
1387 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1388 discard = true;
1389 },
1390 _ => {
1391 mac.back();
1392 break;
1393 }
1394 }
1395 }
1396 },
1397 Some(_) => {mac.back();},
1398 None => {}
1399 }
1400 }
1401 (true, false) => { while let Some(ib) = mac.next() { if let Some(id) = mixed_ascii_to_digit(ib) {
1404 if id < ibase {ipart.push(Natural::from(id));}
1405 else {
1406 synerr!('\'', "Digit {} is too high for base {}", id, ibase);
1407 discard = true;
1408 }
1409 }
1410 else {
1411 mac.back();
1412 break;
1413 }
1414 }
1415 match mac.next() {
1416 Some(b'.') => { let mut recur = false; while let Some(fb) = mac.next() {
1419 if let Some(fd) = mixed_ascii_to_digit(fb) {
1420 if fd < ibase {
1421 if !recur {fpart.push(Natural::from(fd));}
1422 else {rpart.push(Natural::from(fd));}
1423 }
1424 else {
1425 synerr!('\'', "Digit {} is too high for base {}", fd, ibase);
1426 discard = true;
1427 }
1428 }
1429 else if !recur && fb == b'`' {recur = true;}
1430 else {
1431 mac.back();
1432 break;
1433 }
1434 }
1435 },
1436 Some(_) => {mac.back();},
1437 None => {}
1438 }
1439 },
1440 (true, true) => { get_epart = false;
1442 let ns= mac.by_ref().take_while(|b| *b != b'\'').collect::<Vec<u8>>();
1443 if ns.is_empty() {
1444 synerr!('\'', "Empty any-base number");
1445 alt = false;
1446 continue 'cmd;
1447 }
1448 for nc in ns.iter() {
1449 match nc {
1450 b' ' | b'.' | b'0'..=b'9' | b'@' | b'`' => {} wrong => {
1452 synerr!('\'', "Invalid character in any-base number: {}", string_or_bytes(&[*wrong]));
1453 alt = false;
1454 continue 'cmd;
1455 }
1456 }
1457 }
1458 let mut ms = Vec::new();
1459 match ns.split(|b| *b == b'@').collect::<Vec<&[u8]>>()[..] {
1460 [mpart] => { ms = mpart.to_vec();
1462 },
1463 [mpart, epart] => { ms = mpart.to_vec();
1465 let mut es = epart.to_vec();
1466 if let Some(first) = es.first_mut() && *first == b'`' { *first = b'-'; }
1467 match String::from_utf8(es) {
1468 Ok(es) => {
1469 match es.parse::<i64>() {
1470 Ok(i) => { exp = Some(i); },
1471 Err(e) => {
1472 use std::num::IntErrorKind::*;
1473 match e.kind() {
1474 Empty => { exp = Some(0); },
1475 InvalidDigit => {
1476 valerr!('\'', "Invalid exponent: {}", es);
1477 alt = false;
1478 continue 'cmd;
1479 },
1480 PosOverflow | NegOverflow => {
1481 valerr!('\'', "Exponent {} is unrepresentable", es);
1482 alt = false;
1483 continue 'cmd;
1484 },
1485 _ => { unreachable!() }
1486 }
1487 }
1488 }
1489 },
1490 _ => { unreachable!() }
1491 }
1492 },
1493 ref v => {
1494 synerr!('\'', "{} exponent signs (@) in any-base number", v.len() - 1);
1495 drop(ms);
1496 alt = false;
1497 continue 'cmd;
1498 }
1499 }
1500 let mut is = Vec::new();
1501 let mut frs = Vec::new();
1502 match ms.split(|b| *b == b'.').collect::<Vec<&[u8]>>()[..] {
1503 [ipart] => {
1504 is = ipart.to_vec();
1505 },
1506 [ipart, fpart] => {
1507 is = ipart.to_vec();
1508 frs = fpart.to_vec();
1509 },
1510 ref v => {
1511 synerr!('\'', "{} fractional points (.) in any-base number", v.len() - 1);
1512 drop(is);
1513 alt = false;
1514 continue 'cmd;
1515 }
1516 }
1517 if is.contains(&b'`') {
1518 synerr!('\'', "Unexpected negative sign (`) in any-base number");
1519 alt = false;
1520 continue 'cmd;
1521 }
1522 let mut fs = Vec::new();
1523 let mut rs = Vec::new();
1524 match frs.split(|b| *b == b'`').collect::<Vec<&[u8]>>()[..] {
1525 [fpart] => {
1526 fs = fpart.to_vec();
1527 },
1528 [fpart, rpart] => {
1529 fs = fpart.to_vec();
1530 rs = rpart.to_vec();
1531 },
1532 ref v => {
1533 synerr!('\'', "{} recurring marks (`) in any-base number", v.len() - 1);
1534 drop(fs);
1535 alt = false;
1536 continue 'cmd;
1537 }
1538 }
1539 if !is.is_empty() { for id in is.split(|b| *b == b' ') {
1540 let id = str::from_utf8(id).unwrap();
1541 ipart.push(Natural::from_str(id).unwrap());
1542 }}
1543 if !fs.is_empty() { for fd in fs.split(|b| *b == b' ') {
1544 let fd = str::from_utf8(fd).unwrap();
1545 fpart.push(Natural::from_str(fd).unwrap());
1546 }}
1547 if !rs.is_empty() { for rd in rs.split(|b| *b == b' ') {
1548 let rd = str::from_utf8(rd).unwrap();
1549 rpart.push(Natural::from_str(rd).unwrap());
1550 }}
1551 for d in ipart.iter().chain(fpart.iter()).chain(rpart.iter()) {
1552 if *d >= ibase {
1553 synerr!('\'', "Digit {} is too high for base {}", d, ibase);
1554 alt = false;
1555 continue 'cmd;
1556 }
1557 }
1558 }
1559 }
1560
1561 let m_empty = ipart.is_empty() && fpart.is_empty() && rpart.is_empty(); let mut r;
1563 if m_empty {
1564 r = Rational::ZERO;
1565 }
1566 else {
1567 ipart.reverse(); r = Rational::from_digits(&ibase, ipart, RationalSequence::from_vecs(fpart, rpart));
1569 if alt {r.neg_assign();} }
1571
1572 if get_epart {
1573 match mac.next() {
1574 Some(b'@') => { let mut es = String::new();
1576 let mut eneg = false; while let Some(eb) = mac.next() {
1578 match eb {
1579 b'`' if !eneg => { es.push('-'); }
1580 b'0'..=b'9' => { es.push(eb as char); }
1581 _ => {
1582 mac.back();
1583 break;
1584 }
1585 }
1586 eneg = true; }
1588 if es.is_empty() { es.push('0'); }
1589 if m_empty { r = Rational::ONE; } if let Ok(i) = es.parse::<i64>() {
1591 r *= Rational::from(st.params.get_i()).pow(i); }
1593 else {
1594 valerr!('\'', "Exponent {} is unrepresentable", es);
1595 discard = true;
1596 }
1597 }
1598 Some(_) => { mac.back(); }
1599 None => {}
1600 }
1601 }
1602 else if let Some(i) = exp {
1603 if m_empty { r = Rational::ONE; } r *= Rational::from(ibase).pow(i); }
1606
1607 if !discard {
1608 push!(Value::N(r));
1609 }
1610 },
1611 b'[' => { debug!("String literal");
1613 let mut bytes = Vec::new();
1614 let mut discard = false;
1615 let mut nest = 1usize;
1616 while let Some(b) = mac.next() {
1617 match b {
1618 b'[' => {
1619 nest = unsafe { nest.unchecked_add(1) };
1620 bytes.push(b'[');
1621 },
1622 b']' => {
1623 nest = unsafe { nest.unchecked_sub(1) };
1624 if nest == 0 {
1625 break;
1626 }
1627 else {
1628 bytes.push(b']');
1629 }
1630 },
1631 b'\\' => { match mac.next() {
1633 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() {
1647 if let Some(low) = upper_hex_to_nibble(b1) {
1648 bytes.push(high << 4 | low);
1649 }
1650 else {
1651 synerr!('[', "Invalid byte escape: \\{}{}", b0 as char, b1 as char);
1652 discard = true;
1653 }
1654 }
1655 else {
1656 synerr!('[', "Incomplete byte escape: \\{}", b0 as char);
1657 discard = true;
1658 }
1659 }
1660 else { mac.back();
1662 match mac.try_next_char() {
1663 Ok(c) => {
1664 synerr!('[', "Invalid character escape: \\{} (U+{:04X})", c, c as u32);
1665 discard = true;
1666 },
1667 Err(e) => {
1668 *count = Natural::ZERO;
1669 synerr!('\0', "Aborting invalid macro: {}", e);
1670 break 'cmd;
1671 }
1672 }
1673 }
1674 },
1675 None => {
1676 synerr!('[', "Incomplete character escape: \\");
1677 discard = true;
1678 }
1679 }
1680 },
1681 _ => {
1682 bytes.push(b);
1683 }
1684 }
1685 }
1686 if !discard {
1687 match String::try_from(Utf8Iter::from(bytes)) {
1688 Ok(s) => {
1689 push!(Value::S(s));
1690 },
1691 Err(e) => {
1692 synerr!('[', "Invalid string: {}", e);
1693 }
1694 }
1695 }
1696 },
1697 _ => unreachable!()
1698 }
1699 },
1700 Space if b == b'#' => { debug!("Line comment");
1702 mac.find(|b| *b == b'\n');
1703 },
1704 Space => {
1705 },
1707 Wrong => {
1708 mac.back();
1709 match mac.try_next_char() {
1710 Ok(c) => {
1711 synerr!(c, "Invalid command: {} (U+{:04X})", c, c as u32);
1712 },
1713 Err(e) => {
1714 *count = Natural::ZERO;
1715 synerr!('\0', "Aborting invalid macro: {}", e);
1716 break 'cmd;
1717 }
1718 }
1719 }
1720 }
1721
1722 alt = false; } if !dest.is_empty() { st.mstk.push(Arc::new(Value::A(std::mem::take(&mut abuf))));
1727 dest.clear(); }
1729
1730 if *count == Natural::ZERO { call.pop();
1732 }
1733 else { mac.rewind();
1735 }
1736 } Ok(Finished)
1739}