git.delta.rocks / jrsonnet / refs/commits / 097494ede5f1

difftreelog

refactor trivial code review suggestions

Yaroslav Bolyukin2022-09-18parent: #f2fefaf.patch.diff
in: master

8 files changed

modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -25,9 +25,10 @@
 #[no_mangle]
 pub extern "C" fn _start() {}
 
-/// Return the version string of the Jsonnet interpreter.  Conforms to semantic versioning
-/// http://semver.org/ If this does not match LIB_JSONNET_VERSION then there is a mismatch between
-/// header and compiled library.
+/// Return the version string of the Jsonnet interpreter.
+/// Conforms to [semantic versioning](http://semver.org/).
+/// If this does not match `LIB_JSONNET_VERSION`
+/// then there is a mismatch between header and compiled library.
 #[no_mangle]
 pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {
 	b"v0.16.0\0"
@@ -67,7 +68,7 @@
 	}
 }
 
-/// Create a new Jsonnet virtual machine.
+/// Creates a new Jsonnet virtual machine.
 #[no_mangle]
 pub extern "C" fn jsonnet_make() -> *mut State {
 	let state = State::default();
@@ -79,7 +80,7 @@
 	Box::into_raw(Box::new(state))
 }
 
-/// Complement of `jsonnet_vm_make`
+/// Complement of [`jsonnet_vm_make`].
 #[no_mangle]
 #[allow(clippy::boxed_local)]
 pub extern "C" fn jsonnet_destroy(vm: Box<State>) {
@@ -118,7 +119,7 @@
 	}
 }
 
-/// Allocate, resize, or free a buffer.  This will abort if the memory cannot be allocated.  It will
+/// Allocate, resize, or free a buffer.  This will abort if the memory cannot be allocated. It will
 /// only return NULL if sz was zero.
 ///
 /// # Safety
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/native.rs
+++ b/bindings/jsonnet/src/native.rs
@@ -12,9 +12,9 @@
 };
 use jrsonnet_gcmodule::Cc;
 
-/// The returned JsonnetJsonValue* should be allocated with jsonnet_realloc.  It will be cleaned up
-/// along with the objects rooted at argv by libjsonnet when no-longer needed.  Return a string upon
-/// failure, which will appear in Jsonnet as an error.  The argv pointer is an array whose size
+/// The returned `JsonnetJsonValue*` should be allocated with `jsonnet_realloc`. It will be cleaned up
+/// along with the objects rooted at `argv` by `libjsonnet` when no-longer needed. Return a string upon
+/// failure, which will appear in Jsonnet as an error. The `argv` pointer is an array whose size
 /// matches the array of parameters supplied when the native callback was originally registered.
 ///
 /// - `ctx` User pointer, given in jsonnet_native_callback.
modifiedbindings/jsonnet/src/val_extract.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_extract.rs
+++ b/bindings/jsonnet/src/val_extract.rs
@@ -7,7 +7,7 @@
 
 use jrsonnet_evaluator::{State, Val};
 
-/// If the value is a string, return it as UTF8 otherwise return NULL.
+/// If the value is a string, return it as UTF-8, otherwise return `NULL`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_extract_string(_vm: &State, v: &Val) -> *mut c_char {
 	match v {
@@ -16,7 +16,7 @@
 	}
 }
 
-/// If the value is a number, return 1 and store the number in out, otherwise return 0.
+/// If the value is a number, return `1` and store the number in out, otherwise return `0`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_extract_number(_vm: &State, v: &Val, out: &mut c_double) -> c_int {
 	match v {
@@ -28,7 +28,7 @@
 	}
 }
 
-/// Return 0 if the value is false, 1 if it is true, and 2 if it is not a bool.
+/// Return `0` if the value is `false`, `1` if it is `true`, and `2` if it is not a `bool`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_extract_bool(_vm: &State, v: &Val) -> c_int {
 	match v {
@@ -38,7 +38,7 @@
 	}
 }
 
-/// Return 1 if the value is null, else 0.
+/// Return `1` if the value is `null`, otherwise return `0`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_extract_null(_vm: &State, v: &Val) -> c_int {
 	match v {
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_make.rs
+++ b/bindings/jsonnet/src/val_make.rs
@@ -8,7 +8,7 @@
 use jrsonnet_evaluator::{val::ArrValue, ObjValue, State, Val};
 use jrsonnet_gcmodule::Cc;
 
-/// Convert the given UTF8 string to a JsonnetJsonValue.
+/// Convert the given `UTF-8` string to a `JsonnetJsonValue`.
 ///
 /// # Safety
 ///
@@ -20,34 +20,34 @@
 	Box::into_raw(Box::new(Val::Str(val.into())))
 }
 
-/// Convert the given double to a JsonnetJsonValue.
+/// Convert the given double to a `JsonnetJsonValue`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_number(_vm: &State, v: c_double) -> *mut Val {
 	Box::into_raw(Box::new(Val::Num(v)))
 }
 
-/// Convert the given bool (1 or 0) to a JsonnetJsonValue.
+/// Convert the given `bool` (`1` or `0`) to a `JsonnetJsonValue`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_bool(_vm: &State, v: c_int) -> *mut Val {
 	assert!(v == 0 || v == 1, "bad boolean value");
 	Box::into_raw(Box::new(Val::Bool(v == 1)))
 }
 
-/// Make a JsonnetJsonValue representing null.
+/// Make a `JsonnetJsonValue` representing `null`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_null(_vm: &State) -> *mut Val {
 	Box::into_raw(Box::new(Val::Null))
 }
 
-/// Make a JsonnetJsonValue representing an array.
+/// Make a `JsonnetJsonValue` representing an array.
 ///
-/// Assign elements with jsonnet_json_array_append.
+/// Assign elements with [`jsonnet_json_array_append`].
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_array(_vm: &State) -> *mut Val {
 	Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Cc::new(Vec::new())))))
 }
 
-/// Make a JsonnetJsonValue representing an object.
+/// Make a `JsonnetJsonValue` representing an object.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_object(_vm: &State) -> *mut Val {
 	Box::into_raw(Box::new(Val::Obj(ObjValue::new_empty())))
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_modify.rs
+++ b/bindings/jsonnet/src/val_modify.rs
@@ -7,7 +7,7 @@
 use jrsonnet_evaluator::{val::ArrValue, State, Thunk, Val};
 use jrsonnet_gcmodule::Cc;
 
-/// Add value to the end of the array arr
+/// Adds value to the end of the array `arr`.
 ///
 /// # Safety
 ///
@@ -29,13 +29,13 @@
 	}
 }
 
-/// Add the field to the object, bound to value.
+/// Adds the field to the object, bound to value.
 ///
 /// This shadows any previous binding of the field.
 ///
 /// # Safety
 ///
-/// `obj` should be pointer to object value allocated by make_object, or returned by other library call
+/// `obj` should be a valid pointer to object value allocated by `make_object`, or returned by other library call
 /// `name` should be \0-terminated string
 #[no_mangle]
 pub unsafe extern "C" fn jsonnet_json_object_append(
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/lib.rs
1#![warn(clippy::all, clippy::nursery, clippy::pedantic)]2#![allow(3	macro_expanded_macro_exports_accessed_by_absolute_paths,4	clippy::ptr_arg,5	// Too verbose6	clippy::must_use_candidate,7	// A lot of functions pass around errors thrown by code8	clippy::missing_errors_doc,9	// A lot of pointers have interior Rc10	clippy::needless_pass_by_value,11	// Its fine12	clippy::wildcard_imports,13	clippy::enum_glob_use,14	clippy::module_name_repetitions,15	// TODO: fix individual issues, however this works as intended almost everywhere16	clippy::cast_precision_loss,17	clippy::cast_possible_wrap,18	clippy::cast_possible_truncation,19	clippy::cast_sign_loss,20	// False positives21	// https://github.com/rust-lang/rust-clippy/issues/690222	clippy::use_self,23	// https://github.com/rust-lang/rust-clippy/issues/853924	clippy::iter_with_drain,25)]2627// For jrsonnet-macros28extern crate self as jrsonnet_evaluator;2930mod ctx;31mod dynamic;32pub mod error;33mod evaluate;34pub mod function;35pub mod gc;36mod import;37mod integrations;38mod map;39mod obj;40pub mod stdlib;41pub mod trace;42pub mod typed;43pub mod val;4445use std::{46	any::Any,47	cell::{Ref, RefCell, RefMut},48	collections::HashMap,49	fmt::{self, Debug},50	path::Path,51	rc::Rc,52};5354pub use ctx::*;55pub use dynamic::*;56use error::{Error::*, LocError, Result, StackTraceElement};57pub use evaluate::*;58use function::{CallLocation, TlaArg};59use gc::{GcHashMap, TraceBox};60use hashbrown::hash_map::RawEntryMut;61pub use import::*;62use jrsonnet_gcmodule::{Cc, Trace};63pub use jrsonnet_interner::{IBytes, IStr};64pub use jrsonnet_parser as parser;65use jrsonnet_parser::*;66pub use obj::*;67use trace::{CompactFormat, TraceFormat};68pub use val::{ManifestFormat, Thunk, Val};6970pub trait Unbound: Trace {71	type Bound;72	fn bind(&self, s: State, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Self::Bound>;73}7475#[derive(Clone, Trace)]76pub enum LazyBinding {77	Bindable(Cc<TraceBox<dyn Unbound<Bound = Thunk<Val>>>>),78	Bound(Thunk<Val>),79}8081impl Debug for LazyBinding {82	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {83		write!(f, "LazyBinding")84	}85}86impl LazyBinding {87	pub fn evaluate(88		&self,89		s: State,90		sup: Option<ObjValue>,91		this: Option<ObjValue>,92	) -> Result<Thunk<Val>> {93		match self {94			Self::Bindable(v) => v.bind(s, sup, this),95			Self::Bound(v) => Ok(v.clone()),96		}97	}98}99100/// During import, this trait will be called to create initial context for file101/// It may initialize global variables, stdlib for example102pub trait ContextInitializer {103	fn initialize(&self, state: State, for_file: Source) -> Context;104105	fn as_any(&self) -> &dyn Any;106}107108/// Context initializer, which adds noth109pub struct DummyContextInitializer;110impl ContextInitializer for DummyContextInitializer {111	fn initialize(&self, _state: State, _for_file: Source) -> Context {112		Context::default()113	}114	fn as_any(&self) -> &dyn Any {115		self116	}117}118119pub struct EvaluationSettings {120	/// Limits recursion by limiting the number of stack frames121	pub max_stack: usize,122	/// Limits amount of stack trace items preserved123	pub max_trace: usize,124	/// TLA vars125	pub tla_vars: HashMap<IStr, TlaArg>,126	/// Context initializer, which will be used for imports and everything127	/// [`NoopContextInitializer`] is used by default, most likely you want to have `jrsonnet-stdlib`128	pub context_initializer: Box<dyn ContextInitializer>,129	/// Used to resolve file locations/contents130	pub import_resolver: Box<dyn ImportResolver>,131	/// Used in manifestification functions132	pub manifest_format: ManifestFormat,133	/// Used for bindings134	pub trace_format: Box<dyn TraceFormat>,135}136impl Default for EvaluationSettings {137	fn default() -> Self {138		Self {139			max_stack: 200,140			max_trace: 20,141			context_initializer: Box::new(DummyContextInitializer),142			tla_vars: HashMap::default(),143			import_resolver: Box::new(DummyImportResolver),144			manifest_format: ManifestFormat::Json {145				padding: 4,146				#[cfg(feature = "exp-preserve-order")]147				preserve_order: false,148			},149			trace_format: Box::new(CompactFormat {150				padding: 4,151				resolver: trace::PathResolver::Absolute,152			}),153		}154	}155}156157#[derive(Default)]158struct EvaluationData {159	/// Used for stack overflow detection, stacktrace is populated on unwind160	stack_depth: usize,161	/// Updated every time stack entry is popt162	stack_generation: usize,163164	breakpoints: Breakpoints,165166	/// Contains file source codes and evaluation results for imports and pretty-printed stacktraces167	files: GcHashMap<SourcePath, FileData>,168}169struct FileData {170	string: Option<IStr>,171	bytes: Option<IBytes>,172	parsed: Option<LocExpr>,173	evaluated: Option<Val>,174175	evaluating: bool,176}177impl FileData {178	fn new_string(data: IStr) -> Self {179		Self {180			string: Some(data),181			bytes: None,182			parsed: None,183			evaluated: None,184			evaluating: false,185		}186	}187	fn new_bytes(data: IBytes) -> Self {188		Self {189			string: None,190			bytes: Some(data),191			parsed: None,192			evaluated: None,193			evaluating: false,194		}195	}196}197198#[allow(clippy::type_complexity)]199pub struct Breakpoint {200	loc: ExprLocation,201	collected: RefCell<HashMap<usize, (usize, Vec<Result<Val>>)>>,202}203#[derive(Default)]204struct Breakpoints(Vec<Rc<Breakpoint>>);205impl Breakpoints {206	fn insert(207		&self,208		stack_depth: usize,209		stack_generation: usize,210		loc: &ExprLocation,211		result: Result<Val>,212	) -> Result<Val> {213		if self.0.is_empty() {214			return result;215		}216		for item in &self.0 {217			if item.loc.belongs_to(loc) {218				let mut collected = item.collected.borrow_mut();219				let (depth, vals) = collected.entry(stack_generation).or_default();220				if stack_depth > *depth {221					vals.clear();222				}223				vals.push(result.clone());224			}225		}226		result227	}228}229230#[derive(Default)]231pub struct EvaluationStateInternals {232	/// Internal state233	data: RefCell<EvaluationData>,234	/// Settings, safe to change at runtime235	settings: RefCell<EvaluationSettings>,236}237238/// Maintains stack trace and import resolution239#[derive(Default, Clone)]240pub struct State(Rc<EvaluationStateInternals>);241242impl State {243	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise244	pub fn import_resolved_str(&self, path: SourcePath) -> Result<IStr> {245		let mut data = self.data_mut();246		let mut file = data.files.raw_entry_mut().from_key(&path);247248		let file = match file {249			RawEntryMut::Occupied(ref mut d) => d.get_mut(),250			RawEntryMut::Vacant(v) => {251				let data = self.settings().import_resolver.load_file_contents(&path)?;252				v.insert(253					path.clone(),254					FileData::new_string(255						std::str::from_utf8(&data)256							.map_err(|_| ImportBadFileUtf8(path.clone()))?257							.into(),258					),259				)260				.1261			}262		};263		if let Some(str) = &file.string {264			return Ok(str.clone());265		}266		if file.string.is_none() {267			file.string = Some(268				file.bytes269					.as_ref()270					.expect("either string or bytes should be set")271					.clone()272					.cast_str()273					.ok_or_else(|| ImportBadFileUtf8(path.clone()))?,274			);275		}276		Ok(file.string.as_ref().expect("just set").clone())277	}278	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise279	pub fn import_resolved_bin(&self, path: SourcePath) -> Result<IBytes> {280		let mut data = self.data_mut();281		let mut file = data.files.raw_entry_mut().from_key(&path);282283		let file = match file {284			RawEntryMut::Occupied(ref mut d) => d.get_mut(),285			RawEntryMut::Vacant(v) => {286				let data = self.settings().import_resolver.load_file_contents(&path)?;287				v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))288					.1289			}290		};291		if let Some(str) = &file.bytes {292			return Ok(str.clone());293		}294		if file.bytes.is_none() {295			file.bytes = Some(296				file.string297					.as_ref()298					.expect("either string or bytes should be set")299					.clone()300					.cast_bytes(),301			);302		}303		Ok(file.bytes.as_ref().expect("just set").clone())304	}305	/// Should only be called with path retrieved from [`resolve_path`], may panic otherwise306	pub fn import_resolved(&self, path: SourcePath) -> Result<Val> {307		let mut data = self.data_mut();308		let mut file = data.files.raw_entry_mut().from_key(&path);309310		let file = match file {311			RawEntryMut::Occupied(ref mut d) => d.get_mut(),312			RawEntryMut::Vacant(v) => {313				let data = self.settings().import_resolver.load_file_contents(&path)?;314				v.insert(315					path.clone(),316					FileData::new_string(317						std::str::from_utf8(&data)318							.map_err(|_| ImportBadFileUtf8(path.clone()))?319							.into(),320					),321				)322				.1323			}324		};325		if let Some(val) = &file.evaluated {326			return Ok(val.clone());327		}328		if file.string.is_none() {329			file.string = Some(330				std::str::from_utf8(331					file.bytes332						.as_ref()333						.expect("either string or bytes should be set"),334				)335				.map_err(|_| ImportBadFileUtf8(path.clone()))?336				.into(),337			);338		}339		let code = file.string.as_ref().expect("just set");340		let file_name = Source::new(path.clone(), code.clone());341		if file.parsed.is_none() {342			file.parsed = Some(343				jrsonnet_parser::parse(344					code,345					&ParserSettings {346						file_name: file_name.clone(),347					},348				)349				.map_err(|e| ImportSyntaxError {350					path: file_name.clone(),351					error: Box::new(e),352				})?,353			);354		}355		let parsed = file.parsed.as_ref().expect("just set").clone();356		if file.evaluating {357			throw!(InfiniteRecursionDetected)358		}359		file.evaluating = true;360		// Dropping file here, as it borrows data, which may be used in evaluation361		drop(data);362		let res = evaluate(363			self.clone(),364			self.create_default_context(file_name),365			&parsed,366		);367368		let mut data = self.data_mut();369		let mut file = data.files.raw_entry_mut().from_key(&path);370371		let file = match file {372			RawEntryMut::Occupied(ref mut d) => d.get_mut(),373			RawEntryMut::Vacant(_) => unreachable!("this file was just here!"),374		};375		file.evaluating = false;376		match res {377			Ok(v) => {378				file.evaluated = Some(v.clone());379				Ok(v)380			}381			Err(e) => Err(e),382		}383	}384385	/// Has same semantics as `import 'path'` called from `from` file386	pub fn import_from(&self, from: &SourcePath, path: &str) -> Result<Val> {387		let resolved = self.resolve_from(from, path)?;388		self.import_resolved(resolved)389	}390	pub fn import(&self, path: impl AsRef<Path>) -> Result<Val> {391		let resolved = self.resolve(path)?;392		self.import_resolved(resolved)393	}394395	/// Creates context with all passed global variables396	pub fn create_default_context(&self, source: Source) -> Context {397		let context_initializer = &self.settings().context_initializer;398		context_initializer.initialize(self.clone(), source)399	}400401	/// Executes code creating a new stack frame402	pub fn push<T>(403		&self,404		e: CallLocation,405		frame_desc: impl FnOnce() -> String,406		f: impl FnOnce() -> Result<T>,407	) -> Result<T> {408		{409			let mut data = self.data_mut();410			let stack_depth = &mut data.stack_depth;411			if *stack_depth > self.max_stack() {412				// Error creation uses data, so i drop guard here413				drop(data);414				throw!(StackOverflow);415			}416			*stack_depth += 1;417		}418		let result = f();419		{420			let mut data = self.data_mut();421			data.stack_depth -= 1;422			data.stack_generation += 1;423		}424		if let Err(mut err) = result {425			err.trace_mut().0.push(StackTraceElement {426				location: e.0.cloned(),427				desc: frame_desc(),428			});429			return Err(err);430		}431		result432	}433434	/// Executes code creating a new stack frame435	pub fn push_val(436		&self,437		e: &ExprLocation,438		frame_desc: impl FnOnce() -> String,439		f: impl FnOnce() -> Result<Val>,440	) -> Result<Val> {441		{442			let mut data = self.data_mut();443			let stack_depth = &mut data.stack_depth;444			if *stack_depth > self.max_stack() {445				// Error creation uses data, so i drop guard here446				drop(data);447				throw!(StackOverflow);448			}449			*stack_depth += 1;450		}451		let mut result = f();452		{453			let mut data = self.data_mut();454			data.stack_depth -= 1;455			data.stack_generation += 1;456			result = data457				.breakpoints458				.insert(data.stack_depth, data.stack_generation, e, result);459		}460		if let Err(mut err) = result {461			err.trace_mut().0.push(StackTraceElement {462				location: Some(e.clone()),463				desc: frame_desc(),464			});465			return Err(err);466		}467		result468	}469	/// Executes code creating a new stack frame470	pub fn push_description<T>(471		&self,472		frame_desc: impl FnOnce() -> String,473		f: impl FnOnce() -> Result<T>,474	) -> Result<T> {475		{476			let mut data = self.data_mut();477			let stack_depth = &mut data.stack_depth;478			if *stack_depth > self.max_stack() {479				// Error creation uses data, so i drop guard here480				drop(data);481				throw!(StackOverflow);482			}483			*stack_depth += 1;484		}485		let result = f();486		{487			let mut data = self.data_mut();488			data.stack_depth -= 1;489			data.stack_generation += 1;490		}491		if let Err(mut err) = result {492			err.trace_mut().0.push(StackTraceElement {493				location: None,494				desc: frame_desc(),495			});496			return Err(err);497		}498		result499	}500501	/// # Panics502	/// In case of formatting failure503	pub fn stringify_err(&self, e: &LocError) -> String {504		let mut out = String::new();505		self.settings()506			.trace_format507			.write_trace(&mut out, self, e)508			.unwrap();509		out510	}511512	pub fn manifest(&self, val: Val) -> Result<IStr> {513		self.push_description(514			|| "manifestification".to_string(),515			|| val.manifest(self.clone(), &self.manifest_format()),516		)517	}518	pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {519		val.manifest_multi(self.clone(), &self.manifest_format())520	}521	pub fn manifest_stream(&self, val: Val) -> Result<Vec<IStr>> {522		val.manifest_stream(self.clone(), &self.manifest_format())523	}524525	/// If passed value is function then call with set TLA526	pub fn with_tla(&self, val: Val) -> Result<Val> {527		Ok(match val {528			Val::Func(func) => self.push_description(529				|| "during TLA call".to_owned(),530				|| {531					func.evaluate(532						self.clone(),533						self.create_default_context(Source::new_virtual(534							"<tla>".into(),535							IStr::empty(),536						)),537						CallLocation::native(),538						&self.settings().tla_vars,539						true,540					)541				},542			)?,543			v => v,544		})545	}546}547548/// Internals549impl State {550	// fn data(&self) -> Ref<EvaluationData> {551	// 	self.0.data.borrow()552	// }553	fn data_mut(&self) -> RefMut<EvaluationData> {554		self.0.data.borrow_mut()555	}556	pub fn settings(&self) -> Ref<EvaluationSettings> {557		self.0.settings.borrow()558	}559	pub fn settings_mut(&self) -> RefMut<EvaluationSettings> {560		self.0.settings.borrow_mut()561	}562}563564/// Raw methods evaluate passed values but don't perform TLA execution565impl State {566	/// Parses and evaluates the given snippet567	pub fn evaluate_snippet(&self, name: impl Into<IStr>, code: impl Into<IStr>) -> Result<Val> {568		let code = code.into();569		let source = Source::new_virtual(name.into(), code.clone());570		let parsed = jrsonnet_parser::parse(571			&code,572			&ParserSettings {573				file_name: source.clone(),574			},575		)576		.map_err(|e| ImportSyntaxError {577			path: source.clone(),578			error: Box::new(e),579		})?;580		evaluate(self.clone(), self.create_default_context(source), &parsed)581	}582}583584/// Settings utilities585impl State {586	pub fn add_tla(&self, name: IStr, value: Val) {587		self.settings_mut()588			.tla_vars589			.insert(name, TlaArg::Val(value));590	}591	pub fn add_tla_str(&self, name: IStr, value: IStr) {592		self.settings_mut()593			.tla_vars594			.insert(name, TlaArg::String(value));595	}596	pub fn add_tla_code(&self, name: IStr, code: &str) -> Result<()> {597		let source_name = format!("<top-level-arg:{}>", name);598		let source = Source::new_virtual(source_name.into(), code.into());599		let parsed = jrsonnet_parser::parse(600			code,601			&ParserSettings {602				file_name: source.clone(),603			},604		)605		.map_err(|e| ImportSyntaxError {606			path: source,607			error: Box::new(e),608		})?;609		self.settings_mut()610			.tla_vars611			.insert(name, TlaArg::Code(parsed));612		Ok(())613	}614615	// Only panics in case of [`ImportResolver`] contract violation616	#[allow(clippy::missing_panics_doc)]617	pub fn resolve_from(&self, from: &SourcePath, path: &str) -> Result<SourcePath> {618		self.import_resolver().resolve_from(from, path.as_ref())619	}620621	// Only panics in case of [`ImportResolver`] contract violation622	#[allow(clippy::missing_panics_doc)]623	pub fn resolve(&self, path: impl AsRef<Path>) -> Result<SourcePath> {624		self.import_resolver().resolve(path.as_ref())625	}626	pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {627		Ref::map(self.settings(), |s| &*s.import_resolver)628	}629	pub fn set_import_resolver(&self, resolver: Box<dyn ImportResolver>) {630		self.settings_mut().import_resolver = resolver;631	}632	pub fn context_initializer(&self) -> Ref<dyn ContextInitializer> {633		Ref::map(self.settings(), |s| &*s.context_initializer)634	}635636	pub fn manifest_format(&self) -> ManifestFormat {637		self.settings().manifest_format.clone()638	}639	pub fn set_manifest_format(&self, format: ManifestFormat) {640		self.settings_mut().manifest_format = format;641	}642643	pub fn trace_format(&self) -> Ref<dyn TraceFormat> {644		Ref::map(self.settings(), |s| &*s.trace_format)645	}646	pub fn set_trace_format(&self, format: Box<dyn TraceFormat>) {647		self.settings_mut().trace_format = format;648	}649650	pub fn max_trace(&self) -> usize {651		self.settings().max_trace652	}653	pub fn set_max_trace(&self, trace: usize) {654		self.settings_mut().max_trace = trace;655	}656657	pub fn max_stack(&self) -> usize {658		self.settings().max_stack659	}660	pub fn set_max_stack(&self, trace: usize) {661		self.settings_mut().max_stack = trace;662	}663}
modifiedcrates/jrsonnet-stdlib/src/math.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/math.rs
+++ b/crates/jrsonnet-stdlib/src/math.rs
@@ -66,7 +66,7 @@
 }
 
 fn frexp(s: f64) -> (f64, i16) {
-	if 0.0 == s {
+	if s == 0.0 {
 		(s, 0)
 	} else {
 		let lg = s.abs().log2();
modifiedcrates/jrsonnet-stdlib/src/sort.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/sort.rs
+++ b/crates/jrsonnet-stdlib/src/sort.rs
@@ -41,9 +41,9 @@
 			(Val::Num(_), SortKeyType::Unknown) => sort_type = SortKeyType::Number,
 			(Val::Str(_), SortKeyType::String) | (Val::Num(_), SortKeyType::Number) => {}
 			(Val::Str(_) | Val::Num(_), _) => {
-				throw_runtime!("sort elements should have same types")
+				throw_runtime!("sort elements should have the same types")
 			}
-			_ => throw_runtime!("sort key should be string or number"),
+			_ => throw_runtime!("sort key should either be a string or a number"),
 		}
 	}
 	Ok(sort_type)