git.delta.rocks / jrsonnet / refs/commits / 31f2b649c192

difftreelog

source

crates/jrsonnet-parser/src/expr.rs8.9 KiBsourcehistory
1use jrsonnet_gc::{unsafe_empty_trace, Finalize, Trace};2use jrsonnet_interner::IStr;3#[cfg(feature = "deserialize")]4use serde::Deserialize;5#[cfg(feature = "serialize")]6use serde::Serialize;7use std::{8	fmt::{Debug, Display},9	ops::Deref,10	path::{Path, PathBuf},11	rc::Rc,12};1314#[cfg_attr(feature = "serialize", derive(Serialize))]15#[cfg_attr(feature = "deserialize", derive(Deserialize))]16#[derive(Debug, PartialEq, Trace)]17#[trivially_drop]18pub enum FieldName {19	/// {fixed: 2}20	Fixed(IStr),21	/// {["dyn"+"amic"]: 3}22	Dyn(LocExpr),23}2425#[cfg_attr(feature = "serialize", derive(Serialize))]26#[cfg_attr(feature = "deserialize", derive(Deserialize))]27#[derive(Debug, Clone, Copy, PartialEq, Trace)]28#[trivially_drop]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 = "serialize", derive(Serialize))]45#[cfg_attr(feature = "deserialize", derive(Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47#[trivially_drop]48pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4950#[cfg_attr(feature = "serialize", derive(Serialize))]51#[cfg_attr(feature = "deserialize", derive(Deserialize))]52#[derive(Debug, PartialEq, Trace)]53#[trivially_drop]54pub struct FieldMember {55	pub name: FieldName,56	pub plus: bool,57	pub params: Option<ParamsDesc>,58	pub visibility: Visibility,59	pub value: LocExpr,60}6162#[cfg_attr(feature = "serialize", derive(Serialize))]63#[cfg_attr(feature = "deserialize", derive(Deserialize))]64#[derive(Debug, PartialEq, Trace)]65#[trivially_drop]66pub enum Member {67	Field(FieldMember),68	BindStmt(BindSpec),69	AssertStmt(AssertStmt),70}7172#[cfg_attr(feature = "serialize", derive(Serialize))]73#[cfg_attr(feature = "deserialize", derive(Deserialize))]74#[derive(Debug, Clone, Copy, PartialEq, Trace)]75#[trivially_drop]76pub enum UnaryOpType {77	Plus,78	Minus,79	BitNot,80	Not,81}8283impl Display for UnaryOpType {84	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {85		use UnaryOpType::*;86		write!(87			f,88			"{}",89			match self {90				Plus => "+",91				Minus => "-",92				BitNot => "~",93				Not => "!",94			}95		)96	}97}9899#[cfg_attr(feature = "serialize", derive(Serialize))]100#[cfg_attr(feature = "deserialize", derive(Deserialize))]101#[derive(Debug, Clone, Copy, PartialEq, Trace)]102#[trivially_drop]103pub enum BinaryOpType {104	Mul,105	Div,106107	/// Implemented as intrinsic, put here for completeness108	Mod,109110	Add,111	Sub,112113	Lhs,114	Rhs,115116	Lt,117	Gt,118	Lte,119	Gte,120121	BitAnd,122	BitOr,123	BitXor,124125	Eq,126	Neq,127128	And,129	Or,130131	// Equialent to std.objectHasEx(a, b, true)132	In,133}134135impl Display for BinaryOpType {136	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {137		use BinaryOpType::*;138		write!(139			f,140			"{}",141			match self {142				Mul => "*",143				Div => "/",144				Mod => "%",145				Add => "+",146				Sub => "-",147				Lhs => "<<",148				Rhs => ">>",149				Lt => "<",150				Gt => ">",151				Lte => "<=",152				Gte => ">=",153				BitAnd => "&",154				BitOr => "|",155				BitXor => "^",156				Eq => "==",157				Neq => "!=",158				And => "&&",159				Or => "||",160				In => "in",161			}162		)163	}164}165166/// name, default value167#[cfg_attr(feature = "serialize", derive(Serialize))]168#[cfg_attr(feature = "deserialize", derive(Deserialize))]169#[derive(Debug, PartialEq, Trace)]170#[trivially_drop]171pub struct Param(pub IStr, pub Option<LocExpr>);172173/// Defined function parameters174#[cfg_attr(feature = "serialize", derive(Serialize))]175#[cfg_attr(feature = "deserialize", derive(Deserialize))]176#[derive(Debug, Clone, PartialEq)]177pub struct ParamsDesc(pub Rc<Vec<Param>>);178179/// Safety:180/// AST is acyclic, and there should be no gc pointers181unsafe impl Trace for ParamsDesc {182	unsafe_empty_trace!();183}184impl Finalize for ParamsDesc {}185186impl Deref for ParamsDesc {187	type Target = Vec<Param>;188	fn deref(&self) -> &Self::Target {189		&self.0190	}191}192193#[cfg_attr(feature = "serialize", derive(Serialize))]194#[cfg_attr(feature = "deserialize", derive(Deserialize))]195#[derive(Debug, PartialEq, Trace)]196#[trivially_drop]197pub struct ArgsDesc {198	pub unnamed: Vec<LocExpr>,199	pub named: Vec<(IStr, LocExpr)>,200}201impl ArgsDesc {202	pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {203		Self { unnamed, named }204	}205}206207#[cfg_attr(feature = "serialize", derive(Serialize))]208#[cfg_attr(feature = "deserialize", derive(Deserialize))]209#[derive(Debug, Clone, PartialEq, Trace)]210#[trivially_drop]211pub struct BindSpec {212	pub name: IStr,213	pub params: Option<ParamsDesc>,214	pub value: LocExpr,215}216217#[cfg_attr(feature = "serialize", derive(Serialize))]218#[cfg_attr(feature = "deserialize", derive(Deserialize))]219#[derive(Debug, PartialEq, Trace)]220#[trivially_drop]221pub struct IfSpecData(pub LocExpr);222223#[cfg_attr(feature = "serialize", derive(Serialize))]224#[cfg_attr(feature = "deserialize", derive(Deserialize))]225#[derive(Debug, PartialEq, Trace)]226#[trivially_drop]227pub struct ForSpecData(pub IStr, pub LocExpr);228229#[cfg_attr(feature = "serialize", derive(Serialize))]230#[cfg_attr(feature = "deserialize", derive(Deserialize))]231#[derive(Debug, PartialEq, Trace)]232#[trivially_drop]233pub enum CompSpec {234	IfSpec(IfSpecData),235	ForSpec(ForSpecData),236}237238#[cfg_attr(feature = "serialize", derive(Serialize))]239#[cfg_attr(feature = "deserialize", derive(Deserialize))]240#[derive(Debug, PartialEq, Trace)]241#[trivially_drop]242pub struct ObjComp {243	pub pre_locals: Vec<BindSpec>,244	pub key: LocExpr,245	pub plus: bool,246	pub value: LocExpr,247	pub post_locals: Vec<BindSpec>,248	pub compspecs: Vec<CompSpec>,249}250251#[cfg_attr(feature = "serialize", derive(Serialize))]252#[cfg_attr(feature = "deserialize", derive(Deserialize))]253#[derive(Debug, PartialEq, Trace)]254#[trivially_drop]255pub enum ObjBody {256	MemberList(Vec<Member>),257	ObjComp(ObjComp),258}259260#[cfg_attr(feature = "serialize", derive(Serialize))]261#[cfg_attr(feature = "deserialize", derive(Deserialize))]262#[derive(Debug, PartialEq, Clone, Copy, Trace)]263#[trivially_drop]264pub enum LiteralType {265	This,266	Super,267	Dollar,268	Null,269	True,270	False,271}272273#[cfg_attr(feature = "serialize", derive(Serialize))]274#[cfg_attr(feature = "deserialize", derive(Deserialize))]275#[derive(Debug, PartialEq, Trace)]276#[trivially_drop]277pub struct SliceDesc {278	pub start: Option<LocExpr>,279	pub end: Option<LocExpr>,280	pub step: Option<LocExpr>,281}282283/// Syntax base284#[cfg_attr(feature = "serialize", derive(Serialize))]285#[cfg_attr(feature = "deserialize", derive(Deserialize))]286#[derive(Debug, PartialEq, Trace)]287#[trivially_drop]288pub enum Expr {289	Literal(LiteralType),290291	/// String value: "hello"292	Str(IStr),293	/// Number: 1, 2.0, 2e+20294	Num(f64),295	/// Variable name: test296	Var(IStr),297298	/// Array of expressions: [1, 2, "Hello"]299	Arr(Vec<LocExpr>),300	/// Array comprehension:301	/// ```jsonnet302	///  ingredients: [303	///    { kind: kind, qty: 4 / 3 }304	///    for kind in [305	///      'Honey Syrup',306	///      'Lemon Juice',307	///      'Farmers Gin',308	///    ]309	///  ],310	/// ```311	ArrComp(LocExpr, Vec<CompSpec>),312313	/// Object: {a: 2}314	Obj(ObjBody),315	/// Object extension: var1 {b: 2}316	ObjExtend(LocExpr, ObjBody),317318	/// (obj)319	Parened(LocExpr),320321	/// -2322	UnaryOp(UnaryOpType, LocExpr),323	/// 2 - 2324	BinaryOp(LocExpr, BinaryOpType, LocExpr),325	/// assert 2 == 2 : "Math is broken"326	AssertExpr(AssertStmt, LocExpr),327	/// local a = 2; { b: a }328	LocalExpr(Vec<BindSpec>, LocExpr),329330	/// import "hello"331	Import(PathBuf),332	/// importStr "file.txt"333	ImportStr(PathBuf),334	/// error "I'm broken"335	ErrorStmt(LocExpr),336	/// a(b, c)337	Apply(LocExpr, ArgsDesc, bool),338	/// a[b]339	Index(LocExpr, LocExpr),340	/// function(x) x341	Function(ParamsDesc, LocExpr),342	/// std.primitiveEquals343	Intrinsic(IStr),344	/// if true == false then 1 else 2345	IfElse {346		cond: IfSpecData,347		cond_then: LocExpr,348		cond_else: Option<LocExpr>,349	},350	Slice(LocExpr, SliceDesc),351}352353/// file, begin offset, end offset354#[cfg_attr(feature = "serialize", derive(Serialize))]355#[cfg_attr(feature = "deserialize", derive(Deserialize))]356#[derive(Clone, PartialEq, Trace)]357#[trivially_drop]358pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);359360impl Debug for ExprLocation {361	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {362		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)363	}364}365366/// Holds AST expression and its location in source file367#[cfg_attr(feature = "serialize", derive(Serialize))]368#[cfg_attr(feature = "deserialize", derive(Deserialize))]369#[derive(Clone, PartialEq)]370pub struct LocExpr(pub Rc<Expr>, pub Option<ExprLocation>);371/// Safety:372/// AST is acyclic, and there should be no gc pointers373unsafe impl Trace for LocExpr {374	unsafe_empty_trace!();375}376impl Finalize for LocExpr {}377378impl Debug for LocExpr {379	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {380		if f.alternate() {381			write!(f, "{:#?}", self.0)?;382		} else {383			write!(f, "{:?}", self.0)?;384		}385		if let Some(loc) = &self.1 {386			write!(f, " from {:?}", loc)?;387		}388		Ok(())389	}390}391392/// Creates LocExpr from Expr and ExprLocation components393#[macro_export]394macro_rules! loc_expr {395	($expr:expr, $need_loc:expr,($name:expr, $start:expr, $end:expr)) => {396		LocExpr(397			std::rc::Rc::new($expr),398			if $need_loc {399				Some(ExprLocation($name, $start, $end))400			} else {401				None402			},403		)404	};405}