mago_syntax/ast/ast/
construct.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::argument::ArgumentList;
8use crate::ast::ast::expression::Expression;
9use crate::ast::ast::keyword::Keyword;
10use crate::ast::sequence::TokenSeparatedSequence;
11
12#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
13#[serde(tag = "type", content = "value")]
14#[repr(u8)]
15pub enum Construct<'arena> {
16    Isset(IssetConstruct<'arena>),
17    Empty(EmptyConstruct<'arena>),
18    Eval(EvalConstruct<'arena>),
19    Include(IncludeConstruct<'arena>),
20    IncludeOnce(IncludeOnceConstruct<'arena>),
21    Require(RequireConstruct<'arena>),
22    RequireOnce(RequireOnceConstruct<'arena>),
23    Print(PrintConstruct<'arena>),
24    Exit(ExitConstruct<'arena>),
25    Die(DieConstruct<'arena>),
26}
27
28#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
29pub struct IssetConstruct<'arena> {
30    pub isset: Keyword<'arena>,
31    pub left_parenthesis: Span,
32    pub values: TokenSeparatedSequence<'arena, Expression<'arena>>,
33    pub right_parenthesis: Span,
34}
35
36#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
37pub struct EmptyConstruct<'arena> {
38    pub empty: Keyword<'arena>,
39    pub left_parenthesis: Span,
40    pub value: &'arena Expression<'arena>,
41    pub right_parenthesis: Span,
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
45pub struct EvalConstruct<'arena> {
46    pub eval: Keyword<'arena>,
47    pub left_parenthesis: Span,
48    pub value: &'arena Expression<'arena>,
49    pub right_parenthesis: Span,
50}
51
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
53pub struct IncludeConstruct<'arena> {
54    pub include: Keyword<'arena>,
55    pub value: &'arena Expression<'arena>,
56}
57
58#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
59pub struct IncludeOnceConstruct<'arena> {
60    pub include_once: Keyword<'arena>,
61    pub value: &'arena Expression<'arena>,
62}
63
64#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
65pub struct RequireConstruct<'arena> {
66    pub require: Keyword<'arena>,
67    pub value: &'arena Expression<'arena>,
68}
69
70#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
71pub struct RequireOnceConstruct<'arena> {
72    pub require_once: Keyword<'arena>,
73    pub value: &'arena Expression<'arena>,
74}
75
76#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
77pub struct PrintConstruct<'arena> {
78    pub print: Keyword<'arena>,
79    pub value: &'arena Expression<'arena>,
80}
81
82#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
83pub struct ExitConstruct<'arena> {
84    pub exit: Keyword<'arena>,
85    pub arguments: Option<ArgumentList<'arena>>,
86}
87
88#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
89pub struct DieConstruct<'arena> {
90    pub die: Keyword<'arena>,
91    pub arguments: Option<ArgumentList<'arena>>,
92}
93
94impl<'arena> Construct<'arena> {
95    #[must_use]
96    #[inline]
97    pub const fn is_import(&self) -> bool {
98        matches!(
99            self,
100            Construct::Include(_) | Construct::IncludeOnce(_) | Construct::Require(_) | Construct::RequireOnce(_)
101        )
102    }
103
104    #[must_use]
105    #[inline]
106    pub const fn has_bounds(&self) -> bool {
107        !matches!(
108            self,
109            Construct::Include(_)
110                | Construct::IncludeOnce(_)
111                | Construct::Require(_)
112                | Construct::RequireOnce(_)
113                | Construct::Print(_)
114        )
115    }
116}
117
118impl HasSpan for Construct<'_> {
119    fn span(&self) -> Span {
120        match self {
121            Construct::Isset(c) => c.span(),
122            Construct::Empty(c) => c.span(),
123            Construct::Eval(c) => c.span(),
124            Construct::Include(c) => c.span(),
125            Construct::IncludeOnce(c) => c.span(),
126            Construct::Require(c) => c.span(),
127            Construct::RequireOnce(c) => c.span(),
128            Construct::Print(c) => c.span(),
129            Construct::Exit(c) => c.span(),
130            Construct::Die(c) => c.span(),
131        }
132    }
133}
134
135impl HasSpan for IssetConstruct<'_> {
136    fn span(&self) -> Span {
137        self.isset.span().join(self.right_parenthesis.span())
138    }
139}
140
141impl HasSpan for EmptyConstruct<'_> {
142    fn span(&self) -> Span {
143        self.empty.span().join(self.right_parenthesis)
144    }
145}
146
147impl HasSpan for EvalConstruct<'_> {
148    fn span(&self) -> Span {
149        self.eval.span().join(self.right_parenthesis)
150    }
151}
152
153impl HasSpan for IncludeConstruct<'_> {
154    fn span(&self) -> Span {
155        self.include.span().join(self.value.span())
156    }
157}
158
159impl HasSpan for IncludeOnceConstruct<'_> {
160    fn span(&self) -> Span {
161        self.include_once.span().join(self.value.span())
162    }
163}
164
165impl HasSpan for RequireConstruct<'_> {
166    fn span(&self) -> Span {
167        self.require.span().join(self.value.span())
168    }
169}
170
171impl HasSpan for RequireOnceConstruct<'_> {
172    fn span(&self) -> Span {
173        self.require_once.span().join(self.value.span())
174    }
175}
176
177impl HasSpan for PrintConstruct<'_> {
178    fn span(&self) -> Span {
179        self.print.span().join(self.value.span())
180    }
181}
182
183impl HasSpan for ExitConstruct<'_> {
184    fn span(&self) -> Span {
185        if let Some(arguments) = &self.arguments { self.exit.span().join(arguments.span()) } else { self.exit.span() }
186    }
187}
188
189impl HasSpan for DieConstruct<'_> {
190    fn span(&self) -> Span {
191        if let Some(arguments) = &self.arguments { self.die.span().join(arguments.span()) } else { self.die.span() }
192    }
193}