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 typed_value;
36pub mod types;
37pub mod unification;
38pub mod universal_error;
39
40// Re-export from types module
41pub use types::{
42    BuiltinTypes, Type, TypeConstraint, TypeScheme, TypeVar, annotation_to_semantic,
43    annotation_to_string, semantic_to_annotation, substitute,
44};
45
46// Re-export other public types
47pub use checker::{
48    TypeAnalysisMode, TypeCheckResult, TypeChecker, TypeWarning, analyze_program,
49    analyze_program_with_mode,
50};
51pub use environment::TypeEnvironment;
52pub use errors::{TypeError, TypeErrorWithLocation, TypeResult};
53pub use inference::{PropertyAssignment, PropertyAssignmentCollector, TypeInferenceEngine};
54pub use semantic::{EnumVariant, FunctionParam, FunctionSignature, SemanticType, TypeVarId};
55pub use storage::StorageType;
56pub use typed_value::TypedValue;
57pub use universal_error::{ErrorDetails, ErrorLocation, UniversalError};
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use shape_ast::ast::TypeAnnotation;
63
64    #[test]
65    fn test_type_to_semantic_primitives() {
66        let num = BuiltinTypes::number();
67        let semantic = num.to_semantic().unwrap();
68        assert_eq!(semantic, SemanticType::Number);
69
70        let string = BuiltinTypes::string();
71        let semantic = string.to_semantic().unwrap();
72        assert_eq!(semantic, SemanticType::String);
73
74        let boolean = BuiltinTypes::boolean();
75        let semantic = boolean.to_semantic().unwrap();
76        assert_eq!(semantic, SemanticType::Bool);
77    }
78
79    #[test]
80    fn test_type_to_semantic_option() {
81        let option_num = Type::Generic {
82            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
83                "Option".into(),
84            ))),
85            args: vec![BuiltinTypes::number()],
86        };
87        let semantic = option_num.to_semantic().unwrap();
88        assert_eq!(
89            semantic,
90            SemanticType::Option(Box::new(SemanticType::Number))
91        );
92    }
93
94    #[test]
95    fn test_type_to_semantic_result() {
96        let result_num = Type::Generic {
97            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
98                "Result".into(),
99            ))),
100            args: vec![BuiltinTypes::number()],
101        };
102        let semantic = result_num.to_semantic().unwrap();
103        assert_eq!(
104            semantic,
105            SemanticType::Result {
106                ok_type: Box::new(SemanticType::Number),
107                err_type: None
108            }
109        );
110    }
111
112    #[test]
113    fn test_type_to_semantic_generic_table() {
114        let table_num = Type::Generic {
115            base: Box::new(Type::Concrete(TypeAnnotation::Reference(
116                "Table".into(),
117            ))),
118            args: vec![BuiltinTypes::number()],
119        };
120        let semantic = table_num.to_semantic().unwrap();
121        assert_eq!(
122            semantic,
123            SemanticType::Generic {
124                name: "Table".to_string(),
125                args: vec![SemanticType::Number],
126            }
127        );
128    }
129
130    #[test]
131    fn test_semantic_to_inference_roundtrip() {
132        let original = SemanticType::Option(Box::new(SemanticType::Number));
133        let inference = original.to_inference_type();
134        let roundtrip = inference.to_semantic().unwrap();
135        assert_eq!(original, roundtrip);
136    }
137
138    #[test]
139    fn test_semantic_result_to_inference() {
140        let result_type = SemanticType::Result {
141            ok_type: Box::new(SemanticType::String),
142            err_type: None,
143        };
144        let inference = result_type.to_inference_type();
145        let roundtrip = inference.to_semantic().unwrap();
146        assert_eq!(result_type, roundtrip);
147    }
148}