1use std::any::Any;
2use std::str::FromStr;
3use std::sync::Arc;
4
5use vortex_array::{Array, ArrayRef};
6use vortex_dtype::DType;
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 Identifier {
31 pub fn is_identity(&self) -> bool {
32 matches!(self, Self::Identity)
33 }
34}
35
36impl std::fmt::Display for Identifier {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 Identifier::Identity => write!(f, ""),
40 Identifier::Other(v) => write!(f, "{}", v),
41 }
42 }
43}
44
45#[derive(Clone, Default)]
62pub struct Scope {
63 array_len: usize,
64 root_scope: Option<ArrayRef>,
65 arrays: ExprScope<ArrayRef>,
67 vars: ExprScope<Arc<dyn Any + Send + Sync>>,
70}
71
72impl Scope {
73 pub fn new(arr: ArrayRef) -> Self {
74 Self {
75 array_len: arr.len(),
76 root_scope: Some(arr),
77 ..Default::default()
78 }
79 }
80
81 pub fn empty(len: usize) -> Self {
82 Self {
83 array_len: len,
84 ..Default::default()
85 }
86 }
87
88 pub fn array(&self, id: &Identifier) -> Option<&ArrayRef> {
90 if id.is_identity() {
91 return self.root_scope.as_ref();
92 }
93 self.arrays.get(id)
94 }
95
96 pub fn vars(&self, id: Identifier) -> VortexResult<&Arc<dyn Any + Send + Sync>> {
97 self.vars
98 .get(&id)
99 .ok_or_else(|| vortex_err!("cannot find {} in var scope", id))
100 }
101
102 pub fn is_empty(&self) -> bool {
103 self.array_len == 0
104 }
105
106 pub fn len(&self) -> usize {
107 self.array_len
108 }
109
110 pub fn copy_with_value(&self, ident: Identifier, value: ArrayRef) -> Self {
111 self.clone().with_array(ident, value)
112 }
113
114 pub fn with_array(mut self, ident: Identifier, value: ArrayRef) -> Self {
116 assert_eq!(value.len(), self.len());
117
118 if ident.is_identity() {
119 self.root_scope = Some(value);
120 } else {
121 self.arrays.insert(ident, value);
122 }
123 self
124 }
125
126 pub fn with_var(mut self, ident: Identifier, var: Arc<dyn Any + Send + Sync>) -> Self {
127 self.vars.insert(ident, var);
128 self
129 }
130
131 pub fn iter(&self) -> impl Iterator<Item = (&Identifier, &ArrayRef)> {
132 let values = self.arrays.iter();
133
134 self.root_scope
135 .iter()
136 .map(|s| (&Identifier::Identity, s))
137 .chain(values)
138 }
139}
140
141impl From<ArrayRef> for Scope {
142 fn from(value: ArrayRef) -> Self {
143 Self::new(value)
144 }
145}
146
147#[derive(Clone, Default)]
148pub struct ScopeDType {
149 root: Option<DType>,
150 types: ExprScope<DType>,
151}
152
153impl From<&Scope> for ScopeDType {
154 fn from(ctx: &Scope) -> Self {
155 Self {
156 root: ctx.root_scope.as_ref().map(|s| s.dtype().clone()),
157 types: HashMap::from_iter(
158 ctx.arrays
159 .iter()
160 .map(|(k, v)| (k.clone(), v.dtype().clone())),
161 ),
162 }
163 }
164}
165
166impl ScopeDType {
167 pub fn new(dtype: DType) -> Self {
168 Self {
169 root: Some(dtype),
170 ..Default::default()
171 }
172 }
173
174 pub fn dtype(&self, id: &Identifier) -> Option<&DType> {
175 if id.is_identity() {
176 return self.root.as_ref();
177 }
178 self.types.get(id)
179 }
180
181 pub fn copy_with_value(&self, ident: Identifier, dtype: DType) -> Self {
182 self.clone().with_value(ident, dtype)
183 }
184
185 pub fn with_value(mut self, ident: Identifier, dtype: DType) -> Self {
186 if ident.is_identity() {
187 self.root = Some(dtype);
188 } else {
189 self.types.insert(ident, dtype);
190 }
191 self
192 }
193}