1use crate::model::Ast;
15use crate::node::AnyId;
16use crate::node::type_::TypeKind;
17use alloc::vec::Vec;
18use zerodds_ast_core::{BreakCause, PendingRef, Ref};
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum RefKind {
23 Type,
25 Interface,
27 Exception,
29 Const,
31 Enumerator,
37 AnnotationDef,
39}
40
41impl RefKind {
42 pub const ALL: [Self; 6] = [
44 Self::Type,
45 Self::Interface,
46 Self::Exception,
47 Self::Const,
48 Self::Enumerator,
49 Self::AnnotationDef,
50 ];
51
52 #[must_use]
54 pub const fn as_str(self) -> &'static str {
55 match self {
56 Self::Type => "type",
57 Self::Interface => "interface",
58 Self::Exception => "exception",
59 Self::Const => "constant",
60 Self::Enumerator => "enumerator",
61 Self::AnnotationDef => "annotation",
62 }
63 }
64
65 #[must_use]
67 pub const fn accepts(self, any: AnyId) -> bool {
68 matches!(
69 (self, any),
70 (Self::Type, AnyId::Type(..))
71 | (Self::Interface, AnyId::Interface(..))
72 | (Self::Exception, AnyId::Exception(..))
73 | (Self::Const, AnyId::Const(..))
74 | (Self::Enumerator, AnyId::Enumerator(..))
75 | (Self::AnnotationDef, AnyId::AnnotationDef(..))
76 )
77 }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
82pub struct PendingSlot {
83 pub slot: usize,
85 pub key: PendingRef,
87 pub kind: RefKind,
89}
90
91impl Ast {
92 #[must_use]
97 pub fn pending_slots(&self, any: AnyId) -> Vec<PendingSlot> {
98 let mut out = Vec::new();
99 let mut slot = 0usize;
100 let mut push = |reference: Option<&PendingRef>, kind: RefKind, at: usize| {
101 if let Some(key) = reference {
102 out.push(PendingSlot {
103 slot: at,
104 key: key.clone(),
105 kind,
106 });
107 }
108 };
109
110 match any {
111 AnyId::Type(id, _) => {
112 let Ok(node) = self.types.get(id) else {
113 return out;
114 };
115 for reference in node.kind.type_refs() {
116 push(reference.pending_key(), RefKind::Type, slot);
117 slot += 1;
118 }
119 for reference in interface_refs_of_kind(&node.kind) {
120 push(reference.pending_key(), RefKind::Interface, slot);
121 slot += 1;
122 }
123 }
124 AnyId::Member(id, _) => {
125 if let Ok(node) = self.members.get(id) {
126 push(node.type_.pending_key(), RefKind::Type, slot);
127 }
128 }
129 AnyId::Case(..) => {}
132 AnyId::Bitfield(id, _) => {
133 if let Ok(node) = self.bitfields.get(id) {
134 push(
135 node.holder_type.as_ref().and_then(Ref::pending_key),
136 RefKind::Type,
137 slot,
138 );
139 }
140 }
141 AnyId::Const(id, _) => {
142 if let Ok(node) = self.constants.get(id) {
143 push(node.type_.pending_key(), RefKind::Type, slot);
144 }
145 }
146 AnyId::ConstExpr(id, _) => {
147 if let Ok(node) = self.exprs.get(id) {
148 match &node.expr {
149 crate::ConstExpr::NameRef(reference) => {
150 push(reference.pending_key(), RefKind::Const, slot);
151 }
152 crate::ConstExpr::Literal(crate::Literal::Enumerator(reference)) => {
153 push(reference.pending_key(), RefKind::Enumerator, slot);
154 }
155 _ => {}
156 }
157 }
158 }
159 AnyId::Interface(id, _) => {
160 let Ok(node) = self.interfaces.get(id) else {
161 return out;
162 };
163 for base in &node.bases {
164 push(base.pending_key(), RefKind::Interface, slot);
165 slot += 1;
166 }
167 }
168 AnyId::Operation(id, _) => {
169 let Ok(node) = self.operations.get(id) else {
170 return out;
171 };
172 push(
173 node.return_type.as_ref().and_then(Ref::pending_key),
174 RefKind::Type,
175 slot,
176 );
177 slot += 1;
178 for raise in &node.raises {
179 push(raise.pending_key(), RefKind::Exception, slot);
180 slot += 1;
181 }
182 }
183 AnyId::Param(id, _) => {
184 if let Ok(node) = self.params.get(id) {
185 push(node.type_.pending_key(), RefKind::Type, slot);
186 }
187 }
188 AnyId::Attribute(id, _) => {
189 let Ok(node) = self.attributes.get(id) else {
190 return out;
191 };
192 push(node.type_.pending_key(), RefKind::Type, slot);
193 slot += 1;
194 for raise in node.get_raises.iter().chain(node.set_raises.iter()) {
195 push(raise.pending_key(), RefKind::Exception, slot);
196 slot += 1;
197 }
198 }
199 AnyId::AnnotationMember(id, _) => {
200 if let Ok(node) = self.annotation_members.get(id) {
201 push(node.type_.pending_key(), RefKind::Type, slot);
202 }
203 }
204 AnyId::Module(..)
205 | AnyId::Enumerator(..)
206 | AnyId::BitValue(..)
207 | AnyId::Exception(..)
208 | AnyId::AnnotationDef(..)
209 | AnyId::Domain(..)
210 | AnyId::Topic(..)
211 | AnyId::QosProfile(..)
212 | AnyId::Participant(..)
213 | AnyId::Endpoint(..)
214 | AnyId::Library(..) => {}
215 }
216
217 if let Some(corba) = self.facets(any).and_then(|facets| facets.corba.as_ref()) {
224 for (index, reference) in corba_refs(corba).into_iter().enumerate() {
225 let (key, kind) = match reference {
226 CorbaRef::Interface(reference) => (reference.pending_key(), RefKind::Interface),
227 CorbaRef::Type(reference) => (reference.pending_key(), RefKind::Type),
228 };
229 if let Some(key) = key {
230 out.push(PendingSlot {
231 slot: CORBA_SLOT_BASE + index,
232 key: key.clone(),
233 kind,
234 });
235 }
236 }
237 }
238
239 let base = slot.max(FACET_SLOT_BASE);
242 if let Some(facets) = self.facets(any) {
243 for (index, applied) in facets.annotations.iter().enumerate() {
244 if let Some(key) = applied.definition.pending_key() {
245 out.push(PendingSlot {
246 slot: base + index,
247 key: key.clone(),
248 kind: RefKind::AnnotationDef,
249 });
250 }
251 }
252 }
253 out
254 }
255
256 pub(crate) fn set_slot(&mut self, any: AnyId, slot: usize, target: AnyId) -> bool {
260 if slot >= FACET_SLOT_BASE {
261 return self.set_applied_annotation(any, slot - FACET_SLOT_BASE, target);
262 }
263 if slot >= CORBA_SLOT_BASE {
264 let index = slot - CORBA_SLOT_BASE;
265 let Some(corba) = self.facets_mut(any).and_then(|f| f.corba.as_mut()) else {
266 return false;
267 };
268 return match (corba_refs_mut(corba).into_iter().nth(index), target) {
269 (Some(CorbaRefMut::Interface(reference)), AnyId::Interface(id, _)) => {
270 replace(reference, id)
271 }
272 (Some(CorbaRefMut::Type(reference)), AnyId::Type(id, _)) => replace(reference, id),
273 _ => false,
274 };
275 }
276 match (any, target) {
277 (AnyId::Type(id, _), AnyId::Type(target, _)) => self
278 .types
279 .get_mut(id)
280 .is_ok_and(|node| set_type_ref_in_kind(&mut node.kind, slot, target)),
281 (AnyId::Type(id, _), AnyId::Interface(target, _)) => {
282 self.types.get_mut(id).is_ok_and(|node| {
283 let offset = node.kind.type_refs().len();
284 set_interface_ref_in_kind(&mut node.kind, slot.wrapping_sub(offset), target)
285 })
286 }
287 (AnyId::Member(id, _), AnyId::Type(target, _)) => self
288 .members
289 .get_mut(id)
290 .is_ok_and(|node| replace(&mut node.type_, target)),
291 (AnyId::Bitfield(id, _), AnyId::Type(target, _)) => {
292 self.bitfields.get_mut(id).is_ok_and(|node| {
293 node.holder_type
294 .as_mut()
295 .is_some_and(|reference| replace(reference, target))
296 })
297 }
298 (AnyId::Const(id, _), AnyId::Type(target, _)) => self
299 .constants
300 .get_mut(id)
301 .is_ok_and(|node| replace(&mut node.type_, target)),
302 (AnyId::ConstExpr(id, _), AnyId::Const(target, _)) => {
303 self.exprs.get_mut(id).is_ok_and(|node| {
304 if let crate::ConstExpr::NameRef(reference) = &mut node.expr {
305 replace(reference, target)
306 } else {
307 false
308 }
309 })
310 }
311 (AnyId::ConstExpr(id, _), AnyId::Enumerator(target, _)) => {
312 self.exprs.get_mut(id).is_ok_and(|node| {
313 if let crate::ConstExpr::Literal(crate::Literal::Enumerator(reference)) =
314 &mut node.expr
315 {
316 replace(reference, target)
317 } else {
318 false
319 }
320 })
321 }
322 (AnyId::Interface(id, _), AnyId::Interface(target, _)) => self
323 .interfaces
324 .get_mut(id)
325 .is_ok_and(|node| node.bases.get_mut(slot).is_some_and(|b| replace(b, target))),
326 (AnyId::Operation(id, _), AnyId::Type(target, _)) => {
327 self.operations.get_mut(id).is_ok_and(|node| {
328 slot == 0
329 && node
330 .return_type
331 .as_mut()
332 .is_some_and(|reference| replace(reference, target))
333 })
334 }
335 (AnyId::Operation(id, _), AnyId::Exception(target, _)) => {
336 self.operations.get_mut(id).is_ok_and(|node| {
337 node.raises
338 .get_mut(slot.wrapping_sub(1))
339 .is_some_and(|reference| replace(reference, target))
340 })
341 }
342 (AnyId::Param(id, _), AnyId::Type(target, _)) => self
343 .params
344 .get_mut(id)
345 .is_ok_and(|node| replace(&mut node.type_, target)),
346 (AnyId::Attribute(id, _), AnyId::Type(target, _)) => self
347 .attributes
348 .get_mut(id)
349 .is_ok_and(|node| slot == 0 && replace(&mut node.type_, target)),
350 (AnyId::Attribute(id, _), AnyId::Exception(target, _)) => {
351 self.attributes.get_mut(id).is_ok_and(|node| {
352 let at = slot.wrapping_sub(1);
353 let getters = node.get_raises.len();
354 if at < getters {
355 node.get_raises
356 .get_mut(at)
357 .is_some_and(|reference| replace(reference, target))
358 } else {
359 node.set_raises
360 .get_mut(at - getters)
361 .is_some_and(|reference| replace(reference, target))
362 }
363 })
364 }
365 (AnyId::AnnotationMember(id, _), AnyId::Type(target, _)) => self
366 .annotation_members
367 .get_mut(id)
368 .is_ok_and(|node| replace(&mut node.type_, target)),
369 _ => false,
370 }
371 }
372
373 pub(crate) fn break_slot(&mut self, any: AnyId, slot: usize, cause: BreakCause) -> bool {
375 if slot >= FACET_SLOT_BASE {
376 let index = slot - FACET_SLOT_BASE;
377 let Some(facets) = self.facets_mut(any) else {
378 return false;
379 };
380 return facets
381 .annotations
382 .get_mut(index)
383 .is_some_and(|applied| break_ref(&mut applied.definition, cause));
384 }
385 if slot >= CORBA_SLOT_BASE {
386 let index = slot - CORBA_SLOT_BASE;
387 let Some(corba) = self.facets_mut(any).and_then(|f| f.corba.as_mut()) else {
388 return false;
389 };
390 return match corba_refs_mut(corba).into_iter().nth(index) {
391 Some(CorbaRefMut::Interface(reference)) => break_ref(reference, cause),
392 Some(CorbaRefMut::Type(reference)) => break_ref(reference, cause),
393 None => false,
394 };
395 }
396 match any {
397 AnyId::Type(id, _) => self.types.get_mut(id).is_ok_and(|node| {
398 let types = node.kind.type_refs_mut().len();
399 if slot < types {
400 node.kind
401 .type_refs_mut()
402 .into_iter()
403 .nth(slot)
404 .is_some_and(|reference| break_ref(reference, cause))
405 } else {
406 break_interface_ref_in_kind(&mut node.kind, slot - types, cause)
407 }
408 }),
409 AnyId::Member(id, _) => self
410 .members
411 .get_mut(id)
412 .is_ok_and(|node| break_ref(&mut node.type_, cause)),
413 AnyId::Bitfield(id, _) => self.bitfields.get_mut(id).is_ok_and(|node| {
414 node.holder_type
415 .as_mut()
416 .is_some_and(|reference| break_ref(reference, cause))
417 }),
418 AnyId::Const(id, _) => self
419 .constants
420 .get_mut(id)
421 .is_ok_and(|node| break_ref(&mut node.type_, cause)),
422 AnyId::ConstExpr(id, _) => {
423 self.exprs
424 .get_mut(id)
425 .is_ok_and(|node| match &mut node.expr {
426 crate::ConstExpr::NameRef(reference) => break_ref(reference, cause),
427 crate::ConstExpr::Literal(crate::Literal::Enumerator(reference)) => {
428 break_ref(reference, cause)
429 }
430 _ => false,
431 })
432 }
433 AnyId::Interface(id, _) => self.interfaces.get_mut(id).is_ok_and(|node| {
434 node.bases
435 .get_mut(slot)
436 .is_some_and(|reference| break_ref(reference, cause))
437 }),
438 AnyId::Operation(id, _) => self.operations.get_mut(id).is_ok_and(|node| {
439 if slot == 0 {
440 node.return_type
441 .as_mut()
442 .is_some_and(|reference| break_ref(reference, cause))
443 } else {
444 node.raises
445 .get_mut(slot - 1)
446 .is_some_and(|reference| break_ref(reference, cause))
447 }
448 }),
449 AnyId::Param(id, _) => self
450 .params
451 .get_mut(id)
452 .is_ok_and(|node| break_ref(&mut node.type_, cause)),
453 AnyId::Attribute(id, _) => self.attributes.get_mut(id).is_ok_and(|node| {
454 if slot == 0 {
455 return break_ref(&mut node.type_, cause);
456 }
457 let at = slot - 1;
458 let getters = node.get_raises.len();
459 if at < getters {
460 node.get_raises
461 .get_mut(at)
462 .is_some_and(|reference| break_ref(reference, cause))
463 } else {
464 node.set_raises
465 .get_mut(at - getters)
466 .is_some_and(|reference| break_ref(reference, cause))
467 }
468 }),
469 AnyId::AnnotationMember(id, _) => self
470 .annotation_members
471 .get_mut(id)
472 .is_ok_and(|node| break_ref(&mut node.type_, cause)),
473 _ => false,
474 }
475 }
476
477 fn set_applied_annotation(&mut self, any: AnyId, index: usize, target: AnyId) -> bool {
478 let AnyId::AnnotationDef(definition, _) = target else {
479 return false;
480 };
481 let Some(facets) = self.facets_mut(any) else {
482 return false;
483 };
484 facets
485 .annotations
486 .get_mut(index)
487 .is_some_and(|applied| replace(&mut applied.definition, definition))
488 }
489}
490
491const FACET_SLOT_BASE: usize = 1 << 20;
497
498const CORBA_SLOT_BASE: usize = 1 << 19;
504
505enum CorbaRef<'a> {
507 Interface(&'a Ref<crate::InterfaceNode>),
509 Type(&'a Ref<crate::TypeNode>),
511}
512
513enum CorbaRefMut<'a> {
515 Interface(&'a mut Ref<crate::InterfaceNode>),
517 Type(&'a mut Ref<crate::TypeNode>),
519}
520
521fn corba_refs(corba: &crate::CorbaFacet) -> Vec<CorbaRef<'_>> {
527 let mut out = Vec::new();
528 match corba.component_role.as_ref() {
529 Some(crate::ComponentRole::Facet { interface, .. }) => {
530 out.push(CorbaRef::Interface(interface));
531 }
532 Some(crate::ComponentRole::Receptacle { interface, .. }) => {
533 out.push(CorbaRef::Interface(interface));
534 }
535 Some(crate::ComponentRole::EventSource { event, .. }) => {
536 out.push(CorbaRef::Type(event));
537 }
538 Some(crate::ComponentRole::EventSink { event, .. }) => {
539 out.push(CorbaRef::Type(event));
540 }
541 Some(
542 crate::ComponentRole::HomeFactory
543 | crate::ComponentRole::HomeFinder
544 | crate::ComponentRole::PortTypeRole
545 | crate::ComponentRole::ConnectorRole,
546 )
547 | None => {}
548 }
549 if let Some(manages) = corba.manages.as_ref() {
550 out.push(CorbaRef::Interface(&manages.component));
551 if let Some(key) = manages.primary_key.as_ref() {
552 out.push(CorbaRef::Type(key));
553 }
554 }
555 for interface in &corba.supports {
556 out.push(CorbaRef::Interface(interface));
557 }
558 for param in &corba.template_params {
559 if let Some(constraint) = param.constraint.as_ref() {
560 out.push(CorbaRef::Type(constraint));
561 }
562 }
563 for arg in &corba.template_args {
564 if let crate::TemplateArg::Type(reference) = arg {
565 out.push(CorbaRef::Type(reference));
566 }
567 }
568 out
569}
570
571fn corba_refs_mut(corba: &mut crate::CorbaFacet) -> Vec<CorbaRefMut<'_>> {
573 let mut out = Vec::new();
574 match corba.component_role.as_mut() {
575 Some(crate::ComponentRole::Facet { interface, .. }) => {
576 out.push(CorbaRefMut::Interface(interface));
577 }
578 Some(crate::ComponentRole::Receptacle { interface, .. }) => {
579 out.push(CorbaRefMut::Interface(interface));
580 }
581 Some(crate::ComponentRole::EventSource { event, .. }) => {
582 out.push(CorbaRefMut::Type(event));
583 }
584 Some(crate::ComponentRole::EventSink { event, .. }) => {
585 out.push(CorbaRefMut::Type(event));
586 }
587 Some(
588 crate::ComponentRole::HomeFactory
589 | crate::ComponentRole::HomeFinder
590 | crate::ComponentRole::PortTypeRole
591 | crate::ComponentRole::ConnectorRole,
592 )
593 | None => {}
594 }
595 if let Some(manages) = corba.manages.as_mut() {
596 out.push(CorbaRefMut::Interface(&mut manages.component));
597 if let Some(key) = manages.primary_key.as_mut() {
598 out.push(CorbaRefMut::Type(key));
599 }
600 }
601 for interface in &mut corba.supports {
602 out.push(CorbaRefMut::Interface(interface));
603 }
604 for param in &mut corba.template_params {
605 if let Some(constraint) = param.constraint.as_mut() {
606 out.push(CorbaRefMut::Type(constraint));
607 }
608 }
609 for arg in &mut corba.template_args {
610 if let crate::TemplateArg::Type(reference) = arg {
611 out.push(CorbaRefMut::Type(reference));
612 }
613 }
614 out
615}
616
617fn replace<T>(reference: &mut Ref<T>, target: zerodds_ast_core::Id<T>) -> bool {
618 if reference.is_pending() {
619 *reference = Ref::Resolved(target);
620 return true;
621 }
622 false
623}
624
625fn break_ref<T>(reference: &mut Ref<T>, cause: BreakCause) -> bool {
626 if reference.is_pending() {
627 *reference = Ref::Broken(cause);
628 return true;
629 }
630 false
631}
632
633fn break_interface_ref_in_kind(kind: &mut TypeKind, slot: usize, cause: BreakCause) -> bool {
634 match kind {
635 TypeKind::Valuetype { supported, .. } => supported
636 .get_mut(slot)
637 .is_some_and(|reference| break_ref(reference, cause)),
638 TypeKind::ObjectRef {
641 interface: Some(interface),
642 } => slot == 0 && break_ref(interface, cause),
643 _ => false,
644 }
645}
646
647fn interface_refs_of_kind(kind: &TypeKind) -> Vec<&Ref<crate::InterfaceNode>> {
649 match kind {
650 TypeKind::Valuetype { supported, .. } => supported.iter().collect(),
651 TypeKind::ObjectRef {
652 interface: Some(interface),
653 } => alloc::vec![interface],
654 _ => Vec::new(),
655 }
656}
657
658fn set_type_ref_in_kind(
659 kind: &mut TypeKind,
660 slot: usize,
661 target: zerodds_ast_core::Id<crate::TypeNode>,
662) -> bool {
663 kind.type_refs_mut()
664 .into_iter()
665 .nth(slot)
666 .is_some_and(|reference| replace(reference, target))
667}
668
669fn set_interface_ref_in_kind(
670 kind: &mut TypeKind,
671 slot: usize,
672 target: zerodds_ast_core::Id<crate::InterfaceNode>,
673) -> bool {
674 match kind {
675 TypeKind::Valuetype { supported, .. } => supported
676 .get_mut(slot)
677 .is_some_and(|reference| replace(reference, target)),
678 TypeKind::ObjectRef {
679 interface: Some(interface),
680 } => slot == 0 && replace(interface, target),
681 _ => false,
682 }
683}