use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};
use jrsonnet_interner::IStr;
#[cfg(feature = "deserialize")]
use serde::Deserialize;
#[cfg(feature = "serialize")]
use serde::Serialize;
use std::{
fmt::{Debug, Display},
ops::Deref,
path::{Path, PathBuf},
rc::Rc,
};
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub enum FieldName {
Fixed(IStr),
Dyn(LocExpr),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
#[trivially_drop]
pub enum Visibility {
Normal,
Hidden,
Unhide,
}
impl Visibility {
pub fn is_visible(&self) -> bool {
matches!(self, Self::Normal | Self::Unhide)
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct FieldMember {
pub name: FieldName,
pub plus: bool,
pub params: Option<ParamsDesc>,
pub visibility: Visibility,
pub value: LocExpr,
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub enum Member {
Field(FieldMember),
BindStmt(BindSpec),
AssertStmt(AssertStmt),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
#[trivially_drop]
pub enum UnaryOpType {
Plus,
Minus,
BitNot,
Not,
}
impl Display for UnaryOpType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use UnaryOpType::*;
write!(
f,
"{}",
match self {
Plus => "+",
Minus => "-",
BitNot => "~",
Not => "!",
}
)
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Trace)]
#[trivially_drop]
pub enum BinaryOpType {
Mul,
Div,
Mod,
Add,
Sub,
Lhs,
Rhs,
Lt,
Gt,
Lte,
Gte,
BitAnd,
BitOr,
BitXor,
Eq,
Neq,
And,
Or,
In,
}
impl Display for BinaryOpType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use BinaryOpType::*;
write!(
f,
"{}",
match self {
Mul => "*",
Div => "/",
Mod => "%",
Add => "+",
Sub => "-",
Lhs => "<<",
Rhs => ">>",
Lt => "<",
Gt => ">",
Lte => "<=",
Gte => ">=",
BitAnd => "&",
BitOr => "|",
BitXor => "^",
Eq => "==",
Neq => "!=",
And => "&&",
Or => "||",
In => "in",
}
)
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct Param(pub IStr, pub Option<LocExpr>);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct ParamsDesc(pub Rc<Vec<Param>>);
unsafe impl Trace for ParamsDesc {
unsafe_empty_trace!();
}
impl Finalize for ParamsDesc {}
impl Deref for ParamsDesc {
type Target = Vec<Param>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct Arg(pub Option<String>, pub LocExpr);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct ArgsDesc(pub Vec<Arg>);
impl Deref for ArgsDesc {
type Target = Vec<Arg>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, Clone, PartialEq, Trace)]
#[trivially_drop]
pub struct BindSpec {
pub name: IStr,
pub params: Option<ParamsDesc>,
pub value: LocExpr,
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct IfSpecData(pub LocExpr);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct ForSpecData(pub IStr, pub LocExpr);
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub enum CompSpec {
IfSpec(IfSpecData),
ForSpec(ForSpecData),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct ObjComp {
pub pre_locals: Vec<BindSpec>,
pub key: LocExpr,
pub value: LocExpr,
pub post_locals: Vec<BindSpec>,
pub compspecs: Vec<CompSpec>,
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub enum ObjBody {
MemberList(Vec<Member>),
ObjComp(ObjComp),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Clone, Copy, Trace)]
#[trivially_drop]
pub enum LiteralType {
This,
Super,
Dollar,
Null,
True,
False,
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub struct SliceDesc {
pub start: Option<LocExpr>,
pub end: Option<LocExpr>,
pub step: Option<LocExpr>,
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Debug, PartialEq, Trace)]
#[trivially_drop]
pub enum Expr {
Literal(LiteralType),
Str(IStr),
Num(f64),
Var(IStr),
Arr(Vec<LocExpr>),
ArrComp(LocExpr, Vec<CompSpec>),
Obj(ObjBody),
ObjExtend(LocExpr, ObjBody),
Parened(LocExpr),
UnaryOp(UnaryOpType, LocExpr),
BinaryOp(LocExpr, BinaryOpType, LocExpr),
AssertExpr(AssertStmt, LocExpr),
LocalExpr(Vec<BindSpec>, LocExpr),
Import(PathBuf),
ImportStr(PathBuf),
ErrorStmt(LocExpr),
Apply(LocExpr, ArgsDesc, bool),
Index(LocExpr, LocExpr),
Function(ParamsDesc, LocExpr),
Intrinsic(IStr),
IfElse {
cond: IfSpecData,
cond_then: LocExpr,
cond_else: Option<LocExpr>,
},
Slice(LocExpr, SliceDesc),
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, PartialEq, Trace)]
#[trivially_drop]
pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);
impl Debug for ExprLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)
}
}
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Clone, PartialEq)]
pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);
unsafe impl Trace for LocExpr {
unsafe_empty_trace!();
}
impl Finalize for LocExpr {}
impl Debug for LocExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if f.alternate() {
write!(f, "{:#?}", self.0)?;
} else {
write!(f, "{:?}", self.0)?;
}
if let Some(loc) = &self.1 {
write!(f, " from {:?}", loc)?;
}
Ok(())
}
}
#[macro_export]
macro_rules! loc_expr {
($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {
LocExpr(
std::rc::Rc::new($expr),
if $need_loc {
Some(ExprLocation($name, $start, $end))
} else {
None
},
)
};
}
#[macro_export]
macro_rules! loc_expr_todo {
($expr:expr) => {
LocExpr(Rc::new($expr), None)
};
}