1use indexmap::IndexMap;
2
3use crate::codegen::{CodegenDefaultsIr, RootCodegenIr, TypeCodegenIr};
4use crate::emission::EmissionDefaultsIr;
5use crate::error::IrBuildError;
6use crate::ids::{QualifiedTypeName, SchemaNodeIrId, TypeId};
7use crate::rust_binding::RustBindingIr;
8use crate::schema::SchemaNodeIr;
9
10#[derive(Debug, Clone, PartialEq, bon::Builder, Default)]
11#[builder(finish_fn = build_unchecked)]
12pub struct IrModule {
13 #[builder(default)]
14 types: IndexMap<TypeId, TypeDefIr>,
15 #[builder(default)]
16 name_index: IndexMap<QualifiedTypeName, TypeId>,
17 #[builder(default)]
18 roots: Vec<TypeId>,
19 #[builder(default)]
20 root_codegen: RootCodegenIr,
21 #[builder(default)]
22 codegen_defaults: CodegenDefaultsIr,
23 #[builder(default)]
24 emission_defaults: EmissionDefaultsIr,
25}
26
27impl IrModule {
28 pub fn new(
29 types: IndexMap<TypeId, TypeDefIr>,
30 name_index: IndexMap<QualifiedTypeName, TypeId>,
31 roots: Vec<TypeId>,
32 root_codegen: RootCodegenIr,
33 codegen_defaults: CodegenDefaultsIr,
34 emission_defaults: EmissionDefaultsIr,
35 ) -> Result<Self, IrBuildError> {
36 Self {
37 types,
38 name_index,
39 roots,
40 root_codegen,
41 codegen_defaults,
42 emission_defaults,
43 }
44 .into_checked()
45 }
46
47 pub fn into_checked(self) -> Result<Self, IrBuildError> {
48 self.validate()?;
49 Ok(self)
50 }
51
52 pub fn types(&self) -> &IndexMap<TypeId, TypeDefIr> {
53 &self.types
54 }
55
56 pub fn types_mut(&mut self) -> &mut IndexMap<TypeId, TypeDefIr> {
57 &mut self.types
58 }
59
60 pub fn name_index(&self) -> &IndexMap<QualifiedTypeName, TypeId> {
61 &self.name_index
62 }
63
64 pub fn name_index_mut(&mut self) -> &mut IndexMap<QualifiedTypeName, TypeId> {
65 &mut self.name_index
66 }
67
68 pub fn roots(&self) -> &[TypeId] {
69 &self.roots
70 }
71
72 pub fn roots_mut(&mut self) -> &mut Vec<TypeId> {
73 &mut self.roots
74 }
75
76 pub fn root_codegen(&self) -> &RootCodegenIr {
77 &self.root_codegen
78 }
79
80 pub fn root_codegen_mut(&mut self) -> &mut RootCodegenIr {
81 &mut self.root_codegen
82 }
83
84 pub fn codegen_defaults(&self) -> &CodegenDefaultsIr {
85 &self.codegen_defaults
86 }
87
88 pub fn codegen_defaults_mut(&mut self) -> &mut CodegenDefaultsIr {
89 &mut self.codegen_defaults
90 }
91
92 pub fn emission_defaults(&self) -> &EmissionDefaultsIr {
93 &self.emission_defaults
94 }
95
96 pub fn emission_defaults_mut(&mut self) -> &mut EmissionDefaultsIr {
97 &mut self.emission_defaults
98 }
99
100 pub(crate) fn validate(&self) -> Result<(), IrBuildError> {
101 crate::build_check::ensure_module_invariants(self)
102 }
103
104 pub fn get_type(&self, id: &TypeId) -> Option<&TypeDefIr> {
105 self.types.get(id)
106 }
107
108 pub fn get_type_by_name(&self, name: &QualifiedTypeName) -> Option<&TypeDefIr> {
109 self.name_index.get(name).and_then(|id| self.types.get(id))
110 }
111
112 pub fn insert_type(&mut self, id: TypeId, ty: TypeDefIr) -> Option<TypeDefIr> {
113 self.types.insert(id, ty)
114 }
115
116 pub fn insert_name_index(&mut self, name: QualifiedTypeName, id: TypeId) -> Option<TypeId> {
117 self.name_index.insert(name, id)
118 }
119
120 pub fn push_root(&mut self, id: TypeId) {
121 self.roots.push(id);
122 }
123
124 pub fn set_roots(&mut self, roots: Vec<TypeId>) {
125 self.roots = roots;
126 }
127
128 pub fn set_root_codegen(&mut self, root_codegen: RootCodegenIr) {
129 self.root_codegen = root_codegen;
130 }
131
132 pub fn set_codegen_defaults(&mut self, codegen_defaults: CodegenDefaultsIr) {
133 self.codegen_defaults = codegen_defaults;
134 }
135
136 pub fn set_emission_defaults(&mut self, emission_defaults: EmissionDefaultsIr) {
137 self.emission_defaults = emission_defaults;
138 }
139}
140
141impl IrModuleBuilder {
142 pub fn build(self) -> Result<IrModule, IrBuildError> {
143 self.build_unchecked().into_checked()
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, bon::Builder)]
148#[builder(finish_fn = build_unchecked)]
149pub struct TypeDefIr {
150 id: TypeId,
151 names: TypeNamesIr,
152 schema_nodes: IndexMap<SchemaNodeIrId, SchemaNodeIr>,
153 semantic_root: SchemaNodeIrId,
154 rust_binding: RustBindingIr,
155 type_codegen: TypeCodegenIr,
156 origin: TypeOriginIr,
157}
158
159impl TypeDefIr {
160 pub fn new(
161 id: TypeId,
162 names: TypeNamesIr,
163 schema_nodes: IndexMap<SchemaNodeIrId, SchemaNodeIr>,
164 semantic_root: SchemaNodeIrId,
165 rust_binding: RustBindingIr,
166 type_codegen: TypeCodegenIr,
167 origin: TypeOriginIr,
168 ) -> Self {
169 Self {
170 id,
171 names,
172 schema_nodes,
173 semantic_root,
174 rust_binding,
175 type_codegen,
176 origin,
177 }
178 }
179
180 pub fn id(&self) -> &TypeId {
181 &self.id
182 }
183
184 pub fn names(&self) -> &TypeNamesIr {
185 &self.names
186 }
187
188 pub fn schema_nodes(&self) -> &IndexMap<SchemaNodeIrId, SchemaNodeIr> {
189 &self.schema_nodes
190 }
191
192 pub fn schema_nodes_mut(&mut self) -> &mut IndexMap<SchemaNodeIrId, SchemaNodeIr> {
193 &mut self.schema_nodes
194 }
195
196 pub fn semantic_root(&self) -> SchemaNodeIrId {
197 self.semantic_root
198 }
199
200 pub fn rust_binding(&self) -> &RustBindingIr {
201 &self.rust_binding
202 }
203
204 pub fn rust_binding_mut(&mut self) -> &mut RustBindingIr {
205 &mut self.rust_binding
206 }
207
208 pub fn type_codegen(&self) -> &TypeCodegenIr {
209 &self.type_codegen
210 }
211
212 pub fn type_codegen_mut(&mut self) -> &mut TypeCodegenIr {
213 &mut self.type_codegen
214 }
215
216 pub fn origin(&self) -> &TypeOriginIr {
217 &self.origin
218 }
219}
220
221#[derive(Debug, Clone, PartialEq, Eq, bon::Builder)]
222#[builder(finish_fn = build_unchecked)]
223pub struct TypeNamesIr {
224 rust_name: String,
225 schema_name: Option<QualifiedTypeName>,
226}
227
228impl TypeNamesIr {
229 pub fn new(rust_name: String, schema_name: Option<QualifiedTypeName>) -> Self {
230 Self {
231 rust_name,
232 schema_name,
233 }
234 }
235
236 pub fn rust_name(&self) -> &str {
237 &self.rust_name
238 }
239
240 pub fn schema_name(&self) -> Option<&QualifiedTypeName> {
241 self.schema_name.as_ref()
242 }
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
246pub enum TypeOriginIr {
247 Derive,
248 Schema,
249 Mixed,
250}