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