git.delta.rocks / jrsonnet / refs/commits / e87511f456de

difftreelog

feat immutable obj core list

mnxzylovYaroslav Bolyukin2026-04-25parent: #5fc1275.patch.diff
in: master

7 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -163,6 +163,15 @@
 checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
 
 [[package]]
+name = "bitmaps"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
 name = "block-buffer"
 version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -682,6 +691,20 @@
 checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
 
 [[package]]
+name = "im-rc"
+version = "15.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
+dependencies = [
+ "bitmaps",
+ "rand_core 0.6.4",
+ "rand_xoshiro",
+ "sized-chunks",
+ "typenum",
+ "version_check",
+]
+
+[[package]]
 name = "indexmap"
 version = "2.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -793,6 +816,7 @@
  "anyhow",
  "educe",
  "hi-doc",
+ "im-rc",
  "jrsonnet-gcmodule",
  "jrsonnet-interner",
  "jrsonnet-ir",
@@ -837,18 +861,19 @@
 
 [[package]]
 name = "jrsonnet-gcmodule"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f95b976a79e4000bb9e07ff0709dca0ea27bcf1952d4c17d91fb7364d6145683"
+checksum = "8a6a63a6e55ba82764e483d7f8a181f25db95a8f25da8ae6520e95a5fe39c6a6"
 dependencies = [
+ "im-rc",
  "jrsonnet-gcmodule-derive",
 ]
 
 [[package]]
 name = "jrsonnet-gcmodule-derive"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d928626220a310ff0cec815e80cf7fe104697184352ca21c40534e0b0d72d9"
+checksum = "095fe3c4c0acf32de80205a8a479ef63c216b9efb0024dec9eb7fe1c5ef1f1a1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1319,7 +1344,7 @@
 checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
 dependencies = [
  "rand_chacha",
- "rand_core",
+ "rand_core 0.9.5",
 ]
 
 [[package]]
@@ -1329,11 +1354,17 @@
 checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
 dependencies = [
  "ppv-lite86",
- "rand_core",
+ "rand_core 0.9.5",
 ]
 
 [[package]]
 name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
+[[package]]
+name = "rand_core"
 version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
@@ -1342,6 +1373,15 @@
 ]
 
 [[package]]
+name = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
 name = "random_color"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1587,6 +1627,16 @@
 checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
 
 [[package]]
+name = "sized-chunks"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
+dependencies = [
+ "bitmaps",
+ "typenum",
+]
+
+[[package]]
 name = "smallvec"
 version = "1.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
modifiedCargo.tomldiffbeforeafterboth
after · Cargo.toml
1[workspace]2members = ["crates/*", "bindings/jsonnet", "cmds/*", "tests", "xtask"]3default-members = ["cmds/jrsonnet"]4resolver = "2"56[workspace.package]7authors = ["Yaroslav Bolyukin <iam@lach.pw>"]8edition = "2021"9license = "MIT"10repository = "https://github.com/CertainLach/jrsonnet"11version = "0.5.0-pre98"1213[workspace.dependencies]14jrsonnet-evaluator = { path = "./crates/jrsonnet-evaluator", version = "0.5.0-pre98" }15jrsonnet-macros = { path = "./crates/jrsonnet-macros", version = "0.5.0-pre98" }16jrsonnet-ir = { path = "./crates/jrsonnet-ir", version = "0.5.0-pre98" }17jrsonnet-ir-parser = { path = "./crates/jrsonnet-ir-parser", version = "0.5.0-pre98" }18jrsonnet-peg-parser = { path = "./crates/jrsonnet-peg-parser", version = "0.5.0-pre98" }19jrsonnet-rowan-parser = { path = "./crates/jrsonnet-rowan-parser", version = "0.5.0-pre98" }20jrsonnet-interner = { path = "./crates/jrsonnet-interner", version = "0.5.0-pre98" }21jrsonnet-stdlib = { path = "./crates/jrsonnet-stdlib", version = "0.5.0-pre98" }22jrsonnet-cli = { path = "./crates/jrsonnet-cli", version = "0.5.0-pre98" }23jrsonnet-types = { path = "./crates/jrsonnet-types", version = "0.5.0-pre98" }24jrsonnet-formatter = { path = "./crates/jrsonnet-formatter", version = "0.5.0-pre98" }25jrsonnet-gcmodule = { version = "0.4.3", features = ["im-rc"] }26# Diagnostics.27# hi-doc is my library, which handles text formatting very well, but isn't polished enough yet28# Previous implementation was based on annotate-snippets, which I don't like for many reasons.29#30# I'm against using miette, because I want to reuse data between interpreter and annotations, yet miette31#   and other libraries want to handle spans etc by itself, which is okay for compiler diagnostics, but is32#   bad for interpreter, where interpreter and parser are paired much closer.33hi-doc = "0.3.0"34annotate-snippets = "0.12.11"3536# CLI37clap = "4.5"38clap_complete = "4.5"3940# Parsing, manifestification is implemented manually everywhere41serde = "1.0.228"42serde_json = "1.0.149"43serde-saphyr = { version = "0.0.17", default-features = false }4445# Error handling46anyhow = "1.0.101"47thiserror = "2.0.18"4849# Code formatting50dprint-core = "0.67.4"5152# Stdlib hashing functions53md5 = "0.8.0"54sha1 = "0.10.6"55sha2 = "0.10.9"56sha3 = "0.10.8"5758# Source code parsing.59# Jrsonnet has two parsers for jsonnet - one is for execution, and another is for better parsing diagnostics/lints/LSP.60# First (and fast one) is based on peg, second is based on rowan.61peg = "0.8.5"62logos = "0.16.1"63ungrammar = "1.16.1"64rowan = "0.16.1"6566mimallocator = "0.1.3"67indoc = "2.0"68tempfile = "3.24"69pathdiff = "0.2.3"70hashbrown = "0.16.1"71static_assertions = "1.1"72rustc-hash = "2.1"73num-bigint = "0.4.6"74strsim = "0.11.1"75proc-macro2 = "1.0"76quote = "1.0"77syn = "2.0"78drop_bomb = "0.1.5"79base64 = "0.22.1"80indexmap = "2.13.0"81itertools = "0.14.0"82xshell = "0.2.7"8384regex = "1.12"85lru = "0.16.3"8687syn-dissect-closure = "0.1.0"8889# Tests/benchmarks90insta = { version = "1.46", features = ["glob"] }91criterion = { version = "0.8" }9293[workspace.lints.rust]94unsafe_op_in_unsafe_fn = "deny"9596# TODO: add docs everywhere97# missing_doc = "warn"9899elided_lifetimes_in_paths = "allow"100explicit_outlives_requirements = "allow"101noop_method_call = "allow"102single_use_lifetimes = "allow"103variant_size_differences = "allow"104macro_expanded_macro_exports_accessed_by_absolute_paths = "allow"105106[workspace.lints.rustdoc]107all = "warn"108109[workspace.lints.clippy]110all = { level = "warn", priority = -1 }111nursery = { level = "warn", priority = -1 }112pedantic = { level = "warn", priority = -1 }113114ptr_arg = "allow"115# Too verbose116must_use_candidate = "allow"117# A lot of functions pass around errors thrown by code118missing_errors_doc = "allow"119# A lot of pointers have interior Rc120needless_pass_by_value = "allow"121# Its fine122wildcard_imports = "allow"123enum_glob_use = "allow"124module_name_repetitions = "allow"125# False positives126# https://github.com/rust-lang/rust-clippy/issues/6902127use_self = "allow"128# https://github.com/rust-lang/rust-clippy/issues/8539129iter_with_drain = "allow"130type_repetition_in_bounds = "allow"131# ci is being run with nightly, but library should work on stable132missing_const_for_fn = "allow"133# too many false-positives with .expect() calls134missing_panics_doc = "allow"135# false positive for IStr type. There is an configuration option for136# such cases, but it doesn't work:137# https://github.com/rust-lang/rust-clippy/issues/9801138mutable_key_type = "allow"139# false positives140redundant_pub_crate = "allow"141# Sometimes code is fancier without that142manual_let_else = "allow"143# Something is broken about that lint, can't be allowed for144# codegenerated-stdlib block145similar_names = "allow"146147#[profile.test]148#opt-level = 1149150[profile.release]151opt-level = 3152lto = "fat"153codegen-units = 1154debug = 0155panic = "abort"156strip = true157158[profile.releasedebug]159inherits = "release"160debug = 2161panic = "unwind"162strip = false
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/Cargo.toml
+++ b/crates/jrsonnet-evaluator/Cargo.toml
@@ -76,6 +76,7 @@
   "Hash",
   "PartialEq",
 ] }
+im-rc = "15.1.0"
 
 [build-dependencies]
 rustversion = "1.0.22"
modifiedcrates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -144,9 +144,7 @@
 						Thunk!(move || {
 							let full = full.evaluate()?;
 							let mut builder = ObjValueBuilder::new();
-							builder
-								.reserve_cores(1)
-								.extend_with_core(full.as_standalone());
+							builder.extend_with_core(full.as_standalone());
 							builder.with_fields_omitted(captured_fields);
 							Ok(Val::Obj(builder.build()))
 						}),
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -410,7 +410,7 @@
 			let locals = obj.locals.clone();
 			evaluate_comp(ctx, &obj.compspecs, 0, &mut |ctx, reserve| {
 				let uctx = evaluate_object_locals(ctx.clone(), locals.clone());
-				builder.reserve_cores(reserve);
+				builder.reserve_fields(reserve);
 
 				evaluate_field_member(&mut builder, ctx, uctx, &obj.field)
 			})?;
modifiedcrates/jrsonnet-evaluator/src/obj/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/obj/mod.rs
+++ b/crates/jrsonnet-evaluator/src/obj/mod.rs
@@ -11,6 +11,7 @@
 };
 
 use educe::Educe;
+use im_rc::{Vector, vector};
 use jrsonnet_gcmodule::{Acyclic, Cc, Trace, Weak, cc_dyn};
 use jrsonnet_interner::IStr;
 use jrsonnet_ir::Span;
@@ -235,10 +236,11 @@
 	CcObjectCore, ObjectCore,
 	pub fn new() {...}
 );
+
 #[derive(Trace, Educe)]
 #[educe(Debug)]
 struct ObjValueInner {
-	cores: Vec<CcObjectCore>,
+	cores: Vector<CcObjectCore>,
 	assertions_ran: Cell<bool>,
 	has_assertions: bool,
 	value_cache: RefCell<FxHashMap<(IStr, CoreIdx), CacheValue>>,
@@ -266,7 +268,7 @@
 
 thread_local! {
 	static EMPTY_OBJ: ObjValue = ObjValue(Cc::new(ObjValueInner {
-		cores: vec![],
+		cores: vector![],
 		assertions_ran: Cell::new(true),
 		has_assertions: false,
 		value_cache: RefCell::default(),
@@ -428,7 +430,7 @@
 			bail!(NoSuperFound)
 		}
 		let mut out = ObjValue::builder();
-		out.reserve_cores(1).extend_with_core(StandaloneSuperCore {
+		out.extend_with_core(StandaloneSuperCore {
 			sup: self.sup,
 			this: self.this.clone(),
 		});
@@ -484,9 +486,7 @@
 
 	#[must_use]
 	pub fn extend_from(&self, sup: Self) -> Self {
-		let mut cores = Vec::with_capacity(sup.0.cores.len() + self.0.cores.len());
-		cores.extend(sup.0.cores.iter().cloned());
-		cores.extend(self.0.cores.iter().cloned());
+		let cores = sup.0.cores.clone() + self.0.cores.clone();
 		let has_assertions = sup.0.has_assertions || self.0.has_assertions;
 		ObjValue(Cc::new(ObjValueInner {
 			cores,
@@ -521,13 +521,27 @@
 			},
 		)
 	}
+
+	fn iter_cores(&self, idx: CoreIdx) -> impl Iterator<Item = &CcObjectCore> {
+		self.0.cores.iter().take(idx.idx).rev()
+	}
+	fn iter_cores_enumerate(&self, idx: CoreIdx) -> impl Iterator<Item = (CoreIdx, &CcObjectCore)> {
+		self.0
+			.cores
+			.iter()
+			.take(idx.idx)
+			.enumerate()
+			.rev()
+			.map(|(idx, o)| (CoreIdx { idx }, o))
+	}
+
 	fn enum_fields_idx(
 		&self,
 		super_depth: &mut SuperDepth,
 		handler: &mut EnumFieldsHandler<'_>,
 		idx: CoreIdx,
 	) -> bool {
-		for core in self.0.cores[..idx.idx].iter().rev() {
+		for core in self.iter_cores(idx) {
 			if !core.0.enum_fields_core(super_depth, handler) {
 				return false;
 			}
@@ -546,7 +560,7 @@
 	}
 	fn has_field_include_hidden_idx(&self, name: IStr, core: CoreIdx) -> bool {
 		let mut skip = Saturating(0usize);
-		for ele in self.0.cores[..core.idx].iter().rev() {
+		for ele in self.iter_cores(core) {
 			match ele.0.has_field_include_hidden_core(name.clone()) {
 				HasFieldIncludeHidden::Exists => {
 					if skip.0 == 0 {
@@ -616,9 +630,9 @@
 		let mut first_add = None;
 		let mut add_stack: Vec<Val> = Vec::new();
 		let mut skip = Saturating(0);
-		for (sup, core) in self.0.cores[..core.idx].iter().enumerate().rev() {
+		for (sup, core) in self.iter_cores_enumerate(core) {
 			let sup_this = SupThis {
-				sup: CoreIdx { idx: sup },
+				sup,
 				this: self.clone(),
 			};
 			match core.0.get_for_core(key.clone(), sup_this, skip.0 != 0)? {
@@ -686,7 +700,7 @@
 	fn field_visibility_idx(&self, field: IStr, core: CoreIdx) -> Option<Visibility> {
 		let mut exists = false;
 		let mut skip = Saturating(0usize);
-		for ele in self.0.cores[..core.idx].iter().rev() {
+		for ele in self.iter_cores(core) {
 			let vis = ele.0.field_visibility_core(field.clone());
 			match vis {
 				FieldVisibility::Found(vis @ (Visibility::Unhide | Visibility::Hidden)) => {
modifiedcrates/jrsonnet-evaluator/src/obj/oop.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/obj/oop.rs
+++ b/crates/jrsonnet-evaluator/src/obj/oop.rs
@@ -4,6 +4,7 @@
 	ops::ControlFlow,
 };
 
+use im_rc::Vector;
 use jrsonnet_gcmodule::{Cc, Trace};
 use jrsonnet_ir::IStr;
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -117,7 +118,7 @@
 
 #[allow(clippy::module_name_repetitions)]
 pub struct ObjValueBuilder {
-	sup: Vec<CcObjectCore>,
+	sup: Vector<CcObjectCore>,
 	has_assertions: bool,
 
 	new: OopObject,
@@ -129,7 +130,7 @@
 	}
 	pub fn with_capacity(capacity: usize) -> Self {
 		Self {
-			sup: vec![],
+			sup: Vector::new(),
 			has_assertions: false,
 			new: OopObject::new(FxHashMap::with_capacity(capacity), None),
 			next_field_index: FieldIndex::default(),
@@ -137,14 +138,10 @@
 	}
 	pub fn reserve_fields(&mut self, capacity: usize) {
 		self.new.this_entries.reserve(capacity);
-	}
-	pub fn reserve_cores(&mut self, capacity: usize) -> &mut Self {
-		self.sup.reserve_exact(capacity);
-		self
 	}
 	pub fn with_super(&mut self, super_obj: ObjValue) -> &mut Self {
 		self.has_assertions |= super_obj.0.has_assertions;
-		self.sup.clone_from(&super_obj.0.cores);
+		self.sup = super_obj.0.cores.clone();
 		self
 	}
 
@@ -181,19 +178,20 @@
 
 	pub fn extend_with_core(&mut self, core: impl ObjectCore) {
 		self.commit();
-		self.sup.push(CcObjectCore::new(core));
+		self.sup.push_back(CcObjectCore::new(core));
 	}
 
 	fn commit(&mut self) {
 		if !self.new.is_empty() {
-			self.sup.push(CcObjectCore::new(mem::take(&mut self.new)));
+			self.sup
+				.push_back(CcObjectCore::new(mem::take(&mut self.new)));
 		}
 		self.next_field_index = FieldIndex::default();
 	}
 
 	pub fn with_fields_omitted(&mut self, omit: FxHashSet<IStr>) {
 		self.commit();
-		self.sup.push(CcObjectCore::new(OmitFieldsCore {
+		self.sup.push_back(CcObjectCore::new(OmitFieldsCore {
 			omit,
 			prev_layers: self.sup.len(),
 		}));