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