1use crate::Type;
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub enum SyntaxShape {
14 Any,
16
17 Binary,
19
20 Block,
22
23 Boolean,
25
26 CellPath,
28
29 Closure(Option<Vec<SyntaxShape>>),
31
32 DateTime,
34
35 Directory,
37
38 Duration,
40
41 Error,
43
44 Expression,
46
47 ExternalArgument,
52
53 Filepath,
55
56 Filesize,
58
59 Float,
61
62 FullCellPath,
66
67 GlobPattern,
69
70 Int,
72
73 ImportPattern,
75
76 Keyword(Vec<u8>, Box<SyntaxShape>),
78
79 List(Box<SyntaxShape>),
81
82 MathExpression,
84
85 MatchBlock,
87
88 Nothing,
90
91 Number,
93
94 OneOf(Vec<SyntaxShape>),
96
97 Operator,
99
100 Range,
102
103 Record(Vec<(String, SyntaxShape)>),
105
106 RowCondition,
109
110 Signature,
112
113 String,
115
116 Table(Vec<(String, SyntaxShape)>),
118
119 VarWithOptType,
121}
122
123impl SyntaxShape {
124 pub fn to_type(&self) -> Type {
135 let mk_ty = |tys: &[(String, SyntaxShape)]| {
136 tys.iter()
137 .map(|(key, val)| (key.clone(), val.to_type()))
138 .collect()
139 };
140
141 match self {
142 SyntaxShape::Any => Type::Any,
143 SyntaxShape::Block => Type::Block,
144 SyntaxShape::Closure(_) => Type::Closure,
145 SyntaxShape::Binary => Type::Binary,
146 SyntaxShape::CellPath => Type::Any,
147 SyntaxShape::DateTime => Type::Date,
148 SyntaxShape::Duration => Type::Duration,
149 SyntaxShape::Expression => Type::Any,
150 SyntaxShape::ExternalArgument => Type::Any,
151 SyntaxShape::Filepath => Type::String,
152 SyntaxShape::Directory => Type::String,
153 SyntaxShape::Float => Type::Float,
154 SyntaxShape::Filesize => Type::Filesize,
155 SyntaxShape::FullCellPath => Type::Any,
156 SyntaxShape::GlobPattern => Type::Glob,
157 SyntaxShape::Error => Type::Error,
158 SyntaxShape::ImportPattern => Type::Any,
159 SyntaxShape::Int => Type::Int,
160 SyntaxShape::List(x) => {
161 let contents = x.to_type();
162 Type::List(Box::new(contents))
163 }
164 SyntaxShape::Keyword(_, expr) => expr.to_type(),
165 SyntaxShape::MatchBlock => Type::Any,
166 SyntaxShape::MathExpression => Type::Any,
167 SyntaxShape::Nothing => Type::Nothing,
168 SyntaxShape::Number => Type::Number,
169 SyntaxShape::OneOf(_) => Type::Any,
170 SyntaxShape::Operator => Type::Any,
171 SyntaxShape::Range => Type::Range,
172 SyntaxShape::Record(entries) => Type::Record(mk_ty(entries)),
173 SyntaxShape::RowCondition => Type::Bool,
174 SyntaxShape::Boolean => Type::Bool,
175 SyntaxShape::Signature => Type::Any,
176 SyntaxShape::String => Type::String,
177 SyntaxShape::Table(columns) => Type::Table(mk_ty(columns)),
178 SyntaxShape::VarWithOptType => Type::Any,
179 }
180 }
181}
182
183impl Display for SyntaxShape {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185 let mk_fmt = |tys: &[(String, SyntaxShape)]| -> String {
186 tys.iter()
187 .map(|(x, y)| format!("{x}: {y}"))
188 .collect::<Vec<String>>()
189 .join(", ")
190 };
191
192 match self {
193 SyntaxShape::Keyword(kw, shape) => {
194 write!(f, "\"{}\" {}", String::from_utf8_lossy(kw), shape)
195 }
196 SyntaxShape::Any => write!(f, "any"),
197 SyntaxShape::String => write!(f, "string"),
198 SyntaxShape::CellPath => write!(f, "cell-path"),
199 SyntaxShape::FullCellPath => write!(f, "cell-path"),
200 SyntaxShape::Number => write!(f, "number"),
201 SyntaxShape::Range => write!(f, "range"),
202 SyntaxShape::Int => write!(f, "int"),
203 SyntaxShape::Float => write!(f, "float"),
204 SyntaxShape::Filepath => write!(f, "path"),
205 SyntaxShape::Directory => write!(f, "directory"),
206 SyntaxShape::GlobPattern => write!(f, "glob"),
207 SyntaxShape::ImportPattern => write!(f, "import"),
208 SyntaxShape::Block => write!(f, "block"),
209 SyntaxShape::Closure(args) => {
210 if let Some(args) = args {
211 let arg_vec: Vec<_> = args.iter().map(|x| x.to_string()).collect();
212 let arg_string = arg_vec.join(", ");
213 write!(f, "closure({arg_string})")
214 } else {
215 write!(f, "closure()")
216 }
217 }
218 SyntaxShape::Binary => write!(f, "binary"),
219 SyntaxShape::List(x) => write!(f, "list<{x}>"),
220 SyntaxShape::Table(columns) => {
221 if columns.is_empty() {
222 write!(f, "table")
223 } else {
224 write!(f, "table<{}>", mk_fmt(columns))
225 }
226 }
227 SyntaxShape::Record(entries) => {
228 if entries.is_empty() {
229 write!(f, "record")
230 } else {
231 write!(f, "record<{}>", mk_fmt(entries))
232 }
233 }
234 SyntaxShape::Filesize => write!(f, "filesize"),
235 SyntaxShape::Duration => write!(f, "duration"),
236 SyntaxShape::DateTime => write!(f, "datetime"),
237 SyntaxShape::Operator => write!(f, "operator"),
238 SyntaxShape::RowCondition => write!(
239 f,
240 "oneof<condition, {}>",
241 SyntaxShape::Closure(Some(vec![SyntaxShape::Any]))
242 ),
243 SyntaxShape::MathExpression => write!(f, "variable"),
244 SyntaxShape::VarWithOptType => write!(f, "vardecl"),
245 SyntaxShape::Signature => write!(f, "signature"),
246 SyntaxShape::MatchBlock => write!(f, "match-block"),
247 SyntaxShape::Expression => write!(f, "expression"),
248 SyntaxShape::ExternalArgument => write!(f, "external-argument"),
249 SyntaxShape::Boolean => write!(f, "bool"),
250 SyntaxShape::Error => write!(f, "error"),
251 SyntaxShape::OneOf(list) => {
252 write!(f, "oneof<")?;
253 if let Some((last, rest)) = list.split_last() {
254 for ty in rest {
255 write!(f, "{ty}, ")?;
256 }
257 write!(f, "{last}")?;
258 }
259 write!(f, ">")
260 }
261 SyntaxShape::Nothing => write!(f, "nothing"),
262 }
263 }
264}