1use std::borrow::Cow;
2
3use serde::Serialize;
4
5use crate::Span;
6
7fn is_false(b: &bool) -> bool {
8 !*b
9}
10
11pub struct ArenaVec<'arena, T>(bumpalo::collections::Vec<'arena, T>);
13
14impl<'arena, T> ArenaVec<'arena, T> {
15 #[inline]
16 pub fn new_in(arena: &'arena bumpalo::Bump) -> Self {
17 Self(bumpalo::collections::Vec::new_in(arena))
18 }
19 #[inline]
20 pub fn with_capacity_in(cap: usize, arena: &'arena bumpalo::Bump) -> Self {
21 Self(bumpalo::collections::Vec::with_capacity_in(cap, arena))
22 }
23 #[inline]
24 pub fn push(&mut self, val: T) {
25 self.0.push(val)
26 }
27 #[inline]
28 pub fn is_empty(&self) -> bool {
29 self.0.is_empty()
30 }
31 #[inline]
32 pub fn len(&self) -> usize {
33 self.0.len()
34 }
35 #[inline]
36 pub fn last(&self) -> Option<&T> {
37 self.0.last()
38 }
39}
40
41impl<'arena, T> IntoIterator for ArenaVec<'arena, T> {
42 type Item = T;
43 type IntoIter = bumpalo::collections::vec::IntoIter<'arena, T>;
44 #[inline]
45 fn into_iter(self) -> Self::IntoIter {
46 self.0.into_iter()
47 }
48}
49
50impl<'arena, T> std::ops::Deref for ArenaVec<'arena, T> {
51 type Target = [T];
52 #[inline]
53 fn deref(&self) -> &[T] {
54 &self.0
55 }
56}
57
58impl<'arena, T> std::ops::DerefMut for ArenaVec<'arena, T> {
59 #[inline]
60 fn deref_mut(&mut self) -> &mut [T] {
61 &mut self.0
62 }
63}
64
65impl<'arena, T: serde::Serialize> serde::Serialize for ArenaVec<'arena, T> {
66 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
67 self.0.as_slice().serialize(s)
68 }
69}
70
71impl<'arena, T: std::fmt::Debug> std::fmt::Debug for ArenaVec<'arena, T> {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 self.0.as_slice().fmt(f)
74 }
75}
76
77#[derive(Debug, Serialize)]
79pub struct Comment<'src> {
80 pub kind: CommentKind,
81 pub text: &'src str,
83 pub span: Span,
84}
85
86#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)]
88pub enum CommentKind {
89 Line,
91 Hash,
93 Block,
95 Doc,
97}
98
99#[derive(Debug, Serialize)]
102pub struct Program<'arena, 'src> {
103 pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
104 pub span: Span,
105}
106
107pub enum Name<'arena, 'src> {
120 Simple { value: &'src str, span: Span },
123 Complex {
125 parts: ArenaVec<'arena, &'src str>,
126 kind: NameKind,
127 span: Span,
128 },
129}
130
131impl<'arena, 'src> Name<'arena, 'src> {
132 #[inline]
133 pub fn span(&self) -> Span {
134 match self {
135 Self::Simple { span, .. } | Self::Complex { span, .. } => *span,
136 }
137 }
138
139 #[inline]
140 pub fn kind(&self) -> NameKind {
141 match self {
142 Self::Simple { .. } => NameKind::Unqualified,
143 Self::Complex { kind, .. } => *kind,
144 }
145 }
146
147 #[inline]
150 pub fn to_string_repr(&self) -> Cow<'src, str> {
151 match self {
152 Self::Simple { value, .. } => Cow::Borrowed(value),
153 Self::Complex { parts, kind, .. } => {
154 let joined = parts.join("\\");
155 if *kind == NameKind::FullyQualified {
156 Cow::Owned(format!("\\{}", joined))
157 } else {
158 Cow::Owned(joined)
159 }
160 }
161 }
162 }
163
164 #[inline]
167 pub fn join_parts(&self) -> Cow<'src, str> {
168 match self {
169 Self::Simple { value, .. } => Cow::Borrowed(value),
170 Self::Complex { parts, .. } => Cow::Owned(parts.join("\\")),
171 }
172 }
173
174 #[inline]
177 pub fn parts_slice(&self) -> &[&'src str] {
178 match self {
179 Self::Simple { value, .. } => std::slice::from_ref(value),
180 Self::Complex { parts, .. } => parts,
181 }
182 }
183}
184
185impl<'arena, 'src> std::fmt::Debug for Name<'arena, 'src> {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 match self {
188 Self::Simple { value, span } => f
189 .debug_struct("Name")
190 .field("parts", &std::slice::from_ref(value))
191 .field("kind", &NameKind::Unqualified)
192 .field("span", span)
193 .finish(),
194 Self::Complex { parts, kind, span } => f
195 .debug_struct("Name")
196 .field("parts", parts)
197 .field("kind", kind)
198 .field("span", span)
199 .finish(),
200 }
201 }
202}
203
204impl<'arena, 'src> serde::Serialize for Name<'arena, 'src> {
205 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
206 use serde::ser::SerializeStruct;
207 let mut st = s.serialize_struct("Name", 3)?;
208 match self {
209 Self::Simple { value, span } => {
210 st.serialize_field("parts", std::slice::from_ref(value))?;
211 st.serialize_field("kind", &NameKind::Unqualified)?;
212 st.serialize_field("span", span)?;
213 }
214 Self::Complex { parts, kind, span } => {
215 st.serialize_field("parts", parts)?;
216 st.serialize_field("kind", kind)?;
217 st.serialize_field("span", span)?;
218 }
219 }
220 st.end()
221 }
222}
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
225pub enum NameKind {
226 Unqualified,
227 Qualified,
228 FullyQualified,
229 Relative,
230}
231
232#[repr(u8)]
235#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
236pub enum BuiltinType {
237 Int,
238 Integer,
239 Float,
240 Double,
241 String,
242 Bool,
243 Boolean,
244 Void,
245 Never,
246 Mixed,
247 Object,
248 Iterable,
249 Callable,
250 Array,
251 Self_,
252 Parent_,
253 Static,
254 Null,
255 True,
256 False,
257}
258
259impl BuiltinType {
260 #[inline]
262 pub fn as_str(self) -> &'static str {
263 match self {
264 Self::Int => "int",
265 Self::Integer => "integer",
266 Self::Float => "float",
267 Self::Double => "double",
268 Self::String => "string",
269 Self::Bool => "bool",
270 Self::Boolean => "boolean",
271 Self::Void => "void",
272 Self::Never => "never",
273 Self::Mixed => "mixed",
274 Self::Object => "object",
275 Self::Iterable => "iterable",
276 Self::Callable => "callable",
277 Self::Array => "array",
278 Self::Self_ => "self",
279 Self::Parent_ => "parent",
280 Self::Static => "static",
281 Self::Null => "null",
282 Self::True => "true",
283 Self::False => "false",
284 }
285 }
286}
287
288#[derive(Debug, Serialize)]
289pub struct TypeHint<'arena, 'src> {
290 pub kind: TypeHintKind<'arena, 'src>,
291 pub span: Span,
292}
293
294#[derive(Debug)]
302pub enum TypeHintKind<'arena, 'src> {
303 Named(Name<'arena, 'src>),
304 Keyword(BuiltinType, Span),
306 Nullable(&'arena TypeHint<'arena, 'src>),
307 Union(ArenaVec<'arena, TypeHint<'arena, 'src>>),
308 Intersection(ArenaVec<'arena, TypeHint<'arena, 'src>>),
309}
310
311impl<'arena, 'src> serde::Serialize for TypeHintKind<'arena, 'src> {
312 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
313 match self {
314 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
316 Self::Nullable(inner) => {
317 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
318 }
319 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
320 Self::Intersection(types) => {
321 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
322 }
323 Self::Keyword(builtin, span) => {
326 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
327 impl serde::Serialize for BuiltinNameRepr<'_> {
328 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
329 use serde::ser::SerializeStruct;
330 let mut st = s.serialize_struct("Name", 3)?;
331 st.serialize_field("parts", &[self.0.as_str()])?;
332 st.serialize_field("kind", &NameKind::Unqualified)?;
333 st.serialize_field("span", self.1)?;
334 st.end()
335 }
336 }
337 s.serialize_newtype_variant(
338 "TypeHintKind",
339 0,
340 "Named",
341 &BuiltinNameRepr(builtin, span),
342 )
343 }
344 }
345 }
346}
347
348#[derive(Debug, Serialize)]
353pub struct Arg<'arena, 'src> {
354 pub name: Option<Cow<'src, str>>,
355 pub value: Expr<'arena, 'src>,
356 pub unpack: bool,
357 pub by_ref: bool,
358 pub span: Span,
359}
360
361#[derive(Debug, Serialize)]
366pub struct Attribute<'arena, 'src> {
367 pub name: Name<'arena, 'src>,
368 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
369 pub span: Span,
370}
371
372#[derive(Debug, Serialize)]
377pub struct Stmt<'arena, 'src> {
378 pub kind: StmtKind<'arena, 'src>,
379 pub span: Span,
380}
381
382#[derive(Debug, Serialize)]
383pub enum StmtKind<'arena, 'src> {
384 Expression(&'arena Expr<'arena, 'src>),
386
387 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
389
390 Return(Option<&'arena Expr<'arena, 'src>>),
392
393 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
395
396 If(&'arena IfStmt<'arena, 'src>),
398
399 While(&'arena WhileStmt<'arena, 'src>),
401
402 For(&'arena ForStmt<'arena, 'src>),
404
405 Foreach(&'arena ForeachStmt<'arena, 'src>),
407
408 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
410
411 Function(&'arena FunctionDecl<'arena, 'src>),
413
414 Break(Option<&'arena Expr<'arena, 'src>>),
416
417 Continue(Option<&'arena Expr<'arena, 'src>>),
419
420 Switch(&'arena SwitchStmt<'arena, 'src>),
422
423 Goto(&'src str),
425
426 Label(&'arena str),
428
429 Declare(&'arena DeclareStmt<'arena, 'src>),
431
432 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
434
435 Throw(&'arena Expr<'arena, 'src>),
437
438 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
440
441 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
443
444 Class(&'arena ClassDecl<'arena, 'src>),
446
447 Interface(&'arena InterfaceDecl<'arena, 'src>),
449
450 Trait(&'arena TraitDecl<'arena, 'src>),
452
453 Enum(&'arena EnumDecl<'arena, 'src>),
455
456 Namespace(&'arena NamespaceDecl<'arena, 'src>),
458
459 Use(&'arena UseDecl<'arena, 'src>),
461
462 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
464
465 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
467
468 HaltCompiler(&'src str),
470
471 Nop,
473
474 InlineHtml(&'src str),
476
477 Error,
479}
480
481#[derive(Debug, Serialize)]
482pub struct IfStmt<'arena, 'src> {
483 pub condition: Expr<'arena, 'src>,
484 pub then_branch: &'arena Stmt<'arena, 'src>,
485 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
486 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
487}
488
489#[derive(Debug, Serialize)]
490pub struct ElseIfBranch<'arena, 'src> {
491 pub condition: Expr<'arena, 'src>,
492 pub body: Stmt<'arena, 'src>,
493 pub span: Span,
494}
495
496#[derive(Debug, Serialize)]
497pub struct WhileStmt<'arena, 'src> {
498 pub condition: Expr<'arena, 'src>,
499 pub body: &'arena Stmt<'arena, 'src>,
500}
501
502#[derive(Debug, Serialize)]
503pub struct ForStmt<'arena, 'src> {
504 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
505 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
506 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
507 pub body: &'arena Stmt<'arena, 'src>,
508}
509
510#[derive(Debug, Serialize)]
511pub struct ForeachStmt<'arena, 'src> {
512 pub expr: Expr<'arena, 'src>,
513 pub key: Option<Expr<'arena, 'src>>,
514 pub value: Expr<'arena, 'src>,
515 pub body: &'arena Stmt<'arena, 'src>,
516}
517
518#[derive(Debug, Serialize)]
519pub struct DoWhileStmt<'arena, 'src> {
520 pub body: &'arena Stmt<'arena, 'src>,
521 pub condition: Expr<'arena, 'src>,
522}
523
524#[derive(Debug, Serialize)]
525pub struct FunctionDecl<'arena, 'src> {
526 pub name: &'src str,
527 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
528 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
529 pub return_type: Option<TypeHint<'arena, 'src>>,
530 pub by_ref: bool,
531 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
532 #[serde(skip_serializing_if = "Option::is_none")]
533 pub doc_comment: Option<Comment<'src>>,
534}
535
536#[derive(Debug, Serialize)]
537pub struct Param<'arena, 'src> {
538 pub name: &'src str,
539 pub type_hint: Option<TypeHint<'arena, 'src>>,
540 pub default: Option<Expr<'arena, 'src>>,
541 pub by_ref: bool,
542 pub variadic: bool,
543 pub is_readonly: bool,
544 pub is_final: bool,
545 pub visibility: Option<Visibility>,
546 pub set_visibility: Option<Visibility>,
547 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
548 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
549 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
550 pub span: Span,
551}
552
553#[derive(Debug, Serialize)]
554pub struct SwitchStmt<'arena, 'src> {
555 pub expr: Expr<'arena, 'src>,
556 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
557}
558
559#[derive(Debug, Serialize)]
560pub struct SwitchCase<'arena, 'src> {
561 pub value: Option<Expr<'arena, 'src>>,
562 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
563 pub span: Span,
564}
565
566#[derive(Debug, Serialize)]
567pub struct TryCatchStmt<'arena, 'src> {
568 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
569 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
570 pub finally: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
571}
572
573#[derive(Debug, Serialize)]
574pub struct CatchClause<'arena, 'src> {
575 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
576 pub var: Option<&'src str>,
577 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
578 pub span: Span,
579}
580
581#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
586pub enum Visibility {
587 Public,
588 Protected,
589 Private,
590}
591
592#[derive(Debug, Serialize)]
593pub struct ClassDecl<'arena, 'src> {
594 pub name: Option<&'src str>,
595 pub modifiers: ClassModifiers,
596 pub extends: Option<Name<'arena, 'src>>,
597 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
598 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
599 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
600 #[serde(skip_serializing_if = "Option::is_none")]
601 pub doc_comment: Option<Comment<'src>>,
602}
603
604#[derive(Debug, Clone, Serialize, Default)]
605pub struct ClassModifiers {
606 pub is_abstract: bool,
607 pub is_final: bool,
608 pub is_readonly: bool,
609}
610
611#[derive(Debug, Serialize)]
612pub struct ClassMember<'arena, 'src> {
613 pub kind: ClassMemberKind<'arena, 'src>,
614 pub span: Span,
615}
616
617#[derive(Debug, Serialize)]
618pub enum ClassMemberKind<'arena, 'src> {
619 Property(PropertyDecl<'arena, 'src>),
620 Method(MethodDecl<'arena, 'src>),
621 ClassConst(ClassConstDecl<'arena, 'src>),
622 TraitUse(TraitUseDecl<'arena, 'src>),
623}
624
625#[derive(Debug, Serialize)]
626pub struct PropertyDecl<'arena, 'src> {
627 pub name: &'src str,
628 pub visibility: Option<Visibility>,
629 pub set_visibility: Option<Visibility>,
630 pub is_static: bool,
631 pub is_readonly: bool,
632 pub type_hint: Option<TypeHint<'arena, 'src>>,
633 pub default: Option<Expr<'arena, 'src>>,
634 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
635 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
636 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
637 #[serde(skip_serializing_if = "Option::is_none")]
638 pub doc_comment: Option<Comment<'src>>,
639}
640
641#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
642pub enum PropertyHookKind {
643 Get,
644 Set,
645}
646
647#[derive(Debug, Serialize)]
648pub enum PropertyHookBody<'arena, 'src> {
649 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
650 Expression(Expr<'arena, 'src>),
651 Abstract,
652}
653
654#[derive(Debug, Serialize)]
655pub struct PropertyHook<'arena, 'src> {
656 pub kind: PropertyHookKind,
657 pub body: PropertyHookBody<'arena, 'src>,
658 pub is_final: bool,
659 pub by_ref: bool,
660 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
661 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
662 pub span: Span,
663}
664
665#[derive(Debug, Serialize)]
666pub struct MethodDecl<'arena, 'src> {
667 pub name: &'src str,
668 pub visibility: Option<Visibility>,
669 pub is_static: bool,
670 pub is_abstract: bool,
671 pub is_final: bool,
672 pub by_ref: bool,
673 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
674 pub return_type: Option<TypeHint<'arena, 'src>>,
675 pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
676 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
677 #[serde(skip_serializing_if = "Option::is_none")]
678 pub doc_comment: Option<Comment<'src>>,
679}
680
681#[derive(Debug, Serialize)]
682pub struct ClassConstDecl<'arena, 'src> {
683 pub name: &'src str,
684 pub visibility: Option<Visibility>,
685 #[serde(skip_serializing_if = "Option::is_none")]
686 pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
687 pub value: Expr<'arena, 'src>,
688 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
689 #[serde(skip_serializing_if = "Option::is_none")]
690 pub doc_comment: Option<Comment<'src>>,
691}
692
693#[derive(Debug, Serialize)]
694pub struct TraitUseDecl<'arena, 'src> {
695 pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
696 pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
697}
698
699#[derive(Debug, Serialize)]
700pub struct TraitAdaptation<'arena, 'src> {
701 pub kind: TraitAdaptationKind<'arena, 'src>,
702 pub span: Span,
703}
704
705#[derive(Debug, Serialize)]
706pub enum TraitAdaptationKind<'arena, 'src> {
707 Precedence {
709 trait_name: Name<'arena, 'src>,
710 method: &'src str,
711 insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
712 },
713 Alias {
715 trait_name: Option<Name<'arena, 'src>>,
716 method: Cow<'src, str>,
717 new_modifier: Option<Visibility>,
718 new_name: Option<&'src str>,
719 },
720}
721
722#[derive(Debug, Serialize)]
723pub struct InterfaceDecl<'arena, 'src> {
724 pub name: &'src str,
725 pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
726 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
727 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
728 #[serde(skip_serializing_if = "Option::is_none")]
729 pub doc_comment: Option<Comment<'src>>,
730}
731
732#[derive(Debug, Serialize)]
733pub struct TraitDecl<'arena, 'src> {
734 pub name: &'src str,
735 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
736 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
737 #[serde(skip_serializing_if = "Option::is_none")]
738 pub doc_comment: Option<Comment<'src>>,
739}
740
741#[derive(Debug, Serialize)]
742pub struct EnumDecl<'arena, 'src> {
743 pub name: &'src str,
744 pub scalar_type: Option<Name<'arena, 'src>>,
745 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
746 pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
747 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
748 #[serde(skip_serializing_if = "Option::is_none")]
749 pub doc_comment: Option<Comment<'src>>,
750}
751
752#[derive(Debug, Serialize)]
753pub struct EnumMember<'arena, 'src> {
754 pub kind: EnumMemberKind<'arena, 'src>,
755 pub span: Span,
756}
757
758#[derive(Debug, Serialize)]
759pub enum EnumMemberKind<'arena, 'src> {
760 Case(EnumCase<'arena, 'src>),
761 Method(MethodDecl<'arena, 'src>),
762 ClassConst(ClassConstDecl<'arena, 'src>),
763 TraitUse(TraitUseDecl<'arena, 'src>),
764}
765
766#[derive(Debug, Serialize)]
767pub struct EnumCase<'arena, 'src> {
768 pub name: &'src str,
769 pub value: Option<Expr<'arena, 'src>>,
770 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
771 #[serde(skip_serializing_if = "Option::is_none")]
772 pub doc_comment: Option<Comment<'src>>,
773}
774
775#[derive(Debug, Serialize)]
780pub struct NamespaceDecl<'arena, 'src> {
781 pub name: Option<Name<'arena, 'src>>,
782 pub body: NamespaceBody<'arena, 'src>,
783}
784
785#[derive(Debug, Serialize)]
786pub enum NamespaceBody<'arena, 'src> {
787 Braced(ArenaVec<'arena, Stmt<'arena, 'src>>),
788 Simple,
789}
790
791#[derive(Debug, Serialize)]
792pub struct DeclareStmt<'arena, 'src> {
793 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
794 pub body: Option<&'arena Stmt<'arena, 'src>>,
795}
796
797#[derive(Debug, Serialize)]
798pub struct UseDecl<'arena, 'src> {
799 pub kind: UseKind,
800 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
801}
802
803#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
804pub enum UseKind {
805 Normal,
806 Function,
807 Const,
808}
809
810#[derive(Debug, Serialize)]
811pub struct UseItem<'arena, 'src> {
812 pub name: Name<'arena, 'src>,
813 pub alias: Option<&'src str>,
814 #[serde(skip_serializing_if = "Option::is_none")]
815 pub kind: Option<UseKind>,
816 pub span: Span,
817}
818
819#[derive(Debug, Serialize)]
820pub struct ConstItem<'arena, 'src> {
821 pub name: &'src str,
822 pub value: Expr<'arena, 'src>,
823 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
824 pub span: Span,
825}
826
827#[derive(Debug, Serialize)]
828pub struct StaticVar<'arena, 'src> {
829 pub name: &'src str,
830 pub default: Option<Expr<'arena, 'src>>,
831 pub span: Span,
832}
833
834#[derive(Clone, Copy, PartialEq, Eq, Hash)]
853pub enum NameStr<'arena, 'src> {
854 Src(&'src str),
856 Arena(&'arena str),
858}
859
860impl<'arena, 'src> NameStr<'arena, 'src> {
861 #[inline]
862 pub fn as_str(&self) -> &str {
863 match self {
864 NameStr::Src(s) => s,
865 NameStr::Arena(s) => s,
866 }
867 }
868}
869
870impl<'arena, 'src> std::ops::Deref for NameStr<'arena, 'src> {
871 type Target = str;
872 #[inline]
873 fn deref(&self) -> &str {
874 self.as_str()
875 }
876}
877
878impl<'arena, 'src> std::fmt::Debug for NameStr<'arena, 'src> {
879 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
880 self.as_str().fmt(f)
881 }
882}
883
884impl<'arena, 'src> serde::Serialize for NameStr<'arena, 'src> {
885 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
886 self.as_str().serialize(serializer)
887 }
888}
889
890#[derive(Debug, Serialize)]
891pub struct Expr<'arena, 'src> {
892 pub kind: ExprKind<'arena, 'src>,
893 pub span: Span,
894}
895
896#[derive(Debug, Serialize)]
897pub enum ExprKind<'arena, 'src> {
898 Int(i64),
900
901 Float(f64),
903
904 String(&'arena str),
906
907 InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
909
910 Heredoc {
912 label: &'src str,
913 parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
914 },
915
916 Nowdoc {
918 label: &'src str,
919 value: &'arena str,
920 },
921
922 ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
924
925 Bool(bool),
927
928 Null,
930
931 Variable(NameStr<'arena, 'src>),
933
934 VariableVariable(&'arena Expr<'arena, 'src>),
936
937 Identifier(NameStr<'arena, 'src>),
939
940 Assign(AssignExpr<'arena, 'src>),
942
943 Binary(BinaryExpr<'arena, 'src>),
945
946 UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
948
949 UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
951
952 Ternary(TernaryExpr<'arena, 'src>),
954
955 NullCoalesce(NullCoalesceExpr<'arena, 'src>),
957
958 FunctionCall(FunctionCallExpr<'arena, 'src>),
960
961 Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
963
964 ArrayAccess(ArrayAccessExpr<'arena, 'src>),
966
967 Print(&'arena Expr<'arena, 'src>),
969
970 Parenthesized(&'arena Expr<'arena, 'src>),
972
973 Cast(CastKind, &'arena Expr<'arena, 'src>),
975
976 ErrorSuppress(&'arena Expr<'arena, 'src>),
978
979 Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
981
982 Empty(&'arena Expr<'arena, 'src>),
984
985 Include(IncludeKind, &'arena Expr<'arena, 'src>),
987
988 Eval(&'arena Expr<'arena, 'src>),
990
991 Exit(Option<&'arena Expr<'arena, 'src>>),
993
994 MagicConst(MagicConstKind),
996
997 Clone(&'arena Expr<'arena, 'src>),
999
1000 CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
1002
1003 New(NewExpr<'arena, 'src>),
1005
1006 PropertyAccess(PropertyAccessExpr<'arena, 'src>),
1008
1009 NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
1011
1012 MethodCall(&'arena MethodCallExpr<'arena, 'src>),
1014
1015 NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
1017
1018 StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
1020
1021 StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
1023
1024 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1026
1027 ClassConstAccessDynamic {
1029 class: &'arena Expr<'arena, 'src>,
1030 member: &'arena Expr<'arena, 'src>,
1031 },
1032
1033 StaticPropertyAccessDynamic {
1035 class: &'arena Expr<'arena, 'src>,
1036 member: &'arena Expr<'arena, 'src>,
1037 },
1038
1039 Closure(&'arena ClosureExpr<'arena, 'src>),
1041
1042 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1044
1045 Match(MatchExpr<'arena, 'src>),
1047
1048 ThrowExpr(&'arena Expr<'arena, 'src>),
1050
1051 Yield(YieldExpr<'arena, 'src>),
1053
1054 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1056
1057 CallableCreate(CallableCreateExpr<'arena, 'src>),
1059
1060 Omit,
1062
1063 Error,
1065}
1066
1067impl<'arena, 'src> Expr<'arena, 'src> {
1068 pub fn name_str(&self) -> Option<&str> {
1070 match &self.kind {
1071 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
1072 _ => None,
1073 }
1074 }
1075}
1076
1077#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1078pub enum CastKind {
1079 Int,
1080 Float,
1081 String,
1082 Bool,
1083 Array,
1084 Object,
1085 Unset,
1086 Void,
1087}
1088
1089#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1090pub enum IncludeKind {
1091 Include,
1092 IncludeOnce,
1093 Require,
1094 RequireOnce,
1095}
1096
1097#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1098pub enum MagicConstKind {
1099 Class,
1100 Dir,
1101 File,
1102 Function,
1103 Line,
1104 Method,
1105 Namespace,
1106 Trait,
1107 Property,
1108}
1109
1110#[derive(Debug, Serialize)]
1113pub struct AssignExpr<'arena, 'src> {
1114 pub target: &'arena Expr<'arena, 'src>,
1115 pub op: AssignOp,
1116 pub value: &'arena Expr<'arena, 'src>,
1117 #[serde(skip_serializing_if = "is_false")]
1118 pub by_ref: bool,
1119}
1120
1121#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1122pub enum AssignOp {
1123 Assign,
1124 Plus,
1125 Minus,
1126 Mul,
1127 Div,
1128 Mod,
1129 Pow,
1130 Concat,
1131 BitwiseAnd,
1132 BitwiseOr,
1133 BitwiseXor,
1134 ShiftLeft,
1135 ShiftRight,
1136 Coalesce,
1137}
1138
1139#[derive(Debug, Serialize)]
1140pub struct BinaryExpr<'arena, 'src> {
1141 pub left: &'arena Expr<'arena, 'src>,
1142 pub op: BinaryOp,
1143 pub right: &'arena Expr<'arena, 'src>,
1144}
1145
1146#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1147pub enum BinaryOp {
1148 Add,
1149 Sub,
1150 Mul,
1151 Div,
1152 Mod,
1153 Pow,
1154 Concat,
1155 Equal,
1156 NotEqual,
1157 Identical,
1158 NotIdentical,
1159 Less,
1160 Greater,
1161 LessOrEqual,
1162 GreaterOrEqual,
1163 Spaceship,
1164 BooleanAnd,
1165 BooleanOr,
1166 BitwiseAnd,
1167 BitwiseOr,
1168 BitwiseXor,
1169 ShiftLeft,
1170 ShiftRight,
1171 LogicalAnd,
1172 LogicalOr,
1173 LogicalXor,
1174 Instanceof,
1175 Pipe,
1176}
1177
1178#[derive(Debug, Serialize)]
1179pub struct UnaryPrefixExpr<'arena, 'src> {
1180 pub op: UnaryPrefixOp,
1181 pub operand: &'arena Expr<'arena, 'src>,
1182}
1183
1184#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1185pub enum UnaryPrefixOp {
1186 Negate,
1187 Plus,
1188 BooleanNot,
1189 BitwiseNot,
1190 PreIncrement,
1191 PreDecrement,
1192}
1193
1194#[derive(Debug, Serialize)]
1195pub struct UnaryPostfixExpr<'arena, 'src> {
1196 pub operand: &'arena Expr<'arena, 'src>,
1197 pub op: UnaryPostfixOp,
1198}
1199
1200#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1201pub enum UnaryPostfixOp {
1202 PostIncrement,
1203 PostDecrement,
1204}
1205
1206#[derive(Debug, Serialize)]
1207pub struct TernaryExpr<'arena, 'src> {
1208 pub condition: &'arena Expr<'arena, 'src>,
1209 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1211 pub else_expr: &'arena Expr<'arena, 'src>,
1212}
1213
1214#[derive(Debug, Serialize)]
1215pub struct NullCoalesceExpr<'arena, 'src> {
1216 pub left: &'arena Expr<'arena, 'src>,
1217 pub right: &'arena Expr<'arena, 'src>,
1218}
1219
1220#[derive(Debug, Serialize)]
1221pub struct FunctionCallExpr<'arena, 'src> {
1222 pub name: &'arena Expr<'arena, 'src>,
1223 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1224}
1225
1226#[derive(Debug, Serialize)]
1227pub struct ArrayElement<'arena, 'src> {
1228 pub key: Option<Expr<'arena, 'src>>,
1229 pub value: Expr<'arena, 'src>,
1230 pub unpack: bool,
1231 #[serde(skip_serializing_if = "is_false")]
1232 pub by_ref: bool,
1233 pub span: Span,
1234}
1235
1236#[derive(Debug, Serialize)]
1237pub struct ArrayAccessExpr<'arena, 'src> {
1238 pub array: &'arena Expr<'arena, 'src>,
1239 pub index: Option<&'arena Expr<'arena, 'src>>,
1240}
1241
1242#[derive(Debug, Serialize)]
1245pub struct NewExpr<'arena, 'src> {
1246 pub class: &'arena Expr<'arena, 'src>,
1247 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1248}
1249
1250#[derive(Debug, Serialize)]
1251pub struct PropertyAccessExpr<'arena, 'src> {
1252 pub object: &'arena Expr<'arena, 'src>,
1253 pub property: &'arena Expr<'arena, 'src>,
1254}
1255
1256#[derive(Debug, Serialize)]
1257pub struct MethodCallExpr<'arena, 'src> {
1258 pub object: &'arena Expr<'arena, 'src>,
1259 pub method: &'arena Expr<'arena, 'src>,
1260 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1261}
1262
1263#[derive(Debug, Serialize)]
1264pub struct StaticAccessExpr<'arena, 'src> {
1265 pub class: &'arena Expr<'arena, 'src>,
1266 pub member: Cow<'src, str>,
1267}
1268
1269#[derive(Debug, Serialize)]
1270pub struct StaticMethodCallExpr<'arena, 'src> {
1271 pub class: &'arena Expr<'arena, 'src>,
1272 pub method: Cow<'src, str>,
1273 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1274}
1275
1276#[derive(Debug, Serialize)]
1277pub struct ClosureExpr<'arena, 'src> {
1278 pub is_static: bool,
1279 pub by_ref: bool,
1280 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1281 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1282 pub return_type: Option<TypeHint<'arena, 'src>>,
1283 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1284 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1285}
1286
1287#[derive(Debug, Clone, Serialize)]
1288pub struct ClosureUseVar<'src> {
1289 pub name: &'src str,
1290 pub by_ref: bool,
1291 pub span: Span,
1292}
1293
1294#[derive(Debug, Serialize)]
1295pub struct ArrowFunctionExpr<'arena, 'src> {
1296 pub is_static: bool,
1297 pub by_ref: bool,
1298 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1299 pub return_type: Option<TypeHint<'arena, 'src>>,
1300 pub body: &'arena Expr<'arena, 'src>,
1301 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1302}
1303
1304#[derive(Debug, Serialize)]
1305pub struct MatchExpr<'arena, 'src> {
1306 pub subject: &'arena Expr<'arena, 'src>,
1307 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1308}
1309
1310#[derive(Debug, Serialize)]
1311pub struct MatchArm<'arena, 'src> {
1312 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1314 pub body: Expr<'arena, 'src>,
1315 pub span: Span,
1316}
1317
1318#[derive(Debug, Serialize)]
1319pub struct YieldExpr<'arena, 'src> {
1320 pub key: Option<&'arena Expr<'arena, 'src>>,
1321 pub value: Option<&'arena Expr<'arena, 'src>>,
1322 pub is_from: bool,
1324}
1325
1326#[derive(Debug, Serialize)]
1329pub struct CallableCreateExpr<'arena, 'src> {
1330 pub kind: CallableCreateKind<'arena, 'src>,
1331}
1332
1333#[derive(Debug, Serialize)]
1334pub enum CallableCreateKind<'arena, 'src> {
1335 Function(&'arena Expr<'arena, 'src>),
1337 Method {
1339 object: &'arena Expr<'arena, 'src>,
1340 method: &'arena Expr<'arena, 'src>,
1341 },
1342 NullsafeMethod {
1344 object: &'arena Expr<'arena, 'src>,
1345 method: &'arena Expr<'arena, 'src>,
1346 },
1347 StaticMethod {
1349 class: &'arena Expr<'arena, 'src>,
1350 method: Cow<'src, str>,
1351 },
1352}
1353
1354#[derive(Debug, Serialize)]
1357pub enum StringPart<'arena, 'src> {
1358 Literal(&'arena str),
1359 Expr(Expr<'arena, 'src>),
1360}