mago_ast/ast/
construct.rs

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}