Skip to main content

lady_deirdre/units/mutable/
unit.rs

1////////////////////////////////////////////////////////////////////////////////
2// This file is part of "Lady Deirdre", a compiler front-end foundation       //
3// technology.                                                                //
4//                                                                            //
5// This work is proprietary software with source-available code.              //
6//                                                                            //
7// To copy, use, distribute, or contribute to this work, you must agree to    //
8// the terms of the General License Agreement:                                //
9//                                                                            //
10// https://github.com/Eliah-Lakhin/lady-deirdre/blob/master/EULA.md           //
11//                                                                            //
12// The agreement grants a Basic Commercial License, allowing you to use       //
13// this work in non-commercial and limited commercial products with a total   //
14// gross revenue cap. To remove this commercial limit for one of your         //
15// products, you must acquire a Full Commercial License.                      //
16//                                                                            //
17// If you contribute to the source code, documentation, or related materials, //
18// you must grant me an exclusive license to these contributions.             //
19// Contributions are governed by the "Contributions" section of the General   //
20// License Agreement.                                                         //
21//                                                                            //
22// Copying the work in parts is strictly forbidden, except as permitted       //
23// under the General License Agreement.                                       //
24//                                                                            //
25// If you do not or cannot agree to the terms of this Agreement,              //
26// do not use this work.                                                      //
27//                                                                            //
28// This work is provided "as is", without any warranties, express or implied, //
29// except where such disclaimers are legally invalid.                         //
30//                                                                            //
31// Copyright (c) 2024 Ilya Lakhin (Илья Александрович Лахин).                 //
32// All rights reserved.                                                       //
33////////////////////////////////////////////////////////////////////////////////
34
35use std::{
36    fmt::{Debug, Display, Formatter},
37    mem::{replace, take, transmute_copy},
38};
39
40use crate::{
41    arena::{Entry, EntryIndex, Id, Identifiable},
42    format::SnippetFormatter,
43    lexis::{
44        Length,
45        LineIndex,
46        Site,
47        SiteRef,
48        SiteSpan,
49        SourceCode,
50        ToSpan,
51        Token,
52        TokenBuffer,
53        TokenCount,
54        CHUNK_SIZE,
55    },
56    report::{ld_assert, ld_assert_eq, ld_unreachable, system_panic},
57    syntax::{
58        is_void_syntax,
59        Node,
60        NodeRef,
61        SyntaxError,
62        SyntaxTree,
63        VoidSyntax,
64        NON_RULE,
65        ROOT_RULE,
66    },
67    units::{
68        mutable::{
69            cursor::MutableCursor,
70            iters::{MutableCharIter, MutableErrorIter, MutableNodeIter},
71            lexis::{MutableLexisSession, SessionOutput},
72            syntax::MutableSyntaxSession,
73            watcher::VoidWatcher,
74        },
75        storage::{Cache, ChildCursor, Tree, TreeRefs},
76        CompilationUnit,
77        Watcher,
78    },
79};
80
81/// A compilation unit with reparse capabilities.
82///
83/// This serves as an inner component
84/// of the mutable [Document](crate::units::Document).
85///
86/// MutableUnit implements the same set of interfaces and provides the same
87/// set of features, including the ability to edit the source code after
88/// creation.
89///
90/// You are encouraged to use this object if you don’t need a uniform
91/// mutable and immutable API of the Document.
92pub struct MutableUnit<N: Node> {
93    root: Option<Cache>,
94    tree: Tree<N>,
95    refs: TreeRefs<N>,
96    lines: LineIndex,
97    tokens: TokenCount,
98}
99
100// Safety: Tree instance stores data on the heap, and the References instance
101//         refers Tree's heap objects only.
102unsafe impl<N: Node> Send for MutableUnit<N> {}
103
104// Safety:
105//   1. Tree and TreeRefs data mutations can only happen through
106//      the &mut Document exclusive interface that invalidates all other
107//      references to the inner data of the Document's Tree.
108//   2. All "weak" references are safe indexes into the Document's inner data.
109unsafe impl<N: Node> Sync for MutableUnit<N> {}
110
111impl<N: Node> Drop for MutableUnit<N> {
112    fn drop(&mut self) {
113        unsafe { self.tree.free() };
114
115        self.id().clear_name();
116    }
117}
118
119impl<N: Node> Debug for MutableUnit<N> {
120    #[inline]
121    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
122        formatter
123            .debug_struct("MutableUnit")
124            .field("id", &self.id())
125            .field("length", &self.length())
126            .finish_non_exhaustive()
127    }
128}
129
130impl<N: Node> Display for MutableUnit<N> {
131    #[inline(always)]
132    fn fmt(&self, formatter: &mut Formatter) -> std::fmt::Result {
133        formatter
134            .snippet(self)
135            .set_caption(format!("MutableUnit({})", self.id()))
136            .finish()
137    }
138}
139
140impl<N: Node> Identifiable for MutableUnit<N> {
141    #[inline(always)]
142    fn id(&self) -> Id {
143        self.refs.id
144    }
145}
146
147impl<N: Node> SourceCode for MutableUnit<N> {
148    type Token = N::Token;
149
150    type Cursor<'code> = MutableCursor<'code, N>;
151
152    type CharIterator<'code> = MutableCharIter<'code, N>;
153
154    fn chars(&self, span: impl ToSpan) -> Self::CharIterator<'_> {
155        let span = match span.to_site_span(self) {
156            None => panic!("Specified span is invalid."),
157
158            Some(span) => span,
159        };
160
161        unsafe { MutableCharIter::new(self, span) }
162    }
163
164    #[inline(always)]
165    fn has_chunk(&self, chunk_entry: &Entry) -> bool {
166        self.refs.chunks.contains(chunk_entry)
167    }
168
169    #[inline(always)]
170    fn get_token(&self, chunk_entry: &Entry) -> Option<Self::Token> {
171        let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
172
173        ld_assert!(
174            !chunk_cursor.is_dangling(),
175            "Dangling chunk ref in the TreeRefs repository."
176        );
177
178        Some(unsafe { chunk_cursor.token() })
179    }
180
181    #[inline(always)]
182    fn get_site(&self, chunk_entry: &Entry) -> Option<Site> {
183        let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
184
185        Some(unsafe { self.tree.site_of(chunk_cursor) })
186    }
187
188    #[inline(always)]
189    fn get_string(&self, chunk_entry: &Entry) -> Option<&str> {
190        let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
191
192        ld_assert!(
193            !chunk_cursor.is_dangling(),
194            "Dangling chunk ref in the TreeRefs repository."
195        );
196
197        Some(unsafe { chunk_cursor.string() })
198    }
199
200    #[inline(always)]
201    fn get_length(&self, chunk_entry: &Entry) -> Option<Length> {
202        let chunk_cursor = self.refs.chunks.get(chunk_entry)?;
203
204        ld_assert!(
205            !chunk_cursor.is_dangling(),
206            "Dangling chunk ref in the References repository."
207        );
208
209        Some(*unsafe { chunk_cursor.span() })
210    }
211
212    #[inline(always)]
213    fn cursor(&self, span: impl ToSpan) -> Self::Cursor<'_> {
214        let span = match span.to_site_span(self) {
215            None => panic!("Specified span is invalid."),
216
217            Some(span) => span,
218        };
219
220        Self::Cursor::new(self, span)
221    }
222
223    #[inline(always)]
224    fn length(&self) -> Length {
225        ld_assert_eq!(
226            self.tree.code_length(),
227            self.lines.code_length(),
228            "LineIndex and Tree resynchronization.",
229        );
230
231        self.tree.code_length()
232    }
233
234    #[inline(always)]
235    fn tokens(&self) -> TokenCount {
236        self.tokens
237    }
238
239    #[inline(always)]
240    fn lines(&self) -> &LineIndex {
241        &self.lines
242    }
243}
244
245impl<N: Node> SyntaxTree for MutableUnit<N> {
246    type Node = N;
247
248    type NodeIterator<'tree> = MutableNodeIter<'tree, N>;
249
250    type ErrorIterator<'tree> = MutableErrorIter<'tree>;
251
252    #[inline(always)]
253    fn root_node_ref(&self) -> NodeRef {
254        let Some(root) = &self.root else {
255            unsafe { ld_unreachable!("Root cache unset.") };
256        };
257
258        #[cfg(debug_assertions)]
259        if root.primary_node != 0 {
260            system_panic!("Root node moved.");
261        }
262
263        let entry = unsafe { self.refs.nodes.entry_of_unchecked(root.primary_node) };
264
265        #[cfg(debug_assertions)]
266        if entry.version != 1 {
267            system_panic!("Root node moved.");
268        }
269
270        NodeRef {
271            id: self.id(),
272            entry,
273        }
274    }
275
276    #[inline(always)]
277    fn node_refs(&self) -> Self::NodeIterator<'_> {
278        MutableNodeIter {
279            id: self.id(),
280            inner: self.refs.nodes.entries(),
281        }
282    }
283
284    #[inline(always)]
285    fn error_refs(&self) -> Self::ErrorIterator<'_> {
286        MutableErrorIter {
287            id: self.id(),
288            inner: self.refs.errors.entries(),
289        }
290    }
291
292    #[inline(always)]
293    fn has_node(&self, entry: &Entry) -> bool {
294        self.refs.nodes.contains(entry)
295    }
296
297    #[inline(always)]
298    fn get_node(&self, entry: &Entry) -> Option<&Self::Node> {
299        self.refs.nodes.get(entry)
300    }
301
302    #[inline(always)]
303    fn get_node_mut(&mut self, entry: &Entry) -> Option<&mut Self::Node> {
304        self.refs.nodes.get_mut(entry)
305    }
306
307    #[inline(always)]
308    fn has_error(&self, entry: &Entry) -> bool {
309        self.refs.errors.contains(entry)
310    }
311
312    #[inline(always)]
313    fn get_error(&self, entry: &Entry) -> Option<&SyntaxError> {
314        self.refs.errors.get(entry)
315    }
316}
317
318impl<N: Node> Default for MutableUnit<N> {
319    #[inline(always)]
320    fn default() -> Self {
321        let mut tree = Tree::default();
322        let mut refs = TreeRefs::new(Id::new());
323
324        let root = Self::initial_parse(&mut tree, &mut refs);
325
326        Self {
327            root: Some(root),
328            tree,
329            refs,
330            lines: LineIndex::new(),
331            tokens: 0,
332        }
333    }
334}
335
336impl<N: Node, S: AsRef<str>> From<S> for MutableUnit<N> {
337    #[inline(always)]
338    fn from(string: S) -> Self {
339        Self::new(string)
340    }
341}
342
343impl<N: Node> CompilationUnit for MutableUnit<N> {
344    #[inline(always)]
345    fn is_mutable(&self) -> bool {
346        true
347    }
348
349    fn into_token_buffer(self) -> TokenBuffer<N::Token> {
350        let mut buffer = TokenBuffer::with_capacity(self.tokens, self.length());
351
352        let mut chunk_cursor = self.tree.first();
353
354        while !chunk_cursor.is_dangling() {
355            unsafe {
356                chunk_cursor.take_lexis(
357                    &mut buffer.spans,
358                    &mut buffer.tokens,
359                    &mut buffer.indices,
360                    &mut buffer.text,
361                )
362            };
363
364            unsafe { chunk_cursor.next() }
365        }
366
367        buffer.update_line_index();
368
369        let _ = self;
370
371        buffer
372    }
373
374    #[inline(always)]
375    fn into_mutable_unit(self) -> MutableUnit<N> {
376        self
377    }
378}
379
380impl<N: Node> MutableUnit<N> {
381    /// Creates a MutableUnit from the source code `text`.
382    ///
383    /// The parameter could be a [TokenBuffer] or just an arbitrary string.
384    #[inline(always)]
385    pub fn new(text: impl Into<TokenBuffer<N::Token>>) -> Self {
386        let mut buffer = text.into();
387
388        let count = buffer.tokens();
389        let spans = take(&mut buffer.spans).into_iter();
390        let indices = take(&mut buffer.indices).into_iter();
391        let tokens = take(&mut buffer.tokens).into_iter();
392        let lines = take(&mut buffer.lines);
393        let mut refs = TreeRefs::with_capacity(Id::new(), count);
394
395        let mut tree = unsafe {
396            Tree::from_chunks(
397                &mut refs,
398                count,
399                spans,
400                indices,
401                tokens,
402                buffer.text.as_str(),
403            )
404        };
405
406        let root = MutableUnit::initial_parse(&mut tree, &mut refs);
407
408        Self {
409            root: Some(root),
410            tree,
411            refs,
412            lines,
413            tokens: count,
414        }
415    }
416
417    /// Writes user-input edit into this unit.
418    ///
419    /// See [Document::write](crate::units::Document::write) for details.
420    ///
421    /// **Panic**
422    ///
423    /// Panics if the specified span is not valid for this unit.
424    #[inline(always)]
425    pub fn write(&mut self, span: impl ToSpan, text: impl AsRef<str>) {
426        self.write_and_watch(span, text, &mut VoidWatcher)
427    }
428
429    /// Writes user-input edit into this unit, and collects all syntax tree
430    /// components that have been affected by this edit.
431    ///
432    /// See [Document::write_and_watch](crate::units::Document::write_and_watch)
433    /// for details.
434    ///
435    /// **Panic**
436    ///
437    /// Panics if the specified span is not valid for this unit.
438    #[inline(never)]
439    pub fn write_and_watch(
440        &mut self,
441        span: impl ToSpan,
442        text: impl AsRef<str>,
443        watcher: &mut impl Watcher,
444    ) {
445        let span = match span.to_site_span(self) {
446            None => panic!("Specified span is invalid."),
447
448            Some(span) => span,
449        };
450
451        let text = text.as_ref();
452
453        if span.is_empty() && text.is_empty() {
454            return;
455        }
456
457        unsafe { self.lines.write_unchecked(span.clone(), text) };
458
459        let cover = self.update_lexis(watcher, span, text);
460
461        ld_assert_eq!(
462            self.tree.code_length(),
463            self.lines.code_length(),
464            "LineIndex and Tree resynchronization.",
465        );
466
467        if is_void_syntax::<N>() {
468            return;
469        }
470
471        //todo consider removing Self::update_syntax return as it is currently unused
472        let _entry = self.update_syntax(watcher, cover);
473    }
474
475    #[inline(always)]
476    pub(super) fn tree(&self) -> &Tree<N> {
477        &self.tree
478    }
479
480    #[inline(always)]
481    pub(super) fn refs(&self) -> &TreeRefs<N> {
482        &self.refs
483    }
484
485    fn update_lexis(
486        &mut self,
487        watcher: &mut impl Watcher,
488        mut span: SiteSpan,
489        text: &str,
490    ) -> Cover<N> {
491        let mut head;
492        let mut lookback;
493        let mut tail;
494        let mut tail_offset;
495
496        match span.start == span.end {
497            false => {
498                lookback = span.start;
499                head = self.tree.lookup(&mut lookback);
500                tail_offset = span.end;
501                tail = self.tree.lookup(&mut tail_offset);
502            }
503
504            true => {
505                lookback = span.start;
506                head = self.tree.lookup(&mut lookback);
507                tail_offset = lookback;
508                tail = head;
509            }
510        }
511
512        let mut input = Vec::with_capacity(3);
513
514        match lookback > 0 {
515            true => {
516                ld_assert!(
517                    !head.is_dangling(),
518                    "Dangling reference with non-zero offset.",
519                );
520
521                input.push(split_left(unsafe { head.string() }, lookback));
522
523                span.start -= lookback;
524            }
525
526            false => {
527                if head.is_dangling() {
528                    head = self.tree.last();
529
530                    if !head.is_dangling() {
531                        let head_string = unsafe { head.string() };
532                        let head_span = unsafe { *head.span() };
533
534                        input.push(head_string);
535
536                        span.start -= head_span;
537                        lookback = head_span;
538                    }
539                }
540            }
541        }
542
543        if !head.is_dangling() {
544            while lookback < <N::Token as Token>::LOOKBACK {
545                ld_assert!(!head.is_dangling(), "Dangling head.",);
546
547                if unsafe { head.is_first() } {
548                    break;
549                }
550
551                unsafe { head.back() };
552
553                let head_string = unsafe { head.string() };
554                let head_span = unsafe { *head.span() };
555
556                input.insert(0, head_string);
557
558                span.start -= head_span;
559                lookback += head_span;
560            }
561        }
562
563        if !text.is_empty() {
564            input.push(text);
565        }
566
567        if tail_offset > 0 {
568            ld_assert!(
569                !tail.is_dangling(),
570                "Dangling reference with non-zero offset.",
571            );
572
573            let length = unsafe { *tail.span() };
574
575            input.push(split_right(unsafe { tail.string() }, tail_offset));
576
577            span.end += length - tail_offset;
578
579            unsafe { tail.next() }
580        }
581
582        let mut product = match input.is_empty() {
583            false => unsafe { MutableLexisSession::run(text.len() / CHUNK_SIZE + 2, &input, tail) },
584
585            true => SessionOutput {
586                length: 0,
587                spans: Vec::new(),
588                indices: Vec::new(),
589                tokens: Vec::new(),
590                text: String::new(),
591                tail,
592                overlap: 0,
593            },
594        };
595
596        span.end += product.overlap;
597
598        let mut skip = 0;
599
600        loop {
601            if head.is_dangling() {
602                break;
603            }
604
605            if unsafe { head.same_chunk_as(&product.tail) } {
606                break;
607            }
608
609            let product_string = match product.indices.get(skip) {
610                Some(start_byte) => {
611                    let next_index = skip + 1;
612
613                    match next_index < product.indices.len() {
614                        true => {
615                            let end_byte = unsafe { product.indices.get_unchecked(next_index) };
616
617                            unsafe { product.text.get_unchecked(*start_byte..*end_byte) }
618                        }
619
620                        false => unsafe { product.text.get_unchecked(*start_byte..) },
621                    }
622                }
623                None => break,
624            };
625
626            let head_string = unsafe { head.string() };
627
628            if product_string == head_string {
629                let head_span = unsafe { *head.span() };
630
631                span.start += head_span;
632                product.length -= head_span;
633                skip += 1;
634
635                unsafe { head.next() };
636
637                continue;
638            }
639
640            break;
641        }
642
643        loop {
644            if product.count() == skip {
645                break;
646            }
647
648            if unsafe { head.same_chunk_as(&product.tail) } {
649                break;
650            }
651
652            let last = match product.tail.is_dangling() {
653                false => {
654                    let mut previous = product.tail;
655
656                    unsafe { previous.back() };
657
658                    previous
659                }
660
661                true => self.tree.last(),
662            };
663
664            if last.is_dangling() {
665                break;
666            }
667
668            let product_string = match product.indices.last() {
669                Some(start_byte) => unsafe { product.text.as_str().get_unchecked(*start_byte..) },
670                None => break,
671            };
672
673            let last_string = unsafe { last.string() };
674
675            if product_string == last_string {
676                let last_span = unsafe { *last.span() };
677
678                span.end -= last_span;
679
680                let _ = product.spans.pop();
681                let index = product.indices.pop();
682                let _ = product.tokens.pop();
683
684                if let Some(index) = index {
685                    unsafe { product.text.as_mut_vec().set_len(index) };
686                }
687                product.length -= last_span;
688                product.tail = last;
689
690                continue;
691            }
692
693            break;
694        }
695
696        if head.is_dangling() {
697            ld_assert!(
698                product.tail.is_dangling(),
699                "Dangling head and non-dangling tail.",
700            );
701
702            let token_count = product.count() - skip;
703
704            let tail_tree = unsafe {
705                Tree::from_chunks(
706                    &mut self.refs,
707                    token_count,
708                    product.spans.into_iter().skip(skip),
709                    product.indices.into_iter().skip(skip),
710                    product.tokens.into_iter().skip(skip),
711                    product.text.as_str(),
712                )
713            };
714
715            let insert_span = tail_tree.code_length();
716
717            unsafe { self.tree.join(&mut self.refs, tail_tree) };
718
719            self.tokens += token_count;
720
721            let chunk_cursor = {
722                let mut point = span.start;
723
724                let chunk_cursor = self.tree.lookup(&mut point);
725
726                ld_assert_eq!(point, 0, "Bad span alignment.");
727
728                chunk_cursor
729            };
730
731            return Cover {
732                chunk_cursor,
733                span: span.start..(span.start + insert_span),
734            };
735        }
736
737        let insert_count = product.count() - skip;
738
739        if let Some(remove_count) = unsafe { head.continuous_to(&product.tail) } {
740            if unsafe { self.tree.is_writeable(&head, remove_count, insert_count) } {
741                let (chunk_cursor, insert_span) = unsafe {
742                    self.tree.write(
743                        &mut self.refs,
744                        watcher,
745                        head,
746                        remove_count,
747                        insert_count,
748                        product.spans.into_iter().skip(skip),
749                        unsafe { product.indices.get_unchecked(skip..) },
750                        product.tokens.into_iter().skip(skip),
751                        product.text.as_str(),
752                    )
753                };
754
755                self.tokens += insert_count;
756                self.tokens -= remove_count;
757
758                return Cover {
759                    chunk_cursor,
760                    span: span.start..(span.start + insert_span),
761                };
762            }
763        }
764
765        let mut middle = unsafe { self.tree.split(&mut self.refs, head) };
766
767        let middle_split_point = {
768            let mut point = span.end - span.start;
769
770            let chunk_cursor = middle.lookup(&mut point);
771
772            ld_assert_eq!(point, 0, "Bad span alignment.");
773
774            chunk_cursor
775        };
776
777        let right = unsafe { middle.split(&mut self.refs, middle_split_point) };
778
779        let remove_count;
780        let insert_span;
781
782        {
783            let replacement = unsafe {
784                Tree::from_chunks(
785                    &mut self.refs,
786                    insert_count,
787                    product.spans.into_iter().skip(skip),
788                    product.indices.into_iter().skip(skip),
789                    product.tokens.into_iter().skip(skip),
790                    product.text.as_str(),
791                )
792            };
793
794            insert_span = replacement.code_length();
795
796            remove_count = unsafe {
797                replace(&mut middle, replacement).free_as_subtree(&mut self.refs, watcher)
798            };
799        };
800
801        unsafe { self.tree.join(&mut self.refs, middle) };
802        unsafe { self.tree.join(&mut self.refs, right) };
803
804        self.tokens += insert_count;
805        self.tokens -= remove_count;
806
807        head = {
808            let mut point = span.start;
809
810            let chunk_cursor = self.tree.lookup(&mut point);
811
812            ld_assert_eq!(point, 0, "Bad span alignment.");
813
814            chunk_cursor
815        };
816
817        Cover {
818            chunk_cursor: head,
819            span: span.start..(span.start + insert_span),
820        }
821    }
822
823    fn update_syntax(&mut self, watcher: &mut impl Watcher, mut cover: Cover<N>) -> EntryIndex {
824        #[allow(unused_variables)]
825        let mut cover_lookahead = 0;
826
827        loop {
828            let mut shift;
829            let mut rule;
830
831            match cover.chunk_cursor.is_dangling() {
832                false => match unsafe { cover.chunk_cursor.is_first() } {
833                    true => match unsafe { cover.chunk_cursor.cache().is_some() } {
834                        false => {
835                            shift = 0;
836                            rule = ROOT_RULE;
837                        }
838
839                        true => {
840                            shift = 0;
841                            rule = NON_RULE
842                        }
843                    },
844
845                    false => {
846                        unsafe { cover.chunk_cursor.back() };
847
848                        shift = unsafe { *cover.chunk_cursor.span() };
849
850                        rule = NON_RULE;
851                    }
852                },
853
854                true => match self.tree.code_length() == 0 {
855                    true => {
856                        shift = 0;
857                        rule = ROOT_RULE;
858                    }
859
860                    false => {
861                        cover.chunk_cursor = self.tree.last();
862
863                        shift = unsafe { *cover.chunk_cursor.span() };
864
865                        rule = NON_RULE;
866                    }
867                },
868            }
869
870            if rule != ROOT_RULE {
871                loop {
872                    {
873                        match unsafe { cover.chunk_cursor.cache() } {
874                            None => {
875                                unsafe { cover.chunk_cursor.back() };
876
877                                match cover.chunk_cursor.is_dangling() {
878                                    false => {
879                                        shift += unsafe { *cover.chunk_cursor.span() };
880                                        continue;
881                                    }
882
883                                    true => {
884                                        rule = ROOT_RULE;
885                                        break;
886                                    }
887                                }
888                            }
889
890                            Some(cache) => {
891                                let parse_end_site =
892                                    unsafe { cache.end_site(&self.tree, &self.refs) };
893
894                                if let Some(parse_end_site) = parse_end_site {
895                                    if parse_end_site + cache.lookahead < cover.span.start {
896                                        unsafe { cover.chunk_cursor.back() };
897
898                                        match cover.chunk_cursor.is_dangling() {
899                                            false => {
900                                                shift += unsafe { *cover.chunk_cursor.span() };
901                                                continue;
902                                            }
903
904                                            true => {
905                                                rule = ROOT_RULE;
906                                                break;
907                                            }
908                                        }
909                                    }
910
911                                    if parse_end_site >= cover.span.end {
912                                        cover.span.start -= shift;
913                                        cover.span.end = parse_end_site;
914
915                                        #[allow(unused_assignments)]
916                                        {
917                                            cover_lookahead = cache.lookahead;
918                                        }
919
920                                        rule = cache.rule;
921                                        break;
922                                    }
923                                }
924                            }
925                        }
926                    }
927
928                    let cache = unsafe { cover.chunk_cursor.release_cache() };
929
930                    cache.free(&mut self.refs, watcher);
931                }
932            }
933
934            if rule == ROOT_RULE {
935                let head = self.tree.first();
936
937                let Some(root_cache) = take(&mut self.root) else {
938                    unsafe { ld_unreachable!("Missing root cache.") }
939                };
940
941                let (rule, primary_node) = root_cache.free_inner(&mut self.refs, watcher);
942
943                #[cfg(debug_assertions)]
944                if rule != ROOT_RULE {
945                    system_panic!("Root cache refers non-root rule.");
946                }
947
948                let (root_cache, mut parse_end_site) = unsafe {
949                    MutableSyntaxSession::run(
950                        &mut self.tree,
951                        &mut self.refs,
952                        watcher,
953                        0,
954                        head,
955                        rule,
956                        primary_node,
957                    )
958                };
959
960                self.root = Some(root_cache);
961
962                if self.tree.code_length() > 0 {
963                    let mut tail = self.tree.lookup(&mut parse_end_site);
964
965                    ld_assert_eq!(parse_end_site, 0, "Incorrect span alignment.");
966
967                    while !tail.is_dangling() {
968                        let has_cache = unsafe { tail.cache().is_some() };
969
970                        if has_cache {
971                            unsafe { tail.release_cache() }.free(&mut self.refs, watcher);
972                        }
973
974                        unsafe { tail.next() }
975                    }
976                }
977
978                return primary_node;
979            }
980
981            let cache = unsafe { cover.chunk_cursor.release_cache() };
982
983            let (rule, primary_node) = cache.free_inner(&mut self.refs, watcher);
984
985            let (cache, parse_end_site) = unsafe {
986                MutableSyntaxSession::run(
987                    &mut self.tree,
988                    &mut self.refs,
989                    watcher,
990                    cover.span.start,
991                    cover.chunk_cursor,
992                    rule,
993                    primary_node,
994                )
995            };
996
997            unsafe { cover.chunk_cursor.install_cache(cache) }
998
999            //todo check lookahead too
1000            if cover.span.end == parse_end_site {
1001                return primary_node;
1002            }
1003
1004            cover.span.end = cover.span.end.max(parse_end_site);
1005        }
1006    }
1007
1008    // Safety:
1009    // 1. All references of the `tree` belong to `refs` instance.
1010    #[inline(always)]
1011    fn initial_parse<'unit>(tree: &'unit mut Tree<N>, refs: &'unit mut TreeRefs<N>) -> Cache {
1012        if is_void_syntax::<N>() {
1013            let primary_node = refs.nodes.insert_raw(unsafe {
1014                transmute_copy::<VoidSyntax<<N as Node>::Token>, N>(&VoidSyntax::default())
1015            });
1016
1017            return Cache {
1018                rule: ROOT_RULE,
1019                parse_end: SiteRef::nil(),
1020                lookahead: 0,
1021                primary_node,
1022                secondary_nodes: Vec::new(),
1023                errors: Vec::new(),
1024            };
1025        }
1026
1027        let head = tree.first();
1028
1029        let primary_node = refs.nodes.reserve_entry();
1030
1031        let (root_cache, _parsed_end_site) = unsafe {
1032            MutableSyntaxSession::run(
1033                tree,
1034                refs,
1035                &mut VoidWatcher,
1036                0,
1037                head,
1038                ROOT_RULE,
1039                primary_node,
1040            )
1041        };
1042
1043        root_cache
1044    }
1045}
1046
1047impl<T: Token> TokenBuffer<T> {
1048    /// Turns this token buffer into MutableUnit.
1049    ///
1050    /// The `N` generic parameter specifies a type of the syntax tree [Node]
1051    /// with the `T` [lexis](Node::Token).
1052    #[inline(always)]
1053    pub fn into_mutable_unit<N>(self) -> MutableUnit<N>
1054    where
1055        N: Node<Token = T>,
1056    {
1057        MutableUnit::new(self)
1058    }
1059}
1060
1061struct Cover<N: Node> {
1062    chunk_cursor: ChildCursor<N>,
1063    span: SiteSpan,
1064}
1065
1066#[inline]
1067fn split_left(string: &str, mut site: Site) -> &str {
1068    if site == 0 {
1069        return "";
1070    }
1071
1072    for (index, _) in string.char_indices() {
1073        if site == 0 {
1074            return unsafe { string.get_unchecked(0..index) };
1075        }
1076
1077        site -= 1;
1078    }
1079
1080    string
1081}
1082
1083#[inline]
1084fn split_right(string: &str, mut site: Site) -> &str {
1085    if site == 0 {
1086        return string;
1087    }
1088
1089    for (index, _) in string.char_indices() {
1090        if site == 0 {
1091            return unsafe { string.get_unchecked(index..string.len()) };
1092        }
1093
1094        site -= 1;
1095    }
1096
1097    ""
1098}