gruel_air/sema/sema_ctx_builder.rs
1//! SemaContext builder implementation.
2//!
3//! This module contains methods for building a [`SemaContext`] from a [`Sema`]
4//! for use in parallel function body analysis.
5
6use std::collections::HashMap;
7
8use gruel_target::Target;
9use lasso::Spur;
10
11use crate::inference::{FunctionSig, MethodSig};
12use crate::sema_context::{InferenceContext as SemaContextInferenceContext, SemaContext};
13use crate::types::{StructId, Type};
14
15use super::{KnownSymbols, Sema};
16
17impl<'a> Sema<'a> {
18 /// Build a SemaContext from the current Sema state.
19 ///
20 /// This creates an immutable context that can be shared across threads
21 /// for parallel function body analysis. The SemaContext contains all
22 /// type definitions, function signatures, and method signatures.
23 ///
24 /// The returned SemaContext borrows functions and methods from Sema,
25 /// so Sema must outlive the SemaContext. This is reflected in the
26 /// lifetime relationship: the returned context lives for `'s` (the
27 /// borrow of self), not `'a` (the lifetime of the RIR/interner).
28 ///
29 /// # Usage
30 ///
31 /// ```ignore
32 /// let mut sema = Sema::new(rir, interner, preview);
33 /// sema.inject_builtin_types();
34 /// sema.register_type_names()?;
35 /// sema.resolve_declarations()?;
36 /// let ctx = sema.build_sema_context();
37 /// // Now ctx can be shared across threads for parallel analysis
38 /// // (while sema is borrowed)
39 /// ```
40 pub fn build_sema_context<'s>(&'s self) -> SemaContext<'s>
41 where
42 'a: 's,
43 {
44 // Build the inference context
45 let inference_ctx = self.build_sema_context_inference();
46
47 SemaContext {
48 rir: self.rir,
49 interner: self.interner,
50 structs: self.structs.clone(),
51 enums: self.enums.clone(),
52 // Pass references to functions/methods/constants instead of cloning.
53 // This is safe because after declaration gathering, these HashMaps are immutable.
54 functions: &self.functions,
55 methods: &self.methods,
56 constants: &self.constants,
57 preview_features: self.preview_features.clone(),
58 builtin_string_id: self.builtin_string_id,
59 builtin_arch_id: self.builtin_arch_id,
60 builtin_os_id: self.builtin_os_id,
61 builtin_typekind_id: self.builtin_typekind_id,
62 target: Target::default(), // Will be overridden by caller if needed
63 inference_ctx,
64 known: KnownSymbols::new(self.interner),
65 type_pool: self.type_pool.clone(),
66 module_registry: crate::sema_context::ModuleRegistry::new(),
67 source_file_path: None, // Will be set when analyzing specific files
68 file_paths: self.file_paths.clone(), // Copy file paths for module resolution
69 param_arena: &self.param_arena,
70 }
71 }
72
73 /// Build the inference context portion of SemaContext.
74 pub(crate) fn build_sema_context_inference(&self) -> SemaContextInferenceContext {
75 // Build function signatures with InferType for constraint generation
76 let func_sigs: HashMap<Spur, FunctionSig> = self
77 .functions
78 .iter()
79 .map(|(name, info)| {
80 (
81 *name,
82 FunctionSig {
83 param_types: self
84 .param_arena
85 .types(info.params)
86 .iter()
87 .map(|t| self.type_to_infer_type(*t))
88 .collect(),
89 return_type: self.type_to_infer_type(info.return_type),
90 is_generic: info.is_generic,
91 param_modes: self.param_arena.modes(info.params).to_vec(),
92 param_comptime: self.param_arena.comptime(info.params).to_vec(),
93 param_names: self.param_arena.names(info.params).to_vec(),
94 return_type_sym: info.return_type_sym,
95 },
96 )
97 })
98 .collect();
99
100 // Build struct types map (name -> Type::new_struct(id))
101 let struct_types: HashMap<Spur, Type> = self
102 .structs
103 .iter()
104 .map(|(name, id)| (*name, Type::new_struct(*id)))
105 .collect();
106
107 // Build enum types map (name -> Type::new_enum(id))
108 let enum_types: HashMap<Spur, Type> = self
109 .enums
110 .iter()
111 .map(|(name, id)| (*name, Type::new_enum(*id)))
112 .collect();
113
114 // Build method signatures with InferType for constraint generation
115 let method_sigs: HashMap<(StructId, Spur), MethodSig> = self
116 .methods
117 .iter()
118 .map(|((struct_id, method_name), info)| {
119 (
120 (*struct_id, *method_name),
121 MethodSig {
122 struct_type: info.struct_type,
123 has_self: info.has_self,
124 param_types: self
125 .param_arena
126 .types(info.params)
127 .iter()
128 .map(|t| self.type_to_infer_type(*t))
129 .collect(),
130 return_type: self.type_to_infer_type(info.return_type),
131 },
132 )
133 })
134 .collect();
135
136 SemaContextInferenceContext {
137 func_sigs,
138 struct_types,
139 enum_types,
140 method_sigs,
141 }
142 }
143}