synthphonia/expr/ops/
list.rs1use std::cmp::min;
2use std::ops::Not;
3
4use derive_more::DebugCustom;
5use crate::galloc::{AllocForStr, AllocForExactSizeIter, TryAllocForExactSizeIter};
6use crate::utils::F64;
7use crate::{new_op1, new_op2, new_op3, new_op2_opt};
8use itertools::izip;
9
10
11
12use super::{Op1, Op3, Op2};
13
14pub fn to_index(len: usize, i: i64) -> usize {
21 if i >= 0 {
22 min(i as usize, len - 1)
23 } else {
24 len.saturating_sub(i.saturating_neg() as usize)
25 }
26}
27
28new_op2_opt!(At, "list.at",
29 (Str, Int) -> Str { |(s1, s2)| {
30 if !s1.is_empty() {
31 let i = to_index(s1.len(), *s2);
32 Some(s1[i..=i].galloc_str())
33 } else { None }
34 }},
35 (ListInt, Int) -> Int { |(s1, s2)| {
36 if !s1.is_empty() {
37 let i = to_index(s1.len(), *s2);
38 Some(s1[i])
39 } else { None }
40 }},
41 (ListStr, Int) -> Str { |(s1, s2)| {
42 if !s1.is_empty() {
43 let i = to_index(s1.len(), *s2);
44 Some(s1[i])
45 } else { None }
46 }},
47 (Str, Float) -> Str { |(s1, s2)| {
48 if !s1.is_empty() {
49 let i = to_index(s1.len(), **s2 as i64);
50 Some(s1[i..=i].galloc_str())
51 } else { None }
52 }},
53 (ListInt, Float) -> Int { |(s1, s2)| {
54 if !s1.is_empty() {
55 let i = to_index(s1.len(), **s2 as i64);
56 Some(s1[i])
57 } else { None }
58 }},
59 (ListStr, Float) -> Str { |(s1, s2)| {
60 if !s1.is_empty() {
61 let i = to_index(s1.len(), **s2 as i64);
62 Some(s1[i])
63 } else { None }
64 }}
65);
66
67new_op2!(StrAt, "str.at",
68 (Str, Int) -> Str { |(s1, s2)| {
69 if !s1.is_empty() {
70 if *s2 >= 0 && (*s2 as usize) < s1.len() {
71 let i = *s2 as usize;
72 s1[i..=i].galloc_str()
73 } else { "" }
74 } else { "" }
75 }}
76);
77
78new_op1!(Len, "list.len",
79 Str -> Int { |s| s.len() as i64 },
80 ListInt -> Int { |s| s.len() as i64 },
81 ListStr -> Int { |s| s.len() as i64 }
82);
83
84new_op1!(FLen, "list.flen",
85 Str -> Float { |s| F64::from_usize(s.len()) },
86 ListInt -> Float { |s| F64::from_usize(s.len()) },
87 ListStr -> Float { |s| F64::from_usize(s.len()) }
88);
89
90pub mod map;
91pub use map::Map;
92
93pub mod filter;
94pub use filter::Filter;