Skip to main content

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")]
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}