compose_library/foundations/
array.rs1use 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}