use std::borrow::Cow;
use serde::Serialize;
use crate::Span;
fn is_false(b: &bool) -> bool {
!*b
}
pub struct ArenaVec<'arena, T>(bumpalo::collections::Vec<'arena, T>);
impl<'arena, T> ArenaVec<'arena, T> {
#[inline]
pub fn new_in(arena: &'arena bumpalo::Bump) -> Self {
Self(bumpalo::collections::Vec::new_in(arena))
}
#[inline]
pub fn with_capacity_in(cap: usize, arena: &'arena bumpalo::Bump) -> Self {
Self(bumpalo::collections::Vec::with_capacity_in(cap, arena))
}
#[inline]
pub fn push(&mut self, val: T) {
self.0.push(val)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl<'arena, T> IntoIterator for ArenaVec<'arena, T> {
type Item = T;
type IntoIter = bumpalo::collections::vec::IntoIter<'arena, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'arena, T> std::ops::Deref for ArenaVec<'arena, T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
&self.0
}
}
impl<'arena, T> std::ops::DerefMut for ArenaVec<'arena, T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
&mut self.0
}
}
impl<'arena, T: serde::Serialize> serde::Serialize for ArenaVec<'arena, T> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
self.0.as_slice().serialize(s)
}
}
impl<'arena, T: std::fmt::Debug> std::fmt::Debug for ArenaVec<'arena, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.as_slice().fmt(f)
}
}
#[derive(Debug, Serialize)]
pub struct Comment<'src> {
pub kind: CommentKind,
pub text: &'src str,
pub span: Span,
}
#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)]
pub enum CommentKind {
Line,
Hash,
Block,
Doc,
}
#[derive(Debug, Serialize)]
pub struct Program<'arena, 'src> {
pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub span: Span,
}
pub enum Name<'arena, 'src> {
Simple { value: &'src str, span: Span },
Complex {
parts: ArenaVec<'arena, &'src str>,
kind: NameKind,
span: Span,
},
}
impl<'arena, 'src> Name<'arena, 'src> {
#[inline]
pub fn span(&self) -> Span {
match self {
Self::Simple { span, .. } | Self::Complex { span, .. } => *span,
}
}
#[inline]
pub fn kind(&self) -> NameKind {
match self {
Self::Simple { .. } => NameKind::Unqualified,
Self::Complex { kind, .. } => *kind,
}
}
#[inline]
pub fn src_repr(&self, src: &'src str) -> &'src str {
match self {
Self::Simple { value, .. } => value,
Self::Complex { span, .. } => &src[span.start as usize..span.end as usize],
}
}
#[inline]
pub fn to_string_repr(&self) -> Cow<'src, str> {
match self {
Self::Simple { value, .. } => Cow::Borrowed(value),
Self::Complex { parts, kind, .. } => {
let joined = parts.join("\\");
if *kind == NameKind::FullyQualified {
Cow::Owned(format!("\\{}", joined))
} else {
Cow::Owned(joined)
}
}
}
}
#[inline]
pub fn join_parts(&self) -> Cow<'src, str> {
match self {
Self::Simple { value, .. } => Cow::Borrowed(value),
Self::Complex { parts, .. } => Cow::Owned(parts.join("\\")),
}
}
#[inline]
pub fn parts_slice(&self) -> &[&'src str] {
match self {
Self::Simple { value, .. } => std::slice::from_ref(value),
Self::Complex { parts, .. } => parts,
}
}
}
impl<'arena, 'src> std::fmt::Debug for Name<'arena, 'src> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Simple { value, span } => f
.debug_struct("Name")
.field("parts", &std::slice::from_ref(value))
.field("kind", &NameKind::Unqualified)
.field("span", span)
.finish(),
Self::Complex { parts, kind, span } => f
.debug_struct("Name")
.field("parts", parts)
.field("kind", kind)
.field("span", span)
.finish(),
}
}
}
impl<'arena, 'src> serde::Serialize for Name<'arena, 'src> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut st = s.serialize_struct("Name", 3)?;
match self {
Self::Simple { value, span } => {
st.serialize_field("parts", std::slice::from_ref(value))?;
st.serialize_field("kind", &NameKind::Unqualified)?;
st.serialize_field("span", span)?;
}
Self::Complex { parts, kind, span } => {
st.serialize_field("parts", parts)?;
st.serialize_field("kind", kind)?;
st.serialize_field("span", span)?;
}
}
st.end()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum NameKind {
Unqualified,
Qualified,
FullyQualified,
Relative,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum BuiltinType {
Int,
Integer,
Float,
Double,
String,
Bool,
Boolean,
Void,
Never,
Mixed,
Object,
Iterable,
Callable,
Array,
Self_,
Parent_,
Static,
Null,
True,
False,
}
impl BuiltinType {
#[inline]
pub fn as_str(self) -> &'static str {
match self {
Self::Int => "int",
Self::Integer => "integer",
Self::Float => "float",
Self::Double => "double",
Self::String => "string",
Self::Bool => "bool",
Self::Boolean => "boolean",
Self::Void => "void",
Self::Never => "never",
Self::Mixed => "mixed",
Self::Object => "object",
Self::Iterable => "iterable",
Self::Callable => "callable",
Self::Array => "array",
Self::Self_ => "self",
Self::Parent_ => "parent",
Self::Static => "static",
Self::Null => "null",
Self::True => "true",
Self::False => "false",
}
}
}
#[derive(Debug, Serialize)]
pub struct TypeHint<'arena, 'src> {
pub kind: TypeHintKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug)]
pub enum TypeHintKind<'arena, 'src> {
Named(Name<'arena, 'src>),
Keyword(BuiltinType, Span),
Nullable(&'arena TypeHint<'arena, 'src>),
Union(ArenaVec<'arena, TypeHint<'arena, 'src>>),
Intersection(ArenaVec<'arena, TypeHint<'arena, 'src>>),
}
impl<'arena, 'src> serde::Serialize for TypeHintKind<'arena, 'src> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
match self {
Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
Self::Nullable(inner) => {
s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
}
Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
Self::Intersection(types) => {
s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
}
Self::Keyword(builtin, span) => {
struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
impl serde::Serialize for BuiltinNameRepr<'_> {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut st = s.serialize_struct("Name", 3)?;
st.serialize_field("parts", &[self.0.as_str()])?;
st.serialize_field("kind", &NameKind::Unqualified)?;
st.serialize_field("span", self.1)?;
st.end()
}
}
s.serialize_newtype_variant(
"TypeHintKind",
0,
"Named",
&BuiltinNameRepr(builtin, span),
)
}
}
}
}
#[derive(Debug, Serialize)]
pub struct Arg<'arena, 'src> {
pub name: Option<Name<'arena, 'src>>,
pub value: Expr<'arena, 'src>,
pub unpack: bool,
pub by_ref: bool,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct Attribute<'arena, 'src> {
pub name: Name<'arena, 'src>,
pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct Stmt<'arena, 'src> {
pub kind: StmtKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub enum StmtKind<'arena, 'src> {
Expression(&'arena Expr<'arena, 'src>),
Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
Return(Option<&'arena Expr<'arena, 'src>>),
Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
If(&'arena IfStmt<'arena, 'src>),
While(&'arena WhileStmt<'arena, 'src>),
For(&'arena ForStmt<'arena, 'src>),
Foreach(&'arena ForeachStmt<'arena, 'src>),
DoWhile(&'arena DoWhileStmt<'arena, 'src>),
Function(&'arena FunctionDecl<'arena, 'src>),
Break(Option<&'arena Expr<'arena, 'src>>),
Continue(Option<&'arena Expr<'arena, 'src>>),
Switch(&'arena SwitchStmt<'arena, 'src>),
Goto(&'src str),
Label(&'arena str),
Declare(&'arena DeclareStmt<'arena, 'src>),
Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
Throw(&'arena Expr<'arena, 'src>),
TryCatch(&'arena TryCatchStmt<'arena, 'src>),
Global(ArenaVec<'arena, Expr<'arena, 'src>>),
Class(&'arena ClassDecl<'arena, 'src>),
Interface(&'arena InterfaceDecl<'arena, 'src>),
Trait(&'arena TraitDecl<'arena, 'src>),
Enum(&'arena EnumDecl<'arena, 'src>),
Namespace(&'arena NamespaceDecl<'arena, 'src>),
Use(&'arena UseDecl<'arena, 'src>),
Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
HaltCompiler(&'src str),
Nop,
InlineHtml(&'src str),
Error,
}
#[derive(Debug, Serialize)]
pub struct IfStmt<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub then_branch: &'arena Stmt<'arena, 'src>,
pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct ElseIfBranch<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub body: Stmt<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct WhileStmt<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub body: &'arena Stmt<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct ForStmt<'arena, 'src> {
pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
pub body: &'arena Stmt<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct ForeachStmt<'arena, 'src> {
pub expr: Expr<'arena, 'src>,
pub key: Option<Expr<'arena, 'src>>,
pub value: Expr<'arena, 'src>,
pub body: &'arena Stmt<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct DoWhileStmt<'arena, 'src> {
pub body: &'arena Stmt<'arena, 'src>,
pub condition: Expr<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct FunctionDecl<'arena, 'src> {
pub name: &'src str,
pub params: ArenaVec<'arena, Param<'arena, 'src>>,
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub return_type: Option<TypeHint<'arena, 'src>>,
pub by_ref: bool,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct Param<'arena, 'src> {
pub name: &'src str,
pub type_hint: Option<TypeHint<'arena, 'src>>,
pub default: Option<Expr<'arena, 'src>>,
pub by_ref: bool,
pub variadic: bool,
pub is_readonly: bool,
pub is_final: bool,
pub visibility: Option<Visibility>,
pub set_visibility: Option<Visibility>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "ArenaVec::is_empty")]
pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct SwitchStmt<'arena, 'src> {
pub expr: Expr<'arena, 'src>,
pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct SwitchCase<'arena, 'src> {
pub value: Option<Expr<'arena, 'src>>,
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct TryCatchStmt<'arena, 'src> {
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
pub finally: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
}
#[derive(Debug, Serialize)]
pub struct CatchClause<'arena, 'src> {
pub types: ArenaVec<'arena, Name<'arena, 'src>>,
pub var: Option<&'src str>,
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum Visibility {
Public,
Protected,
Private,
}
#[derive(Debug, Serialize)]
pub struct ClassDecl<'arena, 'src> {
pub name: Option<&'src str>,
pub modifiers: ClassModifiers,
pub extends: Option<Name<'arena, 'src>>,
pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct ClassModifiers {
pub is_abstract: bool,
pub is_final: bool,
pub is_readonly: bool,
}
#[derive(Debug, Serialize)]
pub struct ClassMember<'arena, 'src> {
pub kind: ClassMemberKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub enum ClassMemberKind<'arena, 'src> {
Property(PropertyDecl<'arena, 'src>),
Method(MethodDecl<'arena, 'src>),
ClassConst(ClassConstDecl<'arena, 'src>),
TraitUse(TraitUseDecl<'arena, 'src>),
}
#[derive(Debug, Serialize)]
pub struct PropertyDecl<'arena, 'src> {
pub name: &'src str,
pub visibility: Option<Visibility>,
pub set_visibility: Option<Visibility>,
pub is_static: bool,
pub is_readonly: bool,
pub type_hint: Option<TypeHint<'arena, 'src>>,
pub default: Option<Expr<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "ArenaVec::is_empty")]
pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum PropertyHookKind {
Get,
Set,
}
#[derive(Debug, Serialize)]
pub enum PropertyHookBody<'arena, 'src> {
Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
Expression(Expr<'arena, 'src>),
Abstract,
}
#[derive(Debug, Serialize)]
pub struct PropertyHook<'arena, 'src> {
pub kind: PropertyHookKind,
pub body: PropertyHookBody<'arena, 'src>,
pub is_final: bool,
pub by_ref: bool,
pub params: ArenaVec<'arena, Param<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct MethodDecl<'arena, 'src> {
pub name: &'src str,
pub visibility: Option<Visibility>,
pub is_static: bool,
pub is_abstract: bool,
pub is_final: bool,
pub by_ref: bool,
pub params: ArenaVec<'arena, Param<'arena, 'src>>,
pub return_type: Option<TypeHint<'arena, 'src>>,
pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct ClassConstDecl<'arena, 'src> {
pub name: &'src str,
pub visibility: Option<Visibility>,
#[serde(skip_serializing_if = "Option::is_none")]
pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
pub value: Expr<'arena, 'src>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct TraitUseDecl<'arena, 'src> {
pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct TraitAdaptation<'arena, 'src> {
pub kind: TraitAdaptationKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub enum TraitAdaptationKind<'arena, 'src> {
Precedence {
trait_name: Name<'arena, 'src>,
method: Name<'arena, 'src>,
insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
},
Alias {
trait_name: Option<Name<'arena, 'src>>,
method: Name<'arena, 'src>,
new_modifier: Option<Visibility>,
new_name: Option<Name<'arena, 'src>>,
},
}
#[derive(Debug, Serialize)]
pub struct InterfaceDecl<'arena, 'src> {
pub name: &'src str,
pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct TraitDecl<'arena, 'src> {
pub name: &'src str,
pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct EnumDecl<'arena, 'src> {
pub name: &'src str,
pub scalar_type: Option<Name<'arena, 'src>>,
pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct EnumMember<'arena, 'src> {
pub kind: EnumMemberKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub enum EnumMemberKind<'arena, 'src> {
Case(EnumCase<'arena, 'src>),
Method(MethodDecl<'arena, 'src>),
ClassConst(ClassConstDecl<'arena, 'src>),
TraitUse(TraitUseDecl<'arena, 'src>),
}
#[derive(Debug, Serialize)]
pub struct EnumCase<'arena, 'src> {
pub name: &'src str,
pub value: Option<Expr<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug, Serialize)]
pub struct NamespaceDecl<'arena, 'src> {
pub name: Option<Name<'arena, 'src>>,
pub body: NamespaceBody<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub enum NamespaceBody<'arena, 'src> {
Braced(ArenaVec<'arena, Stmt<'arena, 'src>>),
Simple,
}
#[derive(Debug, Serialize)]
pub struct DeclareStmt<'arena, 'src> {
pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
pub body: Option<&'arena Stmt<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct UseDecl<'arena, 'src> {
pub kind: UseKind,
pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum UseKind {
Normal,
Function,
Const,
}
#[derive(Debug, Serialize)]
pub struct UseItem<'arena, 'src> {
pub name: Name<'arena, 'src>,
pub alias: Option<&'src str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<UseKind>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct ConstItem<'arena, 'src> {
pub name: &'src str,
pub value: Expr<'arena, 'src>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct StaticVar<'arena, 'src> {
pub name: &'src str,
pub default: Option<Expr<'arena, 'src>>,
pub span: Span,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum NameStr<'arena, 'src> {
Src(&'src str),
Arena(&'arena str),
}
impl<'arena, 'src> NameStr<'arena, 'src> {
#[inline]
pub fn as_str(&self) -> &str {
match self {
NameStr::Src(s) => s,
NameStr::Arena(s) => s,
}
}
}
impl<'arena, 'src> std::ops::Deref for NameStr<'arena, 'src> {
type Target = str;
#[inline]
fn deref(&self) -> &str {
self.as_str()
}
}
impl<'arena, 'src> std::fmt::Debug for NameStr<'arena, 'src> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().fmt(f)
}
}
impl<'arena, 'src> serde::Serialize for NameStr<'arena, 'src> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.as_str().serialize(serializer)
}
}
#[derive(Debug, Serialize)]
pub struct Expr<'arena, 'src> {
pub kind: ExprKind<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub enum ExprKind<'arena, 'src> {
Int(i64),
Float(f64),
String(&'arena str),
InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
Heredoc {
label: &'src str,
parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
},
Nowdoc {
label: &'src str,
value: &'arena str,
},
ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
Bool(bool),
Null,
Variable(NameStr<'arena, 'src>),
VariableVariable(&'arena Expr<'arena, 'src>),
Identifier(NameStr<'arena, 'src>),
Assign(AssignExpr<'arena, 'src>),
Binary(BinaryExpr<'arena, 'src>),
UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
Ternary(TernaryExpr<'arena, 'src>),
NullCoalesce(NullCoalesceExpr<'arena, 'src>),
FunctionCall(FunctionCallExpr<'arena, 'src>),
Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
ArrayAccess(ArrayAccessExpr<'arena, 'src>),
Print(&'arena Expr<'arena, 'src>),
Parenthesized(&'arena Expr<'arena, 'src>),
Cast(CastKind, &'arena Expr<'arena, 'src>),
ErrorSuppress(&'arena Expr<'arena, 'src>),
Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
Empty(&'arena Expr<'arena, 'src>),
Include(IncludeKind, &'arena Expr<'arena, 'src>),
Eval(&'arena Expr<'arena, 'src>),
Exit(Option<&'arena Expr<'arena, 'src>>),
MagicConst(MagicConstKind),
Clone(&'arena Expr<'arena, 'src>),
CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
New(NewExpr<'arena, 'src>),
PropertyAccess(PropertyAccessExpr<'arena, 'src>),
NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
MethodCall(&'arena MethodCallExpr<'arena, 'src>),
NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
ClassConstAccess(StaticAccessExpr<'arena, 'src>),
ClassConstAccessDynamic {
class: &'arena Expr<'arena, 'src>,
member: &'arena Expr<'arena, 'src>,
},
StaticPropertyAccessDynamic {
class: &'arena Expr<'arena, 'src>,
member: &'arena Expr<'arena, 'src>,
},
Closure(&'arena ClosureExpr<'arena, 'src>),
ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
Match(MatchExpr<'arena, 'src>),
ThrowExpr(&'arena Expr<'arena, 'src>),
Yield(YieldExpr<'arena, 'src>),
AnonymousClass(&'arena ClassDecl<'arena, 'src>),
CallableCreate(CallableCreateExpr<'arena, 'src>),
Omit,
Error,
}
impl<'arena, 'src> Expr<'arena, 'src> {
pub fn name_str(&self) -> Option<&str> {
match &self.kind {
ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s.as_str()),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum CastKind {
Int,
Float,
String,
Bool,
Array,
Object,
Unset,
Void,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum IncludeKind {
Include,
IncludeOnce,
Require,
RequireOnce,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum MagicConstKind {
Class,
Dir,
File,
Function,
Line,
Method,
Namespace,
Trait,
Property,
}
#[derive(Debug, Serialize)]
pub struct AssignExpr<'arena, 'src> {
pub target: &'arena Expr<'arena, 'src>,
pub op: AssignOp,
pub value: &'arena Expr<'arena, 'src>,
#[serde(skip_serializing_if = "is_false")]
pub by_ref: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum AssignOp {
Assign,
Plus,
Minus,
Mul,
Div,
Mod,
Pow,
Concat,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
ShiftLeft,
ShiftRight,
Coalesce,
}
#[derive(Debug, Serialize)]
pub struct BinaryExpr<'arena, 'src> {
pub left: &'arena Expr<'arena, 'src>,
pub op: BinaryOp,
pub right: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum BinaryOp {
Add,
Sub,
Mul,
Div,
Mod,
Pow,
Concat,
Equal,
NotEqual,
Identical,
NotIdentical,
Less,
Greater,
LessOrEqual,
GreaterOrEqual,
Spaceship,
BooleanAnd,
BooleanOr,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
ShiftLeft,
ShiftRight,
LogicalAnd,
LogicalOr,
LogicalXor,
Instanceof,
Pipe,
}
#[derive(Debug, Serialize)]
pub struct UnaryPrefixExpr<'arena, 'src> {
pub op: UnaryPrefixOp,
pub operand: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum UnaryPrefixOp {
Negate,
Plus,
BooleanNot,
BitwiseNot,
PreIncrement,
PreDecrement,
}
#[derive(Debug, Serialize)]
pub struct UnaryPostfixExpr<'arena, 'src> {
pub operand: &'arena Expr<'arena, 'src>,
pub op: UnaryPostfixOp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum UnaryPostfixOp {
PostIncrement,
PostDecrement,
}
#[derive(Debug, Serialize)]
pub struct TernaryExpr<'arena, 'src> {
pub condition: &'arena Expr<'arena, 'src>,
pub then_expr: Option<&'arena Expr<'arena, 'src>>,
pub else_expr: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct NullCoalesceExpr<'arena, 'src> {
pub left: &'arena Expr<'arena, 'src>,
pub right: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct FunctionCallExpr<'arena, 'src> {
pub name: &'arena Expr<'arena, 'src>,
pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct ArrayElement<'arena, 'src> {
pub key: Option<Expr<'arena, 'src>>,
pub value: Expr<'arena, 'src>,
pub unpack: bool,
#[serde(skip_serializing_if = "is_false")]
pub by_ref: bool,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct ArrayAccessExpr<'arena, 'src> {
pub array: &'arena Expr<'arena, 'src>,
pub index: Option<&'arena Expr<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct NewExpr<'arena, 'src> {
pub class: &'arena Expr<'arena, 'src>,
pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct PropertyAccessExpr<'arena, 'src> {
pub object: &'arena Expr<'arena, 'src>,
pub property: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct MethodCallExpr<'arena, 'src> {
pub object: &'arena Expr<'arena, 'src>,
pub method: &'arena Expr<'arena, 'src>,
pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct StaticAccessExpr<'arena, 'src> {
pub class: &'arena Expr<'arena, 'src>,
pub member: &'arena Expr<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub struct StaticMethodCallExpr<'arena, 'src> {
pub class: &'arena Expr<'arena, 'src>,
pub method: &'arena Expr<'arena, 'src>,
pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct ClosureExpr<'arena, 'src> {
pub is_static: bool,
pub by_ref: bool,
pub params: ArenaVec<'arena, Param<'arena, 'src>>,
pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
pub return_type: Option<TypeHint<'arena, 'src>>,
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ClosureUseVar<'src> {
pub name: &'src str,
pub by_ref: bool,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct ArrowFunctionExpr<'arena, 'src> {
pub is_static: bool,
pub by_ref: bool,
pub params: ArenaVec<'arena, Param<'arena, 'src>>,
pub return_type: Option<TypeHint<'arena, 'src>>,
pub body: &'arena Expr<'arena, 'src>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct MatchExpr<'arena, 'src> {
pub subject: &'arena Expr<'arena, 'src>,
pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
}
#[derive(Debug, Serialize)]
pub struct MatchArm<'arena, 'src> {
pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
pub body: Expr<'arena, 'src>,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct YieldExpr<'arena, 'src> {
pub key: Option<&'arena Expr<'arena, 'src>>,
pub value: Option<&'arena Expr<'arena, 'src>>,
pub is_from: bool,
}
#[derive(Debug, Serialize)]
pub struct CallableCreateExpr<'arena, 'src> {
pub kind: CallableCreateKind<'arena, 'src>,
}
#[derive(Debug, Serialize)]
pub enum CallableCreateKind<'arena, 'src> {
Function(&'arena Expr<'arena, 'src>),
Method {
object: &'arena Expr<'arena, 'src>,
method: &'arena Expr<'arena, 'src>,
},
NullsafeMethod {
object: &'arena Expr<'arena, 'src>,
method: &'arena Expr<'arena, 'src>,
},
StaticMethod {
class: &'arena Expr<'arena, 'src>,
method: &'arena Expr<'arena, 'src>,
},
}
#[derive(Debug, Serialize)]
pub enum StringPart<'arena, 'src> {
Literal(&'arena str),
Expr(Expr<'arena, 'src>),
}