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