compose_library/foundations/
array.rs

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