1use indexmap::IndexSet;
2
3use crate::document::interpreter_sink::InterpreterSink;
4use crate::prelude_internal::*;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Scope {
11 id: usize,
12 stack_depth: usize,
13 path_depth: usize,
14}
15
16#[derive(Debug, PartialEq, thiserror::Error, Clone)]
17pub enum ScopeError {
18 #[error("Cannot end scope at root")]
19 CannotEndAtRoot,
20 #[error("Scope must be ended in LIFO order (most recent first)")]
21 NotMostRecentScope,
22}
23
24pub struct DocumentConstructor {
25 document: EureDocument,
26 path: Vec<PathSegment>,
28 stack: Vec<NodeId>,
30 scope_counter: usize,
32 outstanding_scopes: Vec<usize>,
34 hole_bound: Vec<bool>,
36 unbound_nodes: IndexSet<NodeId>,
38}
39
40impl Default for DocumentConstructor {
41 fn default() -> Self {
42 let document = EureDocument::default();
43 let root = document.get_root_id();
44 Self {
45 document,
46 path: vec![],
47 stack: vec![root],
48 hole_bound: vec![false],
49 scope_counter: 0,
50 outstanding_scopes: vec![],
51 unbound_nodes: IndexSet::new(),
52 }
53 }
54}
55
56impl DocumentConstructor {
57 pub fn new() -> Self {
58 Self::default()
59 }
60
61 pub fn current_node_id(&self) -> NodeId {
62 *self.stack.last().expect("Stack should never be empty")
63 }
64
65 pub fn current_node(&self) -> &Node {
66 self.document.node(self.current_node_id())
67 }
68
69 pub fn current_node_mut(&mut self) -> &mut Node {
70 self.document.node_mut(self.current_node_id())
71 }
72
73 pub fn current_path(&self) -> &[PathSegment] {
74 &self.path
75 }
76
77 pub fn document(&self) -> &EureDocument {
78 &self.document
79 }
80
81 pub fn document_mut(&mut self) -> &mut EureDocument {
82 &mut self.document
83 }
84
85 pub fn finish(mut self) -> EureDocument {
86 for node_id in self.unbound_nodes {
87 let node = self.document.node_mut(node_id);
88 if node.content.is_hole() {
89 node.content = NodeValue::Map(Default::default());
90 }
91 }
92 let root_id = self.document.get_root_id();
94 let root_node = self.document.node_mut(root_id);
95 if root_node.content.is_hole() && !self.hole_bound[0] {
96 root_node.content = NodeValue::Map(Default::default());
97 }
98 self.document
99 }
100}
101
102impl DocumentConstructor {
103 pub fn begin_scope(&mut self) -> Scope {
106 let id = self.scope_counter;
107 self.scope_counter += 1;
108 self.outstanding_scopes.push(id);
109 Scope {
110 id,
111 stack_depth: self.stack.len(),
112 path_depth: self.path.len(),
113 }
114 }
115
116 pub fn end_scope(&mut self, scope: Scope) -> Result<(), ScopeError> {
119 if self.outstanding_scopes.last() != Some(&scope.id) {
121 return Err(ScopeError::NotMostRecentScope);
122 }
123 if scope.stack_depth < 1 {
124 return Err(ScopeError::CannotEndAtRoot);
125 }
126 self.outstanding_scopes.pop();
127 for i in scope.stack_depth..self.stack.len() {
128 let hole_bound = self.hole_bound[i];
129 if !hole_bound && self.document.node(self.stack[i]).content.is_hole() {
130 self.unbound_nodes.insert(self.stack[i]);
131 }
132 }
133 self.stack.truncate(scope.stack_depth);
134 self.hole_bound.truncate(scope.stack_depth);
135 self.path.truncate(scope.path_depth);
136 Ok(())
137 }
138
139 pub fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, InsertError> {
142 let current = self.current_node_id();
143 let node_mut = self
144 .document
145 .resolve_child_by_segment(segment.clone(), current)
146 .map_err(|e| InsertError {
147 kind: e,
148 path: EurePath::from_iter(self.path.iter().cloned()),
149 })?;
150 let node_id = node_mut.node_id;
151 self.stack.push(node_id);
152 self.hole_bound.push(false);
153 self.path.push(segment);
154 Ok(node_id)
155 }
156
157 pub fn require_hole(&self) -> Result<(), InsertError> {
160 let node = self.current_node();
161 if !node.content.is_hole() {
162 return Err(InsertError {
163 kind: InsertErrorKind::BindingTargetHasValue,
164 path: EurePath::from_iter(self.path.iter().cloned()),
165 });
166 }
167 Ok(())
168 }
169
170 pub fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), InsertError> {
172 if !self.current_node().content.is_hole() {
173 return Err(InsertError {
174 kind: InsertErrorKind::BindingTargetHasValue,
175 path: EurePath::from_iter(self.current_path().iter().cloned()),
176 });
177 }
178 self.hole_bound[self.stack.len() - 1] = true;
179 self.unbound_nodes.swap_remove(&self.current_node_id());
180 self.current_node_mut().content = NodeValue::Hole(label);
181 Ok(())
182 }
183
184 pub fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), InsertError> {
186 let node = self.current_node_mut();
187 if !node.content.is_hole() {
188 return Err(InsertError {
189 kind: InsertErrorKind::BindingTargetHasValue,
190 path: EurePath::from_iter(self.current_path().iter().cloned()),
191 });
192 }
193 node.content = NodeValue::Primitive(value);
194 Ok(())
195 }
196
197 pub fn bind_from(&mut self, value: impl Into<PrimitiveValue>) -> Result<(), InsertError> {
202 self.bind_primitive(value.into())
203 }
204
205 pub fn bind_empty_map(&mut self) -> Result<(), InsertError> {
207 let node = self.current_node_mut();
208 if !node.content.is_hole() {
209 return Err(InsertError {
210 kind: InsertErrorKind::BindingTargetHasValue,
211 path: EurePath::from_iter(self.current_path().iter().cloned()),
212 });
213 }
214 node.content = NodeValue::Map(Default::default());
215 Ok(())
216 }
217
218 pub fn bind_empty_array(&mut self) -> Result<(), InsertError> {
220 let node = self.current_node_mut();
221 if !node.content.is_hole() {
222 return Err(InsertError {
223 kind: InsertErrorKind::BindingTargetHasValue,
224 path: EurePath::from_iter(self.current_path().iter().cloned()),
225 });
226 }
227 node.content = NodeValue::Array(Default::default());
228 Ok(())
229 }
230
231 pub fn bind_empty_tuple(&mut self) -> Result<(), InsertError> {
233 let node = self.current_node_mut();
234 if !node.content.is_hole() {
235 return Err(InsertError {
236 kind: InsertErrorKind::BindingTargetHasValue,
237 path: EurePath::from_iter(self.current_path().iter().cloned()),
238 });
239 }
240 node.content = NodeValue::Tuple(Default::default());
241 Ok(())
242 }
243
244 pub fn begin_eure_block(&mut self) {}
253
254 pub fn set_block_value(&mut self) -> Result<(), InsertError> {
256 Ok(())
257 }
258
259 pub fn end_eure_block(&mut self) -> Result<(), InsertError> {
261 Ok(())
262 }
263
264 pub fn begin_binding(&mut self) {}
266
267 pub fn end_binding_value(&mut self) -> Result<(), InsertError> {
269 Ok(())
270 }
271
272 pub fn end_binding_block(&mut self) -> Result<(), InsertError> {
274 Ok(())
275 }
276
277 pub fn begin_section(&mut self) {}
279
280 pub fn begin_section_items(&mut self) {}
282
283 pub fn end_section_items(&mut self) -> Result<(), InsertError> {
285 Ok(())
286 }
287
288 pub fn end_section_block(&mut self) -> Result<(), InsertError> {
290 Ok(())
291 }
292}
293
294impl InterpreterSink for DocumentConstructor {
295 type Error = InsertError;
296 type Scope = Scope;
297
298 fn begin_scope(&mut self) -> Self::Scope {
299 DocumentConstructor::begin_scope(self)
300 }
301
302 fn end_scope(&mut self, scope: Self::Scope) -> Result<(), Self::Error> {
303 DocumentConstructor::end_scope(self, scope).map_err(|e| InsertError {
304 kind: InsertErrorKind::ScopeError(e),
305 path: EurePath::from_iter(self.current_path().iter().cloned()),
306 })
307 }
308
309 fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, Self::Error> {
310 DocumentConstructor::navigate(self, segment)
311 }
312
313 fn require_hole(&self) -> Result<(), Self::Error> {
314 DocumentConstructor::require_hole(self)
315 }
316
317 fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), Self::Error> {
318 DocumentConstructor::bind_primitive(self, value)
319 }
320
321 fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), Self::Error> {
322 DocumentConstructor::bind_hole(self, label)
323 }
324
325 fn bind_empty_map(&mut self) -> Result<(), Self::Error> {
326 DocumentConstructor::bind_empty_map(self)
327 }
328
329 fn bind_empty_array(&mut self) -> Result<(), Self::Error> {
330 DocumentConstructor::bind_empty_array(self)
331 }
332
333 fn bind_empty_tuple(&mut self) -> Result<(), Self::Error> {
334 DocumentConstructor::bind_empty_tuple(self)
335 }
336
337 fn current_node_id(&self) -> NodeId {
338 DocumentConstructor::current_node_id(self)
339 }
340
341 fn current_path(&self) -> &[PathSegment] {
342 DocumentConstructor::current_path(self)
343 }
344
345 fn document(&self) -> &EureDocument {
346 DocumentConstructor::document(self)
347 }
348
349 fn document_mut(&mut self) -> &mut EureDocument {
350 DocumentConstructor::document_mut(self)
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357 use crate::identifier::IdentifierParser;
358
359 fn create_identifier(s: &str) -> Identifier {
360 let parser = IdentifierParser::init();
361 parser.parse(s).unwrap()
362 }
363
364 #[test]
365 fn test_new_initializes_at_root() {
366 let constructor = DocumentConstructor::new();
367 let root_id = constructor.document().get_root_id();
368
369 assert_eq!(constructor.current_node_id(), root_id);
370 assert_eq!(constructor.current_path(), &[]);
371 }
372
373 #[test]
374 fn test_current_node_returns_root_initially() {
375 let constructor = DocumentConstructor::new();
376
377 let node = constructor.current_node();
378 assert!(node.content.is_hole());
379 }
380
381 #[test]
382 fn test_navigate_single_ident() {
383 let mut constructor = DocumentConstructor::new();
384
385 let identifier = create_identifier("field");
386 let segment = PathSegment::Ident(identifier.clone());
387
388 let node_id = constructor
389 .navigate(segment.clone())
390 .expect("Failed to navigate");
391
392 assert_eq!(constructor.current_node_id(), node_id);
393 assert_eq!(constructor.current_path(), &[segment]);
394 }
395
396 #[test]
397 fn test_navigate_multiple_times() {
398 let mut constructor = DocumentConstructor::new();
399
400 let id1 = create_identifier("field1");
401 let id2 = create_identifier("field2");
402
403 constructor
404 .navigate(PathSegment::Ident(id1.clone()))
405 .expect("Failed to navigate first");
406
407 let node_id2 = constructor
408 .navigate(PathSegment::Extension(id2.clone()))
409 .expect("Failed to navigate second");
410
411 assert_eq!(constructor.current_node_id(), node_id2);
412 assert_eq!(
413 constructor.current_path(),
414 &[PathSegment::Ident(id1), PathSegment::Extension(id2)]
415 );
416 }
417
418 #[test]
419 fn test_navigate_error_propagates() {
420 let mut constructor = DocumentConstructor::new();
422 let identifier = create_identifier("field");
424 constructor
425 .navigate(PathSegment::Ident(identifier))
426 .expect("Failed to navigate");
427 let node_id = constructor.current_node_id();
429 constructor.document_mut().node_mut(node_id).content =
430 NodeValue::Primitive(PrimitiveValue::Null);
431
432 let result = constructor.navigate(PathSegment::TupleIndex(0));
433
434 assert_eq!(
435 result.map_err(|e| e.kind),
436 Err(InsertErrorKind::ExpectedTuple)
437 );
438 }
439
440 #[test]
441 fn test_scope_success() {
442 let mut constructor = DocumentConstructor::new();
443 let root_id = constructor.document().get_root_id();
444
445 let identifier = create_identifier("field");
446 let token = constructor.begin_scope();
447 let _node_id = constructor
448 .navigate(PathSegment::Ident(identifier.clone()))
449 .expect("Failed to navigate");
450
451 let result = constructor.end_scope(token);
453 assert_eq!(result, Ok(()));
454
455 assert_eq!(constructor.current_node_id(), root_id);
457 assert_eq!(constructor.current_path(), &[]);
458 }
459
460 #[test]
461 fn test_scope_lifo_enforcement() {
462 let mut constructor = DocumentConstructor::new();
463
464 let id1 = create_identifier("field1");
465 let id2 = create_identifier("field2");
466
467 let token1 = constructor.begin_scope();
468 constructor
469 .navigate(PathSegment::Ident(id1))
470 .expect("Failed to navigate");
471
472 let token2 = constructor.begin_scope();
473 constructor
474 .navigate(PathSegment::Extension(id2))
475 .expect("Failed to navigate");
476
477 let result = constructor.end_scope(token1);
479 assert_eq!(result, Err(ScopeError::NotMostRecentScope));
480
481 constructor
483 .end_scope(token2)
484 .expect("Failed to end scope 2");
485 constructor
486 .end_scope(token1)
487 .expect("Failed to end scope 1");
488 }
489
490 #[test]
491 fn test_scope_with_multiple_navigations() {
492 let mut constructor = DocumentConstructor::new();
493 let root_id = constructor.document().get_root_id();
494
495 let id1 = create_identifier("level1");
496 let id2 = create_identifier("level2");
497 let id3 = create_identifier("level3");
498
499 let token = constructor.begin_scope();
500
501 let node_id1 = constructor
503 .navigate(PathSegment::Ident(id1.clone()))
504 .expect("Failed to navigate level1");
505
506 let node_id2 = constructor
507 .navigate(PathSegment::Extension(id2.clone()))
508 .expect("Failed to navigate level2");
509
510 let node_id3 = constructor
511 .navigate(PathSegment::Extension(id3.clone()))
512 .expect("Failed to navigate level3");
513
514 assert_eq!(constructor.current_node_id(), node_id3);
516 assert_eq!(
517 constructor.current_path(),
518 &[
519 PathSegment::Ident(id1.clone()),
520 PathSegment::Extension(id2.clone()),
521 PathSegment::Extension(id3)
522 ]
523 );
524
525 constructor.end_scope(token).expect("Failed to end scope");
527 assert_eq!(constructor.current_node_id(), root_id);
528 assert_eq!(constructor.current_path(), &[]);
529
530 let _ = constructor.document().node(node_id1);
532 let _ = constructor.document().node(node_id2);
533 let _ = constructor.document().node(node_id3);
534 }
535
536 #[test]
537 fn test_nested_scopes() {
538 let mut constructor = DocumentConstructor::new();
539 let root_id = constructor.document().get_root_id();
540
541 let id1 = create_identifier("a");
542 let id2 = create_identifier("b");
543 let id3 = create_identifier("c");
544
545 let token_outer = constructor.begin_scope();
547 let node_a = constructor
548 .navigate(PathSegment::Ident(id1.clone()))
549 .expect("Failed to navigate a");
550
551 let token_inner = constructor.begin_scope();
553 let _node_b = constructor
554 .navigate(PathSegment::Extension(id2.clone()))
555 .expect("Failed to navigate b");
556 let _node_c = constructor
557 .navigate(PathSegment::Extension(id3.clone()))
558 .expect("Failed to navigate c");
559
560 constructor
562 .end_scope(token_inner)
563 .expect("Failed to end inner scope");
564 assert_eq!(constructor.current_node_id(), node_a);
565 assert_eq!(constructor.current_path(), &[PathSegment::Ident(id1)]);
566
567 constructor
569 .end_scope(token_outer)
570 .expect("Failed to end outer scope");
571 assert_eq!(constructor.current_node_id(), root_id);
572 assert_eq!(constructor.current_path(), &[]);
573 }
574
575 #[test]
576 fn test_require_hole_success() {
577 let mut constructor = DocumentConstructor::new();
578
579 let identifier = create_identifier("field");
580 constructor
581 .navigate(PathSegment::Ident(identifier))
582 .expect("Failed to navigate");
583
584 let result = constructor.require_hole();
586 assert_eq!(result, Ok(()));
587 }
588
589 #[test]
590 fn test_require_hole_fails_when_bound() {
591 let mut constructor = DocumentConstructor::new();
592
593 let identifier = create_identifier("field");
594 let node_id = constructor
595 .navigate(PathSegment::Ident(identifier))
596 .expect("Failed to navigate");
597
598 constructor.document_mut().node_mut(node_id).content =
600 NodeValue::Primitive(PrimitiveValue::Bool(true));
601
602 let result = constructor.require_hole();
604 assert_eq!(
605 result.unwrap_err().kind,
606 InsertErrorKind::BindingTargetHasValue
607 );
608 }
609
610 #[test]
611 fn test_bind_primitive_success() {
612 let mut constructor = DocumentConstructor::new();
613 let identifier = create_identifier("field");
614
615 let node_id = constructor
617 .navigate(PathSegment::Ident(identifier))
618 .expect("Failed to navigate");
619
620 let result = constructor.bind_primitive(PrimitiveValue::Bool(true));
622 assert_eq!(result, Ok(()));
623
624 let node = constructor.document().node(node_id);
626 assert!(matches!(
627 node.content,
628 NodeValue::Primitive(PrimitiveValue::Bool(true))
629 ));
630 }
631
632 #[test]
633 fn test_bind_primitive_already_bound() {
634 let mut constructor = DocumentConstructor::new();
635 let identifier = create_identifier("field");
636
637 let node_id = constructor
639 .navigate(PathSegment::Ident(identifier.clone()))
640 .expect("Failed to navigate");
641
642 constructor.document_mut().node_mut(node_id).content =
644 NodeValue::Primitive(PrimitiveValue::Null);
645
646 let result = constructor.bind_primitive(PrimitiveValue::Bool(false));
648
649 assert_eq!(
650 result.unwrap_err().kind,
651 InsertErrorKind::BindingTargetHasValue
652 );
653
654 let node = constructor.document().node(node_id);
656 assert!(matches!(
657 node.content,
658 NodeValue::Primitive(PrimitiveValue::Null)
659 ));
660 }
661
662 #[test]
663 fn test_finish_replaces_uninitialized_root_with_null() {
664 let constructor = DocumentConstructor::new();
665
666 let root_id = constructor.document().get_root_id();
668 assert!(constructor.document().node(root_id).content.is_hole());
669
670 let document = constructor.finish();
672 let root_node = document.node(document.get_root_id());
673 assert_eq!(root_node.content, NodeValue::Map(Default::default()));
674 }
675
676 #[test]
677 fn test_finish_preserves_initialized_root() {
678 let mut constructor = DocumentConstructor::new();
679
680 constructor
682 .bind_primitive(PrimitiveValue::Bool(true))
683 .expect("Failed to bind");
684
685 let document = constructor.finish();
687 let root_node = document.node(document.get_root_id());
688 assert!(matches!(
689 root_node.content,
690 NodeValue::Primitive(PrimitiveValue::Bool(true))
691 ));
692 }
693
694 #[test]
695 fn test_typical_binding_pattern() {
696 let mut constructor = DocumentConstructor::new();
698
699 let id_a = create_identifier("a");
700 let id_b = create_identifier("b");
701 let id_c = create_identifier("c");
702
703 let token = constructor.begin_scope();
704 constructor
705 .navigate(PathSegment::Ident(id_a.clone()))
706 .unwrap();
707 constructor
708 .navigate(PathSegment::Extension(id_b.clone()))
709 .unwrap();
710 let node_c = constructor
711 .navigate(PathSegment::Extension(id_c.clone()))
712 .unwrap();
713 constructor.require_hole().unwrap();
714 constructor
715 .bind_primitive(PrimitiveValue::Bool(true))
716 .unwrap();
717 constructor.end_scope(token).unwrap();
718
719 let node = constructor.document().node(node_c);
721 assert!(matches!(
722 node.content,
723 NodeValue::Primitive(PrimitiveValue::Bool(true))
724 ));
725 }
726}