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 Ref(Box<SemanticType>),
84 RefMut(Box<SemanticType>),
86
87 Never,
90
91 Void,
93
94 Function(Box<FunctionSignature>),
96}
97
98#[derive(Clone, Debug, PartialEq, Eq, Hash)]
100pub struct FunctionSignature {
101 pub params: Vec<FunctionParam>,
102 pub return_type: SemanticType,
103 pub is_fallible: bool, }
105
106#[derive(Clone, Debug, PartialEq, Eq, Hash)]
108pub struct FunctionParam {
109 pub name: Option<String>,
110 pub param_type: SemanticType,
111 pub optional: bool,
112}
113
114#[derive(Clone, Debug, PartialEq, Eq, Hash)]
116pub struct EnumVariant {
117 pub name: String,
118 pub payload: Option<SemanticType>,
119}
120
121impl SemanticType {
122 pub fn option(inner: SemanticType) -> Self {
126 SemanticType::Option(Box::new(inner))
127 }
128
129 pub fn result(ok_type: SemanticType) -> Self {
131 SemanticType::Result {
132 ok_type: Box::new(ok_type),
133 err_type: None,
134 }
135 }
136
137 pub fn result_with_error(ok_type: SemanticType, err_type: SemanticType) -> Self {
139 SemanticType::Result {
140 ok_type: Box::new(ok_type),
141 err_type: Some(Box::new(err_type)),
142 }
143 }
144
145 pub fn array(element: SemanticType) -> Self {
147 SemanticType::Array(Box::new(element))
148 }
149
150 pub fn shared_ref(inner: SemanticType) -> Self {
152 SemanticType::Ref(Box::new(inner))
153 }
154
155 pub fn exclusive_ref(inner: SemanticType) -> Self {
157 SemanticType::RefMut(Box::new(inner))
158 }
159
160 pub fn function(params: Vec<SemanticType>, return_type: SemanticType) -> Self {
162 SemanticType::Function(Box::new(FunctionSignature {
163 params: params
164 .into_iter()
165 .map(|t| FunctionParam {
166 name: None,
167 param_type: t,
168 optional: false,
169 })
170 .collect(),
171 return_type,
172 is_fallible: false,
173 }))
174 }
175
176 pub fn is_numeric(&self) -> bool {
180 self.is_number_family() || self.is_integer_family()
181 }
182
183 pub fn is_integer_family(&self) -> bool {
185 match self {
186 SemanticType::Integer => true,
187 SemanticType::Named(name) => matches!(
188 name.as_str(),
189 "i8" | "u8" | "i16" | "u16" | "i32" | "i64" | "u32" | "u64" | "isize" | "usize"
190 ),
191 _ => false,
192 }
193 }
194
195 pub fn is_number_family(&self) -> bool {
197 match self {
198 SemanticType::Number => true,
199 SemanticType::Named(name) => matches!(name.as_str(), "f32" | "f64"),
200 _ => false,
201 }
202 }
203
204 pub fn is_reference(&self) -> bool {
206 matches!(self, SemanticType::Ref(_) | SemanticType::RefMut(_))
207 }
208
209 pub fn is_exclusive_ref(&self) -> bool {
211 matches!(self, SemanticType::RefMut(_))
212 }
213
214 pub fn deref_type(&self) -> Option<&SemanticType> {
216 match self {
217 SemanticType::Ref(inner) | SemanticType::RefMut(inner) => Some(inner),
218 _ => None,
219 }
220 }
221
222 pub fn auto_deref(&self) -> &SemanticType {
225 match self {
226 SemanticType::Ref(inner) | SemanticType::RefMut(inner) => inner.auto_deref(),
227 other => other,
228 }
229 }
230
231 pub fn is_option(&self) -> bool {
233 matches!(self, SemanticType::Option(_))
234 }
235
236 pub fn is_result(&self) -> bool {
238 matches!(self, SemanticType::Result { .. })
239 }
240
241 pub fn option_inner(&self) -> Option<&SemanticType> {
243 match self {
244 SemanticType::Option(inner) => Some(inner),
245 _ => None,
246 }
247 }
248
249 pub fn result_ok_type(&self) -> Option<&SemanticType> {
251 match self {
252 SemanticType::Result { ok_type, .. } => Some(ok_type),
253 _ => None,
254 }
255 }
256
257 pub fn has_type_vars(&self) -> bool {
259 match self {
260 SemanticType::TypeVar(_) => true,
261 SemanticType::Option(inner) => inner.has_type_vars(),
262 SemanticType::Result { ok_type, err_type } => {
263 ok_type.has_type_vars() || err_type.as_ref().is_some_and(|e| e.has_type_vars())
264 }
265 SemanticType::Array(elem) => elem.has_type_vars(),
266 SemanticType::Struct { fields, .. } => fields.iter().any(|(_, t)| t.has_type_vars()),
267 SemanticType::Enum { variants, .. } => variants
268 .iter()
269 .any(|v| v.payload.as_ref().is_some_and(|t| t.has_type_vars())),
270 SemanticType::Function(sig) => {
271 sig.params.iter().any(|p| p.param_type.has_type_vars())
272 || sig.return_type.has_type_vars()
273 }
274 SemanticType::Generic { args, .. } => args.iter().any(|a| a.has_type_vars()),
275 _ => false,
276 }
277 }
278
279 pub fn to_type_info(&self) -> TypeInfo {
286 match self {
287 SemanticType::Number => TypeInfo::number(),
288 SemanticType::Integer => TypeInfo::integer(),
289 SemanticType::Bool => TypeInfo::bool(),
290 SemanticType::String => TypeInfo::string(),
291
292 SemanticType::Option(inner) => {
293 let inner_info = inner.to_type_info();
294 TypeInfo {
295 name: format!("Option<{}>", inner_info.name),
296 kind: TypeKind::Optional,
297 fields: None,
298 generic_params: Some(vec![inner_info]),
299 variants: None,
300 description: None,
301 metadata: None,
302 }
303 }
304
305 SemanticType::Result { ok_type, err_type } => {
306 let ok_info = ok_type.to_type_info();
307 let name = match err_type {
308 Some(e) => format!("Result<{}, {}>", ok_info.name, e.to_type_info().name),
309 None => format!("Result<{}>", ok_info.name),
310 };
311 let mut params = vec![ok_info];
312 if let Some(e) = err_type {
313 params.push(e.to_type_info());
314 }
315 TypeInfo {
316 name,
317 kind: TypeKind::Result,
318 fields: None,
319 generic_params: Some(params),
320 variants: None,
321 description: None,
322 metadata: None,
323 }
324 }
325
326 SemanticType::Array(elem) => TypeInfo::array(elem.to_type_info()),
327
328 SemanticType::Struct { name, fields } => {
329 let field_infos: Vec<FieldInfo> = fields
330 .iter()
331 .map(|(fname, ftype)| FieldInfo::required(fname, ftype.to_type_info()))
332 .collect();
333 TypeInfo::object(name, field_infos)
334 }
335
336 SemanticType::Enum { name, variants, .. } => {
337 let variant_names: Vec<String> = variants.iter().map(|v| v.name.clone()).collect();
338 TypeInfo {
339 name: name.clone(),
340 kind: TypeKind::Enum,
341 fields: None,
342 generic_params: None,
343 variants: Some(variant_names),
344 description: None,
345 metadata: None,
346 }
347 }
348
349 SemanticType::Interface { name, .. } => TypeInfo::primitive(name),
350
351 SemanticType::TypeVar(id) => TypeInfo::primitive(format!("T{}", id.0)),
352
353 SemanticType::Named(name) => TypeInfo::primitive(name),
354
355 SemanticType::Generic { name, args } => {
356 let arg_infos: Vec<TypeInfo> = args.iter().map(|a| a.to_type_info()).collect();
357 let arg_names: Vec<String> = arg_infos.iter().map(|a| a.name.clone()).collect();
358 TypeInfo {
359 name: format!("{}<{}>", name, arg_names.join(", ")),
360 kind: TypeKind::Object, fields: None,
362 generic_params: Some(arg_infos),
363 variants: None,
364 description: None,
365 metadata: None,
366 }
367 }
368
369 SemanticType::Ref(inner) => {
370 let inner_info = inner.to_type_info();
371 TypeInfo::primitive(format!("&{}", inner_info.name))
372 }
373 SemanticType::RefMut(inner) => {
374 let inner_info = inner.to_type_info();
375 TypeInfo::primitive(format!("&mut {}", inner_info.name))
376 }
377 SemanticType::Never => TypeInfo::primitive("Never"),
378 SemanticType::Void => TypeInfo::null(),
379
380 SemanticType::Function(sig) => {
381 let param_types: Vec<String> = sig
382 .params
383 .iter()
384 .map(|p| p.param_type.to_type_info().name)
385 .collect();
386 let ret_type = sig.return_type.to_type_info().name;
387 TypeInfo {
388 name: format!("({}) -> {}", param_types.join(", "), ret_type),
389 kind: TypeKind::Function,
390 fields: None,
391 generic_params: None,
392 variants: None,
393 description: None,
394 metadata: None,
395 }
396 }
397 }
398 }
399}
400
401impl fmt::Display for SemanticType {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 match self {
404 SemanticType::Number => write!(f, "Number"),
405 SemanticType::Integer => write!(f, "Integer"),
406 SemanticType::Bool => write!(f, "Bool"),
407 SemanticType::String => write!(f, "String"),
408 SemanticType::Option(inner) => write!(f, "Option<{}>", inner),
409 SemanticType::Result { ok_type, err_type } => match err_type {
410 Some(e) => write!(f, "Result<{}, {}>", ok_type, e),
411 None => write!(f, "Result<{}>", ok_type),
412 },
413 SemanticType::Array(elem) => write!(f, "Vec<{}>", elem),
414 SemanticType::Struct { name, .. } => write!(f, "{}", name),
415 SemanticType::Enum { name, .. } => write!(f, "{}", name),
416 SemanticType::Interface { name, .. } => write!(f, "{}", name),
417 SemanticType::TypeVar(id) => write!(f, "T{}", id.0),
418 SemanticType::Named(name) => write!(f, "{}", name),
419 SemanticType::Generic { name, args } => {
420 write!(f, "{}<", name)?;
421 for (i, arg) in args.iter().enumerate() {
422 if i > 0 {
423 write!(f, ", ")?;
424 }
425 write!(f, "{}", arg)?;
426 }
427 write!(f, ">")
428 }
429 SemanticType::Ref(inner) => write!(f, "&{}", inner),
430 SemanticType::RefMut(inner) => write!(f, "&mut {}", inner),
431 SemanticType::Never => write!(f, "Never"),
432 SemanticType::Void => write!(f, "Void"),
433 SemanticType::Function(sig) => {
434 write!(f, "(")?;
435 for (i, param) in sig.params.iter().enumerate() {
436 if i > 0 {
437 write!(f, ", ")?;
438 }
439 write!(f, "{}", param.param_type)?;
440 }
441 write!(f, ") -> {}", sig.return_type)
442 }
443 }
444 }
445}
446
447#[cfg(test)]
448mod tests {
449 use super::*;
450
451 #[test]
452 fn test_option_creation() {
453 let opt = SemanticType::option(SemanticType::Number);
454 assert!(opt.is_option());
455 assert_eq!(opt.option_inner(), Some(&SemanticType::Number));
456 }
457
458 #[test]
459 fn test_result_creation() {
460 let res = SemanticType::result(SemanticType::Number);
461 assert!(res.is_result());
462 match &res {
463 SemanticType::Result { ok_type, err_type } => {
464 assert_eq!(**ok_type, SemanticType::Number);
465 assert!(err_type.is_none());
466 }
467 _ => panic!("Expected Result"),
468 }
469 }
470
471 #[test]
472 fn test_display() {
473 assert_eq!(format!("{}", SemanticType::Number), "Number");
474 assert_eq!(
475 format!("{}", SemanticType::option(SemanticType::Number)),
476 "Option<Number>"
477 );
478 assert_eq!(
479 format!("{}", SemanticType::result(SemanticType::String)),
480 "Result<String>"
481 );
482 }
483
484 #[test]
485 fn test_to_type_info_primitives() {
486 let num = SemanticType::Number.to_type_info();
487 assert_eq!(num.name, "Number");
488 assert_eq!(num.kind, TypeKind::Primitive);
489
490 let int = SemanticType::Integer.to_type_info();
491 assert_eq!(int.name, "Integer");
492
493 let bool_t = SemanticType::Bool.to_type_info();
494 assert_eq!(bool_t.name, "Bool");
495
496 let string_t = SemanticType::String.to_type_info();
497 assert_eq!(string_t.name, "String");
498 }
499
500 #[test]
501 fn test_to_type_info_option() {
502 let opt = SemanticType::option(SemanticType::Number).to_type_info();
503 assert_eq!(opt.name, "Option<Number>");
504 assert_eq!(opt.kind, TypeKind::Optional);
505 assert!(opt.generic_params.is_some());
506 assert_eq!(opt.generic_params.as_ref().unwrap().len(), 1);
507 }
508
509 #[test]
510 fn test_to_type_info_result() {
511 let res = SemanticType::result(SemanticType::String).to_type_info();
512 assert_eq!(res.name, "Result<String>");
513 assert_eq!(res.kind, TypeKind::Result);
514
515 let res_with_err =
516 SemanticType::result_with_error(SemanticType::Number, SemanticType::String)
517 .to_type_info();
518 assert_eq!(res_with_err.name, "Result<Number, String>");
519 }
520
521 #[test]
522 fn test_to_type_info_array() {
523 let arr = SemanticType::array(SemanticType::Bool).to_type_info();
524 assert_eq!(arr.name, "Array<Bool>");
525 assert_eq!(arr.kind, TypeKind::Array);
526 }
527
528 #[test]
529 fn test_named_width_numeric_families() {
530 assert!(SemanticType::Named("i16".to_string()).is_numeric());
531 assert!(SemanticType::Named("u64".to_string()).is_integer_family());
532 assert!(SemanticType::Named("f32".to_string()).is_number_family());
533 assert!(SemanticType::Named("f64".to_string()).is_numeric());
534 assert!(!SemanticType::Named("Candle".to_string()).is_numeric());
535 }
536
537 #[test]
540 fn test_shared_ref_creation() {
541 let r = SemanticType::shared_ref(SemanticType::Integer);
542 assert!(r.is_reference());
543 assert!(!r.is_exclusive_ref());
544 assert_eq!(r.deref_type(), Some(&SemanticType::Integer));
545 }
546
547 #[test]
548 fn test_exclusive_ref_creation() {
549 let r = SemanticType::exclusive_ref(SemanticType::Integer);
550 assert!(r.is_reference());
551 assert!(r.is_exclusive_ref());
552 assert_eq!(r.deref_type(), Some(&SemanticType::Integer));
553 }
554
555 #[test]
556 fn test_auto_deref() {
557 let r = SemanticType::shared_ref(SemanticType::Integer);
558 assert_eq!(r.auto_deref(), &SemanticType::Integer);
559
560 assert_eq!(SemanticType::Integer.auto_deref(), &SemanticType::Integer);
562
563 let nested = SemanticType::shared_ref(SemanticType::shared_ref(SemanticType::Bool));
565 assert_eq!(nested.auto_deref(), &SemanticType::Bool);
566 }
567
568 #[test]
569 fn test_ref_display() {
570 let shared = SemanticType::shared_ref(SemanticType::Integer);
571 assert_eq!(format!("{}", shared), "&Integer");
572
573 let exclusive = SemanticType::exclusive_ref(SemanticType::Integer);
574 assert_eq!(format!("{}", exclusive), "&mut Integer");
575 }
576
577 #[test]
578 fn test_ref_to_type_info() {
579 let r = SemanticType::shared_ref(SemanticType::Number);
580 let info = r.to_type_info();
581 assert_eq!(info.name, "&Number");
582 }
583
584 #[test]
585 fn test_ref_is_not_numeric() {
586 let r = SemanticType::shared_ref(SemanticType::Integer);
587 assert!(!r.is_numeric());
588 }
589
590 #[test]
591 fn test_non_ref_deref_type_is_none() {
592 assert!(SemanticType::Integer.deref_type().is_none());
593 assert!(SemanticType::String.deref_type().is_none());
594 }
595}