Skip to main content

shape_runtime/type_system/
mod.rs

1//! Shape Type System
2//!
3//! This module implements type inference, type checking, and type unification
4//! for the Shape language, providing static type safety while maintaining
5//! ergonomic syntax through type inference.
6//!
7//! ## Architecture: Storage vs Semantic Types
8//!
9//! - **SemanticType**: What users see in code (`Option<f64>`, `Result<Table<Row>>`)
10//! - **StorageType**: How data is physically stored (NaN sentinels, bitmaps)
11//!
12//! This separation allows the type checker to be strict while storage can be
13//! optimized for JIT/SIMD performance.
14//!
15//! ## Module Structure
16//!
17//! - `types/`: Core type definitions (Type, TypeVar, TypeScheme, TypeConstraint)
18//! - `unification/`: Type unification algorithm (Robinson's algorithm)
19//! - `solver/`: Constraint solving
20//! - `checking/`: Pattern checking and type checking
21//! - `environment/`: Type environments and scopes
22//! - `inference/`: Type inference engine
23
24pub mod checker;
25pub mod checking;
26pub mod constraints;
27pub mod environment;
28pub mod error_bridge;
29pub mod errors;
30pub mod exhaustiveness;
31pub mod inference;
32pub mod semantic;
33pub mod storage;
34pub mod suggestions;
35pub mod types;
36pub mod unification;
37pub mod universal_error;
38
39// Re-export from types module
40pub use types::{
41    BuiltinTypes, Type, TypeConstraint, TypeScheme, TypeVar, TypeVarGen, annotation_to_semantic,
42    annotation_to_string, semantic_to_annotation, substitute,
43};
44
45// Re-export other public types
46pub use checker::{
47    TypeAnalysisMode, TypeCheckResult, TypeChecker, TypeWarning, analyze_program,
48    analyze_program_with_mode,
49};
50pub use environment::TypeEnvironment;
51pub use errors::{TypeError, TypeErrorWithLocation, TypeResult};
52pub use inference::{PropertyAssignment, PropertyAssignmentCollector, TypeInferenceEngine};
53pub use semantic::{EnumVariant, FunctionParam, FunctionSignature, SemanticType, TypeVarId};
54pub use storage::StorageType;
55pub use universal_error::{ErrorDetails, ErrorLocation, UniversalError};
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use shape_ast::ast::TypeAnnotation;
61
62    #[test]
63    fn test_type_to_semantic_primitives() {
64        let num = BuiltinTypes::number();
65        let semantic = num.to_semantic().unwrap();
66        assert_eq!(semantic, SemanticType::Number);
67
68        let string = BuiltinTypes::string();
69        let semantic = string.to_semantic().unwrap();
70        assert_eq!(semantic, SemanticType::String);
71
72        let boolean = BuiltinTypes::boolean();
73        let semantic = boolean.to_semantic().unwrap();
74        assert_eq!(semantic, SemanticType::Bool);
75    }
76
77    #[test]
78    fn test_type_to_semantic_option() {
79        let option_num = Type::Generic {
80            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
81                "Option".into(),
82            ))),
83            args: vec![BuiltinTypes::number()],
84        };
85        let semantic = option_num.to_semantic().unwrap();
86        assert_eq!(
87            semantic,
88            SemanticType::Option(Box::new(SemanticType::Number))
89        );
90    }
91
92    #[test]
93    fn test_type_to_semantic_result() {
94        let result_num = Type::Generic {
95            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
96                "Result".into(),
97            ))),
98            args: vec![BuiltinTypes::number()],
99        };
100        let semantic = result_num.to_semantic().unwrap();
101        assert_eq!(
102            semantic,
103            SemanticType::Result {
104                ok_type: Box::new(SemanticType::Number),
105                err_type: None
106            }
107        );
108    }
109
110    #[test]
111    fn test_type_to_semantic_generic_table() {
112        let table_num = Type::Generic {
113            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
114                "Table".into(),
115            ))),
116            args: vec![BuiltinTypes::number()],
117        };
118        let semantic = table_num.to_semantic().unwrap();
119        assert_eq!(
120            semantic,
121            SemanticType::Generic {
122                name: "Table".to_string(),
123                args: vec![SemanticType::Number],
124            }
125        );
126    }
127
128    #[test]
129    fn test_semantic_to_inference_roundtrip() {
130        let original = SemanticType::Option(Box::new(SemanticType::Number));
131        let inference = original.to_inference_type();
132        let roundtrip = inference.to_semantic().unwrap();
133        assert_eq!(original, roundtrip);
134    }
135
136    #[test]
137    fn test_semantic_result_to_inference() {
138        let result_type = SemanticType::Result {
139            ok_type: Box::new(SemanticType::String),
140            err_type: None,
141        };
142        let inference = result_type.to_inference_type();
143        let roundtrip = inference.to_semantic().unwrap();
144        assert_eq!(result_type, roundtrip);
145    }
146}