1use std::any::Any;
2use std::str::FromStr;
3use std::sync::Arc;
4
5use vortex_array::{Array, ArrayRef};
6use vortex_dtype::{DType, FieldPathSet};
7use vortex_error::{VortexError, VortexResult, vortex_bail, vortex_err};
8use vortex_utils::aliases::hash_map::HashMap;
9
10type ExprScope<T> = HashMap<Identifier, T>;
11
12#[derive(Clone, Debug, Eq, PartialEq, Hash)]
13pub enum Identifier {
14 Identity,
15 Other(Arc<str>),
16}
17
18impl FromStr for Identifier {
19 type Err = VortexError;
20
21 fn from_str(s: &str) -> Result<Self, Self::Err> {
22 if s.is_empty() {
23 vortex_bail!("Empty strings aren't allowed in identifiers")
24 } else {
25 Ok(Identifier::Other(s.into()))
26 }
27 }
28}
29
30impl PartialEq<str> for Identifier {
31 fn eq(&self, other: &str) -> bool {
32 match self {
33 Identifier::Identity => other.is_empty(),
34 Identifier::Other(str) => str.as_ref() == other,
35 }
36 }
37}
38
39impl From<&str> for Identifier {
40 fn from(value: &str) -> Self {
41 if value.is_empty() {
42 Identifier::Identity
43 } else {
44 Identifier::Other(Arc::from(value))
45 }
46 }
47}
48
49impl From<&Arc<str>> for Identifier {
50 fn from(value: &Arc<str>) -> Self {
51 if value.as_ref() == "" {
52 Identifier::Identity
53 } else {
54 Identifier::Other(value.clone())
55 }
56 }
57}
58
59impl Identifier {
60 pub fn is_identity(&self) -> bool {
61 matches!(self, Self::Identity)
62 }
63}
64
65impl std::fmt::Display for Identifier {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 match self {
68 Identifier::Identity => write!(f, ""),
69 Identifier::Other(v) => write!(f, "{}", v),
70 }
71 }
72}
73
74#[derive(Clone, Default)]
91pub struct Scope {
92 array_len: usize,
93 root_scope: Option<ArrayRef>,
94 arrays: ExprScope<ArrayRef>,
96 vars: ExprScope<Arc<dyn Any + Send + Sync>>,
99}
100
101impl Scope {
102 pub fn new(arr: ArrayRef) -> Self {
103 Self {
104 array_len: arr.len(),
105 root_scope: Some(arr),
106 ..Default::default()
107 }
108 }
109
110 pub fn empty(len: usize) -> Self {
111 Self {
112 array_len: len,
113 ..Default::default()
114 }
115 }
116
117 pub fn array(&self, id: &Identifier) -> Option<&ArrayRef> {
119 if id.is_identity() {
120 return self.root_scope.as_ref();
121 }
122 self.arrays.get(id)
123 }
124
125 pub fn vars(&self, id: Identifier) -> VortexResult<&Arc<dyn Any + Send + Sync>> {
126 self.vars
127 .get(&id)
128 .ok_or_else(|| vortex_err!("cannot find {} in var scope", id))
129 }
130
131 pub fn is_empty(&self) -> bool {
132 self.array_len == 0
133 }
134
135 pub fn len(&self) -> usize {
136 self.array_len
137 }
138
139 pub fn copy_with_array(&self, ident: Identifier, value: ArrayRef) -> Self {
140 self.clone().with_array(ident, value)
141 }
142
143 pub fn with_array(mut self, ident: Identifier, value: ArrayRef) -> Self {
145 assert_eq!(value.len(), self.len());
146
147 if ident.is_identity() {
148 self.root_scope = Some(value);
149 } else {
150 self.arrays.insert(ident, value);
151 }
152 self
153 }
154
155 pub fn with_var(mut self, ident: Identifier, var: Arc<dyn Any + Send + Sync>) -> Self {
156 self.vars.insert(ident, var);
157 self
158 }
159
160 pub fn iter(&self) -> impl Iterator<Item = (&Identifier, &ArrayRef)> {
161 let values = self.arrays.iter();
162
163 self.root_scope
164 .iter()
165 .map(|s| (&Identifier::Identity, s))
166 .chain(values)
167 }
168}
169
170impl From<ArrayRef> for Scope {
171 fn from(value: ArrayRef) -> Self {
172 Self::new(value)
173 }
174}
175
176#[derive(Clone, Default, Debug)]
177pub struct ScopeDType {
178 root: Option<DType>,
179 types: ExprScope<DType>,
180}
181
182impl From<&Scope> for ScopeDType {
183 fn from(ctx: &Scope) -> Self {
184 Self {
185 root: ctx.root_scope.as_ref().map(|s| s.dtype().clone()),
186 types: HashMap::from_iter(
187 ctx.arrays
188 .iter()
189 .map(|(k, v)| (k.clone(), v.dtype().clone())),
190 ),
191 }
192 }
193}
194
195impl ScopeDType {
196 pub fn new(dtype: DType) -> Self {
197 Self {
198 root: Some(dtype),
199 ..Default::default()
200 }
201 }
202
203 pub fn dtype(&self, id: &Identifier) -> Option<&DType> {
204 if id.is_identity() {
205 return self.root.as_ref();
206 }
207 self.types.get(id)
208 }
209
210 pub fn copy_with_dtype(&self, ident: Identifier, dtype: DType) -> Self {
211 self.clone().with_dtype(ident, dtype)
212 }
213
214 pub fn with_dtype(mut self, ident: Identifier, dtype: DType) -> Self {
215 if ident.is_identity() {
216 self.root = Some(dtype);
217 } else {
218 self.types.insert(ident, dtype);
219 }
220 self
221 }
222}
223
224#[derive(Default, Clone, Debug)]
225pub struct ScopeFieldPathSet {
226 root: Option<FieldPathSet>,
227 sets: ExprScope<FieldPathSet>,
228}
229
230impl ScopeFieldPathSet {
231 pub fn new(path_set: FieldPathSet) -> Self {
232 Self {
233 root: Some(path_set),
234 ..Default::default()
235 }
236 }
237
238 pub fn set(&self, id: &Identifier) -> Option<&FieldPathSet> {
239 if id.is_identity() {
240 return self.root.as_ref();
241 }
242 self.sets.get(id)
243 }
244
245 pub fn copy_with_set(&self, ident: Identifier, set: FieldPathSet) -> Self {
246 self.clone().with_set(ident, set)
247 }
248
249 pub fn with_set(mut self, ident: Identifier, set: FieldPathSet) -> Self {
250 if ident.is_identity() {
251 self.root = Some(set);
252 } else {
253 self.sets.insert(ident, set);
254 }
255 self
256 }
257}