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 #[serde(skip_serializing_if = "Option::is_none")]
881 pub doc_comment: Option<Comment<'src>>,
882}
883
884#[derive(Debug, Serialize)]
885pub struct StaticVar<'arena, 'src> {
886 pub name: &'src str,
887 pub default: Option<Expr<'arena, 'src>>,
888 pub span: Span,
889}
890
891#[derive(Clone, Copy, PartialEq, Eq, Hash)]
910pub enum NameStr<'arena, 'src> {
911 Src(&'src str),
913 Arena(&'arena str),
915}
916
917impl<'arena, 'src> NameStr<'arena, 'src> {
918 #[inline]
919 pub fn as_str(&self) -> &str {
920 match self {
921 NameStr::Src(s) => s,
922 NameStr::Arena(s) => s,
923 }
924 }
925}
926
927impl<'arena, 'src> std::ops::Deref for NameStr<'arena, 'src> {
928 type Target = str;
929 #[inline]
930 fn deref(&self) -> &str {
931 self.as_str()
932 }
933}
934
935impl<'arena, 'src> std::fmt::Debug for NameStr<'arena, 'src> {
936 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
937 self.as_str().fmt(f)
938 }
939}
940
941impl<'arena, 'src> serde::Serialize for NameStr<'arena, 'src> {
942 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
943 self.as_str().serialize(serializer)
944 }
945}
946
947#[derive(Debug, Serialize)]
948pub struct Expr<'arena, 'src> {
949 pub kind: ExprKind<'arena, 'src>,
950 pub span: Span,
951}
952
953#[derive(Debug, Serialize)]
954pub enum ExprKind<'arena, 'src> {
955 Int(i64),
957
958 Float(f64),
960
961 String(&'arena str),
963
964 InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
966
967 Heredoc {
969 label: &'src str,
970 parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
971 },
972
973 Nowdoc {
975 label: &'src str,
976 value: &'arena str,
977 },
978
979 ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
981
982 Bool(bool),
984
985 Null,
987
988 Variable(NameStr<'arena, 'src>),
990
991 VariableVariable(&'arena Expr<'arena, 'src>),
993
994 Identifier(NameStr<'arena, 'src>),
996
997 Assign(AssignExpr<'arena, 'src>),
999
1000 Binary(BinaryExpr<'arena, 'src>),
1002
1003 UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
1005
1006 UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
1008
1009 Ternary(TernaryExpr<'arena, 'src>),
1011
1012 NullCoalesce(NullCoalesceExpr<'arena, 'src>),
1014
1015 FunctionCall(FunctionCallExpr<'arena, 'src>),
1017
1018 Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
1020
1021 ArrayAccess(ArrayAccessExpr<'arena, 'src>),
1023
1024 Print(&'arena Expr<'arena, 'src>),
1026
1027 Parenthesized(&'arena Expr<'arena, 'src>),
1029
1030 Cast(CastKind, &'arena Expr<'arena, 'src>),
1032
1033 ErrorSuppress(&'arena Expr<'arena, 'src>),
1035
1036 Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
1038
1039 Empty(&'arena Expr<'arena, 'src>),
1041
1042 Include(IncludeKind, &'arena Expr<'arena, 'src>),
1044
1045 Eval(&'arena Expr<'arena, 'src>),
1047
1048 Exit(Option<&'arena Expr<'arena, 'src>>),
1050
1051 MagicConst(MagicConstKind),
1053
1054 Clone(&'arena Expr<'arena, 'src>),
1056
1057 CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
1059
1060 New(NewExpr<'arena, 'src>),
1062
1063 PropertyAccess(PropertyAccessExpr<'arena, 'src>),
1065
1066 NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
1068
1069 MethodCall(&'arena MethodCallExpr<'arena, 'src>),
1071
1072 NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
1074
1075 StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
1077
1078 StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
1080
1081 StaticDynMethodCall(&'arena StaticDynMethodCallExpr<'arena, 'src>),
1083
1084 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1086
1087 ClassConstAccessDynamic {
1089 class: &'arena Expr<'arena, 'src>,
1090 member: &'arena Expr<'arena, 'src>,
1091 },
1092
1093 StaticPropertyAccessDynamic {
1095 class: &'arena Expr<'arena, 'src>,
1096 member: &'arena Expr<'arena, 'src>,
1097 },
1098
1099 Closure(&'arena ClosureExpr<'arena, 'src>),
1101
1102 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1104
1105 Match(MatchExpr<'arena, 'src>),
1107
1108 ThrowExpr(&'arena Expr<'arena, 'src>),
1110
1111 Yield(YieldExpr<'arena, 'src>),
1113
1114 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1116
1117 CallableCreate(CallableCreateExpr<'arena, 'src>),
1119
1120 Omit,
1122
1123 Error,
1125}
1126
1127impl<'arena, 'src> Expr<'arena, 'src> {
1128 pub fn name_str(&self) -> Option<&str> {
1130 match &self.kind {
1131 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
1132 _ => None,
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1138pub enum CastKind {
1139 Int,
1141 Float,
1143 String,
1145 Bool,
1147 Array,
1149 Object,
1151 Unset,
1153 Void,
1155}
1156
1157#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1158pub enum IncludeKind {
1159 Include,
1161 IncludeOnce,
1163 Require,
1165 RequireOnce,
1167}
1168
1169#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1170pub enum MagicConstKind {
1171 Class,
1173 Dir,
1175 File,
1177 Function,
1179 Line,
1181 Method,
1183 Namespace,
1185 Trait,
1187 Property,
1189}
1190
1191#[derive(Debug, Serialize)]
1194pub struct AssignExpr<'arena, 'src> {
1195 pub target: &'arena Expr<'arena, 'src>,
1196 pub op: AssignOp,
1197 pub value: &'arena Expr<'arena, 'src>,
1198 #[serde(skip_serializing_if = "is_false")]
1199 pub by_ref: bool,
1200}
1201
1202#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1203pub enum AssignOp {
1204 Assign,
1206 Plus,
1208 Minus,
1210 Mul,
1212 Div,
1214 Mod,
1216 Pow,
1218 Concat,
1220 BitwiseAnd,
1222 BitwiseOr,
1224 BitwiseXor,
1226 ShiftLeft,
1228 ShiftRight,
1230 Coalesce,
1232}
1233
1234#[derive(Debug, Serialize)]
1235pub struct BinaryExpr<'arena, 'src> {
1236 pub left: &'arena Expr<'arena, 'src>,
1237 pub op: BinaryOp,
1238 pub right: &'arena Expr<'arena, 'src>,
1239}
1240
1241#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1242pub enum BinaryOp {
1243 Add,
1245 Sub,
1247 Mul,
1249 Div,
1251 Mod,
1253 Pow,
1255 Concat,
1257 Equal,
1259 NotEqual,
1261 Identical,
1263 NotIdentical,
1265 Less,
1267 Greater,
1269 LessOrEqual,
1271 GreaterOrEqual,
1273 Spaceship,
1275 BooleanAnd,
1277 BooleanOr,
1279 BitwiseAnd,
1281 BitwiseOr,
1283 BitwiseXor,
1285 ShiftLeft,
1287 ShiftRight,
1289 LogicalAnd,
1291 LogicalOr,
1293 LogicalXor,
1295 Instanceof,
1297 Pipe,
1299}
1300
1301#[derive(Debug, Serialize)]
1302pub struct UnaryPrefixExpr<'arena, 'src> {
1303 pub op: UnaryPrefixOp,
1304 pub operand: &'arena Expr<'arena, 'src>,
1305}
1306
1307#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1308pub enum UnaryPrefixOp {
1309 Negate,
1311 Plus,
1313 BooleanNot,
1315 BitwiseNot,
1317 PreIncrement,
1319 PreDecrement,
1321}
1322
1323#[derive(Debug, Serialize)]
1324pub struct UnaryPostfixExpr<'arena, 'src> {
1325 pub operand: &'arena Expr<'arena, 'src>,
1326 pub op: UnaryPostfixOp,
1327}
1328
1329#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1330pub enum UnaryPostfixOp {
1331 PostIncrement,
1333 PostDecrement,
1335}
1336
1337#[derive(Debug, Serialize)]
1338pub struct TernaryExpr<'arena, 'src> {
1339 pub condition: &'arena Expr<'arena, 'src>,
1340 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1342 pub else_expr: &'arena Expr<'arena, 'src>,
1343}
1344
1345#[derive(Debug, Serialize)]
1346pub struct NullCoalesceExpr<'arena, 'src> {
1347 pub left: &'arena Expr<'arena, 'src>,
1348 pub right: &'arena Expr<'arena, 'src>,
1349}
1350
1351#[derive(Debug, Serialize)]
1352pub struct FunctionCallExpr<'arena, 'src> {
1353 pub name: &'arena Expr<'arena, 'src>,
1354 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1355}
1356
1357#[derive(Debug, Serialize)]
1358pub struct ArrayElement<'arena, 'src> {
1359 pub key: Option<Expr<'arena, 'src>>,
1360 pub value: Expr<'arena, 'src>,
1361 pub unpack: bool,
1362 #[serde(skip_serializing_if = "is_false")]
1363 pub by_ref: bool,
1364 pub span: Span,
1365}
1366
1367#[derive(Debug, Serialize)]
1368pub struct ArrayAccessExpr<'arena, 'src> {
1369 pub array: &'arena Expr<'arena, 'src>,
1370 pub index: Option<&'arena Expr<'arena, 'src>>,
1371}
1372
1373#[derive(Debug, Serialize)]
1376pub struct NewExpr<'arena, 'src> {
1377 pub class: &'arena Expr<'arena, 'src>,
1378 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1379}
1380
1381#[derive(Debug, Serialize)]
1382pub struct PropertyAccessExpr<'arena, 'src> {
1383 pub object: &'arena Expr<'arena, 'src>,
1384 pub property: &'arena Expr<'arena, 'src>,
1385}
1386
1387#[derive(Debug, Serialize)]
1388pub struct MethodCallExpr<'arena, 'src> {
1389 pub object: &'arena Expr<'arena, 'src>,
1390 pub method: &'arena Expr<'arena, 'src>,
1391 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1392}
1393
1394#[derive(Debug, Serialize)]
1395pub struct StaticAccessExpr<'arena, 'src> {
1396 pub class: &'arena Expr<'arena, 'src>,
1397 pub member: &'arena Expr<'arena, 'src>,
1398}
1399
1400#[derive(Debug, Serialize)]
1401pub struct StaticMethodCallExpr<'arena, 'src> {
1402 pub class: &'arena Expr<'arena, 'src>,
1403 pub method: &'arena Expr<'arena, 'src>,
1404 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1405}
1406
1407#[derive(Debug, Serialize)]
1408pub struct StaticDynMethodCallExpr<'arena, 'src> {
1409 pub class: &'arena Expr<'arena, 'src>,
1410 pub method: &'arena Expr<'arena, 'src>,
1411 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1412}
1413
1414#[derive(Debug, Serialize)]
1415pub struct ClosureExpr<'arena, 'src> {
1416 pub is_static: bool,
1417 pub by_ref: bool,
1418 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1419 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1420 pub return_type: Option<TypeHint<'arena, 'src>>,
1421 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1422 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1423}
1424
1425#[derive(Debug, Clone, Serialize)]
1426pub struct ClosureUseVar<'src> {
1427 pub name: &'src str,
1428 pub by_ref: bool,
1429 pub span: Span,
1430}
1431
1432#[derive(Debug, Serialize)]
1433pub struct ArrowFunctionExpr<'arena, 'src> {
1434 pub is_static: bool,
1435 pub by_ref: bool,
1436 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1437 pub return_type: Option<TypeHint<'arena, 'src>>,
1438 pub body: &'arena Expr<'arena, 'src>,
1439 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1440}
1441
1442#[derive(Debug, Serialize)]
1443pub struct MatchExpr<'arena, 'src> {
1444 pub subject: &'arena Expr<'arena, 'src>,
1445 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1446}
1447
1448#[derive(Debug, Serialize)]
1449pub struct MatchArm<'arena, 'src> {
1450 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1452 pub body: Expr<'arena, 'src>,
1453 pub span: Span,
1454}
1455
1456#[derive(Debug, Serialize)]
1457pub struct YieldExpr<'arena, 'src> {
1458 pub key: Option<&'arena Expr<'arena, 'src>>,
1459 pub value: Option<&'arena Expr<'arena, 'src>>,
1460 pub is_from: bool,
1462}
1463
1464#[derive(Debug, Serialize)]
1467pub struct CallableCreateExpr<'arena, 'src> {
1468 pub kind: CallableCreateKind<'arena, 'src>,
1469}
1470
1471#[derive(Debug, Serialize)]
1472pub enum CallableCreateKind<'arena, 'src> {
1473 Function(&'arena Expr<'arena, 'src>),
1475 Method {
1477 object: &'arena Expr<'arena, 'src>,
1478 method: &'arena Expr<'arena, 'src>,
1479 },
1480 NullsafeMethod {
1482 object: &'arena Expr<'arena, 'src>,
1483 method: &'arena Expr<'arena, 'src>,
1484 },
1485 StaticMethod {
1487 class: &'arena Expr<'arena, 'src>,
1488 method: &'arena Expr<'arena, 'src>,
1489 },
1490}
1491
1492#[derive(Debug, Serialize)]
1495pub enum StringPart<'arena, 'src> {
1496 Literal(&'arena str),
1498 Expr(Expr<'arena, 'src>),
1500}