1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Acyclic;8use jrsonnet_interner::IStr;910use crate::{11 function::{FunctionSignature, ParamDefault, ParamName, ParamParse},12 source::Source,13};1415#[derive(Debug, PartialEq, Acyclic)]16pub enum FieldName {17 18 Fixed(IStr),19 20 Dyn(Spanned<Expr>),21}2223#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]24#[repr(u8)]25pub enum Visibility {26 27 Normal,28 29 Hidden,30 31 Unhide,32}3334impl Visibility {35 pub fn is_visible(&self) -> bool {36 matches!(self, Self::Normal | Self::Unhide)37 }38}3940#[derive(Debug, PartialEq, Acyclic)]41pub struct AssertStmt(pub Spanned<Expr>, pub Option<Spanned<Expr>>);4243#[derive(Debug, PartialEq, Acyclic)]44pub struct FieldMember {45 pub name: FieldName,46 pub plus: bool,47 pub params: Option<ExprParams>,48 pub visibility: Visibility,49 pub value: Rc<Spanned<Expr>>,50}5152#[derive(Debug, PartialEq, Acyclic)]53pub(crate) enum Member {54 Field(FieldMember),55 BindStmt(BindSpec),56 AssertStmt(AssertStmt),57}5859#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]60pub enum UnaryOpType {61 Plus,62 Minus,63 BitNot,64 Not,65}6667impl Display for UnaryOpType {68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {69 use UnaryOpType::*;70 write!(71 f,72 "{}",73 match self {74 Plus => "+",75 Minus => "-",76 BitNot => "~",77 Not => "!",78 }79 )80 }81}8283#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]84pub enum BinaryOpType {85 Mul,86 Div,8788 89 Mod,9091 Add,92 Sub,9394 Lhs,95 Rhs,9697 Lt,98 Gt,99 Lte,100 Gte,101102 BitAnd,103 BitOr,104 BitXor,105106 Eq,107 Neq,108109 And,110 Or,111 #[cfg(feature = "exp-null-coaelse")]112 NullCoaelse,113114 115 In,116}117118impl Display for BinaryOpType {119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {120 use BinaryOpType::*;121 write!(122 f,123 "{}",124 match self {125 Mul => "*",126 Div => "/",127 Mod => "%",128 Add => "+",129 Sub => "-",130 Lhs => "<<",131 Rhs => ">>",132 Lt => "<",133 Gt => ">",134 Lte => "<=",135 Gte => ">=",136 BitAnd => "&",137 BitOr => "|",138 BitXor => "^",139 Eq => "==",140 Neq => "!=",141 And => "&&",142 Or => "||",143 In => "in",144 #[cfg(feature = "exp-null-coaelse")]145 NullCoaelse => "??",146 }147 )148 }149}150151152#[derive(Debug, PartialEq, Acyclic)]153pub struct ExprParam {154 pub destruct: Destruct,155 pub default: Option<Rc<Spanned<Expr>>>,156}157158159#[derive(Debug, Clone, PartialEq, Acyclic)]160pub struct ExprParams {161 pub exprs: Rc<Vec<ExprParam>>,162 pub signature: FunctionSignature,163 binds_len: usize,164}165impl ExprParams {166 pub fn len(&self) -> usize {167 self.exprs.len()168 }169 pub fn is_empty(&self) -> bool {170 self.exprs.is_empty()171 }172173 pub fn binds_len(&self) -> usize {174 self.binds_len175 }176 pub fn new(exprs: Vec<ExprParam>) -> Self {177 Self {178 signature: FunctionSignature::new(179 exprs180 .iter()181 .map(|p| {182 ParamParse::new(183 p.destruct.name(),184 ParamDefault::exists(p.default.is_some()),185 )186 })187 .collect(),188 ),189 binds_len: exprs.iter().map(|v| v.destruct.binds_len()).sum(),190 exprs: Rc::new(exprs),191 }192 }193}194195#[derive(Debug, PartialEq, Acyclic)]196pub struct ArgsDesc {197 pub unnamed: Vec<Rc<Spanned<Expr>>>,198 pub named: Vec<(IStr, Rc<Spanned<Expr>>)>,199}200impl ArgsDesc {201 pub fn new(unnamed: Vec<Rc<Spanned<Expr>>>, named: Vec<(IStr, Rc<Spanned<Expr>>)>) -> Self {202 Self { unnamed, named }203 }204}205206#[derive(Debug, Clone, PartialEq, Eq, Acyclic)]207pub enum DestructRest {208 209 Keep(IStr),210 211 Drop,212}213214#[derive(Debug, Clone, PartialEq, Acyclic)]215pub enum Destruct {216 Full(IStr),217 #[cfg(feature = "exp-destruct")]218 Skip,219 #[cfg(feature = "exp-destruct")]220 Array {221 start: Vec<Destruct>,222 rest: Option<DestructRest>,223 end: Vec<Destruct>,224 },225 #[cfg(feature = "exp-destruct")]226 Object {227 fields: Vec<(IStr, Option<Destruct>, Option<Spanned<Expr>>)>,228 rest: Option<DestructRest>,229 },230}231impl Destruct {232 233 pub fn name(&self) -> ParamName {234 match self {235 Self::Full(name) => ParamName::Named(name.clone()),236 #[cfg(feature = "exp-destruct")]237 _ => ParamName::Unnamed,238 }239 }240 pub fn binds_len(&self) -> usize {241 #[cfg(feature = "exp-destruct")]242 fn cap_rest(rest: &Option<DestructRest>) -> usize {243 match rest {244 Some(DestructRest::Keep(_)) => 1,245 Some(DestructRest::Drop) => 0,246 None => 0,247 }248 }249 match self {250 Self::Full(_) => 1,251 #[cfg(feature = "exp-destruct")]252 Self::Skip => 0,253 #[cfg(feature = "exp-destruct")]254 Self::Array { start, rest, end } => {255 start.iter().map(Destruct::binds_len).sum::<usize>()256 + end.iter().map(Destruct::binds_len).sum::<usize>()257 + cap_rest(rest)258 }259 #[cfg(feature = "exp-destruct")]260 Self::Object { fields, rest } => {261 let mut out = 0;262 for (_, into, _) in fields {263 match into {264 Some(v) => out += v.capacity_hint(),265 266 None => out += 1,267 }268 }269 out + cap_rest(rest)270 }271 }272 }273}274275#[derive(Debug, PartialEq, Acyclic)]276pub enum BindSpec {277 Field {278 into: Destruct,279 value: Rc<Spanned<Expr>>,280 },281 Function {282 name: IStr,283 params: ExprParams,284 value: Rc<Spanned<Expr>>,285 },286}287impl BindSpec {288 pub fn binds_len(&self) -> usize {289 match self {290 BindSpec::Field { into, .. } => into.binds_len(),291 BindSpec::Function { .. } => 1,292 }293 }294}295296#[derive(Debug, PartialEq, Acyclic)]297pub struct IfSpecData(pub Spanned<Expr>);298299#[derive(Debug, PartialEq, Acyclic)]300pub struct ForSpecData(pub Destruct, pub Spanned<Expr>);301302#[derive(Debug, PartialEq, Acyclic)]303pub enum CompSpec {304 IfSpec(IfSpecData),305 ForSpec(ForSpecData),306}307308#[derive(Debug, PartialEq, Acyclic)]309pub struct ObjComp {310 pub locals: Rc<Vec<BindSpec>>,311 pub field: Rc<FieldMember>,312 pub compspecs: Vec<CompSpec>,313}314315#[derive(Debug, PartialEq, Acyclic)]316pub struct ObjMembers {317 pub locals: Rc<Vec<BindSpec>>,318 pub asserts: Rc<Vec<AssertStmt>>,319 pub fields: Vec<FieldMember>,320}321322#[derive(Debug, PartialEq, Acyclic)]323pub enum ObjBody {324 MemberList(ObjMembers),325 ObjComp(ObjComp),326}327328#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]329pub enum LiteralType {330 This,331 Super,332 Dollar,333 Null,334 True,335 False,336}337338#[derive(Debug, PartialEq, Acyclic)]339pub struct SliceDesc {340 pub start: Option<Spanned<Expr>>,341 pub end: Option<Spanned<Expr>>,342 pub step: Option<Spanned<Expr>>,343}344345#[derive(Debug, PartialEq, Acyclic)]346pub struct AssertExpr {347 pub assert: AssertStmt,348 pub rest: Spanned<Expr>,349}350351#[derive(Debug, PartialEq, Acyclic)]352pub struct BinaryOp {353 pub lhs: Spanned<Expr>,354 pub op: BinaryOpType,355 pub rhs: Spanned<Expr>,356}357358#[derive(Debug, PartialEq, Acyclic)]359pub enum ImportKind {360 Normal,361 Str,362 Bin,363}364365#[derive(Debug, PartialEq, Acyclic)]366pub struct IfElse {367 pub cond: IfSpecData,368 pub cond_then: Spanned<Expr>,369 pub cond_else: Option<Spanned<Expr>>,370}371372#[derive(Debug, PartialEq, Acyclic)]373pub struct Slice {374 pub value: Spanned<Expr>,375 pub slice: SliceDesc,376}377378379#[derive(Debug, PartialEq, Acyclic)]380pub enum Expr {381 Literal(LiteralType),382383 384 Str(IStr),385 386 Num(f64),387 388 Var(IStr),389390 391 Arr(Rc<Vec<Spanned<Expr>>>),392 393 394 395 396 397 398 399 400 401 402 403 ArrComp(Rc<Spanned<Expr>>, Vec<CompSpec>),404405 406 Obj(ObjBody),407 408 ObjExtend(Rc<Spanned<Expr>>, ObjBody),409410 411 UnaryOp(UnaryOpType, Box<Spanned<Expr>>),412 413 BinaryOp(Box<BinaryOp>),414 415 AssertExpr(Rc<AssertExpr>),416 417 LocalExpr(Vec<BindSpec>, Box<Spanned<Expr>>),418419 420 Import(ImportKind, Box<Spanned<Expr>>),421 422 ErrorStmt(Box<Spanned<Expr>>),423 424 Apply(Box<Spanned<Expr>>, ArgsDesc, bool),425 426 Index {427 indexable: Box<Spanned<Expr>>,428 parts: Vec<IndexPart>,429 },430 431 Function(ExprParams, Rc<Spanned<Expr>>),432 433 IfElse(Box<IfElse>),434 Slice(Box<Slice>),435}436437#[derive(Debug, PartialEq, Acyclic)]438pub struct IndexPart {439 pub value: Spanned<Expr>,440 #[cfg(feature = "exp-null-coaelse")]441 pub null_coaelse: bool,442}443444445#[derive(Clone, PartialEq, Eq, Acyclic)]446#[repr(C)]447pub struct Span(pub Source, pub u32, pub u32);448impl Span {449 pub fn belongs_to(&self, other: &Span) -> bool {450 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2451 }452}453454static_assertions::assert_eq_size!(Span, (usize, usize));455456impl Debug for Span {457 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {458 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)459 }460}461462#[derive(Clone, PartialEq, Acyclic)]463pub struct Spanned<T: Acyclic>(T, Span);464impl<T: Acyclic> Deref for Spanned<T> {465 type Target = T;466 fn deref(&self) -> &Self::Target {467 &self.0468 }469}470impl<T: Acyclic> Spanned<T> {471 #[inline]472 pub fn new(v: T, s: Span) -> Self {473 Self(v, s)474 }475 #[inline]476 pub fn span(&self) -> Span {477 self.1.clone()478 }479}480481impl<T: Debug + Acyclic> Debug for Spanned<T> {482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {483 let expr = &**self;484 if f.alternate() {485 write!(f, "{:#?}", expr)?;486 } else {487 write!(f, "{:?}", expr)?;488 }489 write!(f, " from {:?}", self.span())?;490 Ok(())491 }492}