adc_lang/
structs.rs

1//! Storage structs and methods
2
3use std::collections::HashMap;
4use std::fmt::{Display, Formatter};
5use std::sync::{Arc, RwLock, mpsc::Sender};
6use std::thread::JoinHandle;
7use bitvec::prelude::*;
8use malachite::{Natural, Rational};
9use malachite::base::num::basic::traits::{Zero, One};
10use regex::{Regex, RegexBuilder};
11
12#[derive(Debug)]
13pub enum Value {
14	B(BitVec<usize, Lsb0>),
15	N(Rational),
16	S(String),
17	A(Vec<Value>)
18}
19impl Default for Value {
20	fn default() -> Self {
21		Self::A(Vec::new())
22	}
23}
24
25/// Non-recursive heap DFS to avoid overflowing the stack.
26impl Drop for Value {
27	fn drop(&mut self) {
28		use Value::*;
29		use std::mem::take;
30		if let A(a) = self {
31			let mut q: Vec<Vec<Value>> = vec![take(a)];	//init queue for arrays to be processed
32			while let Some(mut a) = q.pop() {
33				for v in &mut a {	//traverse current array
34					if let A(aa) = v {	//if a nested array is encountered
35						q.push(take(aa))	//move it to the queue
36					}
37				}
38				//current array drops here, with no nested contents
39			}
40		}
41		//scalar values drop themselves after this
42	}
43}
44
45/// Non-recursive heap BFS to avoid overflowing the stack, using a monadic identity.
46impl Clone for Value {
47	fn clone(&self) -> Self {
48		use Value::*;
49		match self {
50			//scalar base cases
51			B(b) => B(b.clone()),
52			N(n) => N(n.clone()),
53			S(s) => S(s.clone()),
54			//traverse array using heap pseudorecursion, perform (cloning) identity function on every value
55			//`exec1` takes over instead of continuing call recursion, `f` is never called on `A`.
56			A(_) => unsafe { crate::fns::exec1(|v, _| Ok(v.clone()), self, false).unwrap_unchecked() }	//SAFETY: clone is infallible
57		}
58	}
59}
60
61impl Value {
62	/// Prints scalar values, passing `A` is undefined behavior. `sb` prints brackets around strings.
63	unsafe fn display_scalar(&self, k: usize, o: &Natural, nm: NumOutMode, sb: bool) -> String {
64		use Value::*;
65		match self {
66			B(b) => {
67				b.iter().by_vals().map(|b| if b {'T'} else {'F'}).collect()
68			},
69			N(n) => {
70				use crate::num::*;
71				use NumOutMode::*;
72				match nm {
73					Auto => {
74						nauto(n, k, o)
75					},
76					Norm => {
77						let (neg, ipart, fpart, rpart) = digits(n, k, o);
78						nnorm(neg, &ipart, &fpart, &rpart, o)
79					},
80					Sci => {
81						let (neg, ipart, fpart, rpart) = digits(n, k, o);
82						nsci(neg, &ipart, &fpart, &rpart, o)
83					},
84					Frac => {
85						nfrac(n, k, o)
86					},
87				}
88			},
89			S(s) => {
90				if sb {
91					String::from("[") + s + "]"
92				}
93				else {
94					s.to_owned()
95				}
96			},
97			A(_) => {
98				unsafe { std::hint::unreachable_unchecked() }
99			}
100		}
101	}
102	
103	/// Prints the value, heap DFS to avoid overflowing the stack. `sb` prints brackets around strings.
104	pub fn display(&self, k: usize, o: &Natural, nm: NumOutMode, sb: bool) -> String {
105		use Value::*;
106		match self {
107			A(a) => {	//the fun part
108				let mut stk: Vec<std::slice::Iter<Value>> = vec![a.iter()];
109				let mut res = String::from('(');
110				while let Some(i) = stk.last_mut() {	//keep operating on the top iter
111					if let Some(val) = i.next() {	//advance it
112						match val {
113							A(aa) => {	//nested array encountered
114								if res.ends_with(' ') {res.pop();}
115								res.push('(');
116								stk.push(aa.iter());	//"recursive call"
117							},
118							_ => {	//scalar encountered
119								let s = unsafe { val.display_scalar(k, o, nm, sb) };
120								res += &s;	//append it
121								res.push(' ');
122							}
123						}
124					}
125					else {	//if top iter has ended
126						if res.ends_with(' ') {
127							res.pop();	//remove trailing space
128						}
129						res.push(')');
130						stk.pop();	//"return"
131					}
132				}
133				res
134			},
135			_ => {	//just display scalar
136				unsafe { self.display_scalar(k, o, nm, sb) }
137			}
138		}
139	}
140}
141
142/// Canonical printing function, with default parameters for `N` and brackets for `S`.
143impl Display for Value {
144	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
145		write!(f, "{}", self.display(DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2, DEFAULT_PARAMS.3, true))
146	}
147}
148
149/// Tries to convert register index ([`Rational`]) to a string if it was likely set from one, or displays the number with automatic format
150pub fn reg_index_nice(ri: &Rational) -> String {
151	use malachite::base::num::conversion::traits::PowerOf2Digits;
152	Natural::try_from(ri).ok().and_then(|n| {	//if ri is a natural
153		let bytes: Vec<u8> = n.to_power_of_2_digits_desc(8);	//look at its bytes
154		str::from_utf8(&bytes).ok().map(|s| String::from("[") + s + "]")	//if it parses to a string, ri was likely set from one
155	})
156		.unwrap_or_else(|| {
157			crate::num::nauto(ri, DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2)	//or just return the number in canonical notation
158		})
159}
160
161pub type ThreadResult = (Vec<Arc<Value>>, std::io::Result<crate::ExecResult>);
162
163#[derive(Default, Debug)]
164pub struct Register {
165	/// Stack of values, [`Arc`] to allow shallow copies
166	pub v: Vec<Arc<Value>>,
167	/// Thread handle with result values, kill signal, join signal. Sending or dropping the join signal is required before joining.
168	pub th: Option<(JoinHandle<ThreadResult>, Sender<()>, Sender<()>)>
169}
170/// Clone without thread handles since those are unique
171impl Clone for Register {
172	fn clone(&self) -> Self {
173		Self {
174			v: self.v.clone(),
175			th: None
176		}
177	}
178}
179
180/// Register storage with different indexing modes
181#[derive(Clone, Debug)]
182pub struct RegStore {
183	/// this covers ASCII integer values for frequently-accessed registers (commands like `sa`)
184	pub low: [Register; 128],
185
186	/// arbitrary rational indices otherwise
187	pub high: HashMap<Rational, Register>
188}
189impl RegStore {
190	/// Get register reference, don't create a register if not present
191	pub fn try_get(&self, index: &Rational) -> Option<&Register> {
192		usize::try_from(index).ok()
193			.and_then(|u| self.low.get(u))
194			.or_else(|| self.high.get(index))
195	}
196
197	/// Get mutable register reference, don't create a register if not present
198	pub fn try_get_mut(&mut self, index: &Rational) -> Option<&mut Register> {
199		usize::try_from(index).ok()
200			.and_then(|u| self.low.get_mut(u))
201			.or_else(|| self.high.get_mut(index))
202	}
203
204	/// Get mutable register reference, create register if necessary
205	pub fn get_mut(&mut self, index: &Rational) -> &mut Register {
206		usize::try_from(index).ok()
207			.and_then(|u| self.low.get_mut(u))
208			.unwrap_or_else(|| self.high.entry(index.clone()).or_default())
209	}
210
211	/// Discard unused registers, reallocate used ones to fit
212	pub fn trim(&mut self) {
213		for reg in &mut self.low {
214			reg.v.shrink_to_fit();
215		}
216		self.high.retain(|_, reg| {
217			if reg.v.is_empty() {
218				reg.th.is_some()
219			}
220			else {
221				reg.v.shrink_to_fit();
222				true
223			}
224		});
225	}
226
227	/// Clear all values, don't touch thread handles in `self`
228	pub fn clear_vals(&mut self) {
229		for reg in &mut self.low {
230			reg.v = Vec::new();
231		}
232		self.high.retain(|_, reg| {
233			reg.v = Vec::new();
234			reg.th.is_some()
235		});
236		self.high.shrink_to_fit();
237	}
238
239	/// Replace values with those from `other`, keep thread handles in `self` and discard any in `other`
240	pub fn replace_vals(&mut self, mut other: Self) {
241		for (reg, oreg) in self.low.iter_mut().zip(other.low.into_iter()) {
242			reg.v = oreg.v;
243		}
244		self.high.retain(|ri, reg| {	//retain existing regs if:
245			if let Some(oreg) = other.high.remove(ri) && !oreg.v.is_empty() {	//other has one with the same index
246				reg.v = oreg.v;
247				true
248			}
249			else {	//or a thread handle
250				reg.v = Vec::new();
251				reg.th.is_some()
252			}
253		});
254		for (ori, oreg) in other.high.drain().filter_map(|(ori, oreg)| (!oreg.v.is_empty()).then_some((ori, Register {v: oreg.v, th: None}))) {
255			self.high.insert(ori, oreg);
256		}
257	}
258
259	/// Joins all thread handles, `kill = true` first sends kill signals.
260	/// 
261	/// Returns messages from any unhappy terminations, same as the `j` command.
262	pub fn end_threads(&mut self, kill: bool) -> Vec<String> {
263		use crate::ExecResult::*;
264		
265		let mut res = Vec::new();
266		
267		for (ri, reg) in
268			self.low.iter_mut().enumerate().map(|(ri, reg)| (Rational::from(ri), reg))
269				.chain(self.high.iter_mut().map(|(ri, reg)| (ri.clone(), reg)))
270		{
271			if let Some((jh, ktx, jtx)) = reg.th.take() {
272				if kill {
273					ktx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", reg_index_nice(&ri)));
274				}
275				jtx.send(()).unwrap_or_else(|_| panic!("Thread {} panicked, terminating!", reg_index_nice(&ri)));
276				match jh.join() {
277					Ok(mut tr) => {
278						match tr.1 {
279							Err(e) => {
280								res.push(format!("IO error in thread {}: {}", reg_index_nice(&ri), e));
281							},
282							Ok(SoftQuit(c)) if c != 0 => {
283								res.push(format!("Thread {} quit with code {}", reg_index_nice(&ri), c));
284							},
285							Ok(HardQuit(c)) if c != 0 => {
286								res.push(format!("Thread {} hard-quit with code {}", reg_index_nice(&ri), c));
287							},
288							Ok(Killed) => {
289								res.push(format!("Thread {} was killed", reg_index_nice(&ri)));
290							},
291							_ => {}
292						}
293						
294						reg.v.append(&mut tr.0);
295					},
296					Err(e) => {
297						std::panic::resume_unwind(e);
298					}
299				}
300			}
301		}
302		res
303	}
304}
305impl Default for RegStore {
306	fn default() -> Self {
307		Self {
308			low: std::array::from_fn(|_| Register::default()),
309			high: HashMap::default()
310		}
311	}
312}
313
314/// globally shareable cache for compiled regex automata
315#[derive(Default, Debug)]
316#[repr(transparent)] pub(crate) struct RegexCache(pub(crate) RwLock<HashMap<String, Regex>>);
317
318impl RegexCache {
319	/// get regex from cache or freshly compile
320	pub(crate) fn get(&self, s: &String) -> Result<Regex, String> {
321		if let Some(re) = self.0.read().unwrap().get(s) {
322			Ok(re.clone())
323		}
324		else {
325			match RegexBuilder::new(s)
326				.size_limit(usize::MAX)
327				.dfa_size_limit(usize::MAX)
328				.build() {
329				Ok(re) => {
330					self.0.write().unwrap().insert(s.clone(), re.clone());
331					Ok(re)
332				},
333				Err(e) => Err(format!("can't compile regex: {e}"))
334			}
335		}
336	}
337
338	pub(crate) fn clear(&self) {
339		*self.0.write().unwrap() = HashMap::new();
340	}
341}
342
343/// Hybrid iterator over UTF-8 strings, may be advanced by bytes or chars. Does not expect valid UTF-8 internally.
344///
345/// Convertible [`From`] owned|borrowed × bytes|strings. Manually set nonzero positions are handled as expected.
346///
347/// [`Self::try_next_char`] parses a [`char`] if it's valid UTF-8, and is used for [`TryInto<String>`].
348#[derive(Clone, Debug)]
349pub enum Utf8Iter<'a> {
350	Owned {
351		bytes: Vec<u8>,
352		pos: usize
353	},
354	Borrowed {
355		bytes: &'a [u8],
356		pos: usize
357	}
358}
359impl Default for Utf8Iter<'_> {
360	fn default() -> Self {
361		Self::Owned { bytes: Vec::new(), pos: 0 }
362	}
363}
364
365impl From<Vec<u8>> for Utf8Iter<'_> {
366	fn from(bytes: Vec<u8>) -> Self {
367		Self::Owned { bytes, pos: 0 }
368	}
369}
370impl<'a> From<&'a [u8]> for Utf8Iter<'a> {
371	fn from(bytes: &'a [u8]) -> Self {
372		Self::Borrowed { bytes, pos: 0 }
373	}
374}
375impl From<String> for Utf8Iter<'_> {
376	fn from(s: String) -> Self {
377		Self::Owned { bytes: s.into_bytes(), pos: 0 }
378	}
379}
380impl<'a> From<&'a str> for Utf8Iter<'a> {
381	fn from(s: &'a str) -> Self {
382		Self::Borrowed { bytes: s.as_bytes(), pos: 0 }
383	}
384}
385impl TryFrom<Utf8Iter<'_>> for String {
386	type Error = String;
387
388	fn try_from(mut value: Utf8Iter) -> Result<String, String> {
389		let mut res = String::new();
390		while !value.is_finished() {
391			res.push(value.try_next_char().map_err(|e| format!("At byte {}: {e}", {
392				match value {
393					Utf8Iter::Borrowed {pos, ..} => pos,
394					Utf8Iter::Owned {pos, ..} => pos
395				}
396			}))?);
397		}
398		Ok(res)
399	}
400}
401
402impl Iterator for Utf8Iter<'_> {
403	type Item = u8;
404	fn next(&mut self) -> Option<Self::Item> {
405		let (bytes, pos): (&[u8], &mut usize) = match self {
406			Self::Borrowed {bytes, pos} => (bytes, pos),
407			Self::Owned {bytes, pos} => (bytes, pos)
408		};
409		bytes.get(*pos).copied().inspect(|_| {*pos+=1;})
410	}
411}
412
413impl Utf8Iter<'_> {
414	/// Parses one UTF-8 character starting at the current position, advancing the position in-place.
415	///
416	/// Errors on invalid byte sequences and reports the erroneous values (in ADC literal format), `pos` only advances if parsing is successful.
417	///
418	/// Handles all possible UTF-8 encoding errors:
419	/// - Invalid bytes: C0, C1, F5–FF
420	/// - Character starting with a continuation byte (80–BF)
421	/// - Multi-byte character with missing / non-continuation byte(s)
422	/// - Overlong encodings (3-byte below U+0800 or 4-byte below U+10000)
423	/// - UTF-16 surrogates (U+D800–DFFF)
424	/// - Values above U+10FFFF
425	pub fn try_next_char(&mut self) -> Result<char, String> {
426		let (bytes, pos): (&[u8], &mut usize) = match self {
427			Self::Borrowed {bytes, pos} => (bytes, pos),
428			Self::Owned {bytes, pos} => (bytes, pos)
429		};
430		if let Some(b0) = bytes.get(*pos).copied() {
431			let c;
432			match b0 {
433				//within ASCII
434				0x00..=0x7F => {
435					*pos += 1;
436					Ok(b0 as char)
437				}
438
439				//continuation byte
440				0x80..=0xBF => {
441					Err(format!("Continuation byte at start of character: [\\{b0:02X}]"))
442				}
443
444				//2-byte char
445				0xC2..=0xDF => {
446					if let Some(b1) = bytes.get(*pos+1).copied() {
447						if !(0x80..=0xBF).contains(&b1) {
448							return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}]"));
449						}
450						c = ((b0 & 0x1F) as u32) << 6
451							| (b1 & 0x3F) as u32;
452						//all good:
453						*pos += 2;
454						Ok(unsafe{char::from_u32_unchecked(c)})
455					}
456					else {
457						Err(format!("Unexpected end of string: [\\{b0:02X}]"))
458					}
459				}
460
461				//3-byte char
462				0xE0..=0xEF => {
463					if let Some(b1) = bytes.get(*pos+1).copied() {
464						if let Some(b2) = bytes.get(*pos+2).copied() {
465							if !(0x80..=0xBF).contains(&b1) {
466								return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}\\{b2:02X}]"));
467							}
468							if !(0x80..=0xBF).contains(&b2) {
469								return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}\\{b2:02X}]"));
470							}
471							c = ((b0 & 0x0F) as u32) << 12
472								| ((b1 & 0x3F) as u32) << 6
473								| (b2 & 0x3F) as u32;
474							if c < 0x0800 {
475								return Err(format!("Overlong encoding of U+{c:04X}: [\\{b0:02X}\\{b1:02X}\\{b2:02X}]"));
476							}
477							if (0xD800u32..=0xDFFFu32).contains(&c) {
478								return Err(format!("Unexpected UTF-16 surrogate U+{c:04X}: [\\{b0:02X}\\{b1:02X}\\{b2:02X}]"));
479							}
480							//all good:
481							*pos += 3;
482							Ok(unsafe{char::from_u32_unchecked(c)})
483						}
484						else {
485							Err(format!("Unexpected end of string: [\\{b0:02X}\\{b1:02X}]"))
486						}
487					}
488					else {
489						Err(format!("Unexpected end of string: [\\{b0:02X}]"))
490					}
491				}
492
493				//4-byte char
494				0xF0..=0xF4 => {
495					if let Some(b1) = bytes.get(*pos+1).copied() {
496						if let Some(b2) = bytes.get(*pos+2).copied() {
497							if let Some(b3) = bytes.get(*pos+3).copied() {
498								if !(0x80..=0xBF).contains(&b1) {
499									return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}\\{b2:02X}\\{b3:02X}]"));
500								}
501								if !(0x80..=0xBF).contains(&b2) {
502									return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}\\{b2:02X}\\{b3:02X}]"));
503								}
504								if !(0x80..=0xBF).contains(&b3) {
505									return Err(format!("Non-continuation byte in character: [\\{b0:02X}\\{b1:02X}\\{b2:02X}\\{b3:02X}]"));
506								}
507								c = ((b0 & 0x07) as u32) << 18
508									| ((b1 & 0x3F) as u32) << 12
509									| ((b2 & 0x3F) as u32) << 6
510									| (b3 & 0x3F) as u32;
511								if c < 0x10000 {
512									return Err(format!("Overlong encoding of U+{c:04X}: [\\{b0:02X}\\{b1:02X}\\{b2:02X}\\{b3:02X}]"));
513								}
514								if c > 0x10FFFF {
515									return Err(format!("Out-of-range character U+{c:04X}: [\\{b0:02X}\\{b1:02X}\\{b2:02X}\\{b3:02X}]"));
516								}
517								//all good:
518								*pos += 4;
519								Ok(unsafe{char::from_u32_unchecked(c)})
520							}
521							else {
522								Err(format!("Unexpected end of string: [\\{b0:02X}\\{b1:02X}\\{b2:02X}]"))
523							}
524						}
525						else {
526							Err(format!("Unexpected end of string: [\\{b0:02X}\\{b1:02X}]"))
527						}
528					}
529					else {
530						Err(format!("Unexpected end of string: [\\{b0:02X}]"))
531					}
532				}
533
534				0xC0 | 0xC1 | 0xF5..=0xFF => Err(format!("Impossible byte in string: [\\{b0:02X}]")),
535			}
536		}
537		else { 
538			Err(format!("Position out of bounds: {}", *pos))
539		}
540	}
541
542	/// Converts 1 or 2 [`Value`]s into a stack of macros.
543	///
544	/// Nested array traversal using heap DFS with flattening. Value types should match the syntax in the ADC manual:
545	/// - If only `top` is given, it must be a string.
546	/// - If `top` and `sec` are given and `top` is a string, `sec` is not used and should be returned to the stack.
547	/// - Otherwise, `sec` must be a string, and the number/boolean in `top` decides how often to run `sec`.
548	/// - For arrays, the nesting layout and lengths must match exactly and the contained scalars must all be either strings or non-strings as above.
549	///
550	/// `Ok` contains the macros and repetition counts in reverse (call stack) order and a flag indicating whether `sec` should be returned.
551	pub fn from_vals(top: &Value, sec: Option<&Value>) -> Result<(Vec<(Self, Natural)>, bool), String> {
552		use Value::*;
553		use crate::errors::TypeLabel;
554		use crate::conv::{PromotingIter, lenck2};
555		if let Some(sec) = sec {	//dyadic form
556			if let Ok(res) = Self::from_vals(top, None) { return Ok(res); }	//see if monadic form succeeds (only strings in top), continue if not
557			match (sec, top) {
558				(A(_), A(_)) | (A(_), _) | (_, A(_)) => {	//traverse nested arrays
559					if let Err(e) = lenck2(sec, top) { return Err(e.to_string()); }
560					let mut stk = vec![(PromotingIter::from(sec), PromotingIter::from(top))];
561					let mut res = vec![];
562
563					while let Some((ia, ib)) = stk.last_mut() {	//keep operating on the top iters
564						if let (Some(va), Some(vb)) = (ia.next(), ib.next()) {	//advance them
565							match (va, vb) {
566								(A(_), A(_)) | (A(_), _) | (_, A(_)) => {	//nested array(s)
567									if let Err(e) = lenck2(va, vb) { return Err(e.to_string()); }
568									stk.push((PromotingIter::from(va), PromotingIter::from(vb)));	//"recursive call"
569								},
570								(S(sa), B(bb)) => {
571									let nb = Natural::from(bb.count_ones());
572									if nb != Natural::ZERO {
573										res.push((sa.to_owned().into(), nb));
574									}
575								},
576								(S(sa), N(rb)) => {
577									if let Ok(nb) = Natural::try_from(rb) {
578										if nb != Natural::ZERO {
579											res.push((sa.to_owned().into(), nb));
580										}
581									}
582									else {
583										return Err(format!("Can't possibly repeat a macro {} times", crate::num::nauto(rb, DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2)));
584									}
585								},
586								(_, S(_)) => {	//legitimate strings are already covered by monadic form attempt
587									return Err("Unexpected string in top array".into());
588								},
589								_ => {
590									return Err(format!("Expected only matching strings and non-strings, found {} and {} in arrays", TypeLabel::from(sec), TypeLabel::from(top)));
591								}
592							}
593						}
594						else {	//if top iters have ended
595							stk.pop();	//"return"
596						}
597					}
598
599					res.reverse();
600					Ok((res, false))
601				},
602				//scalars:
603				(S(sa), B(bb)) => {
604					let nb = Natural::from(bb.count_ones());
605					if nb != Natural::ZERO {
606						Ok((vec![(sa.to_owned().into(), nb)], false))
607					}
608					else {Ok((vec![], false))}
609				},
610				(S(sa), N(rb)) => {
611					if let Ok(nb) = Natural::try_from(rb) {
612						if nb != Natural::ZERO {
613							Ok((vec![(sa.to_owned().into(), nb)], false))
614						}
615						else {Ok((vec![], false))}
616					}
617					else {
618						Err(format!("Can't possibly repeat a macro {} times", crate::num::nauto(rb, DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2)))
619					}
620				},
621				(_, S(_)) => {	//already covered by monadic form attempt
622					unsafe { std::hint::unreachable_unchecked() }
623				},
624				_ => {
625					Err(format!("Expected a string and a non-string, {} and {} given", TypeLabel::from(sec), TypeLabel::from(top)))
626				}
627			}
628		}
629		else {	//monadic form
630			match top {
631				A(a) => {	//traverse nested array
632					let mut stk: Vec<std::slice::Iter<Value>> = vec![a.iter()];
633					let mut res = Vec::new();
634					while let Some(i) = stk.last_mut() {	//keep operating on the top iter
635						if let Some(val) = i.next() {	//advance it
636							match val {
637								A(na) => {	//nested array encountered
638									stk.push(na.iter());	//"recursive call"
639								},
640								S(s) => {	//string encountered
641									res.push((s.to_owned().into(), Natural::ONE));
642								},
643								_ => {
644									return Err(format!("Expected only strings, found {} in array", TypeLabel::from(val)));
645								}
646							}
647						}
648						else {	//if top iter has ended
649							stk.pop();	//"return"
650						}
651					}
652					res.reverse();
653					Ok((res, true))
654				},
655				//scalar:
656				S(s) => {
657					Ok((vec![(s.to_owned().into(), Natural::ONE)], true))
658				},
659				_ => {
660					Err(format!("Expected a string, {} given", TypeLabel::from(top)))
661				}
662			}
663		}
664	}
665	
666	pub(crate) fn is_finished(&self) -> bool {
667		let (bytes, pos): (&[u8], &usize) = match self {
668			Self::Borrowed {bytes, pos} => (bytes, pos),
669			Self::Owned {bytes, pos} => (bytes, pos)
670		};
671		bytes.len() <= *pos
672	}
673	
674	pub(crate) fn back(&mut self) {
675		let pos = match self {
676			Self::Borrowed {pos, ..} => pos,
677			Self::Owned {pos, ..} => pos
678		};
679		*pos -= 1;
680	}
681
682	pub(crate) fn rewind(&mut self) {
683		let pos = match self {
684			Self::Borrowed {pos, ..} => pos,
685			Self::Owned {pos, ..} => pos
686		};
687		*pos = 0;
688	}
689}
690
691/// Number output mode
692#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
693#[repr(u8)] pub enum NumOutMode { #[default] Auto=0, Norm=1, Sci=2, Frac=3 }
694
695/// Parameter context tuple: (K, I, O, M)
696pub type Params = (usize, Natural, Natural, NumOutMode);
697
698/// Default values (0, 10, 10, auto)
699pub const DEFAULT_PARAMS: Params = {
700	(0, Natural::const_from(10), Natural::const_from(10), NumOutMode::Auto)
701};
702
703/// Stack for numeric IO parameter contexts, with checked accessors
704#[derive(Clone, Debug)]
705#[repr(transparent)] pub struct ParamStk(Vec<Params>);
706impl ParamStk {
707	/// Creates new context with [`DEFAULT_PARAMS`]
708	pub fn create(&mut self) {
709		self.0.push(DEFAULT_PARAMS)
710	}
711
712	/// Returns to previous context, creates default if none left
713	pub fn destroy(&mut self) {
714		self.0.pop();
715		if self.0.is_empty() {self.create();}
716	}
717
718	/// Discards all contexts, creates default
719	pub fn clear(&mut self) {
720		*self = Self::default();
721	}
722
723	/// Refers to the underlying [`Vec`] for manual access
724	pub fn inner(&self) -> &Vec<Params> {
725		&self.0
726	}
727
728	/// Extracts the underlying [`Vec`] for manual access
729	pub fn into_inner(self) -> Vec<Params> {
730		self.0
731	}
732
733	/// Checked edit of current output precision
734	pub fn try_set_k(&mut self, r: &Rational) -> Result<(), &'static str> {
735		if let Ok(u) = r.try_into() {
736			unsafe { self.0.last_mut().unwrap_unchecked().0 = u; }
737			Ok(())
738		}
739		else {Err(const_format::concatcp!("Output precision must be a natural number <={}", usize::MAX))}
740	}
741
742	/// Checked edit of current input base
743	pub fn try_set_i(&mut self, r: &Rational) -> Result<(), &'static str> {
744		if let Ok(n) = r.try_into() && n>=2u8 {
745			unsafe { self.0.last_mut().unwrap_unchecked().1 = n; }
746			Ok(())
747		}
748		else {Err("Input base must be a natural number >=2")}
749	}
750
751	/// Checked edit of current output base
752	pub fn try_set_o(&mut self, r: &Rational) -> Result<(), &'static str> {
753		if let Ok(n) = r.try_into() && n>=2u8 {
754			unsafe { self.0.last_mut().unwrap_unchecked().2 = n; }
755			Ok(())
756		}
757		else {Err("Output base must be a natural number >=2")}
758	}
759
760	/// Checked edit of current output mode
761	pub fn try_set_m(&mut self, r: &Rational) -> Result<(), &'static str> {
762		if let Ok(u) = u8::try_from(r) && u<=3 {
763			unsafe { self.0.last_mut().unwrap_unchecked().3 = std::mem::transmute::<u8, NumOutMode>(u); }
764			Ok(())
765		}
766		else {Err("Output mode must be 0|1|2|3")}
767	}
768	
769	/// Infallible edit of current output precision
770	pub fn set_k(&mut self, u: usize) {
771		unsafe { self.0.last_mut().unwrap_unchecked().0 = u; }
772	}
773
774	/// Infallible edit of current output mode
775	pub fn set_m(&mut self, m: NumOutMode) {
776		unsafe { self.0.last_mut().unwrap_unchecked().3 = m; }
777	}
778
779	/// Current output precision
780	pub fn get_k(&self) -> usize {
781		unsafe { self.0.last().unwrap_unchecked().0 }
782	}
783
784	/// Current input base
785	pub fn get_i(&self) -> &Natural {
786		unsafe { &self.0.last().unwrap_unchecked().1 }
787	}
788
789	/// Current output base
790	pub fn get_o(&self) -> &Natural {
791		unsafe { &self.0.last().unwrap_unchecked().2 }
792	}
793
794	/// Current number output mode
795	pub fn get_m(&self) -> NumOutMode {
796		unsafe { self.0.last().unwrap_unchecked().3 }
797	}
798}
799/// One entry of [`DEFAULT_PARAMS`].
800impl Default for ParamStk {
801	fn default() -> Self {
802		let mut p = Self(Vec::new());
803		p.create();
804		p
805	}
806}
807/// Length must be at least 1.
808impl TryFrom<Vec<Params>> for ParamStk {
809	type Error = ();
810
811	fn try_from(value: Vec<Params>) -> Result<Self, Self::Error> {
812		(!value.is_empty()).then_some(Self(value)).ok_or(())
813	}
814}
815
816/// Combined interpreter state storage
817///
818/// Typically, just use the [`Default`]. Fields are public to allow for presets and extraction of values, see their documentation.
819///
820/// `regs` may contain thread handles, which are not copied with [`Clone`]. To preserve thread handles in `self`, use:
821/// - `state.clear_vals();` instead of `state = State::default();`
822/// - `state.replace_vals(other);` instead of `state = other;`
823#[derive(Default, Debug, Clone)]
824pub struct State {
825	/// Main stack, [`Arc`] to allow shallow copies
826	pub mstk: Vec<Arc<Value>>,
827
828	/// Registers
829	pub regs: RegStore,
830
831	/// Parameters
832	pub params: ParamStk
833}
834/// Export to state file with standard format
835impl Display for State {
836	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
837		write!(f, "{}", String::from_utf8_lossy(&crate::STATE_FILE_HEADER))?;
838		for (lri, lreg) in self.regs.low.iter().enumerate().filter(|(_, lreg)| !lreg.v.is_empty()) {
839			for val in &lreg.v {
840				writeln!(f, "{val}")?;
841			}
842			writeln!(f, "{lri}:ff")?;
843		}
844		for (hri, hreg) in self.regs.high.iter().filter(|(_, hreg)| !hreg.v.is_empty()) {
845			for val in &hreg.v {
846				writeln!(f, "{val}")?;
847			}
848			writeln!(f, "{}:ff", crate::num::nauto(hri, DEFAULT_PARAMS.0, &DEFAULT_PARAMS.2))?;
849		}
850		for val in &self.mstk {
851			writeln!(f, "{val}")?;
852		}
853		write!(f, "{}", {
854			let v: Vec<String> = self.params.inner().iter().map(|par| {
855				let mut ps = String::new();
856				if par.0 != DEFAULT_PARAMS.0 {ps += &format!("{{{}}}k", par.0);}
857				if par.1 != DEFAULT_PARAMS.1 {ps += &format!("{{{}}}i", par.1);}
858				if par.2 != DEFAULT_PARAMS.2 {ps += &format!("{{{}}}o", par.2);}
859				if par.3 != DEFAULT_PARAMS.3 {ps += &format!("{{{}}}m", par.3 as u8);}
860				ps
861			}).collect();
862			v.join("{")
863		})?;
864		Ok(())
865	}
866}
867impl State {
868	/// Reallocate all fields to fit, do not discard any stored data
869	pub fn trim(&mut self) {
870		self.mstk.shrink_to_fit();
871		self.regs.trim();
872		self.params.0.shrink_to_fit();
873	}
874
875	/// Clear all stored data, do not touch thread handles in `self`
876	pub fn clear_vals(&mut self) {
877		self.mstk = Vec::new();
878		self.regs.clear_vals();
879		self.params = ParamStk::default();
880	}
881
882	/// Replace stored data with contents of `other`, keep thread handles in `self` and discard any in `other`
883	pub fn replace_vals(&mut self, other: Self) {
884		self.mstk = other.mstk;
885		self.regs.replace_vals(other.regs);
886		self.params = other.params;
887	}
888}