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