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]
30 pub fn is_empty(&self) -> bool {
31 self.0.is_empty()
32 }
33}
34
35impl<'arena, T> IntoIterator for ArenaVec<'arena, T> {
36 type Item = T;
37 type IntoIter = bumpalo::collections::vec::IntoIter<'arena, T>;
38 #[inline]
39 fn into_iter(self) -> Self::IntoIter {
40 self.0.into_iter()
41 }
42}
43
44impl<'arena, T> std::ops::Deref for ArenaVec<'arena, T> {
45 type Target = [T];
46 #[inline]
47 fn deref(&self) -> &[T] {
48 &self.0
49 }
50}
51
52impl<'arena, T> std::ops::DerefMut for ArenaVec<'arena, T> {
53 #[inline]
54 fn deref_mut(&mut self) -> &mut [T] {
55 &mut self.0
56 }
57}
58
59impl<'arena, T: serde::Serialize> serde::Serialize for ArenaVec<'arena, T> {
60 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
61 self.0.as_slice().serialize(s)
62 }
63}
64
65impl<'arena, T: std::fmt::Debug> std::fmt::Debug for ArenaVec<'arena, T> {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 self.0.as_slice().fmt(f)
68 }
69}
70
71#[derive(Debug, Serialize)]
73pub struct Comment<'src> {
74 pub kind: CommentKind,
75 pub text: &'src str,
77 pub span: Span,
78}
79
80#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)]
82pub enum CommentKind {
83 Line,
85 Hash,
87 Block,
89 Doc,
91}
92
93#[derive(Debug, Serialize)]
96pub struct Program<'arena, 'src> {
97 pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
98 pub span: Span,
99}
100
101pub enum Name<'arena, 'src> {
114 Simple { value: &'src str, span: Span },
117 Complex {
119 parts: ArenaVec<'arena, &'src str>,
120 kind: NameKind,
121 span: Span,
122 },
123}
124
125impl<'arena, 'src> Name<'arena, 'src> {
126 #[inline]
127 pub fn span(&self) -> Span {
128 match self {
129 Self::Simple { span, .. } | Self::Complex { span, .. } => *span,
130 }
131 }
132
133 #[inline]
134 pub fn kind(&self) -> NameKind {
135 match self {
136 Self::Simple { .. } => NameKind::Unqualified,
137 Self::Complex { kind, .. } => *kind,
138 }
139 }
140
141 #[inline]
150 pub fn src_repr(&self, src: &'src str) -> &'src str {
151 match self {
152 Self::Simple { value, .. } => value,
153 Self::Complex { span, .. } => &src[span.start as usize..span.end as usize],
154 }
155 }
156
157 #[inline]
160 pub fn to_string_repr(&self) -> Cow<'src, str> {
161 match self {
162 Self::Simple { value, .. } => Cow::Borrowed(value),
163 Self::Complex { parts, kind, .. } => {
164 let joined = parts.join("\\");
165 if *kind == NameKind::FullyQualified {
166 Cow::Owned(format!("\\{}", joined))
167 } else {
168 Cow::Owned(joined)
169 }
170 }
171 }
172 }
173
174 #[inline]
177 pub fn join_parts(&self) -> Cow<'src, str> {
178 match self {
179 Self::Simple { value, .. } => Cow::Borrowed(value),
180 Self::Complex { parts, .. } => Cow::Owned(parts.join("\\")),
181 }
182 }
183
184 #[inline]
187 pub fn parts_slice(&self) -> &[&'src str] {
188 match self {
189 Self::Simple { value, .. } => std::slice::from_ref(value),
190 Self::Complex { parts, .. } => parts,
191 }
192 }
193}
194
195impl<'arena, 'src> std::fmt::Debug for Name<'arena, 'src> {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 match self {
198 Self::Simple { value, span } => f
199 .debug_struct("Name")
200 .field("parts", &std::slice::from_ref(value))
201 .field("kind", &NameKind::Unqualified)
202 .field("span", span)
203 .finish(),
204 Self::Complex { parts, kind, span } => f
205 .debug_struct("Name")
206 .field("parts", parts)
207 .field("kind", kind)
208 .field("span", span)
209 .finish(),
210 }
211 }
212}
213
214impl<'arena, 'src> serde::Serialize for Name<'arena, 'src> {
215 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
216 use serde::ser::SerializeStruct;
217 let mut st = s.serialize_struct("Name", 3)?;
218 match self {
219 Self::Simple { value, span } => {
220 st.serialize_field("parts", std::slice::from_ref(value))?;
221 st.serialize_field("kind", &NameKind::Unqualified)?;
222 st.serialize_field("span", span)?;
223 }
224 Self::Complex { parts, kind, span } => {
225 st.serialize_field("parts", parts)?;
226 st.serialize_field("kind", kind)?;
227 st.serialize_field("span", span)?;
228 }
229 }
230 st.end()
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
235pub enum NameKind {
236 Unqualified,
238 Qualified,
240 FullyQualified,
242 Relative,
244}
245
246#[repr(u8)]
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
250pub enum BuiltinType {
251 Int,
253 Integer,
255 Float,
257 Double,
259 String,
261 Bool,
263 Boolean,
265 Void,
267 Never,
269 Mixed,
271 Object,
273 Iterable,
275 Callable,
277 Array,
279 Self_,
281 Parent_,
283 Static,
285 Null,
287 True,
289 False,
291}
292
293impl BuiltinType {
294 #[inline]
296 pub fn as_str(self) -> &'static str {
297 match self {
298 Self::Int => "int",
299 Self::Integer => "integer",
300 Self::Float => "float",
301 Self::Double => "double",
302 Self::String => "string",
303 Self::Bool => "bool",
304 Self::Boolean => "boolean",
305 Self::Void => "void",
306 Self::Never => "never",
307 Self::Mixed => "mixed",
308 Self::Object => "object",
309 Self::Iterable => "iterable",
310 Self::Callable => "callable",
311 Self::Array => "array",
312 Self::Self_ => "self",
313 Self::Parent_ => "parent",
314 Self::Static => "static",
315 Self::Null => "null",
316 Self::True => "true",
317 Self::False => "false",
318 }
319 }
320}
321
322#[derive(Debug, Serialize)]
323pub struct TypeHint<'arena, 'src> {
324 pub kind: TypeHintKind<'arena, 'src>,
325 pub span: Span,
326}
327
328#[derive(Debug)]
336pub enum TypeHintKind<'arena, 'src> {
337 Named(Name<'arena, 'src>),
339 Keyword(BuiltinType, Span),
341 Nullable(&'arena TypeHint<'arena, 'src>),
343 Union(ArenaVec<'arena, TypeHint<'arena, 'src>>),
345 Intersection(ArenaVec<'arena, TypeHint<'arena, 'src>>),
347}
348
349impl<'arena, 'src> serde::Serialize for TypeHintKind<'arena, 'src> {
350 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
351 match self {
352 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
354 Self::Nullable(inner) => {
355 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
356 }
357 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
358 Self::Intersection(types) => {
359 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
360 }
361 Self::Keyword(builtin, span) => {
364 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
365 impl serde::Serialize for BuiltinNameRepr<'_> {
366 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
367 use serde::ser::SerializeStruct;
368 let mut st = s.serialize_struct("Name", 3)?;
369 st.serialize_field("parts", &[self.0.as_str()])?;
370 st.serialize_field("kind", &NameKind::Unqualified)?;
371 st.serialize_field("span", self.1)?;
372 st.end()
373 }
374 }
375 s.serialize_newtype_variant(
376 "TypeHintKind",
377 0,
378 "Named",
379 &BuiltinNameRepr(builtin, span),
380 )
381 }
382 }
383 }
384}
385
386#[derive(Debug, Serialize)]
391pub struct Arg<'arena, 'src> {
392 pub name: Option<Name<'arena, 'src>>,
393 pub value: Expr<'arena, 'src>,
394 pub unpack: bool,
395 pub by_ref: bool,
396 pub span: Span,
397}
398
399#[derive(Debug, Serialize)]
404pub struct Attribute<'arena, 'src> {
405 pub name: Name<'arena, 'src>,
406 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
407 pub span: Span,
408}
409
410#[derive(Debug, Serialize)]
415pub struct Stmt<'arena, 'src> {
416 pub kind: StmtKind<'arena, 'src>,
417 pub span: Span,
418}
419
420#[derive(Debug, Serialize)]
421pub enum StmtKind<'arena, 'src> {
422 Expression(&'arena Expr<'arena, 'src>),
424
425 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
427
428 Return(Option<&'arena Expr<'arena, 'src>>),
430
431 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
433
434 If(&'arena IfStmt<'arena, 'src>),
436
437 While(&'arena WhileStmt<'arena, 'src>),
439
440 For(&'arena ForStmt<'arena, 'src>),
442
443 Foreach(&'arena ForeachStmt<'arena, 'src>),
445
446 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
448
449 Function(&'arena FunctionDecl<'arena, 'src>),
451
452 Break(Option<&'arena Expr<'arena, 'src>>),
454
455 Continue(Option<&'arena Expr<'arena, 'src>>),
457
458 Switch(&'arena SwitchStmt<'arena, 'src>),
460
461 Goto(&'src str),
463
464 Label(&'arena str),
466
467 Declare(&'arena DeclareStmt<'arena, 'src>),
469
470 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
472
473 Throw(&'arena Expr<'arena, 'src>),
475
476 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
478
479 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
481
482 Class(&'arena ClassDecl<'arena, 'src>),
484
485 Interface(&'arena InterfaceDecl<'arena, 'src>),
487
488 Trait(&'arena TraitDecl<'arena, 'src>),
490
491 Enum(&'arena EnumDecl<'arena, 'src>),
493
494 Namespace(&'arena NamespaceDecl<'arena, 'src>),
496
497 Use(&'arena UseDecl<'arena, 'src>),
499
500 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
502
503 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
505
506 HaltCompiler(&'src str),
508
509 Nop,
511
512 InlineHtml(&'src str),
514
515 Error,
517}
518
519#[derive(Debug, Serialize)]
520pub struct IfStmt<'arena, 'src> {
521 pub condition: Expr<'arena, 'src>,
522 pub then_branch: &'arena Stmt<'arena, 'src>,
523 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
524 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
525}
526
527#[derive(Debug, Serialize)]
528pub struct ElseIfBranch<'arena, 'src> {
529 pub condition: Expr<'arena, 'src>,
530 pub body: Stmt<'arena, 'src>,
531 pub span: Span,
532}
533
534#[derive(Debug, Serialize)]
535pub struct WhileStmt<'arena, 'src> {
536 pub condition: Expr<'arena, 'src>,
537 pub body: &'arena Stmt<'arena, 'src>,
538}
539
540#[derive(Debug, Serialize)]
541pub struct ForStmt<'arena, 'src> {
542 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
543 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
544 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
545 pub body: &'arena Stmt<'arena, 'src>,
546}
547
548#[derive(Debug, Serialize)]
549pub struct ForeachStmt<'arena, 'src> {
550 pub expr: Expr<'arena, 'src>,
551 pub key: Option<Expr<'arena, 'src>>,
552 pub value: Expr<'arena, 'src>,
553 pub body: &'arena Stmt<'arena, 'src>,
554}
555
556#[derive(Debug, Serialize)]
557pub struct DoWhileStmt<'arena, 'src> {
558 pub body: &'arena Stmt<'arena, 'src>,
559 pub condition: Expr<'arena, 'src>,
560}
561
562#[derive(Debug, Serialize)]
563pub struct FunctionDecl<'arena, 'src> {
564 pub name: &'src str,
565 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
566 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
567 pub return_type: Option<TypeHint<'arena, 'src>>,
568 pub by_ref: bool,
569 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
570 #[serde(skip_serializing_if = "Option::is_none")]
571 pub doc_comment: Option<Comment<'src>>,
572}
573
574#[derive(Debug, Serialize)]
575pub struct Param<'arena, 'src> {
576 pub name: &'src str,
577 pub type_hint: Option<TypeHint<'arena, 'src>>,
578 pub default: Option<Expr<'arena, 'src>>,
579 pub by_ref: bool,
580 pub variadic: bool,
581 pub is_readonly: bool,
582 pub is_final: bool,
583 pub visibility: Option<Visibility>,
584 pub set_visibility: Option<Visibility>,
585 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
586 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
587 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
588 pub span: Span,
589}
590
591#[derive(Debug, Serialize)]
592pub struct SwitchStmt<'arena, 'src> {
593 pub expr: Expr<'arena, 'src>,
594 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
595}
596
597#[derive(Debug, Serialize)]
598pub struct SwitchCase<'arena, 'src> {
599 pub value: Option<Expr<'arena, 'src>>,
600 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
601 pub span: Span,
602}
603
604#[derive(Debug, Serialize)]
605pub struct TryCatchStmt<'arena, 'src> {
606 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
607 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
608 pub finally: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
609}
610
611#[derive(Debug, Serialize)]
612pub struct CatchClause<'arena, 'src> {
613 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
614 pub var: Option<&'src str>,
615 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
616 pub span: Span,
617}
618
619#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
624pub enum Visibility {
625 Public,
627 Protected,
629 Private,
631}
632
633#[derive(Debug, Serialize)]
634pub struct ClassDecl<'arena, 'src> {
635 pub name: Option<&'src str>,
636 pub modifiers: ClassModifiers,
637 pub extends: Option<Name<'arena, 'src>>,
638 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
639 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
640 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
641 #[serde(skip_serializing_if = "Option::is_none")]
642 pub doc_comment: Option<Comment<'src>>,
643}
644
645#[derive(Debug, Clone, Serialize, Default)]
646pub struct ClassModifiers {
647 pub is_abstract: bool,
648 pub is_final: bool,
649 pub is_readonly: bool,
650}
651
652#[derive(Debug, Serialize)]
653pub struct ClassMember<'arena, 'src> {
654 pub kind: ClassMemberKind<'arena, 'src>,
655 pub span: Span,
656}
657
658#[derive(Debug, Serialize)]
659pub enum ClassMemberKind<'arena, 'src> {
660 Property(PropertyDecl<'arena, 'src>),
661 Method(MethodDecl<'arena, 'src>),
662 ClassConst(ClassConstDecl<'arena, 'src>),
663 TraitUse(TraitUseDecl<'arena, 'src>),
664}
665
666#[derive(Debug, Serialize)]
667pub struct PropertyDecl<'arena, 'src> {
668 pub name: &'src str,
669 pub visibility: Option<Visibility>,
670 pub set_visibility: Option<Visibility>,
671 pub is_static: bool,
672 pub is_readonly: bool,
673 pub type_hint: Option<TypeHint<'arena, 'src>>,
674 pub default: Option<Expr<'arena, 'src>>,
675 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
676 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
677 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
678 #[serde(skip_serializing_if = "Option::is_none")]
679 pub doc_comment: Option<Comment<'src>>,
680}
681
682#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
683pub enum PropertyHookKind {
684 Get,
686 Set,
688}
689
690#[derive(Debug, Serialize)]
691pub enum PropertyHookBody<'arena, 'src> {
692 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
694 Expression(Expr<'arena, 'src>),
696 Abstract,
698}
699
700#[derive(Debug, Serialize)]
701pub struct PropertyHook<'arena, 'src> {
702 pub kind: PropertyHookKind,
703 pub body: PropertyHookBody<'arena, 'src>,
704 pub is_final: bool,
705 pub by_ref: bool,
706 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
707 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
708 pub span: Span,
709}
710
711#[derive(Debug, Serialize)]
712pub struct MethodDecl<'arena, 'src> {
713 pub name: &'src str,
714 pub visibility: Option<Visibility>,
715 pub is_static: bool,
716 pub is_abstract: bool,
717 pub is_final: bool,
718 pub by_ref: bool,
719 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
720 pub return_type: Option<TypeHint<'arena, 'src>>,
721 pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
722 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
723 #[serde(skip_serializing_if = "Option::is_none")]
724 pub doc_comment: Option<Comment<'src>>,
725}
726
727#[derive(Debug, Serialize)]
728pub struct ClassConstDecl<'arena, 'src> {
729 pub name: &'src str,
730 pub visibility: Option<Visibility>,
731 #[serde(skip_serializing_if = "Option::is_none")]
732 pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
733 pub value: Expr<'arena, 'src>,
734 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
735 #[serde(skip_serializing_if = "Option::is_none")]
736 pub doc_comment: Option<Comment<'src>>,
737}
738
739#[derive(Debug, Serialize)]
740pub struct TraitUseDecl<'arena, 'src> {
741 pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
742 pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
743}
744
745#[derive(Debug, Serialize)]
746pub struct TraitAdaptation<'arena, 'src> {
747 pub kind: TraitAdaptationKind<'arena, 'src>,
748 pub span: Span,
749}
750
751#[derive(Debug, Serialize)]
752pub enum TraitAdaptationKind<'arena, 'src> {
753 Precedence {
755 trait_name: Name<'arena, 'src>,
756 method: Name<'arena, 'src>,
757 insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
758 },
759 Alias {
761 trait_name: Option<Name<'arena, 'src>>,
762 method: Name<'arena, 'src>,
763 new_modifier: Option<Visibility>,
764 new_name: Option<Name<'arena, 'src>>,
765 },
766}
767
768#[derive(Debug, Serialize)]
769pub struct InterfaceDecl<'arena, 'src> {
770 pub name: &'src str,
771 pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
772 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
773 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
774 #[serde(skip_serializing_if = "Option::is_none")]
775 pub doc_comment: Option<Comment<'src>>,
776}
777
778#[derive(Debug, Serialize)]
779pub struct TraitDecl<'arena, 'src> {
780 pub name: &'src str,
781 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
782 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
783 #[serde(skip_serializing_if = "Option::is_none")]
784 pub doc_comment: Option<Comment<'src>>,
785}
786
787#[derive(Debug, Serialize)]
788pub struct EnumDecl<'arena, 'src> {
789 pub name: &'src str,
790 pub scalar_type: Option<Name<'arena, 'src>>,
791 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
792 pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
793 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
794 #[serde(skip_serializing_if = "Option::is_none")]
795 pub doc_comment: Option<Comment<'src>>,
796}
797
798#[derive(Debug, Serialize)]
799pub struct EnumMember<'arena, 'src> {
800 pub kind: EnumMemberKind<'arena, 'src>,
801 pub span: Span,
802}
803
804#[derive(Debug, Serialize)]
805pub enum EnumMemberKind<'arena, 'src> {
806 Case(EnumCase<'arena, 'src>),
808 Method(MethodDecl<'arena, 'src>),
810 ClassConst(ClassConstDecl<'arena, 'src>),
812 TraitUse(TraitUseDecl<'arena, 'src>),
814}
815
816#[derive(Debug, Serialize)]
817pub struct EnumCase<'arena, 'src> {
818 pub name: &'src str,
819 pub value: Option<Expr<'arena, 'src>>,
820 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
821 #[serde(skip_serializing_if = "Option::is_none")]
822 pub doc_comment: Option<Comment<'src>>,
823}
824
825#[derive(Debug, Serialize)]
830pub struct NamespaceDecl<'arena, 'src> {
831 pub name: Option<Name<'arena, 'src>>,
832 pub body: NamespaceBody<'arena, 'src>,
833}
834
835#[derive(Debug, Serialize)]
836pub enum NamespaceBody<'arena, 'src> {
837 Braced(ArenaVec<'arena, Stmt<'arena, 'src>>),
839 Simple,
841}
842
843#[derive(Debug, Serialize)]
844pub struct DeclareStmt<'arena, 'src> {
845 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
846 pub body: Option<&'arena Stmt<'arena, 'src>>,
847}
848
849#[derive(Debug, Serialize)]
850pub struct UseDecl<'arena, 'src> {
851 pub kind: UseKind,
852 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
853}
854
855#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
856pub enum UseKind {
857 Normal,
859 Function,
861 Const,
863}
864
865#[derive(Debug, Serialize)]
866pub struct UseItem<'arena, 'src> {
867 pub name: Name<'arena, 'src>,
868 pub alias: Option<&'src str>,
869 #[serde(skip_serializing_if = "Option::is_none")]
870 pub kind: Option<UseKind>,
871 pub span: Span,
872}
873
874#[derive(Debug, Serialize)]
875pub struct ConstItem<'arena, 'src> {
876 pub name: &'src str,
877 pub value: Expr<'arena, 'src>,
878 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
879 pub span: Span,
880}
881
882#[derive(Debug, Serialize)]
883pub struct StaticVar<'arena, 'src> {
884 pub name: &'src str,
885 pub default: Option<Expr<'arena, 'src>>,
886 pub span: Span,
887}
888
889#[derive(Clone, Copy, PartialEq, Eq, Hash)]
908pub enum NameStr<'arena, 'src> {
909 Src(&'src str),
911 Arena(&'arena str),
913}
914
915impl<'arena, 'src> NameStr<'arena, 'src> {
916 #[inline]
917 pub fn as_str(&self) -> &str {
918 match self {
919 NameStr::Src(s) => s,
920 NameStr::Arena(s) => s,
921 }
922 }
923}
924
925impl<'arena, 'src> std::ops::Deref for NameStr<'arena, 'src> {
926 type Target = str;
927 #[inline]
928 fn deref(&self) -> &str {
929 self.as_str()
930 }
931}
932
933impl<'arena, 'src> std::fmt::Debug for NameStr<'arena, 'src> {
934 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
935 self.as_str().fmt(f)
936 }
937}
938
939impl<'arena, 'src> serde::Serialize for NameStr<'arena, 'src> {
940 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
941 self.as_str().serialize(serializer)
942 }
943}
944
945#[derive(Debug, Serialize)]
946pub struct Expr<'arena, 'src> {
947 pub kind: ExprKind<'arena, 'src>,
948 pub span: Span,
949}
950
951#[derive(Debug, Serialize)]
952pub enum ExprKind<'arena, 'src> {
953 Int(i64),
955
956 Float(f64),
958
959 String(&'arena str),
961
962 InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
964
965 Heredoc {
967 label: &'src str,
968 parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
969 },
970
971 Nowdoc {
973 label: &'src str,
974 value: &'arena str,
975 },
976
977 ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
979
980 Bool(bool),
982
983 Null,
985
986 Variable(NameStr<'arena, 'src>),
988
989 VariableVariable(&'arena Expr<'arena, 'src>),
991
992 Identifier(NameStr<'arena, 'src>),
994
995 Assign(AssignExpr<'arena, 'src>),
997
998 Binary(BinaryExpr<'arena, 'src>),
1000
1001 UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
1003
1004 UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
1006
1007 Ternary(TernaryExpr<'arena, 'src>),
1009
1010 NullCoalesce(NullCoalesceExpr<'arena, 'src>),
1012
1013 FunctionCall(FunctionCallExpr<'arena, 'src>),
1015
1016 Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
1018
1019 ArrayAccess(ArrayAccessExpr<'arena, 'src>),
1021
1022 Print(&'arena Expr<'arena, 'src>),
1024
1025 Parenthesized(&'arena Expr<'arena, 'src>),
1027
1028 Cast(CastKind, &'arena Expr<'arena, 'src>),
1030
1031 ErrorSuppress(&'arena Expr<'arena, 'src>),
1033
1034 Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
1036
1037 Empty(&'arena Expr<'arena, 'src>),
1039
1040 Include(IncludeKind, &'arena Expr<'arena, 'src>),
1042
1043 Eval(&'arena Expr<'arena, 'src>),
1045
1046 Exit(Option<&'arena Expr<'arena, 'src>>),
1048
1049 MagicConst(MagicConstKind),
1051
1052 Clone(&'arena Expr<'arena, 'src>),
1054
1055 CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
1057
1058 New(NewExpr<'arena, 'src>),
1060
1061 PropertyAccess(PropertyAccessExpr<'arena, 'src>),
1063
1064 NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
1066
1067 MethodCall(&'arena MethodCallExpr<'arena, 'src>),
1069
1070 NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
1072
1073 StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
1075
1076 StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
1078
1079 StaticDynMethodCall(&'arena StaticDynMethodCallExpr<'arena, 'src>),
1081
1082 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1084
1085 ClassConstAccessDynamic {
1087 class: &'arena Expr<'arena, 'src>,
1088 member: &'arena Expr<'arena, 'src>,
1089 },
1090
1091 StaticPropertyAccessDynamic {
1093 class: &'arena Expr<'arena, 'src>,
1094 member: &'arena Expr<'arena, 'src>,
1095 },
1096
1097 Closure(&'arena ClosureExpr<'arena, 'src>),
1099
1100 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1102
1103 Match(MatchExpr<'arena, 'src>),
1105
1106 ThrowExpr(&'arena Expr<'arena, 'src>),
1108
1109 Yield(YieldExpr<'arena, 'src>),
1111
1112 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1114
1115 CallableCreate(CallableCreateExpr<'arena, 'src>),
1117
1118 Omit,
1120
1121 Error,
1123}
1124
1125impl<'arena, 'src> Expr<'arena, 'src> {
1126 pub fn name_str(&self) -> Option<&str> {
1128 match &self.kind {
1129 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
1130 _ => None,
1131 }
1132 }
1133}
1134
1135#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1136pub enum CastKind {
1137 Int,
1139 Float,
1141 String,
1143 Bool,
1145 Array,
1147 Object,
1149 Unset,
1151 Void,
1153}
1154
1155#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1156pub enum IncludeKind {
1157 Include,
1159 IncludeOnce,
1161 Require,
1163 RequireOnce,
1165}
1166
1167#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1168pub enum MagicConstKind {
1169 Class,
1171 Dir,
1173 File,
1175 Function,
1177 Line,
1179 Method,
1181 Namespace,
1183 Trait,
1185 Property,
1187}
1188
1189#[derive(Debug, Serialize)]
1192pub struct AssignExpr<'arena, 'src> {
1193 pub target: &'arena Expr<'arena, 'src>,
1194 pub op: AssignOp,
1195 pub value: &'arena Expr<'arena, 'src>,
1196 #[serde(skip_serializing_if = "is_false")]
1197 pub by_ref: bool,
1198}
1199
1200#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1201pub enum AssignOp {
1202 Assign,
1204 Plus,
1206 Minus,
1208 Mul,
1210 Div,
1212 Mod,
1214 Pow,
1216 Concat,
1218 BitwiseAnd,
1220 BitwiseOr,
1222 BitwiseXor,
1224 ShiftLeft,
1226 ShiftRight,
1228 Coalesce,
1230}
1231
1232#[derive(Debug, Serialize)]
1233pub struct BinaryExpr<'arena, 'src> {
1234 pub left: &'arena Expr<'arena, 'src>,
1235 pub op: BinaryOp,
1236 pub right: &'arena Expr<'arena, 'src>,
1237}
1238
1239#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1240pub enum BinaryOp {
1241 Add,
1243 Sub,
1245 Mul,
1247 Div,
1249 Mod,
1251 Pow,
1253 Concat,
1255 Equal,
1257 NotEqual,
1259 Identical,
1261 NotIdentical,
1263 Less,
1265 Greater,
1267 LessOrEqual,
1269 GreaterOrEqual,
1271 Spaceship,
1273 BooleanAnd,
1275 BooleanOr,
1277 BitwiseAnd,
1279 BitwiseOr,
1281 BitwiseXor,
1283 ShiftLeft,
1285 ShiftRight,
1287 LogicalAnd,
1289 LogicalOr,
1291 LogicalXor,
1293 Instanceof,
1295 Pipe,
1297}
1298
1299#[derive(Debug, Serialize)]
1300pub struct UnaryPrefixExpr<'arena, 'src> {
1301 pub op: UnaryPrefixOp,
1302 pub operand: &'arena Expr<'arena, 'src>,
1303}
1304
1305#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1306pub enum UnaryPrefixOp {
1307 Negate,
1309 Plus,
1311 BooleanNot,
1313 BitwiseNot,
1315 PreIncrement,
1317 PreDecrement,
1319}
1320
1321#[derive(Debug, Serialize)]
1322pub struct UnaryPostfixExpr<'arena, 'src> {
1323 pub operand: &'arena Expr<'arena, 'src>,
1324 pub op: UnaryPostfixOp,
1325}
1326
1327#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1328pub enum UnaryPostfixOp {
1329 PostIncrement,
1331 PostDecrement,
1333}
1334
1335#[derive(Debug, Serialize)]
1336pub struct TernaryExpr<'arena, 'src> {
1337 pub condition: &'arena Expr<'arena, 'src>,
1338 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1340 pub else_expr: &'arena Expr<'arena, 'src>,
1341}
1342
1343#[derive(Debug, Serialize)]
1344pub struct NullCoalesceExpr<'arena, 'src> {
1345 pub left: &'arena Expr<'arena, 'src>,
1346 pub right: &'arena Expr<'arena, 'src>,
1347}
1348
1349#[derive(Debug, Serialize)]
1350pub struct FunctionCallExpr<'arena, 'src> {
1351 pub name: &'arena Expr<'arena, 'src>,
1352 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1353}
1354
1355#[derive(Debug, Serialize)]
1356pub struct ArrayElement<'arena, 'src> {
1357 pub key: Option<Expr<'arena, 'src>>,
1358 pub value: Expr<'arena, 'src>,
1359 pub unpack: bool,
1360 #[serde(skip_serializing_if = "is_false")]
1361 pub by_ref: bool,
1362 pub span: Span,
1363}
1364
1365#[derive(Debug, Serialize)]
1366pub struct ArrayAccessExpr<'arena, 'src> {
1367 pub array: &'arena Expr<'arena, 'src>,
1368 pub index: Option<&'arena Expr<'arena, 'src>>,
1369}
1370
1371#[derive(Debug, Serialize)]
1374pub struct NewExpr<'arena, 'src> {
1375 pub class: &'arena Expr<'arena, 'src>,
1376 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1377}
1378
1379#[derive(Debug, Serialize)]
1380pub struct PropertyAccessExpr<'arena, 'src> {
1381 pub object: &'arena Expr<'arena, 'src>,
1382 pub property: &'arena Expr<'arena, 'src>,
1383}
1384
1385#[derive(Debug, Serialize)]
1386pub struct MethodCallExpr<'arena, 'src> {
1387 pub object: &'arena Expr<'arena, 'src>,
1388 pub method: &'arena Expr<'arena, 'src>,
1389 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1390}
1391
1392#[derive(Debug, Serialize)]
1393pub struct StaticAccessExpr<'arena, 'src> {
1394 pub class: &'arena Expr<'arena, 'src>,
1395 pub member: &'arena Expr<'arena, 'src>,
1396}
1397
1398#[derive(Debug, Serialize)]
1399pub struct StaticMethodCallExpr<'arena, 'src> {
1400 pub class: &'arena Expr<'arena, 'src>,
1401 pub method: &'arena Expr<'arena, 'src>,
1402 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1403}
1404
1405#[derive(Debug, Serialize)]
1406pub struct StaticDynMethodCallExpr<'arena, 'src> {
1407 pub class: &'arena Expr<'arena, 'src>,
1408 pub method: &'arena Expr<'arena, 'src>,
1409 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1410}
1411
1412#[derive(Debug, Serialize)]
1413pub struct ClosureExpr<'arena, 'src> {
1414 pub is_static: bool,
1415 pub by_ref: bool,
1416 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1417 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1418 pub return_type: Option<TypeHint<'arena, 'src>>,
1419 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1420 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1421}
1422
1423#[derive(Debug, Clone, Serialize)]
1424pub struct ClosureUseVar<'src> {
1425 pub name: &'src str,
1426 pub by_ref: bool,
1427 pub span: Span,
1428}
1429
1430#[derive(Debug, Serialize)]
1431pub struct ArrowFunctionExpr<'arena, 'src> {
1432 pub is_static: bool,
1433 pub by_ref: bool,
1434 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1435 pub return_type: Option<TypeHint<'arena, 'src>>,
1436 pub body: &'arena Expr<'arena, 'src>,
1437 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1438}
1439
1440#[derive(Debug, Serialize)]
1441pub struct MatchExpr<'arena, 'src> {
1442 pub subject: &'arena Expr<'arena, 'src>,
1443 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1444}
1445
1446#[derive(Debug, Serialize)]
1447pub struct MatchArm<'arena, 'src> {
1448 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1450 pub body: Expr<'arena, 'src>,
1451 pub span: Span,
1452}
1453
1454#[derive(Debug, Serialize)]
1455pub struct YieldExpr<'arena, 'src> {
1456 pub key: Option<&'arena Expr<'arena, 'src>>,
1457 pub value: Option<&'arena Expr<'arena, 'src>>,
1458 pub is_from: bool,
1460}
1461
1462#[derive(Debug, Serialize)]
1465pub struct CallableCreateExpr<'arena, 'src> {
1466 pub kind: CallableCreateKind<'arena, 'src>,
1467}
1468
1469#[derive(Debug, Serialize)]
1470pub enum CallableCreateKind<'arena, 'src> {
1471 Function(&'arena Expr<'arena, 'src>),
1473 Method {
1475 object: &'arena Expr<'arena, 'src>,
1476 method: &'arena Expr<'arena, 'src>,
1477 },
1478 NullsafeMethod {
1480 object: &'arena Expr<'arena, 'src>,
1481 method: &'arena Expr<'arena, 'src>,
1482 },
1483 StaticMethod {
1485 class: &'arena Expr<'arena, 'src>,
1486 method: &'arena Expr<'arena, 'src>,
1487 },
1488}
1489
1490#[derive(Debug, Serialize)]
1493pub enum StringPart<'arena, 'src> {
1494 Literal(&'arena str),
1496 Expr(Expr<'arena, 'src>),
1498}