Skip to main content

mago_syntax/ast/ast/
variable.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::expression::Expression;
8
9/// Represents a variable.
10///
11/// # Examples
12///
13/// ```php
14/// $foo
15/// ${foo}
16/// $$foo
17/// ```
18#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
19#[serde(tag = "type", content = "value")]
20pub enum Variable<'arena> {
21    Direct(DirectVariable<'arena>),
22    Indirect(IndirectVariable<'arena>),
23    Nested(NestedVariable<'arena>),
24}
25
26/// Represents a direct variable.
27///
28/// A direct variable is a variable that is directly referenced by its name.
29///
30/// # Examples
31///
32/// ```php
33/// $foo
34/// ```
35#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
36pub struct DirectVariable<'arena> {
37    pub span: Span,
38    pub name: &'arena str,
39}
40
41/// Represents an indirect variable.
42///
43/// An indirect variable is a variable whose name is determined by evaluating an expression at runtime.
44///
45/// The expression is enclosed in curly braces `{}` following a dollar sign `$`.
46///
47/// # Examples
48///
49/// ```php
50/// ${foo}
51/// ```
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
53pub struct IndirectVariable<'arena> {
54    pub dollar_left_brace: Span,
55    pub expression: &'arena Expression<'arena>,
56    pub right_brace: Span,
57}
58
59/// Represents a nested variable.
60///
61/// A nested variable is a variable that is nested inside another variable, commonly known as a variable variable.
62///
63/// # Examples
64///
65/// ```php
66/// $$foo
67/// $${foo}
68/// $$$foo
69/// ```
70#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
71pub struct NestedVariable<'arena> {
72    pub dollar: Span,
73    pub variable: &'arena Variable<'arena>,
74}
75
76impl HasSpan for Variable<'_> {
77    fn span(&self) -> Span {
78        match self {
79            Variable::Direct(node) => node.span(),
80            Variable::Indirect(node) => node.span(),
81            Variable::Nested(node) => node.span(),
82        }
83    }
84}
85
86impl HasSpan for DirectVariable<'_> {
87    fn span(&self) -> Span {
88        self.span
89    }
90}
91
92impl HasSpan for IndirectVariable<'_> {
93    fn span(&self) -> Span {
94        Span::between(self.dollar_left_brace, self.right_brace)
95    }
96}
97
98impl HasSpan for NestedVariable<'_> {
99    fn span(&self) -> Span {
100        Span::between(self.dollar, self.variable.span())
101    }
102}