1use crate::number::ExactNum;
2use crate::eval::{apply_lambda, ensure_comparable, EvalError};
3use crate::Value;
4
5pub fn call_stdlib(name: &str, args: Vec<Value>) -> Option<Result<Value, EvalError>> {
6 match name {
7 "typeOf" => Some(stdlib_type_of(args)),
8 "keys" => Some(stdlib_keys(args)),
9 "values" => Some(stdlib_values(args)),
10 "count" => Some(stdlib_count(args)),
11 "normalizeUnique" => Some(stdlib_normalize_unique(args)),
12 "normalizeFirst" => Some(stdlib_normalize_first(args)),
13 "normalizeLast" => Some(stdlib_normalize_last(args)),
14 "Bind" => Some(stdlib_bind(args)),
15 "asBagKV" => Some(stdlib_as_bag_kv(args)),
16 "mapOpt" => Some(stdlib_map_opt(args)),
17 "bindOpt" => Some(stdlib_bind_opt(args)),
18 "orElseOpt" => Some(stdlib_or_else_opt(args)),
19 "mapRes" => Some(stdlib_map_res(args)),
20 "bindRes" => Some(stdlib_bind_res(args)),
21 "orElseRes" => Some(stdlib_or_else_res(args)),
22 _ => None,
23 }
24}
25
26fn wrong_shape() -> Value {
27 Value::Fail_("t_sda_wrong_shape".to_string(), "wrong shape".to_string())
28}
29
30fn check_arity(_name: &str, args: &[Value], expected: usize) -> Result<(), EvalError> {
31 if args.len() != expected {
32 Err(EvalError::ArityMismatch {
33 expected,
34 got: args.len(),
35 })
36 } else {
37 Ok(())
38 }
39}
40
41fn stdlib_type_of(args: Vec<Value>) -> Result<Value, EvalError> {
42 check_arity("typeOf", &args, 1)?;
43 let type_str = match &args[0] {
44 Value::Null => "null",
45 Value::Bool(_) => "bool",
46 Value::Num(_) => "num",
47 Value::Str(_) => "str",
48 Value::Bytes(_) => "bytes",
49 Value::Seq(_) => "seq",
50 Value::Set(_) => "set",
51 Value::Bag(_) => "bag",
52 Value::Map(_) => "map",
53 Value::Prod(_) => "prod",
54 Value::BagKV(_) => "bagkv",
55 Value::Bind(_, _) => "bind",
56 Value::Some_(_) => "some",
57 Value::None_ => "none",
58 Value::Ok_(_) => "ok",
59 Value::Fail_(_, _) => "fail",
60 Value::Lambda(_, _, _) => "fn",
61 };
62 Ok(Value::Str(type_str.to_string()))
63}
64
65fn stdlib_keys(args: Vec<Value>) -> Result<Value, EvalError> {
66 check_arity("keys", &args, 1)?;
67 match &args[0] {
68 Value::Map(entries) => Ok(Value::Set(
69 entries
70 .iter()
71 .map(|(k, _)| Value::Str(k.clone()))
72 .collect(),
73 )),
74 _ => Ok(wrong_shape()),
75 }
76}
77
78fn stdlib_values(args: Vec<Value>) -> Result<Value, EvalError> {
79 check_arity("values", &args, 1)?;
80 match &args[0] {
81 Value::Map(entries) => {
82 let mut sorted = entries.clone();
83 sorted.sort_by(|(left_key, _), (right_key, _)| left_key.cmp(right_key));
84 Ok(Value::Seq(sorted.into_iter().map(|(_, v)| v).collect()))
85 }
86 _ => Ok(wrong_shape()),
87 }
88}
89
90fn stdlib_count(args: Vec<Value>) -> Result<Value, EvalError> {
91 check_arity("count", &args, 2)?;
92 let mut iter = args.into_iter();
93 let needle = iter.next().unwrap();
94 let haystack = iter.next().unwrap();
95 if ensure_comparable(&needle).is_err() {
96 return Ok(wrong_shape());
97 }
98 let n = match &haystack {
99 Value::Bag(items) => {
100 for item in items {
101 if ensure_comparable(item).is_err() {
102 return Ok(wrong_shape());
103 }
104 }
105 items.iter().filter(|v| *v == &needle).count()
106 }
107 _ => return Ok(wrong_shape()),
108 };
109 Ok(Value::Num(ExactNum::from_usize(n)))
110}
111
112fn stdlib_normalize_unique(args: Vec<Value>) -> Result<Value, EvalError> {
113 check_arity("normalizeUnique", &args, 1)?;
114 match args.into_iter().next().unwrap() {
115 Value::BagKV(pairs) => {
116 let mut map: Vec<(String, Value)> = Vec::new();
117 for (k, v) in pairs {
118 let key_str = match value_as_map_key(&k) {
119 Ok(key) => key,
120 Err(_) => {
121 return Ok(Value::Fail_(
122 "t_sda_wrong_shape".to_string(),
123 "wrong shape".to_string(),
124 ))
125 }
126 };
127 if map.iter().any(|(existing_key, _)| existing_key == &key_str) {
128 return Ok(Value::Fail_(
129 "t_sda_duplicate_key".to_string(),
130 "duplicate key".to_string(),
131 ));
132 }
133 map.push((key_str, v));
134 }
135 Ok(Value::Ok_(Box::new(Value::Map(map))))
136 }
137 _ => Ok(Value::Fail_(
138 "t_sda_wrong_shape".to_string(),
139 "wrong shape".to_string(),
140 )),
141 }
142}
143
144fn stdlib_normalize_first(args: Vec<Value>) -> Result<Value, EvalError> {
145 check_arity("normalizeFirst", &args, 1)?;
146 match args.into_iter().next().unwrap() {
147 Value::BagKV(pairs) => {
148 let mut map: Vec<(String, Value)> = Vec::new();
149 for (k, v) in pairs {
150 let key_str = match value_as_map_key(&k) {
151 Ok(key) => key,
152 Err(_) => {
153 return Ok(Value::Fail_(
154 "t_sda_wrong_shape".to_string(),
155 "wrong shape".to_string(),
156 ))
157 }
158 };
159 if !map.iter().any(|(existing_key, _)| existing_key == &key_str) {
160 map.push((key_str, v));
161 }
162 }
163 Ok(Value::Map(map))
164 }
165 _ => Ok(Value::Fail_(
166 "t_sda_wrong_shape".to_string(),
167 "wrong shape".to_string(),
168 )),
169 }
170}
171
172fn stdlib_normalize_last(args: Vec<Value>) -> Result<Value, EvalError> {
173 check_arity("normalizeLast", &args, 1)?;
174 match args.into_iter().next().unwrap() {
175 Value::BagKV(pairs) => {
176 let mut map: Vec<(String, Value)> = Vec::new();
177 for (k, v) in pairs {
178 let key_str = match value_as_map_key(&k) {
179 Ok(key) => key,
180 Err(_) => {
181 return Ok(Value::Fail_(
182 "t_sda_wrong_shape".to_string(),
183 "wrong shape".to_string(),
184 ))
185 }
186 };
187 if let Some(existing) = map.iter_mut().find(|(existing_key, _)| existing_key == &key_str) {
188 existing.1 = v;
189 } else {
190 map.push((key_str, v));
191 }
192 }
193 Ok(Value::Map(map))
194 }
195 _ => Ok(Value::Fail_(
196 "t_sda_wrong_shape".to_string(),
197 "wrong shape".to_string(),
198 )),
199 }
200}
201
202fn value_as_map_key(v: &Value) -> Result<String, EvalError> {
203 match v {
204 Value::Str(s) => Ok(s.clone()),
205 other => Err(EvalError::TypeError(format!(
206 "Map key must be a string, got {other:?}"
207 ))),
208 }
209}
210
211fn stdlib_bind(args: Vec<Value>) -> Result<Value, EvalError> {
212 check_arity("Bind", &args, 2)?;
213 let mut iter = args.into_iter();
214 let k = iter.next().unwrap();
215 let v = iter.next().unwrap();
216 Ok(Value::Bind(Box::new(k), Box::new(v)))
217}
218
219fn stdlib_as_bag_kv(args: Vec<Value>) -> Result<Value, EvalError> {
220 check_arity("asBagKV", &args, 1)?;
221 match args.into_iter().next().unwrap() {
222 Value::Bag(items) => {
223 let mut pairs = Vec::new();
224 for item in items {
225 match item {
226 Value::Bind(k, v) => match *k {
227 Value::Str(s) => pairs.push((Value::Str(s), *v)),
228 _ => {
229 return Ok(Value::Fail_(
230 "t_sda_wrong_shape".to_string(),
231 "wrong shape".to_string(),
232 ))
233 }
234 },
235 _ => {
236 return Ok(Value::Fail_(
237 "t_sda_wrong_shape".to_string(),
238 "wrong shape".to_string(),
239 ))
240 }
241 }
242 }
243 Ok(Value::Ok_(Box::new(Value::BagKV(pairs))))
244 }
245 _ => Ok(Value::Fail_(
246 "t_sda_wrong_shape".to_string(),
247 "wrong shape".to_string(),
248 )),
249 }
250}
251
252fn stdlib_map_opt(args: Vec<Value>) -> Result<Value, EvalError> {
253 check_arity("mapOpt", &args, 2)?;
254 let mut iter = args.into_iter();
255 let opt = iter.next().unwrap();
256 let f = iter.next().unwrap();
257 match opt {
258 Value::Some_(inner) => {
259 let result = apply_lambda(f, vec![*inner])?;
260 Ok(Value::Some_(Box::new(result)))
261 }
262 Value::None_ => Ok(Value::None_),
263 _ => Ok(wrong_shape()),
264 }
265}
266
267fn stdlib_bind_opt(args: Vec<Value>) -> Result<Value, EvalError> {
268 check_arity("bindOpt", &args, 2)?;
269 let mut iter = args.into_iter();
270 let opt = iter.next().unwrap();
271 let f = iter.next().unwrap();
272 match opt {
273 Value::Some_(inner) => apply_lambda(f, vec![*inner]),
274 Value::None_ => Ok(Value::None_),
275 _ => Ok(wrong_shape()),
276 }
277}
278
279fn stdlib_or_else_opt(args: Vec<Value>) -> Result<Value, EvalError> {
280 check_arity("orElseOpt", &args, 2)?;
281 let mut iter = args.into_iter();
282 let opt = iter.next().unwrap();
283 let default = iter.next().unwrap();
284 match opt {
285 Value::Some_(inner) => Ok(Value::Some_(inner)),
286 Value::None_ => Ok(default),
287 _ => Ok(wrong_shape()),
288 }
289}
290
291fn stdlib_map_res(args: Vec<Value>) -> Result<Value, EvalError> {
292 check_arity("mapRes", &args, 2)?;
293 let mut iter = args.into_iter();
294 let res = iter.next().unwrap();
295 let f = iter.next().unwrap();
296 match res {
297 Value::Ok_(inner) => {
298 let result = apply_lambda(f, vec![*inner])?;
299 Ok(Value::Ok_(Box::new(result)))
300 }
301 Value::Fail_(c, m) => Ok(Value::Fail_(c, m)),
302 _ => Ok(wrong_shape()),
303 }
304}
305
306fn stdlib_bind_res(args: Vec<Value>) -> Result<Value, EvalError> {
307 check_arity("bindRes", &args, 2)?;
308 let mut iter = args.into_iter();
309 let res = iter.next().unwrap();
310 let f = iter.next().unwrap();
311 match res {
312 Value::Ok_(inner) => apply_lambda(f, vec![*inner]),
313 Value::Fail_(c, m) => Ok(Value::Fail_(c, m)),
314 _ => Ok(wrong_shape()),
315 }
316}
317
318fn stdlib_or_else_res(args: Vec<Value>) -> Result<Value, EvalError> {
319 check_arity("orElseRes", &args, 2)?;
320 let mut iter = args.into_iter();
321 let res = iter.next().unwrap();
322 let default = iter.next().unwrap();
323 match res {
324 Value::Ok_(inner) => Ok(Value::Ok_(inner)),
325 Value::Fail_(_, _) => Ok(default),
326 _ => Ok(wrong_shape()),
327 }
328}