compose_library/foundations/
array.rs

1use crate::repr::Repr;
2use crate::{HeapRef, Iter, IterValue, Trace};
3use compose_library::diag::StrResult;
4use compose_library::{ArrayIter, Heap, UntypedRef, Value, Vm};
5use compose_macros::{func, scope, ty};
6use ecow::{eco_format, EcoString};
7use std::ops::{Deref, DerefMut};
8
9#[ty(scope, cast, name = "array")]
10#[derive(Debug, Clone, PartialEq)]
11pub struct ArrayValue(HeapRef<Array>);
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct Array {
15    pub(crate) values: Vec<Value>,
16}
17
18impl From<Vec<Value>> for Array {
19    fn from(value: Vec<Value>) -> Self {
20        Self { values: value }
21    }
22}
23
24impl Deref for Array {
25    type Target = Vec<Value>;
26
27    fn deref(&self) -> &Self::Target {
28        &self.values
29    }
30}
31
32impl DerefMut for Array {
33    fn deref_mut(&mut self) -> &mut Self::Target {
34        &mut self.values
35    }
36}
37
38impl Array {
39    pub fn new() -> Self {
40        Self { values: Vec::new() }
41    }
42}
43
44impl Trace for Array {
45    fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
46        for v in &self.values {
47            v.visit_refs(f);
48        }
49    }
50}
51
52impl ArrayValue {
53    pub fn new(heap: &mut Heap) -> Self {
54        Self(heap.alloc(Array::new()))
55    }
56
57    pub fn from(heap: &mut Heap, values: Vec<Value>) -> Self {
58        Self(heap.alloc(Array::from(values)))
59    }
60}
61
62impl Trace for ArrayValue {
63    fn visit_refs(&self, f: &mut dyn FnMut(UntypedRef)) {
64        f(self.0.key());
65    }
66}
67
68impl Repr for ArrayValue {
69    fn repr(&self, vm: &dyn Vm) -> EcoString {
70        let self_ = self.0.try_get(vm.heap()).expect("array value");
71
72        let items = self_.values.iter().map(|v| v.repr(vm)).collect::<Vec<_>>();
73
74        eco_format!("[{}]", items.join(", "))
75    }
76}
77
78impl ArrayValue {
79    pub(crate) fn try_get<'a>(&self, heap: &'a Heap) -> StrResult<&'a Array> {
80        self.0.try_get(heap)
81    }
82}
83
84#[scope]
85impl ArrayValue {
86    #[func]
87    fn len(&self, vm: &dyn Vm) -> StrResult<usize> {
88        Ok(self.0.try_get(vm.heap())?.len())
89    }
90
91    #[func]
92    fn is_empty(&self, vm: &dyn Vm) -> StrResult<bool> {
93        Ok(self.0.try_get(vm.heap())?.is_empty())
94    }
95
96    #[func]
97    fn push(&mut self, vm: &mut dyn Vm, value: Value) -> StrResult<()> {
98        let arr = self.0.try_get_mut(vm.heap_mut())?;
99
100        arr.push(value);
101
102        Ok(())
103    }
104
105    #[func]
106    fn pop(&mut self, vm: &mut dyn Vm) -> StrResult<Option<Value>> {
107        let arr = self.0.try_get_mut(vm.heap_mut())?;
108
109        Ok(arr.pop())
110    }
111
112    #[func]
113    pub fn shallow_clone(&self, vm: &mut dyn Vm) -> Self {
114        let clone = self.0.get_unwrap(vm.heap()).clone();
115
116        Self(vm.heap_mut().alloc(clone))
117    }
118
119    #[func]
120    pub fn iter(&self, vm: &mut dyn Vm) -> StrResult<IterValue> {
121        let arr = self.0.try_get(vm.heap())?;
122
123        let iter = Iter::Array(ArrayIter::new(arr));
124        Ok(IterValue::new(iter, vm))
125    }
126
127    #[func]
128    pub fn contains(&self, vm: &mut dyn Vm, value: Value) -> StrResult<bool> {
129        let arr = self.0.try_get(vm.heap())?;
130        Ok(arr.contains(&value))
131    }
132    
133    #[func]
134    pub fn get(&self, vm: &mut dyn Vm, index: usize) -> StrResult<Option<Value>> {
135        let arr = self.0.try_get(vm.heap())?;
136        Ok(arr.get(index).cloned())
137    }
138}