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