slang_frontend/semantic_analysis/validation/
coordinator.rs

1use slang_shared::CompilationContext;
2use slang_types::TypeId;
3use slang_ir::ast::{BinaryExpr, Expression, LetStatement};
4
5use super::{
6    TypeChecker,
7    TypeCoercion,
8    TypeInference,
9    TypeValidation,
10    inference::{finalize_inferred_type, determine_let_statement_type},
11    coercion::{check_unspecified_int_for_type, check_unspecified_float_for_type},
12};
13use super::super::traits::SemanticResult;
14
15/// Coordinates between specialized type checking modules
16/// 
17/// This struct provides a unified interface for type checking operations
18/// while delegating to specialized modules for specific concerns like
19/// inference, coercion, and validation.
20pub struct TypeCheckingCoordinator<'a> {
21    checker: TypeChecker<'a>,
22    coercion: TypeCoercion<'a>,
23    _inference: TypeInference, // Unused for now but kept for future extensions
24    validation: TypeValidation<'a>,
25}
26
27impl<'a> TypeCheckingCoordinator<'a> {
28    /// Create a new type checking coordinator
29    /// 
30    /// # Arguments
31    /// * `context` - The compilation context for type information
32    pub fn new(context: &'a CompilationContext) -> Self {
33        Self {
34            checker: TypeChecker::new(context),
35            coercion: TypeCoercion::new(context),
36            _inference: TypeInference{},
37            validation: TypeValidation::new(context),
38        }
39    }
40
41    /// Check if two types are compatible for assignment with coercion
42    /// 
43    /// # Arguments
44    /// * `target` - The target type (left side of assignment)
45    /// * `source` - The source type (right side of assignment)
46    /// 
47    /// # Returns
48    /// `true` if assignment is allowed, `false` otherwise
49    pub fn check_assignment_compatibility(&self, target: &TypeId, source: &TypeId) -> bool {
50        self.checker.check_assignment_compatibility(target, source)
51    }
52
53    /// Check if a function call is valid and return the result type
54    /// 
55    /// # Arguments
56    /// * `function_type` - The function's type signature
57    /// * `argument_types` - The types of the provided arguments
58    /// 
59    /// # Returns
60    /// Result containing the return type or an error
61    pub fn check_function_call(
62        &self,
63        function_type: &TypeId,
64        argument_types: &[TypeId],
65    ) -> SemanticResult {
66        self.checker.check_function_call(function_type, argument_types)
67    }
68
69    /// Check if mixed-type arithmetic operations are allowed with coercion
70    /// 
71    /// # Arguments
72    /// * `left_type` - The type of the left operand
73    /// * `right_type` - The type of the right operand
74    /// * `bin_expr` - The binary expression containing both operands and the operator
75    /// 
76    /// # Returns
77    /// Result containing the operation result type or an error
78    pub fn check_mixed_arithmetic_with_coercion(
79        &self,
80        left_type: &TypeId,
81        right_type: &TypeId,
82        bin_expr: &BinaryExpr,
83    ) -> SemanticResult {
84        self.coercion.check_mixed_arithmetic_operation(left_type, right_type, bin_expr)
85    }
86
87    /// Determine the final type for a let statement with potential inference
88    /// 
89    /// # Arguments
90    /// * `let_stmt` - The let statement being analyzed
91    /// * `expr_type` - The type of the initialization expression
92    /// 
93    /// # Returns
94    /// Result containing the final determined type
95    pub fn determine_let_statement_type(
96        &self,
97        let_stmt: &LetStatement,
98        expr_type: TypeId,
99    ) -> SemanticResult {
100        determine_let_statement_type(self.checker.context(), let_stmt, expr_type)
101    }
102
103    /// Finalize an inferred type (convert unspecified literals to concrete types)
104    /// 
105    /// # Arguments
106    /// * `type_id` - The type to finalize
107    /// 
108    /// # Returns
109    /// The concrete type (i64 for unspecified integers, f64 for unspecified floats)
110    pub fn finalize_inferred_type(&self, type_id: TypeId) -> TypeId {
111        finalize_inferred_type(type_id)
112    }
113
114    /// Validate that a literal value is within range for its target type
115    /// 
116    /// # Arguments
117    /// * `expr` - The expression containing the literal
118    /// * `target_type` - The target type to validate against
119    /// 
120    /// # Returns
121    /// Result indicating if validation passed
122    pub fn validate_literal_range(
123        &self,
124        expr: &Expression,
125        target_type: &TypeId,
126    ) -> SemanticResult {
127        // Use coercion module's range checking capabilities
128        if self.is_integer_type(target_type) {
129            check_unspecified_int_for_type(self.checker.context(), expr, target_type)
130        } else if self.is_float_type(target_type) {
131            check_unspecified_float_for_type(self.checker.context(), expr, target_type)
132        } else {
133            Ok(target_type.clone())
134        }
135    }
136
137    /// Validate function declaration constraints
138    /// 
139    /// # Arguments
140    /// * `func_decl` - The function declaration to validate
141    /// 
142    /// # Returns
143    /// Result indicating if validation passed
144    pub fn validate_function_declaration(
145        &self,
146        func_decl: &slang_ir::ast::FunctionDeclarationStmt,
147    ) -> SemanticResult {
148        self.validation.validate_function_declaration(func_decl)
149    }
150
151    /// Check if a type is numeric
152    pub fn is_numeric_type(&self, type_id: &TypeId) -> bool {
153        self.checker.is_numeric_type(type_id)
154    }
155
156    /// Check if a type is an integer type
157    pub fn is_integer_type(&self, type_id: &TypeId) -> bool {
158        self.checker.is_integer_type(type_id)
159    }
160
161    /// Check if a type is a float type
162    pub fn is_float_type(&self, type_id: &TypeId) -> bool {
163        self.checker.is_float_type(type_id)
164    }
165
166    /// Check if a type is an unsigned integer type
167    pub fn is_unsigned_integer_type(&self, type_id: &TypeId) -> bool {
168        self.checker.is_unsigned_integer_type(type_id)
169    }
170
171    /// Check if an unspecified literal can be coerced to a target type
172    pub fn can_coerce_unspecified_literal(&self, source: &TypeId, target: &TypeId) -> bool {
173        self.coercion.can_coerce(source, target)
174    }
175}