git.delta.rocks / jrsonnet / refs/commits / 2fdeec2fa073

difftreelog

fix Span size is smaller on x32

sulvlmyoLach2026-04-04parent: #4e8e144.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth
after · crates/jrsonnet-ir/src/expr.rs
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	/// {fixed: 2}18	Fixed(IStr),19	/// {["dyn"+"amic"]: 3}20	Dyn(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: Spanned<FieldName>,46	pub plus: bool,47	pub params: Option<ExprParams>,48	pub visibility: Visibility,49	pub value: Rc<Expr>,50}5152#[derive(Debug, PartialEq, Acyclic)]53pub 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	/// Implemented as intrinsic, put here for completeness89	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	// Equialent to std.objectHasEx(a, b, true)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}150151/// name, default value152#[derive(Debug, PartialEq, Acyclic)]153pub struct ExprParam {154	pub destruct: Destruct,155	pub default: Option<Rc<Expr>>,156}157158/// Defined function parameters159#[derive(Debug, Clone, PartialEq, Acyclic)]160pub struct ExprParams {161	pub exprs: Rc<Vec<ExprParam>>,162	pub signature: FunctionSignature,163	pub(crate) 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<Expr>>,198	pub named: Vec<(IStr, Rc<Expr>)>,199}200impl ArgsDesc {201	pub fn new(unnamed: Vec<Rc<Expr>>, named: Vec<(IStr, Rc<Expr>)>) -> Self {202		Self { unnamed, named }203	}204}205206#[derive(Debug, Clone, PartialEq, Eq, Acyclic)]207pub enum DestructRest {208	/// ...rest209	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		#[allow(clippy::type_complexity)]228		fields: Vec<(IStr, Option<Destruct>, Option<Rc<Spanned<Expr>>>)>,229		rest: Option<DestructRest>,230	},231}232impl Destruct {233	/// Name of destructure, used for function parameter names234	pub fn name(&self) -> ParamName {235		match self {236			Self::Full(name) => ParamName::Named(name.clone()),237			#[cfg(feature = "exp-destruct")]238			_ => ParamName::Unnamed,239		}240	}241	pub fn binds_len(&self) -> usize {242		#[cfg(feature = "exp-destruct")]243		fn cap_rest(rest: &Option<DestructRest>) -> usize {244			match rest {245				Some(DestructRest::Keep(_)) => 1,246				Some(DestructRest::Drop) => 0,247				None => 0,248			}249		}250		match self {251			Self::Full(_) => 1,252			#[cfg(feature = "exp-destruct")]253			Self::Skip => 0,254			#[cfg(feature = "exp-destruct")]255			Self::Array { start, rest, end } => {256				start.iter().map(Destruct::binds_len).sum::<usize>()257					+ end.iter().map(Destruct::binds_len).sum::<usize>()258					+ cap_rest(rest)259			}260			#[cfg(feature = "exp-destruct")]261			Self::Object { fields, rest } => {262				let mut out = 0;263				for (_, into, _) in fields {264					match into {265						Some(v) => out += v.binds_len(),266						// Field is destructured to default name267						None => out += 1,268					}269				}270				out + cap_rest(rest)271			}272		}273	}274}275276#[derive(Debug, PartialEq, Acyclic)]277pub enum BindSpec {278	Field {279		into: Destruct,280		value: Rc<Expr>,281	},282	Function {283		name: IStr,284		params: ExprParams,285		value: Rc<Expr>,286	},287}288impl BindSpec {289	pub fn binds_len(&self) -> usize {290		match self {291			BindSpec::Field { into, .. } => into.binds_len(),292			BindSpec::Function { .. } => 1,293		}294	}295}296297#[derive(Debug, PartialEq, Acyclic)]298pub struct IfSpecData {299	pub span: Span,300	pub cond: Expr,301}302303#[derive(Debug, PartialEq, Acyclic)]304pub struct ForSpecData {305	pub destruct: Destruct,306	pub over: Expr,307}308309#[derive(Debug, PartialEq, Acyclic)]310pub enum CompSpec {311	IfSpec(IfSpecData),312	ForSpec(ForSpecData),313}314315#[derive(Debug, PartialEq, Acyclic)]316pub struct ObjComp {317	pub locals: Rc<Vec<BindSpec>>,318	pub field: Rc<FieldMember>,319	pub compspecs: Vec<CompSpec>,320}321322#[derive(Debug, PartialEq, Acyclic)]323pub struct ObjMembers {324	pub locals: Rc<Vec<BindSpec>>,325	pub asserts: Rc<Vec<AssertStmt>>,326	pub fields: Vec<FieldMember>,327}328329#[derive(Debug, PartialEq, Acyclic)]330pub enum ObjBody {331	MemberList(ObjMembers),332	ObjComp(ObjComp),333}334335#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]336pub enum LiteralType {337	This,338	Super,339	Dollar,340	Null,341	True,342	False,343}344345#[derive(Debug, PartialEq, Acyclic)]346pub struct SliceDesc {347	pub start: Option<Spanned<Expr>>,348	pub end: Option<Spanned<Expr>>,349	pub step: Option<Spanned<Expr>>,350}351352#[derive(Debug, PartialEq, Acyclic)]353pub struct AssertExpr {354	pub assert: AssertStmt,355	pub rest: Expr,356}357358#[derive(Debug, PartialEq, Acyclic)]359pub struct BinaryOp {360	pub lhs: Expr,361	pub op: BinaryOpType,362	pub rhs: Expr,363}364365#[derive(Debug, PartialEq, Acyclic)]366pub enum ImportKind {367	Normal,368	Str,369	Bin,370}371372#[derive(Debug, PartialEq, Acyclic)]373pub struct IfElse {374	pub cond: IfSpecData,375	pub cond_then: Expr,376	pub cond_else: Option<Expr>,377}378379#[derive(Debug, PartialEq, Acyclic)]380pub struct Slice {381	pub value: Expr,382	pub slice: SliceDesc,383}384385/// Syntax base386#[derive(Debug, PartialEq, Acyclic)]387pub enum Expr {388	Literal(LiteralType),389390	/// String value: "hello"391	Str(IStr),392	/// Number: 1, 2.0, 2e+20393	Num(f64),394	/// Variable name: test395	Var(Spanned<IStr>),396397	/// Array of expressions: [1, 2, "Hello"]398	Arr(Rc<Vec<Expr>>),399	/// Array comprehension:400	/// ```jsonnet401	///  ingredients: [402	///    { kind: kind, qty: 4 / 3 }403	///    for kind in [404	///      'Honey Syrup',405	///      'Lemon Juice',406	///      'Farmers Gin',407	///    ]408	///  ],409	/// ```410	ArrComp(Rc<Expr>, Vec<CompSpec>),411412	/// Object: {a: 2}413	Obj(ObjBody),414	/// Object extension: var1 {b: 2}415	ObjExtend(Rc<Expr>, ObjBody),416417	/// -2418	UnaryOp(UnaryOpType, Box<Expr>),419	/// 2 - 2420	BinaryOp(Box<BinaryOp>),421	/// assert 2 == 2 : "Math is broken"422	AssertExpr(Rc<AssertExpr>),423	/// local a = 2; { b: a }424	LocalExpr(Vec<BindSpec>, Box<Expr>),425426	/// import* "hello"427	Import(Spanned<ImportKind>, Box<Expr>),428	/// error "I'm broken"429	ErrorStmt(Span, Box<Expr>),430	/// a(b, c)431	Apply(Box<Expr>, Spanned<ArgsDesc>, bool),432	/// a[b], a.b, a?.b433	Index {434		indexable: Box<Expr>,435		parts: Vec<IndexPart>,436	},437	/// function(x) x438	Function(ExprParams, Rc<Expr>),439	/// if true == false then 1 else 2440	IfElse(Box<IfElse>),441	Slice(Box<Slice>),442}443444#[derive(Debug, PartialEq, Acyclic)]445pub struct IndexPart {446	pub span: Span,447	pub value: Expr,448	#[cfg(feature = "exp-null-coaelse")]449	pub null_coaelse: bool,450}451452/// file, begin offset, end offset453#[derive(Clone, PartialEq, Eq, Acyclic)]454#[repr(C)]455pub struct Span(pub Source, pub u32, pub u32);456impl Span {457	pub fn belongs_to(&self, other: &Span) -> bool {458		other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2459	}460}461462#[cfg(target_pointer_width = "64")]463static_assertions::assert_eq_size!(Span, (usize, usize));464465impl Debug for Span {466	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {467		write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)468	}469}470471#[derive(Clone, PartialEq, Acyclic)]472pub struct Spanned<T: Acyclic> {473	pub value: T,474	pub span: Span,475}476impl<T: Acyclic> Deref for Spanned<T> {477	type Target = T;478	fn deref(&self) -> &Self::Target {479		&self.value480	}481}482impl<T: Acyclic> Spanned<T> {483	#[inline]484	pub fn new(value: T, span: Span) -> Self {485		Self { value, span }486	}487}488489impl<T: Debug + Acyclic> Debug for Spanned<T> {490	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {491		let expr = &**self;492		if f.alternate() {493			write!(f, "{:#?}", expr)?;494		} else {495			write!(f, "{:?}", expr)?;496		}497		write!(f, " from {:?}", self.span)?;498		Ok(())499	}500}