use serde::Serialize;
use crate::Span;
use super::{is_false, ArenaVec, Arg, Attribute, ClassDecl, Param, Stmt, TypeHint};
#[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>),
StaticDynMethodCall(&'arena StaticDynMethodCallExpr<'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 StaticDynMethodCallExpr<'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>),
}