1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};11#[cfg(feature = "structdump")]12use structdump::Codegen;1314use crate::source::Source;1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]17#[cfg_attr(feature = "structdump", derive(Codegen))]18#[derive(Debug, PartialEq, Trace)]19pub enum FieldName {20 21 Fixed(IStr),22 23 Dyn(LocExpr),24}2526#[cfg_attr(feature = "structdump", derive(Codegen))]27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]28#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]29pub enum Visibility {30 31 Normal,32 33 Hidden,34 35 Unhide,36}3738impl Visibility {39 pub fn is_visible(&self) -> bool {40 matches!(self, Self::Normal | Self::Unhide)41 }42}4344#[cfg_attr(feature = "structdump", derive(Codegen))]45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4849#[cfg_attr(feature = "structdump", derive(Codegen))]50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]51#[derive(Debug, PartialEq, Trace)]52pub struct FieldMember {53 pub name: FieldName,54 pub plus: bool,55 pub params: Option<ParamsDesc>,56 pub visibility: Visibility,57 pub value: LocExpr,58}5960#[cfg_attr(feature = "structdump", derive(Codegen))]61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, PartialEq, Trace)]63pub enum Member {64 Field(FieldMember),65 BindStmt(BindSpec),66 AssertStmt(AssertStmt),67}6869#[cfg_attr(feature = "structdump", derive(Codegen))]70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]71#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]72pub enum UnaryOpType {73 Plus,74 Minus,75 BitNot,76 Not,77}7879impl Display for UnaryOpType {80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {81 use UnaryOpType::*;82 write!(83 f,84 "{}",85 match self {86 Plus => "+",87 Minus => "-",88 BitNot => "~",89 Not => "!",90 }91 )92 }93}9495#[cfg_attr(feature = "structdump", derive(Codegen))]96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]97#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]98pub enum BinaryOpType {99 Mul,100 Div,101102 103 Mod,104105 Add,106 Sub,107108 Lhs,109 Rhs,110111 Lt,112 Gt,113 Lte,114 Gte,115116 BitAnd,117 BitOr,118 BitXor,119120 Eq,121 Neq,122123 And,124 Or,125 #[cfg(feature = "exp-null-coaelse")]126 NullCoaelse,127128 129 In,130}131132impl Display for BinaryOpType {133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {134 use BinaryOpType::*;135 write!(136 f,137 "{}",138 match self {139 Mul => "*",140 Div => "/",141 Mod => "%",142 Add => "+",143 Sub => "-",144 Lhs => "<<",145 Rhs => ">>",146 Lt => "<",147 Gt => ">",148 Lte => "<=",149 Gte => ">=",150 BitAnd => "&",151 BitOr => "|",152 BitXor => "^",153 Eq => "==",154 Neq => "!=",155 And => "&&",156 Or => "||",157 In => "in",158 #[cfg(feature = "exp-null-coaelse")]159 NullCoaelse => "??",160 }161 )162 }163}164165166#[cfg_attr(feature = "structdump", derive(Codegen))]167#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]168#[derive(Debug, PartialEq, Trace)]169pub struct Param(pub Destruct, pub Option<LocExpr>);170171172#[cfg_attr(feature = "structdump", derive(Codegen))]173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]174#[derive(Debug, Clone, PartialEq, Trace)]175pub struct ParamsDesc(pub Rc<Vec<Param>>);176177impl Deref for ParamsDesc {178 type Target = Vec<Param>;179 fn deref(&self) -> &Self::Target {180 &self.0181 }182}183184#[cfg_attr(feature = "structdump", derive(Codegen))]185#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]186#[derive(Debug, PartialEq, Trace)]187pub struct ArgsDesc {188 pub unnamed: Vec<LocExpr>,189 pub named: Vec<(IStr, LocExpr)>,190}191impl ArgsDesc {192 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {193 Self { unnamed, named }194 }195}196197#[cfg_attr(feature = "structdump", derive(Codegen))]198#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]199#[derive(Debug, Clone, PartialEq, Eq, Trace)]200pub enum DestructRest {201 202 Keep(IStr),203 204 Drop,205}206207#[cfg_attr(feature = "structdump", derive(Codegen))]208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]209#[derive(Debug, Clone, PartialEq, Trace)]210pub enum Destruct {211 Full(IStr),212 #[cfg(feature = "exp-destruct")]213 Skip,214 #[cfg(feature = "exp-destruct")]215 Array {216 start: Vec<Destruct>,217 rest: Option<DestructRest>,218 end: Vec<Destruct>,219 },220 #[cfg(feature = "exp-destruct")]221 Object {222 fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,223 rest: Option<DestructRest>,224 },225}226impl Destruct {227 228 pub fn name(&self) -> Option<IStr> {229 match self {230 Self::Full(name) => Some(name.clone()),231 #[cfg(feature = "exp-destruct")]232 _ => None,233 }234 }235 pub fn capacity_hint(&self) -> usize {236 #[cfg(feature = "exp-destruct")]237 fn cap_rest(rest: &Option<DestructRest>) -> usize {238 match rest {239 Some(DestructRest::Keep(_)) => 1,240 Some(DestructRest::Drop) => 0,241 None => 0,242 }243 }244 match self {245 Self::Full(_) => 1,246 #[cfg(feature = "exp-destruct")]247 Self::Skip => 0,248 #[cfg(feature = "exp-destruct")]249 Self::Array { start, rest, end } => {250 start.iter().map(Destruct::capacity_hint).sum::<usize>()251 + end.iter().map(Destruct::capacity_hint).sum::<usize>()252 + cap_rest(rest)253 }254 #[cfg(feature = "exp-destruct")]255 Self::Object { fields, rest } => {256 let mut out = 0;257 for (_, into, _) in fields {258 match into {259 Some(v) => out += v.capacity_hint(),260 261 None => out += 1,262 }263 }264 out + cap_rest(rest)265 }266 }267 }268}269270#[cfg_attr(feature = "structdump", derive(Codegen))]271#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]272#[derive(Debug, Clone, PartialEq, Trace)]273pub enum BindSpec {274 Field {275 into: Destruct,276 value: LocExpr,277 },278 Function {279 name: IStr,280 params: ParamsDesc,281 value: LocExpr,282 },283}284impl BindSpec {285 pub fn capacity_hint(&self) -> usize {286 match self {287 BindSpec::Field { into, .. } => into.capacity_hint(),288 BindSpec::Function { .. } => 1,289 }290 }291}292293#[cfg_attr(feature = "structdump", derive(Codegen))]294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]295#[derive(Debug, PartialEq, Trace)]296pub struct IfSpecData(pub LocExpr);297298#[cfg_attr(feature = "structdump", derive(Codegen))]299#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]300#[derive(Debug, PartialEq, Trace)]301pub struct ForSpecData(pub Destruct, pub LocExpr);302303#[cfg_attr(feature = "structdump", derive(Codegen))]304#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]305#[derive(Debug, PartialEq, Trace)]306pub enum CompSpec {307 IfSpec(IfSpecData),308 ForSpec(ForSpecData),309}310311#[cfg_attr(feature = "structdump", derive(Codegen))]312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]313#[derive(Debug, PartialEq, Trace)]314pub struct ObjComp {315 pub pre_locals: Vec<BindSpec>,316 pub field: FieldMember,317 pub post_locals: Vec<BindSpec>,318 pub compspecs: Vec<CompSpec>,319}320321#[cfg_attr(feature = "structdump", derive(Codegen))]322#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]323#[derive(Debug, PartialEq, Trace)]324pub enum ObjBody {325 MemberList(Vec<Member>),326 ObjComp(ObjComp),327}328329#[cfg_attr(feature = "structdump", derive(Codegen))]330#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]331#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]332pub enum LiteralType {333 This,334 Super,335 Dollar,336 Null,337 True,338 False,339}340341#[cfg_attr(feature = "structdump", derive(Codegen))]342#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]343#[derive(Debug, PartialEq, Trace)]344pub struct SliceDesc {345 pub start: Option<LocExpr>,346 pub end: Option<LocExpr>,347 pub step: Option<LocExpr>,348}349350351#[cfg_attr(feature = "structdump", derive(Codegen))]352#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]353#[derive(Debug, PartialEq, Trace)]354pub enum Expr {355 Literal(LiteralType),356357 358 Str(IStr),359 360 Num(f64),361 362 Var(IStr),363364 365 Arr(Vec<LocExpr>),366 367 368 369 370 371 372 373 374 375 376 377 ArrComp(LocExpr, Vec<CompSpec>),378379 380 Obj(ObjBody),381 382 ObjExtend(LocExpr, ObjBody),383384 385 Parened(LocExpr),386387 388 UnaryOp(UnaryOpType, LocExpr),389 390 BinaryOp(LocExpr, BinaryOpType, LocExpr),391 392 AssertExpr(AssertStmt, LocExpr),393 394 LocalExpr(Vec<BindSpec>, LocExpr),395396 397 Import(LocExpr),398 399 ImportStr(LocExpr),400 401 ImportBin(LocExpr),402 403 ErrorStmt(LocExpr),404 405 Apply(LocExpr, ArgsDesc, bool),406 407 Index {408 indexable: LocExpr,409 index: LocExpr,410 #[cfg(feature = "exp-null-coaelse")]411 null_coaelse: bool,412 },413 414 Function(ParamsDesc, LocExpr),415 416 IfElse {417 cond: IfSpecData,418 cond_then: LocExpr,419 cond_else: Option<LocExpr>,420 },421 Slice(LocExpr, SliceDesc),422}423424425#[cfg_attr(feature = "structdump", derive(Codegen))]426#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]427#[derive(Clone, PartialEq, Eq, Trace)]428#[trace(skip)]429#[repr(C)]430pub struct ExprLocation(pub Source, pub u32, pub u32);431impl ExprLocation {432 pub fn belongs_to(&self, other: &ExprLocation) -> bool {433 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2434 }435}436437#[cfg(target_pointer_width = "64")]438static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);439440impl Debug for ExprLocation {441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {442 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)443 }444}445446447#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]448#[cfg_attr(feature = "structdump", derive(Codegen))]449#[derive(Clone, PartialEq, Trace)]450pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);451452#[cfg(target_pointer_width = "64")]453static_assertions::assert_eq_size!(LocExpr, [u8; 24]);454455impl Debug for LocExpr {456 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {457 if f.alternate() {458 write!(f, "{:#?}", self.0)?;459 } else {460 write!(f, "{:?}", self.0)?;461 }462 write!(f, " from {:?}", self.1)?;463 Ok(())464 }465}