1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use super::*;
use crate::helper::WrapDisplay;

mod builtin;
mod display;

/// `#module∷name.variant(args) { ... } modifiers`
///
/// The annotations of the statements
#[derive(Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AnnotationNode {
    /// The documentations of the statement
    pub documents: DocumentationList,
    /// The attributes of the statement
    pub attributes: AttributeList,
    /// The modifiers of the statement
    pub modifiers: ModifierList,
}

/// `@module∷name(args) { ... }`
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ProceduralNode {
    /// The kind of this attribute.
    pub kind: AttributeKind,
    /// The names of this attribute.
    pub path: NamePathNode,
    /// The arguments of this attribute.
    pub arguments: ArgumentsList,
    /// The capture of this attribute.
    pub domain: Option<StatementBlock>,
    /// The range of the node
    pub span: Range<u32>,
}

impl From<ProceduralNode> for AttributeTerm {
    fn from(node: ProceduralNode) -> Self {
        AttributeTerm {
            kind: node.kind,
            path: node.path,
            variant: vec![],
            arguments: node.arguments,
            domain: node.domain,
            span: node.span,
        }
    }
}

impl ValkyrieNode for ProceduralNode {
    fn get_range(&self) -> Range<usize> {
        Range { start: self.span.start as usize, end: self.span.end as usize }
    }
}

/// A namepath is a series of identifiers separated by dots.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AttributeKind {
    /// `#`
    Normal,
    /// `##`
    Environment,
    /// `#!`
    Script,
}

/// `@[module∷name.function(args), module∷name.function2(args)] <CAPTURE>`
#[derive(Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AttributeList {
    /// The modifiers in group
    pub terms: Vec<AttributeTerm>,
}

/// `module∷name.variant(args) { CAPTURE }`
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AttributeTerm {
    /// The kind of this attribute.
    pub kind: AttributeKind,
    /// The names of this attribute.
    pub path: NamePathNode,
    /// The names of this attribute.
    pub variant: Vec<IdentifierNode>,
    /// The arguments of this attribute.
    pub arguments: ArgumentsList,
    /// The dsl part of the attribute
    pub domain: Option<StatementBlock>,
    /// The range of the node
    pub span: Range<u32>,
}

/// `public static final synchronized class Main {}`
///
/// - Auxiliary parsing function, not instantiable.
#[derive(Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ModifierList {
    /// The modifiers in group
    pub terms: Vec<IdentifierNode>,
}

impl ModifierList {
    /// Create a new modifier list with given capacity.
    pub fn new(capacity: usize) -> Self {
        Self { terms: Vec::with_capacity(capacity) }
    }
}

impl Default for AttributeKind {
    fn default() -> Self {
        Self::Normal
    }
}

impl Default for AnnotationNode {
    fn default() -> Self {
        Self { documents: Default::default(), attributes: Default::default(), modifiers: Default::default() }
    }
}
impl AnnotationNode {
    /// Check if the modifiers, attributes and documents are empty.
    pub fn is_empty(&self) -> bool {
        self.documents.is_empty() && self.attributes.is_empty() && self.modifiers.is_empty()
    }
}
impl From<AttributeList> for AnnotationNode {
    fn from(value: AttributeList) -> Self {
        Self { documents: Default::default(), attributes: value, modifiers: Default::default() }
    }
}
impl AttributeKind {
    /// Returns the string representation of the macro kind.
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Normal => "#",
            Self::Environment => "##",
            Self::Script => "#!",
        }
    }
}

impl AttributeTerm {}

impl AttributeList {
    /// Create a new modifier list.
    pub fn new(capacity: usize) -> Self {
        Self { terms: Vec::with_capacity(capacity) }
    }

    /// Check if the modifier is present.
    pub fn is_empty(&self) -> bool {
        self.terms.is_empty()
    }
}

impl ModifierList {
    /// Check if the modifier is present.
    pub fn is_empty(&self) -> bool {
        self.terms.is_empty()
    }

    /// Check if the modifier is present.
    pub fn contains(&self, modifier: &str) -> bool {
        self.terms.iter().any(|x| x.name.eq(modifier))
    }
}