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