1fn string_value<'a>(value: &'a Value, operation: &str) -> Result<&'a str, String> {
2 match value {
3 Value::String(value) => Ok(value),
4 _ => Err(format!("{operation} expects a string")),
5 }
6}
7
8fn code_point_length(text: &str) -> usize {
9 text.chars().count()
10}
11
12fn code_point_slice(text: &str, start: usize, end: usize) -> Result<String, String> {
13 let length = text.chars().count();
14 if start > end || end > length {
15 return Err("str/slice range is out of bounds".into());
16 }
17 Ok(text.chars().skip(start).take(end - start).collect())
18}
19
20fn code_point_char_at(text: &str, index: usize) -> Result<char, String> {
21 text.chars()
22 .nth(index)
23 .ok_or_else(|| "str/char-at index out of bounds".into())
24}
25
26fn code_point_byte_index(text: &str, code_point_offset: usize) -> usize {
27 text.char_indices()
28 .nth(code_point_offset)
29 .map(|(byte_index, _)| byte_index)
30 .unwrap_or(text.len())
31}
32
33fn code_point_index(text: &str, byte_index: usize) -> usize {
34 text[..byte_index.min(text.len())].chars().count()
35}
36
37fn code_point_index_of(text: &str, part: &str, offset: usize) -> i64 {
38 let byte_offset = code_point_byte_index(text, offset);
39 text[byte_offset..]
40 .find(part)
41 .map(|index| (code_point_index(text, byte_offset + index)) as i64)
42 .unwrap_or(-1)
43}
44
45fn code_point_last_index_of(text: &str, part: &str, offset: usize) -> i64 {
46 let len = code_point_length(text);
47 if part.is_empty() {
48 return (offset.min(len)) as i64;
49 }
50 let mut code_point_index = 0;
51 let mut last: Option<usize> = None;
52 for (byte_index, _) in text.char_indices() {
53 if code_point_index > offset && offset < len {
54 break;
55 }
56 if text[byte_index..].starts_with(part) {
57 last = Some(code_point_index);
58 }
59 code_point_index += 1;
60 }
61 last.map(|index| index as i64).unwrap_or(-1)
62}
63
64fn string_operation(operation: &str, values: Vec<Value>) -> Result<Value, String> {
65 let pair = |values: &[Value]| -> Result<(String, String), String> {
66 if values.len() != 2 {
67 return Err(format!("{operation} expects two strings"));
68 }
69 Ok((
70 string_value(&values[0], operation)?.to_owned(),
71 string_value(&values[1], operation)?.to_owned(),
72 ))
73 };
74 match operation {
75 "str/starts-with?" | "str/ends-with?" => {
76 let (text, part) = pair(&values)?;
77 Ok(Value::Bool(if operation == "str/starts-with?" {
78 text.starts_with(&part)
79 } else {
80 text.ends_with(&part)
81 }))
82 }
83 "str/includes?" => {
84 let (text, part) = pair(&values)?;
85 Ok(Value::Bool(text.contains(&part)))
86 }
87 "str/pad-left" | "str/pad-right" => {
88 if values.len() != 3 {
89 return Err(format!(
90 "{operation} expects a string, length, and padding string"
91 ));
92 }
93 let text = string_value(&values[0], operation)?;
94 let length = value_index(&values[1])?;
95 let padding = string_value(&values[2], operation)?;
96 let text_length = code_point_length(text);
97 if padding.is_empty() || text_length >= length {
98 return Ok(Value::String(text.into()));
99 }
100 let needed = length - text_length;
101 let padding_chars: Vec<char> = padding.chars().collect();
102 let fill: String = padding_chars.iter().cycle().take(needed).copied().collect();
103 Ok(Value::String(if operation == "str/pad-left" {
104 format!("{fill}{text}")
105 } else {
106 format!("{text}{fill}")
107 }))
108 }
109 "str/char-at" => {
110 if values.len() != 2 {
111 return Err("str/char-at expects a string and index".into());
112 }
113 let text = string_value(&values[0], operation)?;
114 let index = value_index(&values[1])?;
115 code_point_char_at(text, index).map(Value::Character)
116 }
117 "str/split" => {
118 if values.len() != 2 {
119 return Err("str/split expects a string and string or regexp separator".into());
120 }
121 let text = string_value(&values[0], operation)?;
122 if text.is_empty() {
123 return Ok(Value::Nil);
124 }
125 let parts = match &values[1] {
126 Value::String(separator) => text
127 .split(separator)
128 .map(|part| Value::String(part.into()))
129 .collect(),
130 Value::Regex(pattern) => {
131 if pattern.is_empty() {
132 return Ok(Value::Vector(PVector::from_iter(
133 text.chars()
134 .map(|character| Value::String(character.to_string())),
135 )));
136 }
137 let mut parts: Vec<Value> = regex::Regex::new(pattern)
138 .map_err(|error| format!("invalid regexp: {error}"))?
139 .split(text)
140 .map(|part| Value::String(part.into()))
141 .collect();
142 while matches!(parts.last(), Some(Value::String(value)) if value.is_empty()) {
143 parts.pop();
144 }
145 parts
146 }
147 _ => return Err("str/split expects a string and string or regexp separator".into()),
148 };
149 Ok(Value::Vector(parts.into()))
150 }
151 "str/split-lines" => {
152 if values.len() != 1 {
153 return Err("str/split-lines expects one string".into());
154 }
155 let text = string_value(&values[0], operation)?;
156 let parts: Vec<Value> = text
157 .split('\n')
158 .map(|part| Value::String(part.into()))
159 .collect();
160 Ok(Value::Vector(parts.into()))
161 }
162 "str/join" => {
163 if values.len() != 2 {
164 return Err("str/join expects a separator and collection".into());
165 }
166 let separator = string_value(&values[0], operation)?;
167 let parts = iterator_values(values[1].clone())?
168 .into_iter()
169 .map(|value| match value {
170 Value::String(value) => Ok(value),
171 Value::Character(value) => Ok(value.to_string()),
172 _ => Err("str/join expects a collection of strings or characters".into()),
173 })
174 .collect::<Result<Vec<String>, String>>()?;
175 Ok(Value::String(parts.join(separator)))
176 }
177 "str/index-of" => {
178 if values.len() != 2 && values.len() != 3 {
179 return Err("str/index-of expects a string, substring, and optional offset".into());
180 }
181 let text = string_value(&values[0], operation)?;
182 let part = string_value(&values[1], operation)?;
183 let offset = if values.len() == 3 {
184 value_index(&values[2])?
185 } else {
186 0
187 };
188 Ok(Value::Number(code_point_index_of(text, part, offset)))
189 }
190 "str/last-index-of" => {
191 if values.len() != 2 && values.len() != 3 {
192 return Err(
193 "str/last-index-of expects a string, substring, and optional offset".into(),
194 );
195 }
196 let text = string_value(&values[0], operation)?;
197 let part = string_value(&values[1], operation)?;
198 let offset = if values.len() == 3 {
199 value_index(&values[2])?
200 } else {
201 code_point_length(text)
202 };
203 Ok(Value::Number(code_point_last_index_of(text, part, offset)))
204 }
205 "str/slice" => {
206 if values.len() != 2 && values.len() != 3 {
207 return Err("str/slice expects a string, start, and optional end".into());
208 }
209 let text = string_value(&values[0], operation)?;
210 let start = value_index(&values[1])?;
211 let end = if values.len() == 3 {
212 value_index(&values[2])?
213 } else {
214 code_point_length(text)
215 };
216 code_point_slice(text, start, end).map(Value::String)
217 }
218 "str/to-fixed" => {
219 if values.len() != 2 {
220 return Err("str/to-fixed expects a number and precision".into());
221 }
222 let number = numeric::to_f64_explicit(&values[0])
223 .map_err(|_| "str/to-fixed expects a number and precision".to_string())?;
224 let precision = value_index(&values[1])?;
225 if precision > 100 {
226 return Err("str/to-fixed precision must be in the range 0..100".into());
227 }
228 Ok(Value::String(format!("{number:.precision$}")))
229 }
230 "str/replace" => {
231 if values.len() != 3 {
232 return Err("str/replace expects a string, match, and replacement".into());
233 }
234 Ok(Value::String(string_value(&values[0], operation)?.replace(
235 string_value(&values[1], operation)?,
236 string_value(&values[2], operation)?,
237 )))
238 }
239 "str/replace-first" => {
240 if values.len() != 3 {
241 return Err("str/replace-first expects a string, match, and replacement".into());
242 }
243 let text = string_value(&values[0], operation)?;
244 let part = string_value(&values[1], operation)?;
245 let replacement = string_value(&values[2], operation)?;
246 Ok(Value::String(text.replacen(part, replacement, 1)))
247 }
248 "str/trim" | "str/trim-left" | "str/trim-right" => {
249 if values.len() != 1 {
250 return Err(format!("{operation} expects one string"));
251 }
252 let text = string_value(&values[0], operation)?;
253 Ok(Value::String(match operation {
254 "str/trim" => text.trim().into(),
255 "str/trim-left" => text.trim_start().into(),
256 _ => text.trim_end().into(),
257 }))
258 }
259 "str/length" => {
260 if values.len() != 1 {
261 return Err(format!("{operation} expects one string"));
262 }
263 let text = string_value(&values[0], operation)?;
264 Ok(Value::Number(code_point_length(text) as i64))
265 }
266 "str/blank?" => {
267 if values.len() != 1 {
268 return Err("str/blank? expects one string".into());
269 }
270 let text = string_value(&values[0], operation)?;
271 Ok(Value::Bool(text.trim().is_empty()))
272 }
273 "str/repeat" => {
274 if values.len() != 2 {
275 return Err("str/repeat expects a string and count".into());
276 }
277 let text = string_value(&values[0], operation)?;
278 let count = value_index(&values[1])?;
279 Ok(Value::String(text.repeat(count)))
280 }
281 "str/capitalize" => {
282 if values.len() != 1 {
283 return Err("str/capitalize expects one string".into());
284 }
285 let text = string_value(&values[0], operation)?;
286 let mut chars = text.chars();
287 match chars.next() {
288 Some(first) => Ok(Value::String(
289 first.to_uppercase().collect::<String>() + chars.as_str(),
290 )),
291 None => Ok(Value::String(text.into())),
292 }
293 }
294 "str/decapitalize" => {
295 if values.len() != 1 {
296 return Err("str/decapitalize expects one string".into());
297 }
298 let text = string_value(&values[0], operation)?;
299 let mut chars = text.chars();
300 match chars.next() {
301 Some(first) => Ok(Value::String(
302 first.to_lowercase().collect::<String>() + chars.as_str(),
303 )),
304 None => Ok(Value::String(text.into())),
305 }
306 }
307 "str/upper" => {
308 if values.len() != 1 {
309 return Err(format!("{operation} expects one string"));
310 }
311 let text = string_value(&values[0], operation)?;
312 Ok(Value::String(text.to_uppercase()))
313 }
314 "str/lower" => {
315 if values.len() != 1 {
316 return Err(format!("{operation} expects one string"));
317 }
318 let text = string_value(&values[0], operation)?;
319 Ok(Value::String(text.to_lowercase()))
320 }
321 "str/reverse" => {
322 if values.len() != 1 {
323 return Err("str/reverse expects one string".into());
324 }
325 let text = string_value(&values[0], operation)?;
326 Ok(Value::String(text.chars().rev().collect()))
327 }
328 "str/encode-utf8" => {
329 if values.len() != 1 {
330 return Err(format!("{operation} expects one string"));
331 }
332 match &values[0] {
333 Value::String(text) => Ok(Value::ByteBuffer(Rc::new(RefCell::new(
334 text.as_bytes().to_vec(),
335 )))),
336 _ => Err(format!("{operation} expects a string")),
337 }
338 }
339 "str/decode-utf8" => {
340 if values.len() != 1 {
341 return Err(format!("{operation} expects bytes"));
342 }
343 let raw = byte_values(&values[0], operation)?;
344 String::from_utf8(raw)
345 .map(Value::String)
346 .map_err(|_| format!("{operation} invalid UTF-8"))
347 }
348 _ => Err(format!("unknown string operation: {operation}")),
349 }
350}
351fn marker_key(value: &Value, operation: &str) -> Result<String, String> {
352 match value {
353 Value::String(key) => Ok(key.clone()),
354 Value::Keyword(key) => Ok(key.as_str().to_owned()),
355 _ => Err(format!("{operation} expects a string key")),
356 }
357}
358
359fn native_mutable_values(operation: &str, values: Vec<Value>) -> Result<Value, String> {
360 let (type_name, method) = operation
361 .strip_prefix("std.native.")
362 .and_then(|name| name.split_once('/'))
363 .ok_or_else(|| format!("invalid native mutable operation: {operation}"))?;
364 if method == "new" {
365 return if type_name == "Arr" {
366 Ok(Value::Array(Rc::new(RefCell::new(values))))
367 } else {
368 if values.len() % 2 != 0 {
369 return Err("object expects key/value pairs".into());
370 }
371 let pairs = values
372 .chunks(2)
373 .map(|pair| Ok((marker_key(&pair[0], "object")?, pair[1].clone())))
374 .collect::<Result<Vec<_>, String>>()?;
375 Ok(Value::Object(Rc::new(RefCell::new(pairs))))
376 };
377 }
378 if values.is_empty() {
379 return Err(format!(
380 "std.native.{type_name}/{method} expects a receiver"
381 ));
382 }
383 let supported = native_declarations()
384 .iter()
385 .find(|declaration| declaration.name == type_name)
386 .is_some_and(|declaration| declaration.method(method));
387 if !supported {
388 return Err(format!("unknown std.native.{type_name} method: {method}"));
389 }
390 let receiver = values[0].clone();
391 let args = values[1..].to_vec();
392 marker_call_values(receiver, method, args)
393}
394
395fn dot_call(
396 receiver: Value,
397 method: &Form,
398 env: &mut HashMap<String, Value>,
399) -> Result<Value, String> {
400 let parts = match method {
401 Form::List(parts) if !parts.is_empty() => parts,
402 _ => return Err("dot call expects a method list".into()),
403 };
404 let name = match &parts[0] {
405 Form::Symbol(name) => name.as_str(),
406 _ => return Err("dot method must be a symbol".into()),
407 };
408 let args = parts[1..]
409 .iter()
410 .map(|form| eval(form, env))
411 .collect::<Result<Vec<_>, _>>()?;
412 dot_call_values(receiver, name, args)
413}
414
415pub(crate) fn dot_call_values(
416 receiver: Value,
417 name: &str,
418 args: Vec<Value>,
419) -> Result<Value, String> {
420 if matches!(receiver, Value::Array(_) | Value::Object(_)) {
421 return Err(
422 "dot calls do not support arrays or objects; use Arr/ or Obj/ functions".into(),
423 );
424 }
425 marker_call_values(receiver, name, args)
426}
427
428fn marker_call_values(receiver: Value, name: &str, args: Vec<Value>) -> Result<Value, String> {
429 match receiver {
430 Value::Array(array) => match name {
431 "get" => {
432 if args.len() < 1 || args.len() > 2 {
433 return Err("array/get expects an index and optional default".into());
434 }
435 let index = value_index(&args[0])?;
436 Ok(array
437 .borrow()
438 .get(index)
439 .cloned()
440 .or_else(|| args.get(1).cloned())
441 .unwrap_or(Value::Nil))
442 }
443 "set" => {
444 if args.len() != 2 {
445 return Err("array/set expects an index and value".into());
446 }
447 let index = value_index(&args[0])?;
448 let mut values = array.borrow_mut();
449 if index >= values.len() {
450 return Err("array/set index out of bounds".into());
451 }
452 values[index] = args[1].clone();
453 drop(values);
454 Ok(Value::Array(array))
455 }
456 "push-first" => {
457 if args.len() != 1 {
458 return Err("array/push-first expects one value".into());
459 }
460 array.borrow_mut().insert(0, args[0].clone());
461 Ok(Value::Array(array))
462 }
463 "push-last" => {
464 if args.len() != 1 {
465 return Err("array/push-last expects one value".into());
466 }
467 array.borrow_mut().push(args[0].clone());
468 Ok(Value::Array(array))
469 }
470 "pop-first" => {
471 if !args.is_empty() {
472 return Err("array/pop-first expects no arguments".into());
473 }
474 let mut values = array.borrow_mut();
475 Ok(if values.is_empty() {
476 Value::Nil
477 } else {
478 values.remove(0)
479 })
480 }
481 "pop-last" => {
482 if !args.is_empty() {
483 return Err("array/pop-last expects no arguments".into());
484 }
485 Ok(array.borrow_mut().pop().unwrap_or(Value::Nil))
486 }
487 "insert" => {
488 if args.len() != 2 {
489 return Err("array/insert expects an index and value".into());
490 }
491 let index = value_index(&args[0])?;
492 let mut values = array.borrow_mut();
493 if index > values.len() {
494 return Err("array/insert index out of bounds".into());
495 }
496 values.insert(index, args[1].clone());
497 drop(values);
498 Ok(Value::Array(array))
499 }
500 "remove" => {
501 if args.len() != 1 {
502 return Err("array/remove expects an index".into());
503 }
504 let index = value_index(&args[0])?;
505 let mut values = array.borrow_mut();
506 if index >= values.len() {
507 return Err("array/remove index out of bounds".into());
508 }
509 Ok(values.remove(index))
510 }
511 "clone" => {
512 if !args.is_empty() {
513 return Err("array/clone expects no arguments".into());
514 }
515 Ok(Value::Array(Rc::new(RefCell::new(array.borrow().clone()))))
516 }
517 "slice" => {
518 if args.is_empty() || args.len() > 2 {
519 return Err("array/slice expects start and optional end".into());
520 }
521 let start = value_index(&args[0])?;
522 let end = if args.len() == 2 {
523 value_index(&args[1])?
524 } else {
525 array.borrow().len()
526 };
527 let values = array.borrow();
528 if start > end || end > values.len() {
529 return Err("array/slice range is out of bounds".into());
530 }
531 Ok(Value::Array(Rc::new(RefCell::new(
532 values[start..end].to_vec(),
533 ))))
534 }
535 "map" | "filter" => {
536 if args.len() != 1 {
537 return Err(format!("array/{name} expects one function"));
538 }
539 let function = match &args[0] {
540 Value::Function(function) => function,
541 _ => return Err(format!("array/{name} expects a function")),
542 };
543 let mut output = Vec::new();
544 for value in array.borrow().iter().cloned() {
545 let mapped = call_function(function, vec![value.clone()])?;
546 if name == "map" {
547 output.push(mapped);
548 } else if mapped.truthy() {
549 output.push(value);
550 }
551 }
552 Ok(Value::Array(Rc::new(RefCell::new(output))))
553 }
554 "fold-left" | "fold-right" => {
555 if args.len() != 2 {
556 return Err(format!("array/{name} expects a function and initial value"));
557 }
558 let function = match &args[0] {
559 Value::Function(function) => function,
560 _ => return Err(format!("array/{name} expects a function")),
561 };
562 let values = array.borrow();
563 let mut output = args[1].clone();
564 if name == "fold-left" {
565 for value in values.iter().cloned() {
566 output = call_function(function, vec![output, value])?;
567 }
568 } else {
569 for value in values.iter().rev().cloned() {
570 output = call_function(function, vec![value, output])?;
571 }
572 }
573 Ok(output)
574 }
575 _ => Err(format!("unsupported array method: {name}")),
576 },
577 Value::Object(object) => match name {
578 "has?" => {
579 if args.len() != 1 {
580 return Err("object/has? expects a key".into());
581 }
582 let key = marker_key(&args[0], "object/has?")?;
583 Ok(Value::Bool(
584 object
585 .borrow()
586 .iter()
587 .any(|(candidate, _)| candidate == &key),
588 ))
589 }
590 "get" => {
591 if args.len() < 1 || args.len() > 2 {
592 return Err("object/get expects a key and optional default".into());
593 }
594 let key = marker_key(&args[0], "object/get")?;
595 Ok(object
596 .borrow()
597 .iter()
598 .find(|(candidate, _)| candidate == &key)
599 .map(|(_, value)| value.clone())
600 .or_else(|| args.get(1).cloned())
601 .unwrap_or(Value::Nil))
602 }
603 "set" => {
604 if args.len() != 2 {
605 return Err("object/set expects a key and value".into());
606 }
607 let key = marker_key(&args[0], "object/set")?;
608 let mut values = object.borrow_mut();
609 if let Some((_, value)) = values.iter_mut().find(|(candidate, _)| candidate == &key)
610 {
611 *value = args[1].clone();
612 } else {
613 values.push((key, args[1].clone()));
614 }
615 drop(values);
616 Ok(Value::Object(object))
617 }
618 "delete" => {
619 if args.len() != 1 {
620 return Err("object/delete expects a key".into());
621 }
622 let key = marker_key(&args[0], "object/delete")?;
623 let mut values = object.borrow_mut();
624 if let Some(index) = values.iter().position(|(candidate, _)| candidate == &key) {
625 Ok(values.remove(index).1)
626 } else {
627 Ok(Value::Nil)
628 }
629 }
630 "keys" | "vals" | "pairs" => {
631 if !args.is_empty() {
632 return Err(format!("object/{name} expects no arguments"));
633 }
634 let output = object
635 .borrow()
636 .iter()
637 .map(|(key, value)| match name {
638 "keys" => Value::String(key.clone()),
639 "vals" => value.clone(),
640 _ => Value::Array(Rc::new(RefCell::new(vec![
641 Value::String(key.clone()),
642 value.clone(),
643 ]))),
644 })
645 .collect();
646 Ok(Value::Array(Rc::new(RefCell::new(output))))
647 }
648 "assign" => {
649 if args.len() != 1 {
650 return Err("object/assign expects an object".into());
651 }
652 let other = match &args[0] {
653 Value::Object(other) => other.clone(),
654 _ => return Err("object/assign expects an object".into()),
655 };
656 let mut values = object.borrow_mut();
657 for (key, value) in other.borrow().iter() {
658 if let Some((_, existing)) =
659 values.iter_mut().find(|(candidate, _)| candidate == key)
660 {
661 *existing = value.clone();
662 } else {
663 values.push((key.clone(), value.clone()));
664 }
665 }
666 drop(values);
667 Ok(Value::Object(object))
668 }
669 "clone" => {
670 if !args.is_empty() {
671 return Err("object/clone expects no arguments".into());
672 }
673 Ok(Value::Object(Rc::new(RefCell::new(
674 object.borrow().clone(),
675 ))))
676 }
677 _ => Err(format!("unsupported object method: {name}")),
678 },
679 _ => Err("dot calls require an array or object marker".into()),
680 }
681}
682
683fn byte_input(value: &Value, operation: &str) -> Result<u8, String> {
684 match value {
685 Value::Number(number) if (-128..=255).contains(number) => Ok((*number as i8) as u8),
686 _ => Err(format!(
687 "{operation} expects a value in the range -128..255"
688 )),
689 }
690}
691
692fn byte_buffer(value: &Value, operation: &str) -> Result<Rc<RefCell<Vec<u8>>>, String> {
693 match value {
694 Value::ByteBuffer(bytes) => Ok(bytes.clone()),
695 _ => Err(format!("{operation} expects bytes")),
696 }
697}
698
699fn byte_values(value: &Value, operation: &str) -> Result<Vec<u8>, String> {
700 match value {
701 Value::Bytes(bytes) => Ok(bytes.clone()),
702 Value::ByteBuffer(bytes) => Ok(bytes.borrow().clone()),
703 _ => Err(format!("{operation} expects bytes")),
704 }
705}
706
707fn byte_count(value: &Value) -> Result<Value, String> {
708 match value {
709 Value::Bytes(bytes) => Ok(Value::Number(bytes.len() as i64)),
710 Value::ByteBuffer(bytes) => Ok(Value::Number(bytes.borrow().len() as i64)),
711 _ => Err("bytes/count expects bytes".into()),
712 }
713}
714
715fn byte_get(value: &Value, index: &Value, default: Option<Value>) -> Result<Value, String> {
716 let index = value_index(index)?;
717 let found = match value {
718 Value::Bytes(bytes) => bytes.get(index).copied(),
719 Value::ByteBuffer(bytes) => bytes.borrow().get(index).copied(),
720 _ => return Err("bytes/get expects bytes".into()),
721 };
722 match found {
723 Some(byte) => Ok(Value::Number(byte as i64)),
724 None => default.ok_or_else(|| "bytes/get index out of bounds".into()),
725 }
726}
727
728fn byte_copy(value: &Value) -> Result<Value, String> {
729 let bytes = byte_buffer(value, "bytes/copy")?;
730 let copied = bytes.borrow().clone();
731 Ok(Value::ByteBuffer(Rc::new(RefCell::new(copied))))
732}
733
734fn byte_slice(value: &Value, start: &Value, end: &Value) -> Result<Value, String> {
735 let start = value_index(start)?;
736 let end = value_index(end)?;
737 let bytes = byte_buffer(value, "bytes/slice")?;
738 let bytes = bytes.borrow();
739 if start > end || end > bytes.len() {
740 return Err(format!(
741 "bytes/slice range is out of bounds: {start}..{end}"
742 ));
743 }
744 Ok(Value::ByteBuffer(Rc::new(RefCell::new(
745 bytes[start..end].to_vec(),
746 ))))
747}
748
749fn byte_set(value: &Value, index: &Value, item: &Value) -> Result<Value, String> {
750 let index = value_index(index)?;
751 let item = byte_input(item, "bytes/set")?;
752 let bytes = byte_buffer(value, "bytes/set")?;
753 let mut bytes = bytes.borrow_mut();
754 if index >= bytes.len() {
755 return Err("bytes/set index out of bounds".into());
756 }
757 bytes[index] = item;
758 Ok(value.clone())
759}
760
761pub(crate) fn iterator_values(value: Value) -> Result<Vec<Value>, String> {
762 match value {
763 Value::Seq(values) => values.iter().collect::<Result<Vec<_>, _>>(),
764 Value::Extension(receiver) => {
765 let value = Value::Extension(receiver.clone());
766 let iterator = extension_protocol_call(
767 &receiver,
768 "std.protocol.iiter.IIter",
769 "iter",
770 std::slice::from_ref(&value),
771 )?;
772 iterator_values(iterator)
773 }
774 Value::Nil => Ok(Vec::new()),
775 Value::Tuple(values) => Ok(values.iter().cloned().collect()),
776 Value::Vector(values) => Ok(values.iter().cloned().collect()),
777 Value::MapEntry(entry) => Ok(entry.iter().cloned().collect()),
778 Value::List(values) => Ok(values.iter().cloned().collect()),
779 Value::Cons(values) => Ok(values.iter().collect()),
780 Value::Deque(values) => Ok(values.iter().cloned().collect()),
781 Value::Queue(values) => Ok(values.iter().cloned().collect()),
782 Value::PriorityMap(values) => Ok(values
783 .iter()
784 .map(|(key, value)| pair_value(key, value))
785 .collect()),
786 Value::String(text) => Ok(text.chars().map(Value::Character).collect()),
787 Value::Bytes(bytes) => Ok(bytes
788 .into_iter()
789 .map(|byte| Value::Number(byte as i8 as i64))
790 .collect()),
791 Value::ByteBuffer(bytes) => Ok(bytes
792 .borrow()
793 .iter()
794 .map(|byte| Value::Number(*byte as i8 as i64))
795 .collect()),
796 Value::Array(values) => Ok(values.borrow().clone()),
797 Value::Object(values) => Ok(values
798 .borrow()
799 .iter()
800 .map(|(key, value)| pair_value(Value::String(key.clone()), value.clone()))
801 .collect()),
802 Value::Struct(value) => Ok(value
803 .ordered_entries()
804 .into_iter()
805 .map(|(key, value)| pair_value(key, value))
806 .collect()),
807 Value::Mutable(value) => Ok(value
808 .ordered_entries()
809 .into_iter()
810 .map(|(key, value)| pair_value(key, value))
811 .collect()),
812 Value::MutableCollection(collection) => {
813 let borrowed = collection.borrow();
814 let collection = borrowed
815 .as_ref()
816 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
817 match collection {
818 MutableCollection::Map(values) => Ok(values
819 .iter()
820 .map(|(key, value)| pair_value(key.clone(), value.clone()))
821 .collect()),
822 MutableCollection::OrderedMap(values) => Ok(values
823 .iter()
824 .map(|(key, value)| pair_value(key.clone(), value.clone()))
825 .collect()),
826 MutableCollection::SortedMap(values) => Ok(values
827 .iter()
828 .map(|(key, value)| pair_value(key.clone(), value.clone()))
829 .collect()),
830 MutableCollection::Trie(values) => Ok(values
831 .entries()
832 .into_iter()
833 .map(|(key, value)| pair_value(Value::String(key.clone()), value.clone()))
834 .collect()),
835 MutableCollection::Set(values) => Ok(values.iter().cloned().collect()),
836 MutableCollection::OrderedSet(values) => Ok(values.iter().cloned().collect()),
837 MutableCollection::SortedSet(values) => Ok(values.iter().cloned().collect()),
838 MutableCollection::List(values) => Ok(values.iter().cloned().collect()),
839 MutableCollection::Queue(values) => Ok(values.iter().cloned().collect()),
840 MutableCollection::Vector(values) => Ok(values.iter().cloned().collect()),
841 }
842 }
843 Value::Pointer(pointer) => Ok(pointer
844 .fields()
845 .iter()
846 .map(|(key, value)| pair_value(key.clone(), value.clone()))
847 .collect()),
848 value @ (Value::Map(_) | Value::OrderedMap(_) | Value::SortedMap(_) | Value::Trie(_)) => {
849 Ok(map_entries(&value)
850 .unwrap()
851 .into_iter()
852 .map(|(key, value)| pair_value(key, value))
853 .collect())
854 }
855 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
856 Ok(set_items(&value).unwrap().into_iter().cloned().collect())
857 }
858 Value::Iterator(_) => {
859 let mut values = Vec::new();
860 while let Some(item) = iterator_try_next(&value)? {
861 values.push(item);
862 }
863 Ok(values)
864 }
865 value => Err(format!(
866 "iter expects a collection, got {}",
867 value.display()
868 )),
869 }
870}
871
872fn iterator_to_vec(value: Value) -> Result<Vec<Value>, String> {
873 iterator_values(value)
874}
875
876fn make_iterator(value: Value) -> Result<Value, String> {
877 match &value {
878 Value::Iterator(_) => Ok(value),
879 Value::Seq(sequence) => Ok(Value::Iterator(Rc::new(RefCell::new(
880 IteratorState::generated(IteratorGenerator::Seq((**sequence).clone())),
881 )))),
882 Value::Nil
883 | Value::String(_)
884 | Value::Bytes(_)
885 | Value::ByteBuffer(_)
886 | Value::Array(_)
887 | Value::Object(_)
888 | Value::Struct(_)
889 | Value::Mutable(_)
890 | Value::MutableCollection(_)
891 | Value::Map(_)
892 | Value::OrderedMap(_)
893 | Value::SortedMap(_)
894 | Value::Trie(_)
895 | Value::PriorityMap(_)
896 | Value::Pointer(_)
897 | Value::Set(_)
898 | Value::OrderedSet(_)
899 | Value::SortedSet(_)
900 | Value::List(_)
901 | Value::Cons(_)
902 | Value::Queue(_)
903 | Value::Deque(_)
904 | Value::Tuple(_)
905 | Value::MapEntry(_)
906 | Value::Vector(_) => Ok(Value::Iterator(Rc::new(RefCell::new(IteratorState::new(
907 iterator_values(value)?,
908 ))))),
909 _ => match protocol_call("std.protocol.iiter.IIter", "iter", &[value])? {
910 Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
911 _ => Err("IIter/iter must return an iterator".into()),
912 },
913 }
914}
915
916pub fn iterator_from_values(values: Vec<Value>) -> Value {
917 Value::Iterator(Rc::new(RefCell::new(IteratorState::new(values))))
918}
919
920fn iterator_seq(value: Value) -> Result<Value, String> {
921 if matches!(value, Value::Seq(_)) {
922 return Ok(value);
923 }
924 let source = make_iterator(value)?;
925 let sequence = PSeq::new(RuntimeSeqSource {
926 source,
927 finished: false,
928 });
929 match sequence.peek_first() {
930 None => Ok(Value::Nil),
931 Some(Ok(_)) => Ok(Value::Seq(Box::new(sequence))),
932 Some(Err(error)) => Err(error),
933 }
934}
935
936struct RuntimeSeqSource {
937 source: Value,
938 finished: bool,
939}
940
941impl Iterator for RuntimeSeqSource {
942 type Item = Result<Value, String>;
943
944 fn next(&mut self) -> Option<Self::Item> {
945 if self.finished {
946 return None;
947 }
948 match iterator_try_next(&self.source) {
949 Ok(Some(value)) => Some(Ok(value)),
950 Ok(None) => {
951 self.finished = true;
952 None
953 }
954 Err(error) => {
955 self.finished = true;
956 Some(Err(error))
957 }
958 }
959 }
960}
961
962fn iterator_constant(value: Value) -> Value {
963 Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
964 IteratorGenerator::Constant(value),
965 ))))
966}
967fn iterator_prepend(head: Value, source: Value) -> Result<Value, String> {
968 let source = match source {
969 Value::Iterator(iterator) => Value::Iterator(iterator),
970 value => make_iterator(value)?,
971 };
972 let state = IteratorState::generated(IteratorGenerator::Prepend(Some(head), source));
973 Ok(Value::Iterator(Rc::new(RefCell::new(state))))
974}
975fn iterator_repeated(function: Value) -> Value {
976 Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
977 IteratorGenerator::Repeated(function),
978 ))))
979}
980fn iterator_iterate(function: Value, seed: Value) -> Value {
981 Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
982 IteratorGenerator::Iterate(function, seed),
983 ))))
984}
985fn iterator_take_while(function: Value, value: Value) -> Result<Value, String> {
986 let source = match value {
987 Value::Iterator(iterator) => Value::Iterator(iterator),
988 value => make_iterator(value)?,
989 };
990 Ok(Value::Iterator(Rc::new(RefCell::new(
991 IteratorState::generated(IteratorGenerator::TakeWhile(function, source)),
992 ))))
993}
994fn iterator_map(function: Value, value: Value) -> Result<Value, String> {
995 iterator_map_with(function, value, false)
996}
997fn iterator_map_with(function: Value, value: Value, spread: bool) -> Result<Value, String> {
998 let source = match value {
999 Value::Iterator(iterator) => Value::Iterator(iterator),
1000 value => make_iterator(value)?,
1001 };
1002 Ok(Value::Iterator(Rc::new(RefCell::new(
1003 IteratorState::generated(IteratorGenerator::Map(function, source, spread)),
1004 ))))
1005}
1006fn iterator_partition(value: Value, amount: usize, all: bool) -> Result<Value, String> {
1007 if amount == 0 {
1008 return Err("partition amount must be positive".into());
1009 }
1010 let source = match value {
1011 Value::Iterator(iterator) => Value::Iterator(iterator),
1012 value => make_iterator(value)?,
1013 };
1014 Ok(Value::Iterator(Rc::new(RefCell::new(
1015 IteratorState::generated(IteratorGenerator::Partition(source, amount, all)),
1016 ))))
1017}
1018
1019fn iterator_interleave(values: Vec<Value>) -> Result<Value, String> {
1020 let sources = values
1021 .into_iter()
1022 .map(|value| match value {
1023 Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1024 value => make_iterator(value),
1025 })
1026 .collect::<Result<Vec<_>, _>>()?;
1027 Ok(Value::Iterator(Rc::new(RefCell::new(
1028 IteratorState::generated(IteratorGenerator::Interleave(sources, 0)),
1029 ))))
1030}
1031
1032fn iterator_interpose(separator: Value, value: Value) -> Result<Value, String> {
1033 let source = match value {
1034 Value::Iterator(iterator) => Value::Iterator(iterator),
1035 value => make_iterator(value)?,
1036 };
1037 Ok(Value::Iterator(Rc::new(RefCell::new(
1038 IteratorState::generated(IteratorGenerator::Interpose(source, separator, true, None)),
1039 ))))
1040}
1041
1042fn iterator_concat(values: Vec<Value>) -> Result<Value, String> {
1043 let sources = values
1044 .into_iter()
1045 .map(|value| match value {
1046 Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1047 value => make_iterator(value),
1048 })
1049 .collect::<Result<Vec<_>, _>>()?;
1050 Ok(Value::Iterator(Rc::new(RefCell::new(
1051 IteratorState::generated(IteratorGenerator::Concat(sources, 0)),
1052 ))))
1053}
1054
1055fn iterator_zip(values: Vec<Value>) -> Result<Value, String> {
1056 let sources = values
1057 .into_iter()
1058 .map(|value| match value {
1059 Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1060 value => make_iterator(value),
1061 })
1062 .collect::<Result<Vec<_>, _>>()?;
1063 Ok(Value::Iterator(Rc::new(RefCell::new(
1064 IteratorState::generated(IteratorGenerator::Zip(sources)),
1065 ))))
1066}
1067
1068fn iterator_mapcat(function: Value, value: Value) -> Result<Value, String> {
1069 let source = match value {
1070 Value::Iterator(iterator) => Value::Iterator(iterator),
1071 value => make_iterator(value)?,
1072 };
1073 Ok(Value::Iterator(Rc::new(RefCell::new(
1074 IteratorState::generated(IteratorGenerator::Mapcat(function, source, None)),
1075 ))))
1076}
1077fn iterator_keep(function: Value, value: Value) -> Result<Value, String> {
1078 let source = match value {
1079 Value::Iterator(iterator) => Value::Iterator(iterator),
1080 value => make_iterator(value)?,
1081 };
1082 Ok(Value::Iterator(Rc::new(RefCell::new(
1083 IteratorState::generated(IteratorGenerator::Keep(function, source)),
1084 ))))
1085}
1086
1087fn iterator_filter(function: Value, value: Value) -> Result<Value, String> {
1088 let source = match value {
1089 Value::Iterator(iterator) => Value::Iterator(iterator),
1090 value => make_iterator(value)?,
1091 };
1092 Ok(Value::Iterator(Rc::new(RefCell::new(
1093 IteratorState::generated(IteratorGenerator::Filter(function, source)),
1094 ))))
1095}
1096
1097fn iterator_drop_while(function: Value, value: Value) -> Result<Value, String> {
1098 let source = match value {
1099 Value::Iterator(iterator) => Value::Iterator(iterator),
1100 value => make_iterator(value)?,
1101 };
1102 Ok(Value::Iterator(Rc::new(RefCell::new(
1103 IteratorState::generated(IteratorGenerator::DropWhile(function, source, false)),
1104 ))))
1105}
1106fn iterator_take(value: Value, amount: usize) -> Result<Value, String> {
1107 let source = match value {
1108 Value::Iterator(iterator) => Value::Iterator(iterator),
1109 value => make_iterator(value)?,
1110 };
1111 Ok(Value::Iterator(Rc::new(RefCell::new(
1112 IteratorState::generated(IteratorGenerator::Take(source, amount)),
1113 ))))
1114}
1115fn iterator_drop(value: Value, amount: usize) -> Result<Value, String> {
1116 let source = match value {
1117 Value::Iterator(iterator) => Value::Iterator(iterator),
1118 value => make_iterator(value)?,
1119 };
1120 Ok(Value::Iterator(Rc::new(RefCell::new(
1121 IteratorState::generated(IteratorGenerator::Drop(source, amount)),
1122 ))))
1123}
1124
1125fn iterator_cycle(value: Value) -> Result<Value, String> {
1126 let source = match value {
1127 Value::Iterator(iterator) => Value::Iterator(iterator),
1128 value => make_iterator(value)?,
1129 };
1130 if !matches!(iterator_has_next(&source)?, Value::Bool(true)) {
1131 return Err("cycle expects a non-empty source".into());
1132 }
1133 Ok(Value::Iterator(Rc::new(RefCell::new(
1134 IteratorState::generated(IteratorGenerator::Cycle(source, Vec::new(), 0, false)),
1135 ))))
1136}
1137
1138fn iterator_has_next(value: &Value) -> Result<Value, String> {
1139 match value {
1140 Value::Iterator(iterator) => Ok(Value::Bool(iterator.borrow_mut().has_next()?)),
1141 _ => Err("iter-next? expects an iterator".into()),
1142 }
1143}
1144
1145fn iterator_try_next(value: &Value) -> Result<Option<Value>, String> {
1146 match value {
1147 Value::Iterator(iterator) => iterator.borrow_mut().try_next(),
1148 _ => Err("iter-next expects an iterator".into()),
1149 }
1150}
1151
1152fn iterator_next(value: &Value) -> Result<Value, String> {
1153 iterator_try_next(value)?.ok_or_else(|| "iter-next reached the end of the iterator".into())
1154}
1155
1156fn iterator_close(value: &Value) -> Result<Value, String> {
1157 match value {
1158 Value::Iterator(iterator) => {
1159 iterator.borrow_mut().close();
1160 Ok(Value::Nil)
1161 }
1162 _ => Err("iter-close expects an iterator".into()),
1163 }
1164}
1165
1166fn collection_first(value: Value) -> Result<Value, String> {
1167 match value {
1168 Value::Seq(sequence) => sequence
1169 .peek_first()
1170 .transpose()?
1171 .ok_or_else(|| "invalid empty Seq value".to_string()),
1172 Value::Iterator(iterator) => Ok(iterator.borrow_mut().try_next()?.unwrap_or(Value::Nil)),
1173 value => Ok(iterator_values(value)?
1174 .into_iter()
1175 .next()
1176 .unwrap_or(Value::Nil)),
1177 }
1178}
1179
1180fn collection_rest(value: Value) -> Result<Value, String> {
1181 if let Value::Seq(sequence) = value {
1182 let tail = sequence.pop_first();
1183 return match tail.peek_first() {
1184 None => Ok(Value::Nil),
1185 Some(Ok(_)) => Ok(Value::Seq(Box::new(tail))),
1186 Some(Err(error)) => Err(error),
1187 };
1188 }
1189 let source = match value {
1190 Value::Iterator(iterator) => Value::Iterator(iterator),
1191 value => make_iterator(value)?,
1192 };
1193 if iterator_try_next(&source)?.is_none() {
1194 return Ok(Value::Nil);
1195 }
1196 iterator_seq(source)
1197}
1198
1199fn collection_last(value: Value) -> Result<Value, String> {
1200 Ok(iterator_to_vec(value)?
1201 .into_iter()
1202 .last()
1203 .unwrap_or(Value::Nil))
1204}
1205
1206fn collection_empty_value(value: Value) -> Result<Value, String> {
1207 match value {
1208 Value::Extension(receiver) => extension_protocol_call(
1209 &receiver,
1210 "std.protocol.iempty.IEmpty",
1211 "empty",
1212 &[Value::Extension(receiver.clone())],
1213 ),
1214 Value::Nil => Ok(Value::Nil),
1215 Value::Array(_) => Ok(Value::Array(Rc::new(RefCell::new(Vec::new())))),
1216 Value::Object(_) => Ok(Value::Object(Rc::new(RefCell::new(Vec::new())))),
1217 Value::List(values) => Ok(Value::List(values.empty())),
1218 Value::Cons(values) => Ok(Value::List(PList::new().with_meta(values.meta().cloned()))),
1219 Value::Queue(values) => Ok(Value::Queue(Box::new(values.empty()))),
1220 Value::Deque(values) => Ok(Value::Deque(Box::new(values.empty()))),
1221 Value::Vector(values) => Ok(Value::Vector(values.empty())),
1222 Value::Tuple(values) => Ok(Value::Tuple(Box::new(values.empty()))),
1223 Value::Seq(values) => Ok(Value::Tuple(Box::new(
1224 PTuple::Tup0.with_meta(values.meta().cloned()),
1225 ))),
1226 Value::Map(values) => Ok(Value::Map(values.empty())),
1227 Value::OrderedMap(values) => Ok(Value::OrderedMap(Box::new(values.empty()))),
1228 Value::SortedMap(values) => Ok(Value::SortedMap(Box::new(values.empty()))),
1229 Value::Trie(values) => Ok(Value::Trie(Box::new(values.empty()))),
1230 Value::PriorityMap(values) => Ok(Value::PriorityMap(Box::new(values.empty()))),
1231 Value::Set(values) => Ok(Value::Set(values.empty())),
1232 Value::OrderedSet(values) => Ok(Value::OrderedSet(Box::new(values.empty()))),
1233 Value::SortedSet(values) => Ok(Value::SortedSet(Box::new(values.empty()))),
1234 Value::Struct(value) => Ok(Value::Struct(Rc::new(StructValue::from_values(
1235 value.ty.clone(),
1236 vec![Value::Nil; value.ty.fields.len()],
1237 value.metadata.clone(),
1238 )?))),
1239 Value::Mutable(_) => Err("empty does not support mutable values".into()),
1240 value => Err(format!(
1241 "empty expects a collection, got {}",
1242 portable_type_name(&value)
1243 )),
1244 }
1245}
1246
1247fn collection_count(value: &Value) -> Result<Value, String> {
1248 if let Value::Extension(receiver) = value {
1249 return extension_protocol_call(
1250 receiver,
1251 "std.protocol.icount.ICount",
1252 "count",
1253 std::slice::from_ref(value),
1254 );
1255 }
1256 let count = match value {
1257 Value::Nil => 0,
1258 Value::String(v) => v.chars().count(),
1259 Value::Tuple(v) => v.len(),
1260 Value::Vector(v) => v.len(),
1261 Value::MapEntry(_) => 2,
1262 Value::List(v) => v.len(),
1263 Value::Cons(v) => v.iter().count(),
1264 Value::Queue(v) => v.len(),
1265 Value::Deque(v) => v.len(),
1266 value @ (Value::Map(_)
1267 | Value::OrderedMap(_)
1268 | Value::SortedMap(_)
1269 | Value::Trie(_)
1270 | Value::PriorityMap(_)) => map_entries(value).unwrap().len(),
1271 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
1272 set_items(value).unwrap().len()
1273 }
1274 Value::Bytes(v) => v.len(),
1275 Value::ByteBuffer(v) => v.borrow().len(),
1276 Value::Array(v) => v.borrow().len(),
1277 Value::Object(v) => v.borrow().len(),
1278 Value::Struct(v) => v.ty.fields.len(),
1279 Value::Mutable(v) => v.ty.fields.len(),
1280 Value::Pointer(v) => v.fields().len(),
1281 Value::MutableCollection(collection) => {
1282 let borrowed = collection.borrow();
1283 let mutable = borrowed
1284 .as_ref()
1285 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1286 match mutable {
1287 MutableCollection::Map(values) => values.len(),
1288 MutableCollection::OrderedMap(values) => values.len(),
1289 MutableCollection::SortedMap(values) => values.len(),
1290 MutableCollection::Trie(values) => values.len(),
1291 MutableCollection::Set(values) => values.len(),
1292 MutableCollection::OrderedSet(values) => values.len(),
1293 MutableCollection::SortedSet(values) => values.len(),
1294 MutableCollection::List(values) => values.len(),
1295 MutableCollection::Queue(values) => values.len(),
1296 MutableCollection::Vector(values) => values.len(),
1297 }
1298 }
1299 Value::Seq(sequence) => {
1300 let mut count = 0;
1301 for value in sequence.iter() {
1302 value?;
1303 count += 1;
1304 }
1305 count
1306 }
1307 Value::Iterator(_) => {
1308 let mut count = 0;
1309 while iterator_try_next(value)?.is_some() {
1310 count += 1;
1311 }
1312 count
1313 }
1314 _ => return Err("count expects a collection".into()),
1315 };
1316 Ok(Value::Number(count as i64))
1317}
1318
1319fn iterator_is_finite(value: &Value) -> bool {
1320 match value {
1321 Value::Iterator(iterator) => iterator.borrow().is_finite(),
1322 Value::Seq(_) => false,
1323 _ => true,
1324 }
1325}
1326
1327fn collection_get(value: &Value, key: &Value, default: Value) -> Result<Value, String> {
1328 match value {
1329 Value::Extension(receiver) => extension_protocol_call(
1330 receiver,
1331 "std.protocol.ilookup.ILookup",
1332 "lookup",
1333 &[value.clone(), key.clone(), default],
1334 ),
1335 Value::Nil | Value::Seq(_) => Ok(default),
1336 Value::Tuple(values) => {
1337 let index = value_index(key)?;
1338 Ok(values.get(index).cloned().unwrap_or(default))
1339 }
1340 Value::Vector(values) => {
1341 let index = value_index(key)?;
1342 Ok(values.get(index).cloned().unwrap_or(default))
1343 }
1344 Value::MapEntry(entry) => {
1345 let index = value_index(key)?;
1346 Ok(entry.nth(index).cloned().unwrap_or(default))
1347 }
1348 Value::Array(values) => {
1349 let index = value_index(key)?;
1350 Ok(values.borrow().get(index).cloned().unwrap_or(default))
1351 }
1352 Value::Cons(values) => {
1353 let index = value_index(key)?;
1354 Ok(values.iter().nth(index).unwrap_or(default))
1355 }
1356 Value::List(values) => {
1357 let index = value_index(key)?;
1358 Ok(values.get(index).cloned().unwrap_or(default))
1359 }
1360 Value::Queue(values) => {
1361 let index = value_index(key)?;
1362 Ok(values.get(index).cloned().unwrap_or(default))
1363 }
1364 Value::Deque(values) => {
1365 let index = value_index(key)?;
1366 Ok(values.get(index).cloned().unwrap_or(default))
1367 }
1368 Value::MutableCollection(collection) => {
1369 let borrowed = collection.borrow();
1370 let mutable = borrowed
1371 .as_ref()
1372 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1373 let found = match mutable {
1374 MutableCollection::Map(values) => values.get(key).cloned(),
1375 MutableCollection::OrderedMap(values) => values.get(key).cloned(),
1376 MutableCollection::SortedMap(values) => values.get(key).cloned(),
1377 MutableCollection::Trie(values) => values.get(&marker_key(key, "trie")?).cloned(),
1378 MutableCollection::Set(values) => values.get(key).cloned(),
1379 MutableCollection::OrderedSet(values) => values.get(key).cloned(),
1380 MutableCollection::SortedSet(values) => values.get(key).cloned(),
1381 MutableCollection::List(values) => values.get(value_index(key)?).cloned(),
1382 MutableCollection::Queue(values) => values.get(value_index(key)?).cloned(),
1383 MutableCollection::Vector(values) => values.get(value_index(key)?).cloned(),
1384 };
1385 Ok(found.unwrap_or(default))
1386 }
1387 Value::Bytes(_) | Value::ByteBuffer(_) => byte_get(value, key, Some(default)),
1388 Value::String(text) => {
1389 let index = value_index(key)?;
1390 Ok(text
1391 .chars()
1392 .nth(index)
1393 .map(Value::Character)
1394 .unwrap_or(default))
1395 }
1396 value @ (Value::Map(_)
1397 | Value::OrderedMap(_)
1398 | Value::SortedMap(_)
1399 | Value::Trie(_)
1400 | Value::PriorityMap(_)) => Ok(map_value(value, key).cloned().unwrap_or(default)),
1401 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
1402 Ok(set_find(value, key).unwrap_or(default))
1403 }
1404 Value::Object(entries) => {
1405 let name = match key {
1406 Value::String(name) => name.as_str(),
1407 Value::Keyword(name) => name.as_str(),
1408 _ => return Ok(default),
1409 };
1410 Ok(entries
1411 .borrow()
1412 .iter()
1413 .find(|(candidate, _)| candidate == name)
1414 .map(|(_, value)| value.clone())
1415 .unwrap_or(default))
1416 }
1417 Value::Struct(value) => Ok(named_field_name(key)
1418 .and_then(|name| value.get(name))
1419 .cloned()
1420 .unwrap_or(default)),
1421 Value::Mutable(value) => Ok(named_field_name(key)
1422 .and_then(|name| value.get(name))
1423 .unwrap_or(default)),
1424 Value::Pointer(pointer) => Ok(pointer.get(key).cloned().unwrap_or(default)),
1425 Value::Result(result) => {
1426 let Value::Keyword(key) = key else {
1427 return Ok(default);
1428 };
1429 Ok(match key.as_str() {
1430 "status" => result.status_value(),
1431 "data" => result.data.clone(),
1432 "error" => result.error_value(),
1433 "context" => {
1434 if map_entries(&result.context).is_some_and(|entries| entries.is_empty()) {
1435 Value::Nil
1436 } else {
1437 result.context.clone()
1438 }
1439 }
1440 _ => default,
1441 })
1442 }
1443 value => Err(format!(
1444 "get expects a collection, received {}",
1445 portable_type_name(value)
1446 )),
1447 }
1448}
1449
1450fn collection_nth(value: &Value, key: &Value) -> Result<Value, String> {
1451 let index = value_index(key)?;
1452 if let Value::Iterator(iterator) = value {
1453 let mut state = iterator.borrow_mut();
1454 for _ in 0..index {
1455 if state.try_next()?.is_none() {
1456 return Err("nth index out of bounds".into());
1457 }
1458 }
1459 return state
1460 .try_next()?
1461 .ok_or_else(|| "nth index out of bounds".into());
1462 }
1463 let result = match value {
1464 Value::Tuple(values) => values.get(index).cloned(),
1465 Value::Vector(values) => values.get(index).cloned(),
1466 Value::MapEntry(entry) => entry.nth(index).cloned(),
1467 Value::Array(values) => values.borrow().get(index).cloned(),
1468 Value::Cons(values) => values.iter().nth(index),
1469 Value::List(values) => values.get(index).cloned(),
1470 Value::Queue(values) => values.get(index).cloned(),
1471 Value::Deque(values) => values.get(index).cloned(),
1472 Value::MutableCollection(collection) => {
1473 let borrowed = collection.borrow();
1474 let mutable = borrowed
1475 .as_ref()
1476 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1477 match mutable {
1478 MutableCollection::List(values) => values.get(index).cloned(),
1479 MutableCollection::Queue(values) => values.get(index).cloned(),
1480 MutableCollection::Vector(values) => values.get(index).cloned(),
1481 _ => return Err("nth expects an indexed collection".into()),
1482 }
1483 }
1484 Value::String(text) => text
1485 .chars()
1486 .nth(index)
1487 .map(Value::Character),
1488 _ => return Err("nth expects an indexed collection".into()),
1489 };
1490 result.ok_or_else(|| "nth index out of bounds".into())
1491}
1492
1493fn collection_assoc(value: &Value, key: &Value, replacement: Value) -> Result<Value, String> {
1494 match value {
1495 Value::Extension(receiver) => extension_protocol_call(
1496 receiver,
1497 "std.protocol.iassoc.IAssoc",
1498 "assoc",
1499 &[value.clone(), key.clone(), replacement],
1500 ),
1501 Value::MutableCollection(collection) => {
1502 let mut borrowed = collection.borrow_mut();
1503 let mutable = borrowed
1504 .as_mut()
1505 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1506 match mutable {
1507 MutableCollection::Map(values) => {
1508 values.assoc(key.clone(), replacement);
1509 }
1510 MutableCollection::OrderedMap(values) => {
1511 values.assoc(key.clone(), replacement);
1512 }
1513 MutableCollection::SortedMap(values) => {
1514 values.assoc(key.clone(), replacement);
1515 }
1516 MutableCollection::Trie(values) => {
1517 values.assoc(marker_key(key, "trie")?, replacement);
1518 }
1519 MutableCollection::Vector(values) => {
1520 values.assoc(value_index(key)?, replacement);
1521 }
1522 MutableCollection::List(values) => {
1523 values
1524 .assoc(value_index(key)?, replacement)
1525 .ok_or_else(|| "assoc index out of bounds".to_string())?;
1526 }
1527 _ => return Err("assoc expects a mutable map, vector, or list".into()),
1528 }
1529 Ok(Value::MutableCollection(collection.clone()))
1530 }
1531 Value::Tuple(values) => {
1532 let index = value_index(key)?;
1533 if index == values.len() {
1534 return tuple_push_last(values, replacement);
1535 }
1536 if index > values.len() {
1537 return Err("assoc index out of bounds".into());
1538 }
1539 let mut items: Vec<Value> = values.iter().cloned().collect();
1540 items[index] = replacement;
1541 Ok(Value::Tuple(Box::new(
1542 PTuple::from_values(items)?.with_meta(values.meta().cloned()),
1543 )))
1544 }
1545 Value::Vector(values) => {
1546 let index = value_index(key)?;
1547 values
1548 .assoc_value(index, replacement)
1549 .map(Value::Vector)
1550 .ok_or_else(|| "assoc index out of bounds".into())
1551 }
1552 Value::Deque(values) => values
1553 .assoc_value(value_index(key)?, replacement)
1554 .map(|values| Value::Deque(Box::new(values)))
1555 .ok_or_else(|| "assoc index out of bounds".to_string()),
1556 value @ (Value::Map(_)
1557 | Value::OrderedMap(_)
1558 | Value::SortedMap(_)
1559 | Value::Trie(_)
1560 | Value::PriorityMap(_)) => map_assoc_value(value, key.clone(), replacement),
1561 Value::Object(entries) => {
1562 let name = marker_key(key, "object")?;
1563 let mut output = entries.borrow().clone();
1564 if let Some((_, item)) = output.iter_mut().find(|(candidate, _)| candidate == &name) {
1565 *item = replacement;
1566 } else {
1567 output.push((name, replacement));
1568 }
1569 Ok(Value::Object(Rc::new(RefCell::new(output))))
1570 }
1571 Value::Struct(value) => {
1572 let name = named_field_name(key).ok_or_else(|| {
1573 "assoc struct field must be an unqualified string, keyword, or symbol".to_string()
1574 })?;
1575 if !value.ty.fields.iter().any(|candidate| candidate == name) {
1576 return Err(format!("unknown struct field: {name}"));
1577 }
1578 Ok(Value::Struct(Rc::new(StructValue {
1579 ty: value.ty.clone(),
1580 values: value.values.assoc_value(named_field_key(name), replacement),
1581 metadata: value.metadata.clone(),
1582 })))
1583 }
1584 Value::Mutable(_) => Err("assoc does not support mutable values".into()),
1585 Value::Nil => Ok(Value::Map(
1586 PMap::new().assoc_value(key.clone(), replacement),
1587 )),
1588 _ => Err("assoc expects a vector, map, object, or struct".into()),
1589 }
1590}
1591
1592fn collection_dissoc(value: &Value, keys: &[Value]) -> Result<Value, String> {
1593 match value {
1594 Value::Extension(_) => keys.iter().try_fold(value.clone(), |current, key| {
1595 let Value::Extension(receiver) = ¤t else {
1596 return collection_dissoc(¤t, std::slice::from_ref(key));
1597 };
1598 extension_protocol_call(
1599 receiver,
1600 "std.protocol.idissoc.IDissoc",
1601 "dissoc",
1602 &[current.clone(), key.clone()],
1603 )
1604 }),
1605 Value::Mutable(_) => Err("dissoc does not support mutable values".into()),
1606 Value::Struct(value) => {
1607 let declared = keys
1608 .iter()
1609 .filter_map(named_field_name)
1610 .any(|name| value.ty.fields.iter().any(|candidate| candidate == name));
1611 if !declared {
1612 return Ok(Value::Struct(value.clone()));
1613 }
1614 let mut values = value.values.with_meta(value.metadata.clone());
1615 for key in keys {
1616 if let Some(name) = named_field_name(key) {
1617 values = values.dissoc_value(&named_field_key(name));
1618 }
1619 }
1620 Ok(Value::OrderedMap(Box::new(values)))
1621 }
1622 Value::MutableCollection(collection) => {
1623 let mut collection_value = collection.borrow_mut();
1624 let mutable = collection_value
1625 .as_mut()
1626 .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1627 for key in keys {
1628 match &mut *mutable {
1629 MutableCollection::Map(values) => {
1630 values.dissoc(key);
1631 }
1632 MutableCollection::OrderedMap(values) => {
1633 values.dissoc(key);
1634 }
1635 MutableCollection::SortedMap(values) => {
1636 values.dissoc(key);
1637 }
1638 MutableCollection::Trie(values) => {
1639 values.dissoc(&marker_key(key, "trie")?);
1640 }
1641 MutableCollection::Set(values) => {
1642 values.dissoc(key);
1643 }
1644 MutableCollection::OrderedSet(values) => {
1645 values.dissoc(key);
1646 }
1647 MutableCollection::SortedSet(values) => {
1648 values.dissoc(key);
1649 }
1650 _ => return Err("dissoc expects a mutable map or set".into()),
1651 }
1652 }
1653 drop(collection_value);
1654 Ok(Value::MutableCollection(collection.clone()))
1655 }
1656 value @ (Value::Map(_)
1657 | Value::OrderedMap(_)
1658 | Value::SortedMap(_)
1659 | Value::Trie(_)
1660 | Value::PriorityMap(_)) => keys
1661 .iter()
1662 .try_fold(value.clone(), |map, key| map_dissoc_value(&map, key)),
1663 value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => keys
1664 .iter()
1665 .try_fold(value.clone(), |set, key| set_dissoc_value(&set, key)),
1666 Value::Nil => Ok(Value::Map(PMap::new())),
1667 _ => Err("dissoc expects a map".into()),
1668 }
1669}
1670
1671fn unique_values(values: Vec<Value>) -> Vec<Value> {
1672 let mut unique = Vec::new();
1673 for value in values {
1674 if !unique.contains(&value) {
1675 unique.push(value);
1676 }
1677 }
1678 unique
1679}