cuicui_chirp/parser/ast/
list.rs1use std::marker::PhantomData;
12
13use super::node::{Argument, Code, IdentOffset, Import, StType};
14use super::node::{ChirpFile, Fn, Method, Spawn, Statement, Template};
15use super::{as_usize, header::Block};
16
17macro_rules! dummy {
18 ($($_:tt)*) => {};
19}
20macro_rules! impl_node {
21 ($($ty:ident : $($header:ident)? |$it:ident| $compute:expr),* $(,)?)=>{
22 $(impl<'a> Node<'a> for $ty<'a> {
23 #[inline] fn len(self) -> u32 { let $it = self; $compute }
24 #[inline] fn first(blocks: &'a [Block]) -> Self { Self::new(blocks) }
25 $(dummy!{$header} #[inline] fn len_from_header(self) -> Option<u32> {Some(self.len())})?
26 })*}
27}
28macro_rules! impl_simple_node {
29 ($($ty:ident: $size:literal),* $(,)?)=>{
30 $(impl SimpleNode for $ty<'_> { const SIZE: u32 = $size; })*
31 impl_node! {$( $ty : header |_it| Self::SIZE ,)*}
32 }
33}
34
35pub(in crate::parser) trait Node<'a>: Copy {
38 fn len_from_header(self) -> Option<u32> {
43 None
44 }
45 fn len(self) -> u32;
47 fn first(blocks: &'a [Block]) -> Self;
48}
49pub(in crate::parser) trait SimpleNode {
50 const SIZE: u32;
51}
52impl_node! {
53 ChirpFile: |it| it.root_statement_offset() + it.root_statement().len(),
54 Fn: |it| Self::HEADER_SIZE + it.parameter_len() + it.body().len(),
55 Method: header |it| Self::HEADER_SIZE + it.argument_len(),
56 Template: header |it| Self::HEADER_SIZE + it.argument_len() + it.methods_len() + it.children_len(),
57 Spawn: header |it| Self::HEADER_SIZE + it.methods_len() + it.children_len(),
58 Statement: header |it| match it.typed() {
59 StType::Spawn(s) => s.len(),
60 StType::Template(s) => s.len(),
61 StType::Code(_) => Code::SIZE,
62 },
63}
64impl_simple_node! {Import: 2, Argument: 2, Code: 1}
65
66#[rustfmt::skip] impl SimpleNode for IdentOffset { const SIZE: u32 = 1; }
67#[rustfmt::skip] impl<'a> Node<'a> for IdentOffset {
68 fn len(self) -> u32 { Self::SIZE }
69 fn first(blocks: &'a [Block]) -> Self { Self { start: blocks[0].0 } }
70}
71
72#[derive(Clone, Copy)]
73pub(in crate::parser) struct List<'a, T: Node<'a>>(&'a [Block], PhantomData<T>);
74
75#[derive(Clone)]
76pub(in crate::parser) struct ListIter<'a, T: Node<'a>>(List<'a, T>);
77
78impl<'a, T: Node<'a>> List<'a, T> {
79 pub fn empty() -> Self {
80 Self(&[], PhantomData)
81 }
82 #[inline]
83 pub(super) fn new(blocks: &'a [Block]) -> Self {
84 Self(blocks, PhantomData)
85 }
86 pub fn is_empty(self) -> bool {
87 self.0.is_empty()
88 }
89 #[inline]
90 pub fn first(&self) -> Option<T> {
91 if self.is_empty() {
92 return None;
93 }
94 Some(T::first(self.0))
95 }
96 #[inline]
97 pub fn iter(self) -> ListIter<'a, T> {
98 ListIter(self)
99 }
100}
101impl<'a, T: Node<'a>> Iterator for ListIter<'a, T> {
102 type Item = T;
103
104 #[inline]
105 fn next(&mut self) -> Option<Self::Item> {
106 let ret = self.0.first()?;
107 self.0 .0 = &self.0 .0[as_usize(ret.len())..];
108 Some(ret)
109 }
110}
111impl<'a, T: SimpleNode + Node<'a>> List<'a, T> {
112 pub const fn count(&self) -> usize {
113 self.0.len() / as_usize(T::SIZE)
114 }
115 pub fn get(&self, index: usize) -> Option<T> {
116 let start = index * as_usize(T::SIZE);
117 let end = (index + 1) * as_usize(T::SIZE);
118 let blocks = self.0.get(start..end)?;
119 Some(T::first(blocks))
120 }
121 pub fn last(&self) -> Option<T> {
122 let index = self.count().checked_sub(1)?;
123 self.get(index)
124 }
125}