1use crate::error::AstError;
14use crate::invariant::{self, InvariantViolation};
15use crate::model::Ast;
16use crate::node::AnyId;
17use crate::node::type_::TypeKind;
18use alloc::vec::Vec;
19use zerodds_ast_core::{
20 Change, Changeset, FieldValue, NodeId, Ref, TxnLog, UndoPayload, UndoRecord,
21};
22
23pub(crate) enum Stashed {
26 Type(crate::TypeNode),
28 Member(crate::MemberNode, usize),
30}
31
32pub struct AstTransaction<'a> {
38 ast: &'a mut Ast,
39 finished: bool,
40}
41
42impl<'a> AstTransaction<'a> {
43 pub(crate) fn new(ast: &'a mut Ast) -> Self {
44 ast.sequence = ast.sequence.saturating_add(1);
45 let sequence = ast.sequence;
46 ast.pending = Some(TxnLog::new(sequence));
47 Self {
48 ast,
49 finished: false,
50 }
51 }
52
53 pub fn ast(&mut self) -> &mut Ast {
58 self.ast
59 }
60
61 #[must_use]
63 pub fn model(&self) -> &Ast {
64 self.ast
65 }
66
67 pub fn commit(mut self) -> Result<Changeset, AstError> {
74 self.finished = true;
75 let Some(log) = self.ast.pending.take() else {
76 return Ok(Changeset::new(self.ast.sequence));
77 };
78
79 let touched: Vec<NodeId> = log.nodes_touched().collect();
80 let violations = invariant::check(self.ast, &touched);
81 if !violations.is_empty() {
82 self.ast.apply_rollback(&log);
83 return Err(AstError::Invariant(violations));
84 }
85
86 let changeset = log.into_changeset();
87 self.ast.stash.clear();
88 self.ast.observers.notify(&changeset);
89 Ok(changeset)
90 }
91
92 pub fn rollback(mut self) {
94 self.finished = true;
95 if let Some(log) = self.ast.pending.take() {
96 self.ast.apply_rollback(&log);
97 }
98 }
99}
100
101impl Drop for AstTransaction<'_> {
102 fn drop(&mut self) {
103 if !self.finished {
104 if let Some(log) = self.ast.pending.take() {
105 self.ast.apply_rollback(&log);
106 }
107 }
108 }
109}
110
111impl Ast {
112 pub fn begin(&mut self) -> AstTransaction<'_> {
117 AstTransaction::new(self)
118 }
119
120 pub(crate) fn record_created(&mut self, any: AnyId) -> Result<(), AstError> {
123 let change = Change::Created {
124 node: any.node_id(),
125 kind: any.kind().tag(),
126 };
127 let undo = UndoRecord {
128 node: any.node_id(),
129 payload: UndoPayload::Remove,
130 };
131 self.record(undo, change)
132 }
133
134 fn record(&mut self, undo: UndoRecord, change: Change) -> Result<(), AstError> {
135 if let Some(log) = self.pending.as_mut() {
136 log.record(undo, change);
137 return Ok(());
138 }
139 self.record_standalone(undo, change)
140 }
141
142 pub(crate) fn record_standalone(
144 &mut self,
145 undo: UndoRecord,
146 change: Change,
147 ) -> Result<(), AstError> {
148 self.sequence = self.sequence.saturating_add(1);
150 let mut log = TxnLog::new(self.sequence);
151 log.record(undo, change);
152
153 let touched: Vec<NodeId> = log.nodes_touched().collect();
154 let violations = invariant::check(self, &touched);
155 if !violations.is_empty() {
156 self.apply_rollback(&log);
157 return Err(AstError::Invariant(violations));
158 }
159
160 let changeset = log.into_changeset();
161 self.stash.clear();
162 self.observers.notify(&changeset);
163 Ok(())
164 }
165
166 pub(crate) fn apply_rollback(&mut self, log: &TxnLog) {
168 for record in log.undo_records().rev() {
169 self.apply_undo(record);
170 }
171 self.stash.clear();
172 }
173
174 fn apply_undo(&mut self, record: &UndoRecord) {
175 match &record.payload {
176 UndoPayload::Remove => {
177 if let Some(any) = self.resolve_node_id(record.node) {
178 self.detach_and_remove(any);
179 }
180 }
181 UndoPayload::Recreate { stash } => {
182 self.restore_from_stash(*stash as usize);
183 }
184 UndoPayload::RestoreField { field, value } => {
185 self.restore_field(record.node, *field, value);
186 }
187 UndoPayload::RestorePending { key, slot } => {
188 self.restore_pending(record.node, key, *slot);
189 }
190 }
191 }
192
193 fn restore_field(
199 &mut self,
200 node: NodeId,
201 field: zerodds_ast_core::FieldTag,
202 value: &FieldValue,
203 ) {
204 let Some(any) = self.resolve_node_id(node) else {
205 return;
206 };
207 match field {
208 crate::field::COMPLETENESS => {
209 let FieldValue::Bool(complete) = value else {
210 return;
211 };
212 if let Some(id) = any.as_type() {
213 if let Ok(t) = self.types.get_mut(id) {
214 t.completeness = if *complete {
215 crate::Completeness::Complete
216 } else {
217 crate::Completeness::Forward
218 };
219 }
220 }
221 }
222 crate::field::NAME => {
223 let FieldValue::Text(name) = value else {
224 return;
225 };
226 self.restore_name(any, name);
227 }
228 _ => {}
232 }
233 }
234
235 fn restore_name(&mut self, any: AnyId, name: &str) {
236 match any {
237 AnyId::Type(id, _) => {
238 if let Ok(t) = self.types.get_mut(id) {
239 t.name = name.into();
240 }
241 }
242 AnyId::Member(id, _) => {
243 if let Ok(m) = self.members.get_mut(id) {
244 m.name = name.into();
245 }
246 }
247 AnyId::Module(id, _) => {
248 if let Ok(m) = self.modules.get_mut(id) {
249 m.name = name.into();
250 }
251 }
252 _ => {}
253 }
254 }
255
256 fn restore_pending(&mut self, node: NodeId, key: &zerodds_ast_core::PendingRef, slot: usize) {
258 let Some(any) = self.resolve_node_id(node) else {
259 return;
260 };
261 let back = Ref::Pending(key.clone());
262 match any {
263 AnyId::Type(id, _) => {
264 if let Ok(t) = self.types.get_mut(id) {
265 if let Some(reference) = t.kind.type_refs_mut().into_iter().nth(slot) {
266 *reference = back;
267 }
268 }
269 }
270 AnyId::Member(id, _) => {
271 if let Ok(m) = self.members.get_mut(id) {
272 m.type_ = back;
273 }
274 }
275 _ => return,
276 }
277 self.index_pending(any);
279 }
280
281 fn restore_from_stash(&mut self, index: usize) {
282 let Some(entry) = self.stash.get_mut(index).and_then(Option::take) else {
283 return;
284 };
285 match entry {
286 Stashed::Type(node) => {
287 let module = node.module;
288 let node_id = node.node_id;
289 if let Ok(id) = self.types.insert(node) {
290 let any = AnyId::Type(id, node_id);
291 let _ = self.by_node_id.insert(node_id, any);
292 if let Ok(m) = self.modules.get_mut(module) {
293 m.children.push(any);
294 }
295 self.index_node(any);
296 }
297 }
298 Stashed::Member(node, position) => {
299 let parent = node.parent;
300 let node_id = node.node_id;
301 if let Ok(id) = self.members.insert(node) {
302 let any = AnyId::Member(id, node_id);
303 let _ = self.by_node_id.insert(node_id, any);
304 self.index_node(any);
305 if let Some(type_id) = parent.as_type() {
306 if let Ok(t) = self.types.get_mut(type_id) {
307 match &mut t.kind {
308 TypeKind::Structure { members, .. }
309 | TypeKind::Valuetype { state: members, .. } => {
310 let at = position.min(members.len());
311 members.insert(at, id);
312 }
313 _ => {}
314 }
315 }
316 }
317 }
318 }
319 }
320 }
321
322 pub fn remove(&mut self, any: AnyId) -> Result<(), AstError> {
334 if self.resolve_node_id(any.node_id()).is_none() {
335 return Err(AstError::NotFound {
336 node: any.node_id(),
337 });
338 }
339
340 let own_transaction = self.pending.is_none();
341 if own_transaction {
342 self.sequence = self.sequence.saturating_add(1);
343 let sequence = self.sequence;
344 self.pending = Some(TxnLog::new(sequence));
345 }
346
347 self.remove_cascade(any);
348
349 if !own_transaction {
350 return Ok(());
351 }
352
353 let Some(log) = self.pending.take() else {
354 return Ok(());
355 };
356 let touched: Vec<NodeId> = log.nodes_touched().collect();
357 let violations = invariant::check(self, &touched);
358 if !violations.is_empty() {
359 self.apply_rollback(&log);
360 return Err(AstError::Invariant(violations));
361 }
362 let changeset = log.into_changeset();
363 self.stash.clear();
364 self.observers.notify(&changeset);
365 Ok(())
366 }
367
368 fn remove_cascade(&mut self, any: AnyId) {
369 for child in self.owned_parts_of(any) {
372 self.remove_cascade(child);
373 }
374
375 let node_id = any.node_id();
376 let stash_index = self.stash_node(any);
377 self.detach_and_remove(any);
378 self.break_references_to(any);
379
380 let undo = UndoRecord {
381 node: node_id,
382 payload: stash_index
383 .map_or(UndoPayload::Remove, |stash| UndoPayload::Recreate { stash }),
384 };
385 let change = Change::Deleted {
386 node: node_id,
387 kind: any.kind().tag(),
388 };
389 if let Some(log) = self.pending.as_mut() {
390 log.record(undo, change);
391 }
392 }
393
394 fn owned_parts_of(&self, any: AnyId) -> Vec<AnyId> {
401 match any {
402 AnyId::Type(id, _) => self.owned_parts_of_type(id),
403 AnyId::Interface(id, _) => {
404 let Ok(node) = self.interfaces.get(id) else {
405 return Vec::new();
406 };
407 let mut out = Vec::new();
408 for operation in &node.operations {
409 if let Ok(o) = self.operations.get(*operation) {
410 out.push(AnyId::Operation(*operation, o.node_id));
411 }
412 }
413 for attribute in &node.attributes {
414 if let Ok(a) = self.attributes.get(*attribute) {
415 out.push(AnyId::Attribute(*attribute, a.node_id));
416 }
417 }
418 out
419 }
420 AnyId::Operation(id, _) => {
421 let Ok(node) = self.operations.get(id) else {
422 return Vec::new();
423 };
424 node.params
425 .iter()
426 .filter_map(|param| {
427 self.params
428 .get(*param)
429 .ok()
430 .map(|p| AnyId::Param(*param, p.node_id))
431 })
432 .collect()
433 }
434 AnyId::AnnotationDef(id, _) => {
435 let Ok(node) = self.annotation_defs.get(id) else {
436 return Vec::new();
437 };
438 node.members
439 .iter()
440 .filter_map(|member| {
441 self.annotation_members
442 .get(*member)
443 .ok()
444 .map(|m| AnyId::AnnotationMember(*member, m.node_id))
445 })
446 .collect()
447 }
448 AnyId::Exception(id, _) => {
449 let Ok(node) = self.exceptions.get(id) else {
450 return Vec::new();
451 };
452 node.members
453 .iter()
454 .filter_map(|member| {
455 self.members
456 .get(*member)
457 .ok()
458 .map(|m| AnyId::Member(*member, m.node_id))
459 })
460 .collect()
461 }
462 _ => Vec::new(),
463 }
464 }
465
466 fn owned_parts_of_type(&self, id: zerodds_ast_core::Id<crate::TypeNode>) -> Vec<AnyId> {
467 let Ok(node) = self.types.get(id) else {
468 return Vec::new();
469 };
470 let mut out = Vec::new();
471 match &node.kind {
472 TypeKind::Structure { members, .. } | TypeKind::Valuetype { state: members, .. } => {
473 for member in members {
474 if let Ok(m) = self.members.get(*member) {
475 out.push(AnyId::Member(*member, m.node_id));
476 }
477 }
478 }
479 TypeKind::Union { cases, .. } => {
480 for case in cases {
481 if let Ok(c) = self.cases.get(*case) {
482 if let Ok(m) = self.members.get(c.member) {
483 out.push(AnyId::Member(c.member, m.node_id));
484 }
485 out.push(AnyId::Case(*case, c.node_id));
486 }
487 }
488 }
489 TypeKind::Enumeration { enumerators } => {
490 for enumerator in enumerators {
491 if let Ok(e) = self.enumerators.get(*enumerator) {
492 out.push(AnyId::Enumerator(*enumerator, e.node_id));
493 }
494 }
495 }
496 TypeKind::Bitmask { bits } => {
497 for bit in bits {
498 if let Ok(b) = self.bit_values.get(*bit) {
499 out.push(AnyId::BitValue(*bit, b.node_id));
500 }
501 }
502 }
503 TypeKind::Bitset { fields, .. } => {
504 for field in fields {
505 if let Ok(b) = self.bitfields.get(*field) {
506 out.push(AnyId::Bitfield(*field, b.node_id));
507 }
508 }
509 }
510 _ => {}
511 }
512 out
513 }
514
515 fn stash_node(&mut self, any: AnyId) -> Option<u32> {
521 let entry = match any {
522 AnyId::Type(id, _) => Stashed::Type(self.types.get(id).ok()?.clone()),
523 AnyId::Member(id, _) => {
524 let member = self.members.get(id).ok()?.clone();
525 let position = member
526 .parent
527 .as_type()
528 .and_then(|t| self.types.get(t).ok())
529 .and_then(|t| t.kind.members().iter().position(|m| *m == id))
530 .unwrap_or(0);
531 Stashed::Member(member, position)
532 }
533 _ => return None,
534 };
535 let index = u32::try_from(self.stash.len()).ok()?;
536 self.stash.push(Some(entry));
537 Some(index)
538 }
539
540 fn detach_and_remove(&mut self, any: AnyId) {
541 let node_id = any.node_id();
542 let _ = self.by_node_id.remove(&node_id);
543 self.unindex_node(node_id);
546
547 match any {
548 AnyId::Type(id, _) => {
549 if let Ok(node) = self.types.get(id) {
550 let module = node.module;
551 if let Ok(m) = self.modules.get_mut(module) {
552 m.children.retain(|c| c.node_id() != node_id);
553 }
554 }
555 let _ = self.types.remove(id);
556 }
557 AnyId::Member(id, _) => {
558 if let Ok(node) = self.members.get(id) {
559 let parent = node.parent;
560 if let Some(type_id) = parent.as_type() {
561 if let Ok(t) = self.types.get_mut(type_id) {
562 match &mut t.kind {
563 TypeKind::Structure { members, .. }
564 | TypeKind::Valuetype { state: members, .. } => {
565 members.retain(|m| *m != id);
566 }
567 _ => {}
568 }
569 }
570 }
571 }
572 let _ = self.members.remove(id);
573 }
574 AnyId::Case(id, _) => {
575 if let Ok(node) = self.cases.get(id) {
576 let parent = node.parent;
577 if let Ok(t) = self.types.get_mut(parent) {
578 if let TypeKind::Union {
579 cases,
580 default_case,
581 ..
582 } = &mut t.kind
583 {
584 cases.retain(|c| *c != id);
585 if *default_case == Some(id) {
586 *default_case = None;
587 }
588 }
589 }
590 }
591 let _ = self.cases.remove(id);
592 }
593 AnyId::Enumerator(id, _) => {
594 if let Ok(node) = self.enumerators.get(id) {
595 let parent = node.parent;
596 if let Ok(t) = self.types.get_mut(parent) {
597 if let TypeKind::Enumeration { enumerators } = &mut t.kind {
598 enumerators.retain(|e| *e != id);
599 }
600 }
601 }
602 let _ = self.enumerators.remove(id);
603 }
604 AnyId::BitValue(id, _) => {
605 if let Ok(node) = self.bit_values.get(id) {
606 let parent = node.parent;
607 if let Ok(t) = self.types.get_mut(parent) {
608 if let TypeKind::Bitmask { bits } = &mut t.kind {
609 bits.retain(|b| *b != id);
610 }
611 }
612 }
613 let _ = self.bit_values.remove(id);
614 }
615 AnyId::Bitfield(id, _) => {
616 if let Ok(node) = self.bitfields.get(id) {
617 let parent = node.parent;
618 if let Ok(t) = self.types.get_mut(parent) {
619 if let TypeKind::Bitset { fields, .. } = &mut t.kind {
620 fields.retain(|f| *f != id);
621 }
622 }
623 }
624 let _ = self.bitfields.remove(id);
625 }
626 AnyId::Module(id, _) => {
627 if let Ok(node) = self.modules.get(id) {
628 if let Some(parent) = node.parent {
629 if let Ok(m) = self.modules.get_mut(parent) {
630 m.children.retain(|c| c.node_id() != node_id);
631 }
632 }
633 }
634 let _ = self.modules.remove(id);
635 }
636 AnyId::Const(id, _) => {
644 if let Ok(node) = self.constants.get(id) {
645 let module = node.module;
646 if let Ok(m) = self.modules.get_mut(module) {
647 m.children.retain(|c| c.node_id() != node_id);
648 }
649 }
650 let _ = self.constants.remove(id);
651 }
652 AnyId::ConstExpr(id, _) => {
653 let _ = self.exprs.remove(id);
654 }
655 AnyId::Interface(id, _) => {
656 if let Ok(node) = self.interfaces.get(id) {
657 let module = node.module;
658 if let Ok(m) = self.modules.get_mut(module) {
659 m.children.retain(|c| c.node_id() != node_id);
660 }
661 }
662 let _ = self.interfaces.remove(id);
663 }
664 AnyId::Operation(id, _) => {
665 if let Ok(node) = self.operations.get(id) {
666 if let Some(interface) = node.parent.as_interface() {
667 if let Ok(i) = self.interfaces.get_mut(interface) {
668 i.operations.retain(|o| *o != id);
669 }
670 }
671 if let Some(type_id) = node.parent.as_type() {
672 if let Ok(t) = self.types.get_mut(type_id) {
673 if let TypeKind::Valuetype { initializers, .. } = &mut t.kind {
674 initializers.retain(|o| *o != id);
675 }
676 }
677 }
678 }
679 let _ = self.operations.remove(id);
680 }
681 AnyId::Param(id, _) => {
682 if let Ok(node) = self.params.get(id) {
683 let parent = node.parent;
684 if let Ok(o) = self.operations.get_mut(parent) {
685 o.params.retain(|p| *p != id);
686 }
687 }
688 let _ = self.params.remove(id);
689 }
690 AnyId::Attribute(id, _) => {
691 if let Ok(node) = self.attributes.get(id) {
692 let parent = node.parent;
693 if let Ok(i) = self.interfaces.get_mut(parent) {
694 i.attributes.retain(|a| *a != id);
695 }
696 }
697 let _ = self.attributes.remove(id);
698 }
699 AnyId::Exception(id, _) => {
700 if let Ok(node) = self.exceptions.get(id) {
701 let module = node.module;
702 if let Ok(m) = self.modules.get_mut(module) {
703 m.children.retain(|c| c.node_id() != node_id);
704 }
705 }
706 let _ = self.exceptions.remove(id);
707 }
708 AnyId::AnnotationDef(id, _) => {
709 if let Ok(node) = self.annotation_defs.get(id) {
710 let module = node.module;
711 if let Ok(m) = self.modules.get_mut(module) {
712 m.children.retain(|c| c.node_id() != node_id);
713 }
714 }
715 let _ = self.annotation_defs.remove(id);
716 }
717 AnyId::AnnotationMember(id, _) => {
718 if let Ok(node) = self.annotation_members.get(id) {
719 let parent = node.parent;
720 if let Ok(d) = self.annotation_defs.get_mut(parent) {
721 d.members.retain(|m| *m != id);
722 }
723 }
724 let _ = self.annotation_members.remove(id);
725 }
726 AnyId::Domain(id, _) => {
727 let _ = self.domains.remove(id);
728 }
729 AnyId::Topic(id, _) => {
730 let _ = self.topics.remove(id);
731 }
732 AnyId::QosProfile(id, _) => {
733 let _ = self.qos_profiles.remove(id);
734 }
735 AnyId::Participant(id, _) => {
736 let _ = self.participants.remove(id);
737 }
738 AnyId::Endpoint(id, _) => {
739 let _ = self.endpoints.remove(id);
740 }
741 AnyId::Library(id, _) => {
742 let _ = self.libraries.remove(id);
743 }
744 }
745 }
746
747 fn break_references_to(&mut self, removed: AnyId) {
750 let Some(type_id) = removed.as_type() else {
751 return;
752 };
753 let cause = zerodds_ast_core::BreakCause::NotFound {
754 what: zerodds_ast_core::PendingRef::ScopedName(zerodds_ast_core::ScopedName::absolute(
755 alloc::vec::Vec::new(),
756 )),
757 };
758
759 for (_, node) in self.types.iter_mut_all() {
760 break_in_kind(&mut node.kind, type_id, &cause);
761 }
762 for (_, member) in self.members.iter_mut_all() {
763 if member.type_.resolved() == Some(type_id) {
764 member.type_ = Ref::Broken(cause.clone());
765 }
766 }
767 }
768}
769
770fn break_in_kind(
771 kind: &mut TypeKind,
772 removed: zerodds_ast_core::Id<crate::TypeNode>,
773 cause: &zerodds_ast_core::BreakCause,
774) {
775 let fix = |reference: &mut Ref<crate::TypeNode>| {
776 if reference.resolved() == Some(removed) {
777 *reference = Ref::Broken(cause.clone());
778 }
779 };
780 match kind {
781 TypeKind::Sequence { element, .. } | TypeKind::Array { element, .. } => fix(element),
782 TypeKind::Map { key, value, .. } => {
783 fix(key);
784 fix(value);
785 }
786 TypeKind::Alias { aliased } => fix(aliased),
787 TypeKind::ValueBox { boxed } => fix(boxed),
788 TypeKind::Union { discriminator, .. } => fix(discriminator),
789 TypeKind::Structure { base, .. } | TypeKind::Bitset { base, .. } => {
790 if let Some(base) = base.as_mut() {
791 fix(base);
792 }
793 }
794 TypeKind::Valuetype { bases, .. } => {
795 for base in bases.iter_mut() {
796 fix(base);
797 }
798 }
799 _ => {}
800 }
801}
802
803pub use crate::invariant::InvariantViolation as CommitViolation;
805
806const _: () = {
807 let _ = core::mem::size_of::<InvariantViolation>();
809};