synthphonia/text/formatting/
mod.rs1use crate::{expr::ops::Op1Enum, galloc, value::{consts_to_value, ConstValue, Value}};
2
3
4trait FormattingOp where Self: Sized {
5 fn format(&self, input: &'static str) -> Option<(Self, ConstValue, &'static str)>;
6 fn union(self, other: Self) -> Option<Self>;
7 fn bad_value() -> ConstValue;
8 fn format_all(&self, input: &'static [&'static str]) -> Option<(Self, Value, Value, Value)> {
9 let mut a = Vec::with_capacity(input.len());
10 let mut b = galloc::new_bvec(input.len());
11 let mut cond = galloc::new_bvec(input.len());
12 let mut newop: Option<Self> = None;
13 for i in input {
14 if let Some((op, x, y)) = self.format(i) {
15 if let Some(no) = newop {
16 newop = no.union(op);
17 newop.as_ref()?;
18 } else { newop = Some(op); }
19 a.push(x);
20 b.push(y);
21 cond.push(true);
22 } else {
23 a.push(Self::bad_value());
24 b.push(i);
25 cond.push(false);
26 }
27 }
28 newop.map(|no| (no, consts_to_value(a), Value::Str(b.into_bump_slice()), cond.into_bump_slice().into()))
29 }
30}
31
32use ext_trait::extension;
33pub mod int;
34pub use int::*;
35pub mod float;
36pub use float::*;
37pub mod time;
38pub use time::*;
39pub mod month;
40pub use month::*;
41
42pub mod weekday;
43pub use weekday::*;
44
45#[macro_export]
46macro_rules! for_all_formatting_op {
47 () => {
48 _do!(FormatInt);
49 _do!(FormatFloat);
50 _do!(FormatTime);
51 _do!(FormatMonth);
52 _do!(FormatWeekday);
53 };
54}
55
56
57impl Op1Enum {
58 pub fn is_formatting_op(&self) -> bool {
59 macro_rules! _do {($op:ident) => {
60 if let Self::$op(_) = self { return true }
61 };}
62 crate::for_all_formatting_op!();
63 false
64 }
65 pub fn format_all(&self, input: &'static [&'static str]) -> Option<(Op1Enum, Value, Value, Value)> {
66 macro_rules! _do {($op:ident) => {
67 if let Self::$op(op) = self { return op.format_all(input).map(|(a, b, c, d)| (a.into(), b, c, d)); }
68 };}
69 crate::for_all_formatting_op!();
70 panic!();
71 }
72}
73
74#[macro_export]
75macro_rules! impl_formatop {
76 ($opname:ident, $t:ident, $costf:expr) => {
77 impl $crate::expr::ops::Op1 for $opname {
78 fn cost(&self) -> usize {
79 $costf(self)
80 }
81 fn try_eval(&self,a1:$crate::value::Value) -> (bool, $crate::value::Value) {
82 match a1 {
83 Value::$t(s) => (true, Value::Str(s.iter().map(|s1| {
84 self.format_single(*s1).galloc_str()
85 }).galloc_scollect())),
86 _ => (false, Value::Null),
87 }
88 }
89 }
90 };
91}