1use shape_wire::metadata::{FieldInfo, TypeInfo, TypeKind};
12use std::fmt;
13use std::hash::Hash;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct TypeVarId(pub u32);
18
19#[derive(Clone, Debug, PartialEq, Eq, Hash)]
21pub enum SemanticType {
22 Number,
25 Integer,
27 Bool,
29 String,
31
32 Option(Box<SemanticType>),
37
38 Result {
41 ok_type: Box<SemanticType>,
42 err_type: Option<Box<SemanticType>>,
43 },
44
45 Array(Box<SemanticType>),
47
48 Struct {
51 name: String,
52 fields: Vec<(String, SemanticType)>,
53 },
54
55 Enum {
57 name: String,
58 variants: Vec<EnumVariant>,
59 type_params: Vec<String>,
60 },
61
62 Interface {
64 name: String,
65 methods: Vec<(String, FunctionSignature)>,
66 },
67
68 TypeVar(TypeVarId),
71
72 Named(String),
74
75 Generic {
77 name: String,
78 args: Vec<SemanticType>,
79 },
80
81 Never,
84
85 Any,
87
88 Void,
90
91 Function(Box<FunctionSignature>),
93}
94
95#[derive(Clone, Debug, PartialEq, Eq, Hash)]
97pub struct FunctionSignature {
98 pub params: Vec<FunctionParam>,
99 pub return_type: SemanticType,
100 pub is_fallible: bool, }
102
103#[derive(Clone, Debug, PartialEq, Eq, Hash)]
105pub struct FunctionParam {
106 pub name: Option<String>,
107 pub param_type: SemanticType,
108 pub optional: bool,
109}
110
111#[derive(Clone, Debug, PartialEq, Eq, Hash)]
113pub struct EnumVariant {
114 pub name: String,
115 pub payload: Option<SemanticType>,
116}
117
118impl SemanticType {
119 pub fn option(inner: SemanticType) -> Self {
123 SemanticType::Option(Box::new(inner))
124 }
125
126 pub fn result(ok_type: SemanticType) -> Self {
128 SemanticType::Result {
129 ok_type: Box::new(ok_type),
130 err_type: None,
131 }
132 }
133
134 pub fn result_with_error(ok_type: SemanticType, err_type: SemanticType) -> Self {
136 SemanticType::Result {
137 ok_type: Box::new(ok_type),
138 err_type: Some(Box::new(err_type)),
139 }
140 }
141
142 pub fn array(element: SemanticType) -> Self {
144 SemanticType::Array(Box::new(element))
145 }
146
147 pub fn function(params: Vec<SemanticType>, return_type: SemanticType) -> Self {
149 SemanticType::Function(Box::new(FunctionSignature {
150 params: params
151 .into_iter()
152 .map(|t| FunctionParam {
153 name: None,
154 param_type: t,
155 optional: false,
156 })
157 .collect(),
158 return_type,
159 is_fallible: false,
160 }))
161 }
162
163 pub fn is_numeric(&self) -> bool {
167 self.is_number_family() || self.is_integer_family()
168 }
169
170 pub fn is_integer_family(&self) -> bool {
172 match self {
173 SemanticType::Integer => true,
174 SemanticType::Named(name) => matches!(
175 name.as_str(),
176 "i8" | "u8" | "i16" | "u16" | "i32" | "i64" | "u32" | "u64" | "isize" | "usize"
177 ),
178 _ => false,
179 }
180 }
181
182 pub fn is_number_family(&self) -> bool {
184 match self {
185 SemanticType::Number => true,
186 SemanticType::Named(name) => matches!(name.as_str(), "f32" | "f64"),
187 _ => false,
188 }
189 }
190
191 pub fn is_option(&self) -> bool {
193 matches!(self, SemanticType::Option(_))
194 }
195
196 pub fn is_result(&self) -> bool {
198 matches!(self, SemanticType::Result { .. })
199 }
200
201 pub fn option_inner(&self) -> Option<&SemanticType> {
203 match self {
204 SemanticType::Option(inner) => Some(inner),
205 _ => None,
206 }
207 }
208
209 pub fn result_ok_type(&self) -> Option<&SemanticType> {
211 match self {
212 SemanticType::Result { ok_type, .. } => Some(ok_type),
213 _ => None,
214 }
215 }
216
217 pub fn has_type_vars(&self) -> bool {
219 match self {
220 SemanticType::TypeVar(_) => true,
221 SemanticType::Option(inner) => inner.has_type_vars(),
222 SemanticType::Result { ok_type, err_type } => {
223 ok_type.has_type_vars() || err_type.as_ref().is_some_and(|e| e.has_type_vars())
224 }
225 SemanticType::Array(elem) => elem.has_type_vars(),
226 SemanticType::Struct { fields, .. } => fields.iter().any(|(_, t)| t.has_type_vars()),
227 SemanticType::Enum { variants, .. } => variants
228 .iter()
229 .any(|v| v.payload.as_ref().is_some_and(|t| t.has_type_vars())),
230 SemanticType::Function(sig) => {
231 sig.params.iter().any(|p| p.param_type.has_type_vars())
232 || sig.return_type.has_type_vars()
233 }
234 SemanticType::Generic { args, .. } => args.iter().any(|a| a.has_type_vars()),
235 _ => false,
236 }
237 }
238
239 pub fn to_type_info(&self) -> TypeInfo {
246 match self {
247 SemanticType::Number => TypeInfo::number(),
248 SemanticType::Integer => TypeInfo::integer(),
249 SemanticType::Bool => TypeInfo::bool(),
250 SemanticType::String => TypeInfo::string(),
251
252 SemanticType::Option(inner) => {
253 let inner_info = inner.to_type_info();
254 TypeInfo {
255 name: format!("Option<{}>", inner_info.name),
256 kind: TypeKind::Optional,
257 fields: None,
258 generic_params: Some(vec![inner_info]),
259 variants: None,
260 description: None,
261 metadata: None,
262 }
263 }
264
265 SemanticType::Result { ok_type, err_type } => {
266 let ok_info = ok_type.to_type_info();
267 let name = match err_type {
268 Some(e) => format!("Result<{}, {}>", ok_info.name, e.to_type_info().name),
269 None => format!("Result<{}>", ok_info.name),
270 };
271 let mut params = vec![ok_info];
272 if let Some(e) = err_type {
273 params.push(e.to_type_info());
274 }
275 TypeInfo {
276 name,
277 kind: TypeKind::Result,
278 fields: None,
279 generic_params: Some(params),
280 variants: None,
281 description: None,
282 metadata: None,
283 }
284 }
285
286 SemanticType::Array(elem) => TypeInfo::array(elem.to_type_info()),
287
288 SemanticType::Struct { name, fields } => {
289 let field_infos: Vec<FieldInfo> = fields
290 .iter()
291 .map(|(fname, ftype)| FieldInfo::required(fname, ftype.to_type_info()))
292 .collect();
293 TypeInfo::object(name, field_infos)
294 }
295
296 SemanticType::Enum { name, variants, .. } => {
297 let variant_names: Vec<String> = variants.iter().map(|v| v.name.clone()).collect();
298 TypeInfo {
299 name: name.clone(),
300 kind: TypeKind::Enum,
301 fields: None,
302 generic_params: None,
303 variants: Some(variant_names),
304 description: None,
305 metadata: None,
306 }
307 }
308
309 SemanticType::Interface { name, .. } => TypeInfo::primitive(name),
310
311 SemanticType::TypeVar(id) => TypeInfo::primitive(format!("T{}", id.0)),
312
313 SemanticType::Named(name) => TypeInfo::primitive(name),
314
315 SemanticType::Generic { name, args } => {
316 let arg_infos: Vec<TypeInfo> = args.iter().map(|a| a.to_type_info()).collect();
317 let arg_names: Vec<String> = arg_infos.iter().map(|a| a.name.clone()).collect();
318 TypeInfo {
319 name: format!("{}<{}>", name, arg_names.join(", ")),
320 kind: TypeKind::Object, fields: None,
322 generic_params: Some(arg_infos),
323 variants: None,
324 description: None,
325 metadata: None,
326 }
327 }
328
329 SemanticType::Never => TypeInfo::primitive("Never"),
330 SemanticType::Any => TypeInfo::primitive("Any"),
331 SemanticType::Void => TypeInfo::null(),
332
333 SemanticType::Function(sig) => {
334 let param_types: Vec<String> = sig
335 .params
336 .iter()
337 .map(|p| p.param_type.to_type_info().name)
338 .collect();
339 let ret_type = sig.return_type.to_type_info().name;
340 TypeInfo {
341 name: format!("({}) -> {}", param_types.join(", "), ret_type),
342 kind: TypeKind::Function,
343 fields: None,
344 generic_params: None,
345 variants: None,
346 description: None,
347 metadata: None,
348 }
349 }
350 }
351 }
352}
353
354impl fmt::Display for SemanticType {
355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 match self {
357 SemanticType::Number => write!(f, "Number"),
358 SemanticType::Integer => write!(f, "Integer"),
359 SemanticType::Bool => write!(f, "Bool"),
360 SemanticType::String => write!(f, "String"),
361 SemanticType::Option(inner) => write!(f, "Option<{}>", inner),
362 SemanticType::Result { ok_type, err_type } => match err_type {
363 Some(e) => write!(f, "Result<{}, {}>", ok_type, e),
364 None => write!(f, "Result<{}>", ok_type),
365 },
366 SemanticType::Array(elem) => write!(f, "Vec<{}>", elem),
367 SemanticType::Struct { name, .. } => write!(f, "{}", name),
368 SemanticType::Enum { name, .. } => write!(f, "{}", name),
369 SemanticType::Interface { name, .. } => write!(f, "{}", name),
370 SemanticType::TypeVar(id) => write!(f, "T{}", id.0),
371 SemanticType::Named(name) => write!(f, "{}", name),
372 SemanticType::Generic { name, args } => {
373 write!(f, "{}<", name)?;
374 for (i, arg) in args.iter().enumerate() {
375 if i > 0 {
376 write!(f, ", ")?;
377 }
378 write!(f, "{}", arg)?;
379 }
380 write!(f, ">")
381 }
382 SemanticType::Never => write!(f, "Never"),
383 SemanticType::Any => write!(f, "Any"),
384 SemanticType::Void => write!(f, "Void"),
385 SemanticType::Function(sig) => {
386 write!(f, "(")?;
387 for (i, param) in sig.params.iter().enumerate() {
388 if i > 0 {
389 write!(f, ", ")?;
390 }
391 write!(f, "{}", param.param_type)?;
392 }
393 write!(f, ") -> {}", sig.return_type)
394 }
395 }
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use super::*;
402
403 #[test]
404 fn test_option_creation() {
405 let opt = SemanticType::option(SemanticType::Number);
406 assert!(opt.is_option());
407 assert_eq!(opt.option_inner(), Some(&SemanticType::Number));
408 }
409
410 #[test]
411 fn test_result_creation() {
412 let res = SemanticType::result(SemanticType::Number);
413 assert!(res.is_result());
414 match &res {
415 SemanticType::Result { ok_type, err_type } => {
416 assert_eq!(**ok_type, SemanticType::Number);
417 assert!(err_type.is_none());
418 }
419 _ => panic!("Expected Result"),
420 }
421 }
422
423 #[test]
424 fn test_display() {
425 assert_eq!(format!("{}", SemanticType::Number), "Number");
426 assert_eq!(
427 format!("{}", SemanticType::option(SemanticType::Number)),
428 "Option<Number>"
429 );
430 assert_eq!(
431 format!("{}", SemanticType::result(SemanticType::String)),
432 "Result<String>"
433 );
434 }
435
436 #[test]
437 fn test_to_type_info_primitives() {
438 let num = SemanticType::Number.to_type_info();
439 assert_eq!(num.name, "Number");
440 assert_eq!(num.kind, TypeKind::Primitive);
441
442 let int = SemanticType::Integer.to_type_info();
443 assert_eq!(int.name, "Integer");
444
445 let bool_t = SemanticType::Bool.to_type_info();
446 assert_eq!(bool_t.name, "Bool");
447
448 let string_t = SemanticType::String.to_type_info();
449 assert_eq!(string_t.name, "String");
450 }
451
452 #[test]
453 fn test_to_type_info_option() {
454 let opt = SemanticType::option(SemanticType::Number).to_type_info();
455 assert_eq!(opt.name, "Option<Number>");
456 assert_eq!(opt.kind, TypeKind::Optional);
457 assert!(opt.generic_params.is_some());
458 assert_eq!(opt.generic_params.as_ref().unwrap().len(), 1);
459 }
460
461 #[test]
462 fn test_to_type_info_result() {
463 let res = SemanticType::result(SemanticType::String).to_type_info();
464 assert_eq!(res.name, "Result<String>");
465 assert_eq!(res.kind, TypeKind::Result);
466
467 let res_with_err =
468 SemanticType::result_with_error(SemanticType::Number, SemanticType::String)
469 .to_type_info();
470 assert_eq!(res_with_err.name, "Result<Number, String>");
471 }
472
473 #[test]
474 fn test_to_type_info_array() {
475 let arr = SemanticType::array(SemanticType::Bool).to_type_info();
476 assert_eq!(arr.name, "Array<Bool>");
477 assert_eq!(arr.kind, TypeKind::Array);
478 }
479
480 #[test]
481 fn test_named_width_numeric_families() {
482 assert!(SemanticType::Named("i16".to_string()).is_numeric());
483 assert!(SemanticType::Named("u64".to_string()).is_integer_family());
484 assert!(SemanticType::Named("f32".to_string()).is_number_family());
485 assert!(SemanticType::Named("f64".to_string()).is_numeric());
486 assert!(!SemanticType::Named("Candle".to_string()).is_numeric());
487 }
488}