mago_syntax/ast/ast/
use.rs

1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_span::HasSpan;
6use mago_span::Position;
7use mago_span::Span;
8
9use crate::ast::ast::identifier::Identifier;
10use crate::ast::ast::identifier::LocalIdentifier;
11use crate::ast::ast::keyword::Keyword;
12use crate::ast::ast::terminator::Terminator;
13use crate::ast::sequence::TokenSeparatedSequence;
14
15#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
16#[repr(C)]
17pub struct Use {
18    pub r#use: Keyword,
19    pub items: UseItems,
20    pub terminator: Terminator,
21}
22
23#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
24#[serde(tag = "type", content = "value")]
25#[repr(C, u8)]
26pub enum UseItems {
27    Sequence(UseItemSequence),
28    TypedSequence(TypedUseItemSequence),
29    TypedList(TypedUseItemList),
30    MixedList(MixedUseItemList),
31}
32
33#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
34#[serde(tag = "type", content = "value")]
35#[repr(C, u8)]
36pub enum UseType {
37    Function(Keyword),
38    Const(Keyword),
39}
40
41#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
42#[repr(C)]
43pub struct UseItemSequence {
44    pub start: Position,
45    pub items: TokenSeparatedSequence<UseItem>,
46}
47
48#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
49#[repr(C)]
50pub struct TypedUseItemSequence {
51    pub r#type: UseType,
52    pub items: TokenSeparatedSequence<UseItem>,
53}
54
55#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
56#[repr(C)]
57pub struct TypedUseItemList {
58    pub r#type: UseType,
59    pub namespace: Identifier,
60    pub namespace_separator: Span,
61    pub left_brace: Span,
62    pub items: TokenSeparatedSequence<UseItem>,
63    pub right_brace: Span,
64}
65
66#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
67#[repr(C)]
68pub struct MixedUseItemList {
69    pub namespace: Identifier,
70    pub namespace_separator: Span,
71    pub left_brace: Span,
72    pub items: TokenSeparatedSequence<MaybeTypedUseItem>,
73    pub right_brace: Span,
74}
75
76#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
77#[repr(C)]
78pub struct MaybeTypedUseItem {
79    pub r#type: Option<UseType>,
80    pub item: UseItem,
81}
82
83#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
84#[repr(C)]
85pub struct UseItem {
86    pub name: Identifier,
87    pub alias: Option<UseItemAlias>,
88}
89
90#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
91#[repr(C)]
92pub struct UseItemAlias {
93    pub r#as: Keyword,
94    pub identifier: LocalIdentifier,
95}
96
97impl UseType {
98    #[inline]
99    pub const fn is_function(&self) -> bool {
100        matches!(self, UseType::Function(_))
101    }
102
103    #[inline]
104    pub const fn is_const(&self) -> bool {
105        matches!(self, UseType::Const(_))
106    }
107}
108
109impl HasSpan for Use {
110    fn span(&self) -> Span {
111        self.r#use.span().join(self.terminator.span())
112    }
113}
114
115impl HasSpan for UseItems {
116    fn span(&self) -> Span {
117        match self {
118            UseItems::Sequence(items) => items.span(),
119            UseItems::TypedSequence(items) => items.span(),
120            UseItems::TypedList(items) => items.span(),
121            UseItems::MixedList(items) => items.span(),
122        }
123    }
124}
125
126impl HasSpan for UseType {
127    fn span(&self) -> Span {
128        match self {
129            UseType::Function(keyword) => keyword.span(),
130            UseType::Const(keyword) => keyword.span(),
131        }
132    }
133}
134
135impl HasSpan for UseItemSequence {
136    fn span(&self) -> Span {
137        self.items.span(self.start)
138    }
139}
140
141impl HasSpan for TypedUseItemSequence {
142    fn span(&self) -> Span {
143        self.r#type.span().join(self.items.span(self.r#type.span().end))
144    }
145}
146
147impl HasSpan for TypedUseItemList {
148    fn span(&self) -> Span {
149        self.r#type.span().join(self.right_brace)
150    }
151}
152
153impl HasSpan for MixedUseItemList {
154    fn span(&self) -> Span {
155        self.namespace.span().join(self.right_brace)
156    }
157}
158
159impl HasSpan for MaybeTypedUseItem {
160    fn span(&self) -> Span {
161        if let Some(r#type) = &self.r#type { r#type.span().join(self.item.span()) } else { self.item.span() }
162    }
163}
164
165impl HasSpan for UseItem {
166    fn span(&self) -> Span {
167        if let Some(alias) = &self.alias { self.name.span().join(alias.span()) } else { self.name.span() }
168    }
169}
170
171impl HasSpan for UseItemAlias {
172    fn span(&self) -> Span {
173        self.r#as.span().join(self.identifier.span())
174    }
175}