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 ExternalSignature,
115
116 String,
118
119 Table(Vec<(String, SyntaxShape)>),
121
122 VarWithOptType,
124}
125
126impl SyntaxShape {
127 pub fn to_type(&self) -> Type {
138 let mk_ty = |tys: &[(String, SyntaxShape)]| {
139 tys.iter()
140 .map(|(key, val)| (key.clone(), val.to_type()))
141 .collect()
142 };
143
144 match self {
145 SyntaxShape::Any => Type::Any,
146 SyntaxShape::Block => Type::Block,
147 SyntaxShape::Closure(_) => Type::Closure,
148 SyntaxShape::Binary => Type::Binary,
149 SyntaxShape::CellPath => Type::CellPath,
150 SyntaxShape::DateTime => Type::Date,
151 SyntaxShape::Duration => Type::Duration,
152 SyntaxShape::Expression => Type::Any,
153 SyntaxShape::ExternalArgument => Type::Any,
154 SyntaxShape::Filepath => Type::String,
155 SyntaxShape::Directory => Type::String,
156 SyntaxShape::Float => Type::Float,
157 SyntaxShape::Filesize => Type::Filesize,
158 SyntaxShape::FullCellPath => Type::Any,
159 SyntaxShape::GlobPattern => Type::Glob,
160 SyntaxShape::Error => Type::Error,
161 SyntaxShape::ImportPattern => Type::Any,
162 SyntaxShape::Int => Type::Int,
163 SyntaxShape::List(x) => {
164 let contents = x.to_type();
165 Type::List(Box::new(contents))
166 }
167 SyntaxShape::Keyword(_, expr) => expr.to_type(),
168 SyntaxShape::MatchBlock => Type::Any,
169 SyntaxShape::MathExpression => Type::Any,
170 SyntaxShape::Nothing => Type::Nothing,
171 SyntaxShape::Number => Type::Number,
172 SyntaxShape::OneOf(types) => Type::one_of(types.iter().map(SyntaxShape::to_type)),
173 SyntaxShape::Operator => Type::Any,
174 SyntaxShape::Range => Type::Range,
175 SyntaxShape::Record(entries) => Type::Record(mk_ty(entries)),
176 SyntaxShape::RowCondition => Type::Bool,
177 SyntaxShape::Boolean => Type::Bool,
178 SyntaxShape::Signature | SyntaxShape::ExternalSignature => Type::Any,
179 SyntaxShape::String => Type::String,
180 SyntaxShape::Table(columns) => Type::Table(mk_ty(columns)),
181 SyntaxShape::VarWithOptType => Type::Any,
182 }
183 }
184}
185
186impl Display for SyntaxShape {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 let mk_fmt = |tys: &[(String, SyntaxShape)]| -> String {
189 tys.iter()
190 .map(|(x, y)| format!("{x}: {y}"))
191 .collect::<Vec<String>>()
192 .join(", ")
193 };
194
195 match self {
196 SyntaxShape::Keyword(kw, shape) => {
197 write!(f, "\"{}\" {}", String::from_utf8_lossy(kw), shape)
198 }
199 SyntaxShape::Any => write!(f, "any"),
200 SyntaxShape::String => write!(f, "string"),
201 SyntaxShape::CellPath => write!(f, "cell-path"),
202 SyntaxShape::FullCellPath => write!(f, "cell-path"),
203 SyntaxShape::Number => write!(f, "number"),
204 SyntaxShape::Range => write!(f, "range"),
205 SyntaxShape::Int => write!(f, "int"),
206 SyntaxShape::Float => write!(f, "float"),
207 SyntaxShape::Filepath => write!(f, "path"),
208 SyntaxShape::Directory => write!(f, "directory"),
209 SyntaxShape::GlobPattern => write!(f, "glob"),
210 SyntaxShape::ImportPattern => write!(f, "import"),
211 SyntaxShape::Block => write!(f, "block"),
212 SyntaxShape::Closure(args) => {
213 if let Some(args) = args {
214 let arg_vec: Vec<_> = args.iter().map(|x| x.to_string()).collect();
215 let arg_string = arg_vec.join(", ");
216 write!(f, "closure({arg_string})")
217 } else {
218 write!(f, "closure()")
219 }
220 }
221 SyntaxShape::Binary => write!(f, "binary"),
222 SyntaxShape::List(x) => write!(f, "list<{x}>"),
223 SyntaxShape::Table(columns) => {
224 if columns.is_empty() {
225 write!(f, "table")
226 } else {
227 write!(f, "table<{}>", mk_fmt(columns))
228 }
229 }
230 SyntaxShape::Record(entries) => {
231 if entries.is_empty() {
232 write!(f, "record")
233 } else {
234 write!(f, "record<{}>", mk_fmt(entries))
235 }
236 }
237 SyntaxShape::Filesize => write!(f, "filesize"),
238 SyntaxShape::Duration => write!(f, "duration"),
239 SyntaxShape::DateTime => write!(f, "datetime"),
240 SyntaxShape::Operator => write!(f, "operator"),
241 SyntaxShape::RowCondition => write!(
242 f,
243 "oneof<condition, {}>",
244 SyntaxShape::Closure(Some(vec![SyntaxShape::Any]))
245 ),
246 SyntaxShape::MathExpression => write!(f, "variable"),
247 SyntaxShape::VarWithOptType => write!(f, "vardecl"),
248 SyntaxShape::Signature => write!(f, "signature"),
249 SyntaxShape::ExternalSignature => write!(f, "external-signature"),
250 SyntaxShape::MatchBlock => write!(f, "match-block"),
251 SyntaxShape::Expression => write!(f, "expression"),
252 SyntaxShape::ExternalArgument => write!(f, "external-argument"),
253 SyntaxShape::Boolean => write!(f, "bool"),
254 SyntaxShape::Error => write!(f, "error"),
255 SyntaxShape::OneOf(list) => {
256 write!(f, "oneof")?;
257 let [first, rest @ ..] = &**list else {
258 return Ok(());
259 };
260 write!(f, "<{first}")?;
261 for t in rest {
262 write!(f, ", {t}")?;
263 }
264 f.write_str(">")
265 }
266 SyntaxShape::Nothing => write!(f, "nothing"),
267 }
268 }
269}