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