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