1use indexmap::IndexSet;
2
3use crate::document::interpreter_sink::InterpreterSink;
4use crate::map::PartialNodeMap;
5use crate::prelude_internal::*;
6use crate::value::PartialObjectKey;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Scope {
13 id: usize,
14 stack_depth: usize,
15 path_depth: usize,
16}
17
18#[derive(Debug, PartialEq, thiserror::Error, Clone)]
19pub enum ScopeError {
20 #[error("Cannot end scope at root")]
21 CannotEndAtRoot,
22 #[error("Scope must be ended in LIFO order (most recent first)")]
23 NotMostRecentScope,
24}
25
26pub struct DocumentConstructor {
27 document: EureDocument,
28 path: Vec<PathSegment>,
30 stack: Vec<NodeId>,
32 scope_counter: usize,
34 outstanding_scopes: Vec<usize>,
36 hole_bound: Vec<bool>,
38 unbound_nodes: IndexSet<NodeId>,
40}
41
42impl Default for DocumentConstructor {
43 fn default() -> Self {
44 let document = EureDocument::default();
45 let root = document.get_root_id();
46 Self {
47 document,
48 path: vec![],
49 stack: vec![root],
50 hole_bound: vec![false],
51 scope_counter: 0,
52 outstanding_scopes: vec![],
53 unbound_nodes: IndexSet::new(),
54 }
55 }
56}
57
58impl DocumentConstructor {
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn current_node_id(&self) -> NodeId {
64 *self.stack.last().expect("Stack should never be empty")
65 }
66
67 pub fn current_node(&self) -> &Node {
68 self.document.node(self.current_node_id())
69 }
70
71 pub fn current_node_mut(&mut self) -> &mut Node {
72 self.document.node_mut(self.current_node_id())
73 }
74
75 pub fn current_path(&self) -> &[PathSegment] {
76 &self.path
77 }
78
79 pub fn document(&self) -> &EureDocument {
80 &self.document
81 }
82
83 pub fn document_mut(&mut self) -> &mut EureDocument {
84 &mut self.document
85 }
86
87 pub fn finish(mut self) -> EureDocument {
88 for node_id in self.unbound_nodes {
89 let node = self.document.node_mut(node_id);
90 if node.content.is_hole() {
91 node.content = NodeValue::Map(Default::default());
92 }
93 }
94 let root_id = self.document.get_root_id();
96 let root_node = self.document.node_mut(root_id);
97 if root_node.content.is_hole() && !self.hole_bound[0] {
98 root_node.content = NodeValue::Map(Default::default());
99 }
100 self.document
101 }
102}
103
104impl DocumentConstructor {
105 pub fn begin_scope(&mut self) -> Scope {
108 let id = self.scope_counter;
109 self.scope_counter += 1;
110 self.outstanding_scopes.push(id);
111 Scope {
112 id,
113 stack_depth: self.stack.len(),
114 path_depth: self.path.len(),
115 }
116 }
117
118 pub fn end_scope(&mut self, scope: Scope) -> Result<(), ScopeError> {
121 if self.outstanding_scopes.last() != Some(&scope.id) {
123 return Err(ScopeError::NotMostRecentScope);
124 }
125 if scope.stack_depth < 1 {
126 return Err(ScopeError::CannotEndAtRoot);
127 }
128 self.outstanding_scopes.pop();
129 for i in scope.stack_depth..self.stack.len() {
130 let hole_bound = self.hole_bound[i];
131 if !hole_bound && self.document.node(self.stack[i]).content.is_hole() {
132 self.unbound_nodes.insert(self.stack[i]);
133 }
134 }
135 self.stack.truncate(scope.stack_depth);
136 self.hole_bound.truncate(scope.stack_depth);
137 self.path.truncate(scope.path_depth);
138 Ok(())
139 }
140
141 pub fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, InsertError> {
144 let current = self.current_node_id();
145 let node_mut = self
146 .document
147 .resolve_child_by_segment(segment.clone(), current)
148 .map_err(|e| InsertError {
149 kind: e,
150 path: EurePath::from_iter(self.path.iter().cloned()),
151 })?;
152 let node_id = node_mut.node_id;
153 self.stack.push(node_id);
154 self.hole_bound.push(false);
155 self.path.push(segment);
156 Ok(node_id)
157 }
158
159 pub fn navigate_partial_map_entry(
165 &mut self,
166 key: PartialObjectKey,
167 ) -> Result<NodeId, InsertError> {
168 let current = self.current_node_id();
169 let existing = self
170 .document
171 .node(current)
172 .as_partial_map()
173 .and_then(|pm| pm.find(&key))
174 .copied();
175
176 let node_id = if let Some(node_id) = existing {
177 node_id
178 } else {
179 self.document
180 .add_partial_map_child(key.clone(), current)
181 .map_err(|kind| InsertError {
182 kind,
183 path: EurePath::from_iter(self.path.iter().cloned()),
184 })?
185 .node_id
186 };
187
188 let segment = PathSegment::from_partial_object_key(key);
189
190 self.stack.push(node_id);
191 self.hole_bound.push(false);
192 self.path.push(segment);
193 Ok(node_id)
194 }
195
196 pub fn require_hole(&self) -> Result<(), InsertError> {
199 let node = self.current_node();
200 if !node.content.is_hole() {
201 return Err(InsertError {
202 kind: InsertErrorKind::BindingTargetHasValue,
203 path: EurePath::from_iter(self.path.iter().cloned()),
204 });
205 }
206 Ok(())
207 }
208
209 pub fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), InsertError> {
211 if !self.current_node().content.is_hole() {
212 return Err(InsertError {
213 kind: InsertErrorKind::BindingTargetHasValue,
214 path: EurePath::from_iter(self.current_path().iter().cloned()),
215 });
216 }
217 self.hole_bound[self.stack.len() - 1] = true;
218 self.unbound_nodes.swap_remove(&self.current_node_id());
219 self.current_node_mut().content = NodeValue::Hole(label);
220 Ok(())
221 }
222
223 pub fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), InsertError> {
225 let node = self.current_node_mut();
226 if !node.content.is_hole() {
227 return Err(InsertError {
228 kind: InsertErrorKind::BindingTargetHasValue,
229 path: EurePath::from_iter(self.current_path().iter().cloned()),
230 });
231 }
232 node.content = NodeValue::Primitive(value);
233 Ok(())
234 }
235
236 pub fn bind_from(&mut self, value: impl Into<PrimitiveValue>) -> Result<(), InsertError> {
241 self.bind_primitive(value.into())
242 }
243
244 pub fn bind_empty_map(&mut self) -> Result<(), InsertError> {
246 let node = self.current_node_mut();
247 if !node.content.is_hole() {
248 return Err(InsertError {
249 kind: InsertErrorKind::BindingTargetHasValue,
250 path: EurePath::from_iter(self.current_path().iter().cloned()),
251 });
252 }
253 node.content = NodeValue::Map(Default::default());
254 Ok(())
255 }
256
257 pub fn bind_empty_partial_map(&mut self) -> Result<(), InsertError> {
259 let node = self.current_node_mut();
260 if !node.content.is_hole() {
261 return Err(InsertError {
262 kind: InsertErrorKind::BindingTargetHasValue,
263 path: EurePath::from_iter(self.current_path().iter().cloned()),
264 });
265 }
266 node.content = NodeValue::PartialMap(PartialNodeMap::new());
267 Ok(())
268 }
269
270 pub fn bind_empty_array(&mut self) -> Result<(), InsertError> {
272 let node = self.current_node_mut();
273 if !node.content.is_hole() {
274 return Err(InsertError {
275 kind: InsertErrorKind::BindingTargetHasValue,
276 path: EurePath::from_iter(self.current_path().iter().cloned()),
277 });
278 }
279 node.content = NodeValue::Array(Default::default());
280 Ok(())
281 }
282
283 pub fn bind_empty_tuple(&mut self) -> Result<(), InsertError> {
285 let node = self.current_node_mut();
286 if !node.content.is_hole() {
287 return Err(InsertError {
288 kind: InsertErrorKind::BindingTargetHasValue,
289 path: EurePath::from_iter(self.current_path().iter().cloned()),
290 });
291 }
292 node.content = NodeValue::Tuple(Default::default());
293 Ok(())
294 }
295
296 pub fn begin_eure_block(&mut self) {}
305
306 pub fn set_block_value(&mut self) -> Result<(), InsertError> {
308 Ok(())
309 }
310
311 pub fn end_eure_block(&mut self) -> Result<(), InsertError> {
313 Ok(())
314 }
315
316 pub fn begin_binding(&mut self) {}
318
319 pub fn end_binding_value(&mut self) -> Result<(), InsertError> {
321 Ok(())
322 }
323
324 pub fn end_binding_block(&mut self) -> Result<(), InsertError> {
326 Ok(())
327 }
328
329 pub fn begin_section(&mut self) {}
331
332 pub fn begin_section_items(&mut self) {}
334
335 pub fn end_section_items(&mut self) -> Result<(), InsertError> {
337 Ok(())
338 }
339
340 pub fn end_section_block(&mut self) -> Result<(), InsertError> {
342 Ok(())
343 }
344}
345
346impl InterpreterSink for DocumentConstructor {
347 type Error = InsertError;
348 type Scope = Scope;
349
350 fn begin_scope(&mut self) -> Self::Scope {
351 DocumentConstructor::begin_scope(self)
352 }
353
354 fn end_scope(&mut self, scope: Self::Scope) -> Result<(), Self::Error> {
355 DocumentConstructor::end_scope(self, scope).map_err(|e| InsertError {
356 kind: InsertErrorKind::ScopeError(e),
357 path: EurePath::from_iter(self.current_path().iter().cloned()),
358 })
359 }
360
361 fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, Self::Error> {
362 DocumentConstructor::navigate(self, segment)
363 }
364
365 fn require_hole(&self) -> Result<(), Self::Error> {
366 DocumentConstructor::require_hole(self)
367 }
368
369 fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), Self::Error> {
370 DocumentConstructor::bind_primitive(self, value)
371 }
372
373 fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), Self::Error> {
374 DocumentConstructor::bind_hole(self, label)
375 }
376
377 fn bind_empty_map(&mut self) -> Result<(), Self::Error> {
378 DocumentConstructor::bind_empty_map(self)
379 }
380
381 fn bind_empty_array(&mut self) -> Result<(), Self::Error> {
382 DocumentConstructor::bind_empty_array(self)
383 }
384
385 fn bind_empty_tuple(&mut self) -> Result<(), Self::Error> {
386 DocumentConstructor::bind_empty_tuple(self)
387 }
388
389 fn current_node_id(&self) -> NodeId {
390 DocumentConstructor::current_node_id(self)
391 }
392
393 fn current_path(&self) -> &[PathSegment] {
394 DocumentConstructor::current_path(self)
395 }
396
397 fn document(&self) -> &EureDocument {
398 DocumentConstructor::document(self)
399 }
400
401 fn document_mut(&mut self) -> &mut EureDocument {
402 DocumentConstructor::document_mut(self)
403 }
404}
405
406#[cfg(test)]
407mod tests {
408 use super::*;
409 use crate::identifier::IdentifierParser;
410 use crate::value::{PartialObjectKey, Tuple};
411
412 fn create_identifier(s: &str) -> Identifier {
413 let parser = IdentifierParser::init();
414 parser.parse(s).unwrap()
415 }
416
417 #[test]
418 fn test_new_initializes_at_root() {
419 let constructor = DocumentConstructor::new();
420 let root_id = constructor.document().get_root_id();
421
422 assert_eq!(constructor.current_node_id(), root_id);
423 assert_eq!(constructor.current_path(), &[]);
424 }
425
426 #[test]
427 fn test_current_node_returns_root_initially() {
428 let constructor = DocumentConstructor::new();
429
430 let node = constructor.current_node();
431 assert!(node.content.is_hole());
432 }
433
434 #[test]
435 fn test_navigate_single_ident() {
436 let mut constructor = DocumentConstructor::new();
437
438 let identifier = create_identifier("field");
439 let segment = PathSegment::Ident(identifier.clone());
440
441 let node_id = constructor
442 .navigate(segment.clone())
443 .expect("Failed to navigate");
444
445 assert_eq!(constructor.current_node_id(), node_id);
446 assert_eq!(constructor.current_path(), &[segment]);
447 }
448
449 #[test]
450 fn test_navigate_multiple_times() {
451 let mut constructor = DocumentConstructor::new();
452
453 let id1 = create_identifier("field1");
454 let id2 = create_identifier("field2");
455
456 constructor
457 .navigate(PathSegment::Ident(id1.clone()))
458 .expect("Failed to navigate first");
459
460 let node_id2 = constructor
461 .navigate(PathSegment::Extension(id2.clone()))
462 .expect("Failed to navigate second");
463
464 assert_eq!(constructor.current_node_id(), node_id2);
465 assert_eq!(
466 constructor.current_path(),
467 &[PathSegment::Ident(id1), PathSegment::Extension(id2)]
468 );
469 }
470
471 #[test]
472 fn test_navigate_error_propagates() {
473 let mut constructor = DocumentConstructor::new();
475 let identifier = create_identifier("field");
477 constructor
478 .navigate(PathSegment::Ident(identifier))
479 .expect("Failed to navigate");
480 let node_id = constructor.current_node_id();
482 constructor.document_mut().node_mut(node_id).content =
483 NodeValue::Primitive(PrimitiveValue::Null);
484
485 let result = constructor.navigate(PathSegment::TupleIndex(0));
486
487 assert_eq!(
488 result.map_err(|e| e.kind),
489 Err(InsertErrorKind::ExpectedTuple)
490 );
491 }
492
493 #[test]
494 fn test_scope_success() {
495 let mut constructor = DocumentConstructor::new();
496 let root_id = constructor.document().get_root_id();
497
498 let identifier = create_identifier("field");
499 let token = constructor.begin_scope();
500 let _node_id = constructor
501 .navigate(PathSegment::Ident(identifier.clone()))
502 .expect("Failed to navigate");
503
504 let result = constructor.end_scope(token);
506 assert_eq!(result, Ok(()));
507
508 assert_eq!(constructor.current_node_id(), root_id);
510 assert_eq!(constructor.current_path(), &[]);
511 }
512
513 #[test]
514 fn test_scope_lifo_enforcement() {
515 let mut constructor = DocumentConstructor::new();
516
517 let id1 = create_identifier("field1");
518 let id2 = create_identifier("field2");
519
520 let token1 = constructor.begin_scope();
521 constructor
522 .navigate(PathSegment::Ident(id1))
523 .expect("Failed to navigate");
524
525 let token2 = constructor.begin_scope();
526 constructor
527 .navigate(PathSegment::Extension(id2))
528 .expect("Failed to navigate");
529
530 let result = constructor.end_scope(token1);
532 assert_eq!(result, Err(ScopeError::NotMostRecentScope));
533
534 constructor
536 .end_scope(token2)
537 .expect("Failed to end scope 2");
538 constructor
539 .end_scope(token1)
540 .expect("Failed to end scope 1");
541 }
542
543 #[test]
544 fn test_scope_with_multiple_navigations() {
545 let mut constructor = DocumentConstructor::new();
546 let root_id = constructor.document().get_root_id();
547
548 let id1 = create_identifier("level1");
549 let id2 = create_identifier("level2");
550 let id3 = create_identifier("level3");
551
552 let token = constructor.begin_scope();
553
554 let node_id1 = constructor
556 .navigate(PathSegment::Ident(id1.clone()))
557 .expect("Failed to navigate level1");
558
559 let node_id2 = constructor
560 .navigate(PathSegment::Extension(id2.clone()))
561 .expect("Failed to navigate level2");
562
563 let node_id3 = constructor
564 .navigate(PathSegment::Extension(id3.clone()))
565 .expect("Failed to navigate level3");
566
567 assert_eq!(constructor.current_node_id(), node_id3);
569 assert_eq!(
570 constructor.current_path(),
571 &[
572 PathSegment::Ident(id1.clone()),
573 PathSegment::Extension(id2.clone()),
574 PathSegment::Extension(id3)
575 ]
576 );
577
578 constructor.end_scope(token).expect("Failed to end scope");
580 assert_eq!(constructor.current_node_id(), root_id);
581 assert_eq!(constructor.current_path(), &[]);
582
583 let _ = constructor.document().node(node_id1);
585 let _ = constructor.document().node(node_id2);
586 let _ = constructor.document().node(node_id3);
587 }
588
589 #[test]
590 fn test_nested_scopes() {
591 let mut constructor = DocumentConstructor::new();
592 let root_id = constructor.document().get_root_id();
593
594 let id1 = create_identifier("a");
595 let id2 = create_identifier("b");
596 let id3 = create_identifier("c");
597
598 let token_outer = constructor.begin_scope();
600 let node_a = constructor
601 .navigate(PathSegment::Ident(id1.clone()))
602 .expect("Failed to navigate a");
603
604 let token_inner = constructor.begin_scope();
606 let _node_b = constructor
607 .navigate(PathSegment::Extension(id2.clone()))
608 .expect("Failed to navigate b");
609 let _node_c = constructor
610 .navigate(PathSegment::Extension(id3.clone()))
611 .expect("Failed to navigate c");
612
613 constructor
615 .end_scope(token_inner)
616 .expect("Failed to end inner scope");
617 assert_eq!(constructor.current_node_id(), node_a);
618 assert_eq!(constructor.current_path(), &[PathSegment::Ident(id1)]);
619
620 constructor
622 .end_scope(token_outer)
623 .expect("Failed to end outer scope");
624 assert_eq!(constructor.current_node_id(), root_id);
625 assert_eq!(constructor.current_path(), &[]);
626 }
627
628 #[test]
629 fn test_require_hole_success() {
630 let mut constructor = DocumentConstructor::new();
631
632 let identifier = create_identifier("field");
633 constructor
634 .navigate(PathSegment::Ident(identifier))
635 .expect("Failed to navigate");
636
637 let result = constructor.require_hole();
639 assert_eq!(result, Ok(()));
640 }
641
642 #[test]
643 fn test_require_hole_fails_when_bound() {
644 let mut constructor = DocumentConstructor::new();
645
646 let identifier = create_identifier("field");
647 let node_id = constructor
648 .navigate(PathSegment::Ident(identifier))
649 .expect("Failed to navigate");
650
651 constructor.document_mut().node_mut(node_id).content =
653 NodeValue::Primitive(PrimitiveValue::Bool(true));
654
655 let result = constructor.require_hole();
657 assert_eq!(
658 result.unwrap_err().kind,
659 InsertErrorKind::BindingTargetHasValue
660 );
661 }
662
663 #[test]
664 fn test_bind_primitive_success() {
665 let mut constructor = DocumentConstructor::new();
666 let identifier = create_identifier("field");
667
668 let node_id = constructor
670 .navigate(PathSegment::Ident(identifier))
671 .expect("Failed to navigate");
672
673 let result = constructor.bind_primitive(PrimitiveValue::Bool(true));
675 assert_eq!(result, Ok(()));
676
677 let node = constructor.document().node(node_id);
679 assert!(matches!(
680 node.content,
681 NodeValue::Primitive(PrimitiveValue::Bool(true))
682 ));
683 }
684
685 #[test]
686 fn test_bind_primitive_already_bound() {
687 let mut constructor = DocumentConstructor::new();
688 let identifier = create_identifier("field");
689
690 let node_id = constructor
692 .navigate(PathSegment::Ident(identifier.clone()))
693 .expect("Failed to navigate");
694
695 constructor.document_mut().node_mut(node_id).content =
697 NodeValue::Primitive(PrimitiveValue::Null);
698
699 let result = constructor.bind_primitive(PrimitiveValue::Bool(false));
701
702 assert_eq!(
703 result.unwrap_err().kind,
704 InsertErrorKind::BindingTargetHasValue
705 );
706
707 let node = constructor.document().node(node_id);
709 assert!(matches!(
710 node.content,
711 NodeValue::Primitive(PrimitiveValue::Null)
712 ));
713 }
714
715 #[test]
716 fn test_finish_replaces_uninitialized_root_with_null() {
717 let constructor = DocumentConstructor::new();
718
719 let root_id = constructor.document().get_root_id();
721 assert!(constructor.document().node(root_id).content.is_hole());
722
723 let document = constructor.finish();
725 let root_node = document.node(document.get_root_id());
726 assert_eq!(root_node.content, NodeValue::Map(Default::default()));
727 }
728
729 #[test]
730 fn test_finish_preserves_initialized_root() {
731 let mut constructor = DocumentConstructor::new();
732
733 constructor
735 .bind_primitive(PrimitiveValue::Bool(true))
736 .expect("Failed to bind");
737
738 let document = constructor.finish();
740 let root_node = document.node(document.get_root_id());
741 assert!(matches!(
742 root_node.content,
743 NodeValue::Primitive(PrimitiveValue::Bool(true))
744 ));
745 }
746
747 #[test]
748 fn test_finish_preserves_partial_map_root() {
749 let mut constructor = DocumentConstructor::new();
750
751 constructor
752 .navigate_partial_map_entry(PartialObjectKey::Hole(Some(create_identifier("x"))))
753 .unwrap();
754 constructor
755 .bind_primitive(PrimitiveValue::Integer(1.into()))
756 .unwrap();
757
758 let document = constructor.finish();
759 assert!(matches!(
760 document.node(document.get_root_id()).content,
761 NodeValue::PartialMap(_)
762 ));
763 }
764
765 #[test]
766 fn test_navigate_partial_map_entry_does_not_reuse_tuple_with_anonymous_hole() {
767 let mut constructor = DocumentConstructor::new();
768 let scope = constructor.begin_scope();
769
770 let key = PartialObjectKey::Tuple(Tuple(vec![
771 PartialObjectKey::Number(1.into()),
772 PartialObjectKey::Hole(None),
773 ]));
774
775 let first = constructor.navigate_partial_map_entry(key.clone()).unwrap();
776 constructor.end_scope(scope).unwrap();
777
778 let second_scope = constructor.begin_scope();
779 let second = constructor.navigate_partial_map_entry(key).unwrap();
780
781 assert_ne!(first, second);
782 constructor.end_scope(second_scope).unwrap();
783 }
784
785 #[test]
786 fn test_navigate_reuses_labeled_hole_key_segment() {
787 let mut constructor = DocumentConstructor::new();
788 let label = create_identifier("x");
789
790 let scope = constructor.begin_scope();
791 let first = constructor
792 .navigate(PathSegment::HoleKey(Some(label.clone())))
793 .unwrap();
794 constructor.end_scope(scope).unwrap();
795
796 let scope = constructor.begin_scope();
797 let second = constructor
798 .navigate(PathSegment::HoleKey(Some(label)))
799 .unwrap();
800
801 assert_eq!(first, second);
802 constructor.end_scope(scope).unwrap();
803 }
804
805 #[test]
806 fn test_typical_binding_pattern() {
807 let mut constructor = DocumentConstructor::new();
809
810 let id_a = create_identifier("a");
811 let id_b = create_identifier("b");
812 let id_c = create_identifier("c");
813
814 let token = constructor.begin_scope();
815 constructor
816 .navigate(PathSegment::Ident(id_a.clone()))
817 .unwrap();
818 constructor
819 .navigate(PathSegment::Extension(id_b.clone()))
820 .unwrap();
821 let node_c = constructor
822 .navigate(PathSegment::Extension(id_c.clone()))
823 .unwrap();
824 constructor.require_hole().unwrap();
825 constructor
826 .bind_primitive(PrimitiveValue::Bool(true))
827 .unwrap();
828 constructor.end_scope(token).unwrap();
829
830 let node = constructor.document().node(node_c);
832 assert!(matches!(
833 node.content,
834 NodeValue::Primitive(PrimitiveValue::Bool(true))
835 ));
836 }
837}