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 StaticDynMethodCall(&'arena StaticDynMethodCallExpr<'arena, 'src>),
1036
1037 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1039
1040 ClassConstAccessDynamic {
1042 class: &'arena Expr<'arena, 'src>,
1043 member: &'arena Expr<'arena, 'src>,
1044 },
1045
1046 StaticPropertyAccessDynamic {
1048 class: &'arena Expr<'arena, 'src>,
1049 member: &'arena Expr<'arena, 'src>,
1050 },
1051
1052 Closure(&'arena ClosureExpr<'arena, 'src>),
1054
1055 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1057
1058 Match(MatchExpr<'arena, 'src>),
1060
1061 ThrowExpr(&'arena Expr<'arena, 'src>),
1063
1064 Yield(YieldExpr<'arena, 'src>),
1066
1067 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1069
1070 CallableCreate(CallableCreateExpr<'arena, 'src>),
1072
1073 Omit,
1075
1076 Error,
1078}
1079
1080impl<'arena, 'src> Expr<'arena, 'src> {
1081 pub fn name_str(&self) -> Option<&str> {
1083 match &self.kind {
1084 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
1085 _ => None,
1086 }
1087 }
1088}
1089
1090#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1091pub enum CastKind {
1092 Int,
1093 Float,
1094 String,
1095 Bool,
1096 Array,
1097 Object,
1098 Unset,
1099 Void,
1100}
1101
1102#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1103pub enum IncludeKind {
1104 Include,
1105 IncludeOnce,
1106 Require,
1107 RequireOnce,
1108}
1109
1110#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1111pub enum MagicConstKind {
1112 Class,
1113 Dir,
1114 File,
1115 Function,
1116 Line,
1117 Method,
1118 Namespace,
1119 Trait,
1120 Property,
1121}
1122
1123#[derive(Debug, Serialize)]
1126pub struct AssignExpr<'arena, 'src> {
1127 pub target: &'arena Expr<'arena, 'src>,
1128 pub op: AssignOp,
1129 pub value: &'arena Expr<'arena, 'src>,
1130 #[serde(skip_serializing_if = "is_false")]
1131 pub by_ref: bool,
1132}
1133
1134#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1135pub enum AssignOp {
1136 Assign,
1137 Plus,
1138 Minus,
1139 Mul,
1140 Div,
1141 Mod,
1142 Pow,
1143 Concat,
1144 BitwiseAnd,
1145 BitwiseOr,
1146 BitwiseXor,
1147 ShiftLeft,
1148 ShiftRight,
1149 Coalesce,
1150}
1151
1152#[derive(Debug, Serialize)]
1153pub struct BinaryExpr<'arena, 'src> {
1154 pub left: &'arena Expr<'arena, 'src>,
1155 pub op: BinaryOp,
1156 pub right: &'arena Expr<'arena, 'src>,
1157}
1158
1159#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1160pub enum BinaryOp {
1161 Add,
1162 Sub,
1163 Mul,
1164 Div,
1165 Mod,
1166 Pow,
1167 Concat,
1168 Equal,
1169 NotEqual,
1170 Identical,
1171 NotIdentical,
1172 Less,
1173 Greater,
1174 LessOrEqual,
1175 GreaterOrEqual,
1176 Spaceship,
1177 BooleanAnd,
1178 BooleanOr,
1179 BitwiseAnd,
1180 BitwiseOr,
1181 BitwiseXor,
1182 ShiftLeft,
1183 ShiftRight,
1184 LogicalAnd,
1185 LogicalOr,
1186 LogicalXor,
1187 Instanceof,
1188 Pipe,
1189}
1190
1191#[derive(Debug, Serialize)]
1192pub struct UnaryPrefixExpr<'arena, 'src> {
1193 pub op: UnaryPrefixOp,
1194 pub operand: &'arena Expr<'arena, 'src>,
1195}
1196
1197#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1198pub enum UnaryPrefixOp {
1199 Negate,
1200 Plus,
1201 BooleanNot,
1202 BitwiseNot,
1203 PreIncrement,
1204 PreDecrement,
1205}
1206
1207#[derive(Debug, Serialize)]
1208pub struct UnaryPostfixExpr<'arena, 'src> {
1209 pub operand: &'arena Expr<'arena, 'src>,
1210 pub op: UnaryPostfixOp,
1211}
1212
1213#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1214pub enum UnaryPostfixOp {
1215 PostIncrement,
1216 PostDecrement,
1217}
1218
1219#[derive(Debug, Serialize)]
1220pub struct TernaryExpr<'arena, 'src> {
1221 pub condition: &'arena Expr<'arena, 'src>,
1222 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1224 pub else_expr: &'arena Expr<'arena, 'src>,
1225}
1226
1227#[derive(Debug, Serialize)]
1228pub struct NullCoalesceExpr<'arena, 'src> {
1229 pub left: &'arena Expr<'arena, 'src>,
1230 pub right: &'arena Expr<'arena, 'src>,
1231}
1232
1233#[derive(Debug, Serialize)]
1234pub struct FunctionCallExpr<'arena, 'src> {
1235 pub name: &'arena Expr<'arena, 'src>,
1236 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1237}
1238
1239#[derive(Debug, Serialize)]
1240pub struct ArrayElement<'arena, 'src> {
1241 pub key: Option<Expr<'arena, 'src>>,
1242 pub value: Expr<'arena, 'src>,
1243 pub unpack: bool,
1244 #[serde(skip_serializing_if = "is_false")]
1245 pub by_ref: bool,
1246 pub span: Span,
1247}
1248
1249#[derive(Debug, Serialize)]
1250pub struct ArrayAccessExpr<'arena, 'src> {
1251 pub array: &'arena Expr<'arena, 'src>,
1252 pub index: Option<&'arena Expr<'arena, 'src>>,
1253}
1254
1255#[derive(Debug, Serialize)]
1258pub struct NewExpr<'arena, 'src> {
1259 pub class: &'arena Expr<'arena, 'src>,
1260 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1261}
1262
1263#[derive(Debug, Serialize)]
1264pub struct PropertyAccessExpr<'arena, 'src> {
1265 pub object: &'arena Expr<'arena, 'src>,
1266 pub property: &'arena Expr<'arena, 'src>,
1267}
1268
1269#[derive(Debug, Serialize)]
1270pub struct MethodCallExpr<'arena, 'src> {
1271 pub object: &'arena Expr<'arena, 'src>,
1272 pub method: &'arena Expr<'arena, 'src>,
1273 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1274}
1275
1276#[derive(Debug, Serialize)]
1277pub struct StaticAccessExpr<'arena, 'src> {
1278 pub class: &'arena Expr<'arena, 'src>,
1279 pub member: &'arena Expr<'arena, 'src>,
1280}
1281
1282#[derive(Debug, Serialize)]
1283pub struct StaticMethodCallExpr<'arena, 'src> {
1284 pub class: &'arena Expr<'arena, 'src>,
1285 pub method: &'arena Expr<'arena, 'src>,
1286 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1287}
1288
1289#[derive(Debug, Serialize)]
1290pub struct StaticDynMethodCallExpr<'arena, 'src> {
1291 pub class: &'arena Expr<'arena, 'src>,
1292 pub method: &'arena Expr<'arena, 'src>,
1293 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1294}
1295
1296#[derive(Debug, Serialize)]
1297pub struct ClosureExpr<'arena, 'src> {
1298 pub is_static: bool,
1299 pub by_ref: bool,
1300 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1301 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1302 pub return_type: Option<TypeHint<'arena, 'src>>,
1303 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1304 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1305}
1306
1307#[derive(Debug, Clone, Serialize)]
1308pub struct ClosureUseVar<'src> {
1309 pub name: &'src str,
1310 pub by_ref: bool,
1311 pub span: Span,
1312}
1313
1314#[derive(Debug, Serialize)]
1315pub struct ArrowFunctionExpr<'arena, 'src> {
1316 pub is_static: bool,
1317 pub by_ref: bool,
1318 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1319 pub return_type: Option<TypeHint<'arena, 'src>>,
1320 pub body: &'arena Expr<'arena, 'src>,
1321 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1322}
1323
1324#[derive(Debug, Serialize)]
1325pub struct MatchExpr<'arena, 'src> {
1326 pub subject: &'arena Expr<'arena, 'src>,
1327 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1328}
1329
1330#[derive(Debug, Serialize)]
1331pub struct MatchArm<'arena, 'src> {
1332 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1334 pub body: Expr<'arena, 'src>,
1335 pub span: Span,
1336}
1337
1338#[derive(Debug, Serialize)]
1339pub struct YieldExpr<'arena, 'src> {
1340 pub key: Option<&'arena Expr<'arena, 'src>>,
1341 pub value: Option<&'arena Expr<'arena, 'src>>,
1342 pub is_from: bool,
1344}
1345
1346#[derive(Debug, Serialize)]
1349pub struct CallableCreateExpr<'arena, 'src> {
1350 pub kind: CallableCreateKind<'arena, 'src>,
1351}
1352
1353#[derive(Debug, Serialize)]
1354pub enum CallableCreateKind<'arena, 'src> {
1355 Function(&'arena Expr<'arena, 'src>),
1357 Method {
1359 object: &'arena Expr<'arena, 'src>,
1360 method: &'arena Expr<'arena, 'src>,
1361 },
1362 NullsafeMethod {
1364 object: &'arena Expr<'arena, 'src>,
1365 method: &'arena Expr<'arena, 'src>,
1366 },
1367 StaticMethod {
1369 class: &'arena Expr<'arena, 'src>,
1370 method: &'arena Expr<'arena, 'src>,
1371 },
1372}
1373
1374#[derive(Debug, Serialize)]
1377pub enum StringPart<'arena, 'src> {
1378 Literal(&'arena str),
1379 Expr(Expr<'arena, 'src>),
1380}