mago_ast/ast/loop/
foreach.rs1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_span::HasSpan;
6use mago_span::Span;
7
8use crate::ast::expression::Expression;
9use crate::ast::keyword::Keyword;
10use crate::ast::statement::Statement;
11use crate::ast::terminator::Terminator;
12use crate::sequence::Sequence;
13
14#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
26#[repr(C)]
27pub struct Foreach {
28 pub foreach: Keyword,
29 pub left_parenthesis: Span,
30 pub expression: Box<Expression>,
31 pub r#as: Keyword,
32 pub target: ForeachTarget,
33 pub right_parenthesis: Span,
34 pub body: ForeachBody,
35}
36
37#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
39#[serde(tag = "type", content = "value")]
40#[repr(C, u8)]
41pub enum ForeachTarget {
42 Value(ForeachValueTarget),
43 KeyValue(ForeachKeyValueTarget),
44}
45
46#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
58#[repr(C)]
59pub struct ForeachValueTarget {
60 pub value: Box<Expression>,
61}
62
63#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
75#[repr(C)]
76pub struct ForeachKeyValueTarget {
77 pub key: Box<Expression>,
78 pub double_arrow: Span,
79 pub value: Box<Expression>,
80}
81
82#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
84#[serde(tag = "type", content = "value")]
85#[repr(C, u8)]
86pub enum ForeachBody {
87 Statement(Box<Statement>),
89 ColonDelimited(ForeachColonDelimitedBody),
91}
92
93#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
105#[repr(C)]
106pub struct ForeachColonDelimitedBody {
107 pub colon: Span,
108 pub statements: Sequence<Statement>,
109 pub end_foreach: Keyword,
110 pub terminator: Terminator,
111}
112
113impl HasSpan for Foreach {
114 fn span(&self) -> Span {
115 self.foreach.span().join(self.body.span())
116 }
117}
118
119impl HasSpan for ForeachTarget {
120 fn span(&self) -> Span {
121 match self {
122 ForeachTarget::Value(value) => value.span(),
123 ForeachTarget::KeyValue(key_value) => key_value.span(),
124 }
125 }
126}
127
128impl HasSpan for ForeachValueTarget {
129 fn span(&self) -> Span {
130 self.value.span()
131 }
132}
133
134impl HasSpan for ForeachKeyValueTarget {
135 fn span(&self) -> Span {
136 self.key.span().join(self.value.span())
137 }
138}
139
140impl HasSpan for ForeachBody {
141 fn span(&self) -> Span {
142 match self {
143 ForeachBody::Statement(statement) => statement.span(),
144 ForeachBody::ColonDelimited(body) => body.span(),
145 }
146 }
147}
148
149impl HasSpan for ForeachColonDelimitedBody {
150 fn span(&self) -> Span {
151 self.colon.join(self.terminator.span())
152 }
153}