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,
237 Qualified,
238 FullyQualified,
239 Relative,
240}
241
242#[repr(u8)]
245#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
246pub enum BuiltinType {
247 Int,
248 Integer,
249 Float,
250 Double,
251 String,
252 Bool,
253 Boolean,
254 Void,
255 Never,
256 Mixed,
257 Object,
258 Iterable,
259 Callable,
260 Array,
261 Self_,
262 Parent_,
263 Static,
264 Null,
265 True,
266 False,
267}
268
269impl BuiltinType {
270 #[inline]
272 pub fn as_str(self) -> &'static str {
273 match self {
274 Self::Int => "int",
275 Self::Integer => "integer",
276 Self::Float => "float",
277 Self::Double => "double",
278 Self::String => "string",
279 Self::Bool => "bool",
280 Self::Boolean => "boolean",
281 Self::Void => "void",
282 Self::Never => "never",
283 Self::Mixed => "mixed",
284 Self::Object => "object",
285 Self::Iterable => "iterable",
286 Self::Callable => "callable",
287 Self::Array => "array",
288 Self::Self_ => "self",
289 Self::Parent_ => "parent",
290 Self::Static => "static",
291 Self::Null => "null",
292 Self::True => "true",
293 Self::False => "false",
294 }
295 }
296}
297
298#[derive(Debug, Serialize)]
299pub struct TypeHint<'arena, 'src> {
300 pub kind: TypeHintKind<'arena, 'src>,
301 pub span: Span,
302}
303
304#[derive(Debug)]
312pub enum TypeHintKind<'arena, 'src> {
313 Named(Name<'arena, 'src>),
314 Keyword(BuiltinType, Span),
316 Nullable(&'arena TypeHint<'arena, 'src>),
317 Union(ArenaVec<'arena, TypeHint<'arena, 'src>>),
318 Intersection(ArenaVec<'arena, TypeHint<'arena, 'src>>),
319}
320
321impl<'arena, 'src> serde::Serialize for TypeHintKind<'arena, 'src> {
322 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
323 match self {
324 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
326 Self::Nullable(inner) => {
327 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
328 }
329 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
330 Self::Intersection(types) => {
331 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
332 }
333 Self::Keyword(builtin, span) => {
336 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
337 impl serde::Serialize for BuiltinNameRepr<'_> {
338 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
339 use serde::ser::SerializeStruct;
340 let mut st = s.serialize_struct("Name", 3)?;
341 st.serialize_field("parts", &[self.0.as_str()])?;
342 st.serialize_field("kind", &NameKind::Unqualified)?;
343 st.serialize_field("span", self.1)?;
344 st.end()
345 }
346 }
347 s.serialize_newtype_variant(
348 "TypeHintKind",
349 0,
350 "Named",
351 &BuiltinNameRepr(builtin, span),
352 )
353 }
354 }
355 }
356}
357
358#[derive(Debug, Serialize)]
363pub struct Arg<'arena, 'src> {
364 pub name: Option<Name<'arena, 'src>>,
365 pub value: Expr<'arena, 'src>,
366 pub unpack: bool,
367 pub by_ref: bool,
368 pub span: Span,
369}
370
371#[derive(Debug, Serialize)]
376pub struct Attribute<'arena, 'src> {
377 pub name: Name<'arena, 'src>,
378 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
379 pub span: Span,
380}
381
382#[derive(Debug, Serialize)]
387pub struct Stmt<'arena, 'src> {
388 pub kind: StmtKind<'arena, 'src>,
389 pub span: Span,
390}
391
392#[derive(Debug, Serialize)]
393pub enum StmtKind<'arena, 'src> {
394 Expression(&'arena Expr<'arena, 'src>),
396
397 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
399
400 Return(Option<&'arena Expr<'arena, 'src>>),
402
403 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
405
406 If(&'arena IfStmt<'arena, 'src>),
408
409 While(&'arena WhileStmt<'arena, 'src>),
411
412 For(&'arena ForStmt<'arena, 'src>),
414
415 Foreach(&'arena ForeachStmt<'arena, 'src>),
417
418 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
420
421 Function(&'arena FunctionDecl<'arena, 'src>),
423
424 Break(Option<&'arena Expr<'arena, 'src>>),
426
427 Continue(Option<&'arena Expr<'arena, 'src>>),
429
430 Switch(&'arena SwitchStmt<'arena, 'src>),
432
433 Goto(&'src str),
435
436 Label(&'arena str),
438
439 Declare(&'arena DeclareStmt<'arena, 'src>),
441
442 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
444
445 Throw(&'arena Expr<'arena, 'src>),
447
448 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
450
451 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
453
454 Class(&'arena ClassDecl<'arena, 'src>),
456
457 Interface(&'arena InterfaceDecl<'arena, 'src>),
459
460 Trait(&'arena TraitDecl<'arena, 'src>),
462
463 Enum(&'arena EnumDecl<'arena, 'src>),
465
466 Namespace(&'arena NamespaceDecl<'arena, 'src>),
468
469 Use(&'arena UseDecl<'arena, 'src>),
471
472 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
474
475 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
477
478 HaltCompiler(&'src str),
480
481 Nop,
483
484 InlineHtml(&'src str),
486
487 Error,
489}
490
491#[derive(Debug, Serialize)]
492pub struct IfStmt<'arena, 'src> {
493 pub condition: Expr<'arena, 'src>,
494 pub then_branch: &'arena Stmt<'arena, 'src>,
495 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
496 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
497}
498
499#[derive(Debug, Serialize)]
500pub struct ElseIfBranch<'arena, 'src> {
501 pub condition: Expr<'arena, 'src>,
502 pub body: Stmt<'arena, 'src>,
503 pub span: Span,
504}
505
506#[derive(Debug, Serialize)]
507pub struct WhileStmt<'arena, 'src> {
508 pub condition: Expr<'arena, 'src>,
509 pub body: &'arena Stmt<'arena, 'src>,
510}
511
512#[derive(Debug, Serialize)]
513pub struct ForStmt<'arena, 'src> {
514 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
515 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
516 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
517 pub body: &'arena Stmt<'arena, 'src>,
518}
519
520#[derive(Debug, Serialize)]
521pub struct ForeachStmt<'arena, 'src> {
522 pub expr: Expr<'arena, 'src>,
523 pub key: Option<Expr<'arena, 'src>>,
524 pub value: Expr<'arena, 'src>,
525 pub body: &'arena Stmt<'arena, 'src>,
526}
527
528#[derive(Debug, Serialize)]
529pub struct DoWhileStmt<'arena, 'src> {
530 pub body: &'arena Stmt<'arena, 'src>,
531 pub condition: Expr<'arena, 'src>,
532}
533
534#[derive(Debug, Serialize)]
535pub struct FunctionDecl<'arena, 'src> {
536 pub name: &'src str,
537 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
538 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
539 pub return_type: Option<TypeHint<'arena, 'src>>,
540 pub by_ref: bool,
541 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
542 #[serde(skip_serializing_if = "Option::is_none")]
543 pub doc_comment: Option<Comment<'src>>,
544}
545
546#[derive(Debug, Serialize)]
547pub struct Param<'arena, 'src> {
548 pub name: &'src str,
549 pub type_hint: Option<TypeHint<'arena, 'src>>,
550 pub default: Option<Expr<'arena, 'src>>,
551 pub by_ref: bool,
552 pub variadic: bool,
553 pub is_readonly: bool,
554 pub is_final: bool,
555 pub visibility: Option<Visibility>,
556 pub set_visibility: Option<Visibility>,
557 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
558 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
559 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
560 pub span: Span,
561}
562
563#[derive(Debug, Serialize)]
564pub struct SwitchStmt<'arena, 'src> {
565 pub expr: Expr<'arena, 'src>,
566 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
567}
568
569#[derive(Debug, Serialize)]
570pub struct SwitchCase<'arena, 'src> {
571 pub value: Option<Expr<'arena, 'src>>,
572 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
573 pub span: Span,
574}
575
576#[derive(Debug, Serialize)]
577pub struct TryCatchStmt<'arena, 'src> {
578 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
579 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
580 pub finally: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
581}
582
583#[derive(Debug, Serialize)]
584pub struct CatchClause<'arena, 'src> {
585 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
586 pub var: Option<&'src str>,
587 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
588 pub span: Span,
589}
590
591#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
596pub enum Visibility {
597 Public,
598 Protected,
599 Private,
600}
601
602#[derive(Debug, Serialize)]
603pub struct ClassDecl<'arena, 'src> {
604 pub name: Option<&'src str>,
605 pub modifiers: ClassModifiers,
606 pub extends: Option<Name<'arena, 'src>>,
607 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
608 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
609 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
610 #[serde(skip_serializing_if = "Option::is_none")]
611 pub doc_comment: Option<Comment<'src>>,
612}
613
614#[derive(Debug, Clone, Serialize, Default)]
615pub struct ClassModifiers {
616 pub is_abstract: bool,
617 pub is_final: bool,
618 pub is_readonly: bool,
619}
620
621#[derive(Debug, Serialize)]
622pub struct ClassMember<'arena, 'src> {
623 pub kind: ClassMemberKind<'arena, 'src>,
624 pub span: Span,
625}
626
627#[derive(Debug, Serialize)]
628pub enum ClassMemberKind<'arena, 'src> {
629 Property(PropertyDecl<'arena, 'src>),
630 Method(MethodDecl<'arena, 'src>),
631 ClassConst(ClassConstDecl<'arena, 'src>),
632 TraitUse(TraitUseDecl<'arena, 'src>),
633}
634
635#[derive(Debug, Serialize)]
636pub struct PropertyDecl<'arena, 'src> {
637 pub name: &'src str,
638 pub visibility: Option<Visibility>,
639 pub set_visibility: Option<Visibility>,
640 pub is_static: bool,
641 pub is_readonly: bool,
642 pub type_hint: Option<TypeHint<'arena, 'src>>,
643 pub default: Option<Expr<'arena, 'src>>,
644 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
645 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
646 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
647 #[serde(skip_serializing_if = "Option::is_none")]
648 pub doc_comment: Option<Comment<'src>>,
649}
650
651#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
652pub enum PropertyHookKind {
653 Get,
654 Set,
655}
656
657#[derive(Debug, Serialize)]
658pub enum PropertyHookBody<'arena, 'src> {
659 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
660 Expression(Expr<'arena, 'src>),
661 Abstract,
662}
663
664#[derive(Debug, Serialize)]
665pub struct PropertyHook<'arena, 'src> {
666 pub kind: PropertyHookKind,
667 pub body: PropertyHookBody<'arena, 'src>,
668 pub is_final: bool,
669 pub by_ref: bool,
670 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
671 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
672 pub span: Span,
673}
674
675#[derive(Debug, Serialize)]
676pub struct MethodDecl<'arena, 'src> {
677 pub name: &'src str,
678 pub visibility: Option<Visibility>,
679 pub is_static: bool,
680 pub is_abstract: bool,
681 pub is_final: bool,
682 pub by_ref: bool,
683 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
684 pub return_type: Option<TypeHint<'arena, 'src>>,
685 pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
686 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
687 #[serde(skip_serializing_if = "Option::is_none")]
688 pub doc_comment: Option<Comment<'src>>,
689}
690
691#[derive(Debug, Serialize)]
692pub struct ClassConstDecl<'arena, 'src> {
693 pub name: &'src str,
694 pub visibility: Option<Visibility>,
695 #[serde(skip_serializing_if = "Option::is_none")]
696 pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
697 pub value: Expr<'arena, 'src>,
698 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
699 #[serde(skip_serializing_if = "Option::is_none")]
700 pub doc_comment: Option<Comment<'src>>,
701}
702
703#[derive(Debug, Serialize)]
704pub struct TraitUseDecl<'arena, 'src> {
705 pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
706 pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
707}
708
709#[derive(Debug, Serialize)]
710pub struct TraitAdaptation<'arena, 'src> {
711 pub kind: TraitAdaptationKind<'arena, 'src>,
712 pub span: Span,
713}
714
715#[derive(Debug, Serialize)]
716pub enum TraitAdaptationKind<'arena, 'src> {
717 Precedence {
719 trait_name: Name<'arena, 'src>,
720 method: Name<'arena, 'src>,
721 insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
722 },
723 Alias {
725 trait_name: Option<Name<'arena, 'src>>,
726 method: Name<'arena, 'src>,
727 new_modifier: Option<Visibility>,
728 new_name: Option<Name<'arena, 'src>>,
729 },
730}
731
732#[derive(Debug, Serialize)]
733pub struct InterfaceDecl<'arena, 'src> {
734 pub name: &'src str,
735 pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
736 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
737 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
738 #[serde(skip_serializing_if = "Option::is_none")]
739 pub doc_comment: Option<Comment<'src>>,
740}
741
742#[derive(Debug, Serialize)]
743pub struct TraitDecl<'arena, 'src> {
744 pub name: &'src str,
745 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
746 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
747 #[serde(skip_serializing_if = "Option::is_none")]
748 pub doc_comment: Option<Comment<'src>>,
749}
750
751#[derive(Debug, Serialize)]
752pub struct EnumDecl<'arena, 'src> {
753 pub name: &'src str,
754 pub scalar_type: Option<Name<'arena, 'src>>,
755 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
756 pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
757 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
758 #[serde(skip_serializing_if = "Option::is_none")]
759 pub doc_comment: Option<Comment<'src>>,
760}
761
762#[derive(Debug, Serialize)]
763pub struct EnumMember<'arena, 'src> {
764 pub kind: EnumMemberKind<'arena, 'src>,
765 pub span: Span,
766}
767
768#[derive(Debug, Serialize)]
769pub enum EnumMemberKind<'arena, 'src> {
770 Case(EnumCase<'arena, 'src>),
771 Method(MethodDecl<'arena, 'src>),
772 ClassConst(ClassConstDecl<'arena, 'src>),
773 TraitUse(TraitUseDecl<'arena, 'src>),
774}
775
776#[derive(Debug, Serialize)]
777pub struct EnumCase<'arena, 'src> {
778 pub name: &'src str,
779 pub value: Option<Expr<'arena, 'src>>,
780 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
781 #[serde(skip_serializing_if = "Option::is_none")]
782 pub doc_comment: Option<Comment<'src>>,
783}
784
785#[derive(Debug, Serialize)]
790pub struct NamespaceDecl<'arena, 'src> {
791 pub name: Option<Name<'arena, 'src>>,
792 pub body: NamespaceBody<'arena, 'src>,
793}
794
795#[derive(Debug, Serialize)]
796pub enum NamespaceBody<'arena, 'src> {
797 Braced(ArenaVec<'arena, Stmt<'arena, 'src>>),
798 Simple,
799}
800
801#[derive(Debug, Serialize)]
802pub struct DeclareStmt<'arena, 'src> {
803 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
804 pub body: Option<&'arena Stmt<'arena, 'src>>,
805}
806
807#[derive(Debug, Serialize)]
808pub struct UseDecl<'arena, 'src> {
809 pub kind: UseKind,
810 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
811}
812
813#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
814pub enum UseKind {
815 Normal,
816 Function,
817 Const,
818}
819
820#[derive(Debug, Serialize)]
821pub struct UseItem<'arena, 'src> {
822 pub name: Name<'arena, 'src>,
823 pub alias: Option<&'src str>,
824 #[serde(skip_serializing_if = "Option::is_none")]
825 pub kind: Option<UseKind>,
826 pub span: Span,
827}
828
829#[derive(Debug, Serialize)]
830pub struct ConstItem<'arena, 'src> {
831 pub name: &'src str,
832 pub value: Expr<'arena, 'src>,
833 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
834 pub span: Span,
835}
836
837#[derive(Debug, Serialize)]
838pub struct StaticVar<'arena, 'src> {
839 pub name: &'src str,
840 pub default: Option<Expr<'arena, 'src>>,
841 pub span: Span,
842}
843
844#[derive(Clone, Copy, PartialEq, Eq, Hash)]
863pub enum NameStr<'arena, 'src> {
864 Src(&'src str),
866 Arena(&'arena str),
868}
869
870impl<'arena, 'src> NameStr<'arena, 'src> {
871 #[inline]
872 pub fn as_str(&self) -> &str {
873 match self {
874 NameStr::Src(s) => s,
875 NameStr::Arena(s) => s,
876 }
877 }
878}
879
880impl<'arena, 'src> std::ops::Deref for NameStr<'arena, 'src> {
881 type Target = str;
882 #[inline]
883 fn deref(&self) -> &str {
884 self.as_str()
885 }
886}
887
888impl<'arena, 'src> std::fmt::Debug for NameStr<'arena, 'src> {
889 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
890 self.as_str().fmt(f)
891 }
892}
893
894impl<'arena, 'src> serde::Serialize for NameStr<'arena, 'src> {
895 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
896 self.as_str().serialize(serializer)
897 }
898}
899
900#[derive(Debug, Serialize)]
901pub struct Expr<'arena, 'src> {
902 pub kind: ExprKind<'arena, 'src>,
903 pub span: Span,
904}
905
906#[derive(Debug, Serialize)]
907pub enum ExprKind<'arena, 'src> {
908 Int(i64),
910
911 Float(f64),
913
914 String(&'arena str),
916
917 InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
919
920 Heredoc {
922 label: &'src str,
923 parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
924 },
925
926 Nowdoc {
928 label: &'src str,
929 value: &'arena str,
930 },
931
932 ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
934
935 Bool(bool),
937
938 Null,
940
941 Variable(NameStr<'arena, 'src>),
943
944 VariableVariable(&'arena Expr<'arena, 'src>),
946
947 Identifier(NameStr<'arena, 'src>),
949
950 Assign(AssignExpr<'arena, 'src>),
952
953 Binary(BinaryExpr<'arena, 'src>),
955
956 UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
958
959 UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
961
962 Ternary(TernaryExpr<'arena, 'src>),
964
965 NullCoalesce(NullCoalesceExpr<'arena, 'src>),
967
968 FunctionCall(FunctionCallExpr<'arena, 'src>),
970
971 Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
973
974 ArrayAccess(ArrayAccessExpr<'arena, 'src>),
976
977 Print(&'arena Expr<'arena, 'src>),
979
980 Parenthesized(&'arena Expr<'arena, 'src>),
982
983 Cast(CastKind, &'arena Expr<'arena, 'src>),
985
986 ErrorSuppress(&'arena Expr<'arena, 'src>),
988
989 Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
991
992 Empty(&'arena Expr<'arena, 'src>),
994
995 Include(IncludeKind, &'arena Expr<'arena, 'src>),
997
998 Eval(&'arena Expr<'arena, 'src>),
1000
1001 Exit(Option<&'arena Expr<'arena, 'src>>),
1003
1004 MagicConst(MagicConstKind),
1006
1007 Clone(&'arena Expr<'arena, 'src>),
1009
1010 CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
1012
1013 New(NewExpr<'arena, 'src>),
1015
1016 PropertyAccess(PropertyAccessExpr<'arena, 'src>),
1018
1019 NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
1021
1022 MethodCall(&'arena MethodCallExpr<'arena, 'src>),
1024
1025 NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
1027
1028 StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
1030
1031 StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
1033
1034 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1036
1037 ClassConstAccessDynamic {
1039 class: &'arena Expr<'arena, 'src>,
1040 member: &'arena Expr<'arena, 'src>,
1041 },
1042
1043 StaticPropertyAccessDynamic {
1045 class: &'arena Expr<'arena, 'src>,
1046 member: &'arena Expr<'arena, 'src>,
1047 },
1048
1049 Closure(&'arena ClosureExpr<'arena, 'src>),
1051
1052 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1054
1055 Match(MatchExpr<'arena, 'src>),
1057
1058 ThrowExpr(&'arena Expr<'arena, 'src>),
1060
1061 Yield(YieldExpr<'arena, 'src>),
1063
1064 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1066
1067 CallableCreate(CallableCreateExpr<'arena, 'src>),
1069
1070 Omit,
1072
1073 Error,
1075}
1076
1077impl<'arena, 'src> Expr<'arena, 'src> {
1078 pub fn name_str(&self) -> Option<&str> {
1080 match &self.kind {
1081 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
1082 _ => None,
1083 }
1084 }
1085}
1086
1087#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1088pub enum CastKind {
1089 Int,
1090 Float,
1091 String,
1092 Bool,
1093 Array,
1094 Object,
1095 Unset,
1096 Void,
1097}
1098
1099#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1100pub enum IncludeKind {
1101 Include,
1102 IncludeOnce,
1103 Require,
1104 RequireOnce,
1105}
1106
1107#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1108pub enum MagicConstKind {
1109 Class,
1110 Dir,
1111 File,
1112 Function,
1113 Line,
1114 Method,
1115 Namespace,
1116 Trait,
1117 Property,
1118}
1119
1120#[derive(Debug, Serialize)]
1123pub struct AssignExpr<'arena, 'src> {
1124 pub target: &'arena Expr<'arena, 'src>,
1125 pub op: AssignOp,
1126 pub value: &'arena Expr<'arena, 'src>,
1127 #[serde(skip_serializing_if = "is_false")]
1128 pub by_ref: bool,
1129}
1130
1131#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1132pub enum AssignOp {
1133 Assign,
1134 Plus,
1135 Minus,
1136 Mul,
1137 Div,
1138 Mod,
1139 Pow,
1140 Concat,
1141 BitwiseAnd,
1142 BitwiseOr,
1143 BitwiseXor,
1144 ShiftLeft,
1145 ShiftRight,
1146 Coalesce,
1147}
1148
1149#[derive(Debug, Serialize)]
1150pub struct BinaryExpr<'arena, 'src> {
1151 pub left: &'arena Expr<'arena, 'src>,
1152 pub op: BinaryOp,
1153 pub right: &'arena Expr<'arena, 'src>,
1154}
1155
1156#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1157pub enum BinaryOp {
1158 Add,
1159 Sub,
1160 Mul,
1161 Div,
1162 Mod,
1163 Pow,
1164 Concat,
1165 Equal,
1166 NotEqual,
1167 Identical,
1168 NotIdentical,
1169 Less,
1170 Greater,
1171 LessOrEqual,
1172 GreaterOrEqual,
1173 Spaceship,
1174 BooleanAnd,
1175 BooleanOr,
1176 BitwiseAnd,
1177 BitwiseOr,
1178 BitwiseXor,
1179 ShiftLeft,
1180 ShiftRight,
1181 LogicalAnd,
1182 LogicalOr,
1183 LogicalXor,
1184 Instanceof,
1185 Pipe,
1186}
1187
1188#[derive(Debug, Serialize)]
1189pub struct UnaryPrefixExpr<'arena, 'src> {
1190 pub op: UnaryPrefixOp,
1191 pub operand: &'arena Expr<'arena, 'src>,
1192}
1193
1194#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1195pub enum UnaryPrefixOp {
1196 Negate,
1197 Plus,
1198 BooleanNot,
1199 BitwiseNot,
1200 PreIncrement,
1201 PreDecrement,
1202}
1203
1204#[derive(Debug, Serialize)]
1205pub struct UnaryPostfixExpr<'arena, 'src> {
1206 pub operand: &'arena Expr<'arena, 'src>,
1207 pub op: UnaryPostfixOp,
1208}
1209
1210#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1211pub enum UnaryPostfixOp {
1212 PostIncrement,
1213 PostDecrement,
1214}
1215
1216#[derive(Debug, Serialize)]
1217pub struct TernaryExpr<'arena, 'src> {
1218 pub condition: &'arena Expr<'arena, 'src>,
1219 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1221 pub else_expr: &'arena Expr<'arena, 'src>,
1222}
1223
1224#[derive(Debug, Serialize)]
1225pub struct NullCoalesceExpr<'arena, 'src> {
1226 pub left: &'arena Expr<'arena, 'src>,
1227 pub right: &'arena Expr<'arena, 'src>,
1228}
1229
1230#[derive(Debug, Serialize)]
1231pub struct FunctionCallExpr<'arena, 'src> {
1232 pub name: &'arena Expr<'arena, 'src>,
1233 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1234}
1235
1236#[derive(Debug, Serialize)]
1237pub struct ArrayElement<'arena, 'src> {
1238 pub key: Option<Expr<'arena, 'src>>,
1239 pub value: Expr<'arena, 'src>,
1240 pub unpack: bool,
1241 #[serde(skip_serializing_if = "is_false")]
1242 pub by_ref: bool,
1243 pub span: Span,
1244}
1245
1246#[derive(Debug, Serialize)]
1247pub struct ArrayAccessExpr<'arena, 'src> {
1248 pub array: &'arena Expr<'arena, 'src>,
1249 pub index: Option<&'arena Expr<'arena, 'src>>,
1250}
1251
1252#[derive(Debug, Serialize)]
1255pub struct NewExpr<'arena, 'src> {
1256 pub class: &'arena Expr<'arena, 'src>,
1257 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1258}
1259
1260#[derive(Debug, Serialize)]
1261pub struct PropertyAccessExpr<'arena, 'src> {
1262 pub object: &'arena Expr<'arena, 'src>,
1263 pub property: &'arena Expr<'arena, 'src>,
1264}
1265
1266#[derive(Debug, Serialize)]
1267pub struct MethodCallExpr<'arena, 'src> {
1268 pub object: &'arena Expr<'arena, 'src>,
1269 pub method: &'arena Expr<'arena, 'src>,
1270 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1271}
1272
1273#[derive(Debug, Serialize)]
1274pub struct StaticAccessExpr<'arena, 'src> {
1275 pub class: &'arena Expr<'arena, 'src>,
1276 pub member: &'arena Expr<'arena, 'src>,
1277}
1278
1279#[derive(Debug, Serialize)]
1280pub struct StaticMethodCallExpr<'arena, 'src> {
1281 pub class: &'arena Expr<'arena, 'src>,
1282 pub method: &'arena Expr<'arena, 'src>,
1283 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1284}
1285
1286#[derive(Debug, Serialize)]
1287pub struct ClosureExpr<'arena, 'src> {
1288 pub is_static: bool,
1289 pub by_ref: bool,
1290 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1291 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1292 pub return_type: Option<TypeHint<'arena, 'src>>,
1293 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1294 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1295}
1296
1297#[derive(Debug, Clone, Serialize)]
1298pub struct ClosureUseVar<'src> {
1299 pub name: &'src str,
1300 pub by_ref: bool,
1301 pub span: Span,
1302}
1303
1304#[derive(Debug, Serialize)]
1305pub struct ArrowFunctionExpr<'arena, 'src> {
1306 pub is_static: bool,
1307 pub by_ref: bool,
1308 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1309 pub return_type: Option<TypeHint<'arena, 'src>>,
1310 pub body: &'arena Expr<'arena, 'src>,
1311 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1312}
1313
1314#[derive(Debug, Serialize)]
1315pub struct MatchExpr<'arena, 'src> {
1316 pub subject: &'arena Expr<'arena, 'src>,
1317 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1318}
1319
1320#[derive(Debug, Serialize)]
1321pub struct MatchArm<'arena, 'src> {
1322 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1324 pub body: Expr<'arena, 'src>,
1325 pub span: Span,
1326}
1327
1328#[derive(Debug, Serialize)]
1329pub struct YieldExpr<'arena, 'src> {
1330 pub key: Option<&'arena Expr<'arena, 'src>>,
1331 pub value: Option<&'arena Expr<'arena, 'src>>,
1332 pub is_from: bool,
1334}
1335
1336#[derive(Debug, Serialize)]
1339pub struct CallableCreateExpr<'arena, 'src> {
1340 pub kind: CallableCreateKind<'arena, 'src>,
1341}
1342
1343#[derive(Debug, Serialize)]
1344pub enum CallableCreateKind<'arena, 'src> {
1345 Function(&'arena Expr<'arena, 'src>),
1347 Method {
1349 object: &'arena Expr<'arena, 'src>,
1350 method: &'arena Expr<'arena, 'src>,
1351 },
1352 NullsafeMethod {
1354 object: &'arena Expr<'arena, 'src>,
1355 method: &'arena Expr<'arena, 'src>,
1356 },
1357 StaticMethod {
1359 class: &'arena Expr<'arena, 'src>,
1360 method: &'arena Expr<'arena, 'src>,
1361 },
1362}
1363
1364#[derive(Debug, Serialize)]
1367pub enum StringPart<'arena, 'src> {
1368 Literal(&'arena str),
1369 Expr(Expr<'arena, 'src>),
1370}