1use crate::compiler::{
2 Context, Expression,
3 expression::{Container, Resolved, Variable},
4 parser::ast::Ident,
5 state::ExternalEnv,
6 state::{TypeInfo, TypeState},
7 type_def::Details,
8};
9use crate::path::{OwnedTargetPath, OwnedValuePath, PathPrefix};
10use crate::value::Value;
11use std::fmt;
12
13#[derive(Clone, PartialEq)]
14pub struct Query {
15 target: Target,
16 path: OwnedValuePath,
17}
18
19impl Query {
20 #[must_use]
24 pub fn new(target: Target, path: OwnedValuePath) -> Self {
25 Query { target, path }
26 }
27
28 #[must_use]
29 pub fn path(&self) -> &OwnedValuePath {
30 &self.path
31 }
32
33 #[must_use]
34 pub fn target(&self) -> &Target {
35 &self.target
36 }
37
38 #[must_use]
39 pub fn is_external(&self) -> bool {
40 matches!(self.target, Target::External(_))
41 }
42
43 #[must_use]
44 pub fn external_path(&self) -> Option<OwnedTargetPath> {
45 match self.target {
46 Target::External(prefix) => Some(OwnedTargetPath {
47 prefix,
48 path: self.path.clone(),
49 }),
50 _ => None,
51 }
52 }
53
54 #[must_use]
55 pub fn as_variable(&self) -> Option<&Variable> {
56 match &self.target {
57 Target::Internal(variable) => Some(variable),
58 _ => None,
59 }
60 }
61
62 #[must_use]
63 pub fn variable_ident(&self) -> Option<&Ident> {
64 match &self.target {
65 Target::Internal(v) => Some(v.ident()),
66 _ => None,
67 }
68 }
69
70 #[must_use]
71 pub fn expression_target(&self) -> Option<&dyn Expression> {
72 match &self.target {
73 Target::FunctionCall(expr) => Some(expr),
74 Target::Container(expr) => Some(expr),
75 _ => None,
76 }
77 }
78
79 pub fn delete_type_def(&self, external: &mut ExternalEnv, compact: bool) {
82 if let Some(target_path) = self.external_path() {
83 match target_path.prefix {
84 PathPrefix::Event => {
85 let mut type_def = external.target().type_def.clone();
86 type_def.remove(&target_path.path, compact);
87 external.update_target(Details {
88 type_def,
89 value: None,
90 });
91 }
92 PathPrefix::Metadata => {
93 let mut kind = external.metadata_kind().clone();
94 kind.remove(&target_path.path, compact);
95 external.update_metadata(kind);
96 }
97 }
98 }
99 }
100}
101
102impl Expression for Query {
103 fn resolve(&self, ctx: &mut Context) -> Resolved {
104 use Target::{Container, External, FunctionCall, Internal};
105
106 let value = match &self.target {
107 External(prefix) => {
108 let path = OwnedTargetPath {
109 prefix: *prefix,
110 path: self.path.clone(),
111 };
112 return Ok(ctx
113 .target()
114 .target_get(&path)
115 .ok()
116 .flatten()
117 .cloned()
118 .unwrap_or(Value::Null));
119 }
120 Internal(variable) => variable.resolve(ctx)?,
121 FunctionCall(call) => call.resolve(ctx)?,
122 Container(container) => container.resolve(ctx)?,
123 };
124
125 Ok(value.get(&self.path).cloned().unwrap_or(Value::Null))
126 }
127
128 fn resolve_constant(&self, state: &TypeState) -> Option<Value> {
129 match self.target {
130 Target::Internal(ref variable) => variable
131 .resolve_constant(state)
132 .and_then(|v| v.get(self.path()).cloned()),
133 _ => None,
134 }
135 }
136
137 fn type_info(&self, state: &TypeState) -> TypeInfo {
138 use Target::{Container, External, FunctionCall, Internal};
139
140 match &self.target {
141 External(prefix) => {
142 let result = state.external.kind(*prefix).at_path(&self.path).into();
143 TypeInfo::new(state, result)
144 }
145 Internal(variable) => {
146 let result = variable.type_def(state).at_path(&self.path);
147 TypeInfo::new(state, result)
148 }
149 FunctionCall(call) => call
150 .type_info(state)
151 .map_result(|result| result.at_path(&self.path)),
152 Container(container) => container
153 .type_info(state)
154 .map_result(|result| result.at_path(&self.path)),
155 }
156 }
157}
158
159impl fmt::Display for Query {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self.target {
162 Target::Internal(_)
163 if !self.path.is_root() && !self.path.segments.first().unwrap().is_index() =>
164 {
165 write!(f, "{}.{}", self.target, self.path)
166 }
167 _ => write!(f, "{}{}", self.target, self.path),
168 }
169 }
170}
171
172impl fmt::Debug for Query {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 write!(f, "Query({:?}, {:?})", self.target, self.path)
175 }
176}
177
178#[derive(Clone, PartialEq)]
179pub enum Target {
180 Internal(Variable),
181 External(PathPrefix),
182 FunctionCall(crate::compiler::expression::FunctionCall),
183 Container(Container),
184}
185
186impl fmt::Display for Target {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 use Target::{Container, External, FunctionCall, Internal};
189
190 match self {
191 Internal(v) => v.fmt(f),
192 External(prefix) => match prefix {
193 PathPrefix::Event => write!(f, "."),
194 PathPrefix::Metadata => write!(f, "%"),
195 },
196 FunctionCall(v) => v.fmt(f),
197 Container(v) => v.fmt(f),
198 }
199 }
200}
201
202impl fmt::Debug for Target {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 use Target::{Container, External, FunctionCall, Internal};
205
206 match self {
207 Internal(v) => write!(f, "Internal({v:?})"),
208 External(prefix) => match prefix {
209 PathPrefix::Event => f.write_str("External(Event)"),
210 PathPrefix::Metadata => f.write_str("External(Metadata)"),
211 },
212 FunctionCall(v) => v.fmt(f),
213 Container(v) => v.fmt(f),
214 }
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 #[test]
223 fn test_type_def() {
224 let query = Query {
225 target: Target::External(PathPrefix::Event),
226 path: OwnedValuePath::root(),
227 };
228
229 let state = TypeState::default();
230 let type_def = query.type_info(&state).result;
231
232 assert!(type_def.is_infallible());
233 assert!(type_def.is_object());
234
235 let object = type_def.as_object().unwrap();
236
237 assert!(object.is_any());
238 }
239}