git.delta.rocks / jrsonnet / refs/commits / 69d179bf913a

difftreelog

perf O(1) std.reverse, std.range

Yaroslav Bolyukin2022-04-20parent: #629c80c.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -11,6 +11,7 @@
 };
 use crate::{Either, ObjValue};
 use format::{format_arr, format_obj};
+use gcmodule::Cc;
 use jrsonnet_interner::IStr;
 use serde::Deserialize;
 use serde_yaml::DeserializingQuirks;
@@ -142,11 +143,11 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_length(x: Either![IStr, VecVal, ObjValue, FuncVal]) -> Result<usize> {
+fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> Result<usize> {
 	use Either4::*;
 	Ok(match x {
 		A(x) => x.chars().count(),
-		B(x) => x.0.len(),
+		B(x) => x.len(),
 		C(x) => x
 			.fields_visibility()
 			.into_iter()
@@ -167,7 +168,7 @@
 	for i in 0..sz {
 		out.push(func.evaluate_simple(&[i as f64].as_slice())?)
 	}
-	Ok(VecVal(out))
+	Ok(VecVal(Cc::new(out)))
 }
 
 #[jrsonnet_macros::builtin]
@@ -178,7 +179,9 @@
 #[jrsonnet_macros::builtin]
 fn builtin_object_fields_ex(obj: ObjValue, inc_hidden: bool) -> Result<VecVal> {
 	let out = obj.fields_ex(inc_hidden);
-	Ok(VecVal(out.into_iter().map(Val::Str).collect::<Vec<_>>()))
+	Ok(VecVal(Cc::new(
+		out.into_iter().map(Val::Str).collect::<Vec<_>>(),
+	)))
 }
 
 #[jrsonnet_macros::builtin]
@@ -432,15 +435,11 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_range(from: i32, to: i32) -> Result<VecVal> {
+fn builtin_range(from: i32, to: i32) -> Result<ArrValue> {
 	if to < from {
-		return Ok(VecVal(Vec::new()));
+		return Ok(ArrValue::new_eager());
 	}
-	let mut out = Vec::with_capacity((1 + to as usize - from as usize).max(0));
-	for i in from as usize..=to as usize {
-		out.push(Val::Num(i as f64));
-	}
-	Ok(VecVal(out))
+	Ok(ArrValue::new_range(from, to))
 }
 
 #[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/typed/conversions.rs
1use std::{2	convert::{TryFrom, TryInto},3	rc::Rc,4};56use gcmodule::Cc;7use jrsonnet_interner::IStr;8pub use jrsonnet_macros::Typed;9use jrsonnet_types::{ComplexValType, ValType};1011use crate::{12	error::{Error::*, LocError, Result},13	throw,14	typed::CheckType,15	ArrValue, FuncDesc, FuncVal, IndexableVal, ObjValue, ObjValueBuilder, Val,16};1718pub trait TypedObj: Typed {19	fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;20	fn parse(obj: &ObjValue) -> Result<Self>;21	fn into_object(self) -> Result<ObjValue> {22		let mut builder = ObjValueBuilder::new();23		self.serialize(&mut builder)?;24		Ok(builder.build())25	}26}2728pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {29	const TYPE: &'static ComplexValType;30}3132macro_rules! impl_int {33	($($ty:ty)*) => {$(34		impl Typed for $ty {35			const TYPE: &'static ComplexValType =36				&ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));37		}38		impl TryFrom<Val> for $ty {39			type Error = LocError;4041			fn try_from(value: Val) -> Result<Self> {42				<Self as Typed>::TYPE.check(&value)?;43				match value {44					Val::Num(n) => {45						if n.trunc() != n {46							throw!(RuntimeError(47								format!(48									"cannot convert number with fractional part to {}",49									stringify!($ty)50								)51								.into()52							))53						}54						Ok(n as Self)55					}56					_ => unreachable!(),57				}58			}59		}60		impl TryFrom<$ty> for Val {61			type Error = LocError;6263			fn try_from(value: $ty) -> Result<Self> {64				Ok(Self::Num(value as f64))65			}66		}67	)*};68}6970impl_int!(i8 u8 i16 u16 i32 u32);7172impl Typed for f64 {73	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);74}75impl TryFrom<Val> for f64 {76	type Error = LocError;7778	fn try_from(value: Val) -> Result<Self> {79		<Self as Typed>::TYPE.check(&value)?;80		match value {81			Val::Num(n) => Ok(n),82			_ => unreachable!(),83		}84	}85}86impl TryFrom<f64> for Val {87	type Error = LocError;8889	fn try_from(value: f64) -> Result<Self> {90		Ok(Self::Num(value))91	}92}9394pub struct PositiveF64(pub f64);95impl Typed for PositiveF64 {96	const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);97}98impl TryFrom<Val> for PositiveF64 {99	type Error = LocError;100101	fn try_from(value: Val) -> Result<Self> {102		<Self as Typed>::TYPE.check(&value)?;103		match value {104			Val::Num(n) => Ok(Self(n)),105			_ => unreachable!(),106		}107	}108}109impl TryFrom<PositiveF64> for Val {110	type Error = LocError;111112	fn try_from(value: PositiveF64) -> Result<Self> {113		Ok(Self::Num(value.0))114	}115}116117impl Typed for usize {118	// It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility119	const TYPE: &'static ComplexValType =120		&ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));121}122impl TryFrom<Val> for usize {123	type Error = LocError;124125	fn try_from(value: Val) -> Result<Self> {126		<Self as Typed>::TYPE.check(&value)?;127		match value {128			Val::Num(n) => {129				if n.trunc() != n {130					throw!(RuntimeError(131						"cannot convert number with fractional part to usize".into()132					))133				}134				Ok(n as Self)135			}136			_ => unreachable!(),137		}138	}139}140impl TryFrom<usize> for Val {141	type Error = LocError;142143	fn try_from(value: usize) -> Result<Self> {144		if value > u32::MAX as usize {145			throw!(RuntimeError("number is too large".into()))146		}147		Ok(Self::Num(value as f64))148	}149}150151impl Typed for IStr {152	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);153}154impl TryFrom<Val> for IStr {155	type Error = LocError;156157	fn try_from(value: Val) -> Result<Self> {158		<Self as Typed>::TYPE.check(&value)?;159		match value {160			Val::Str(s) => Ok(s),161			_ => unreachable!(),162		}163	}164}165impl TryFrom<IStr> for Val {166	type Error = LocError;167168	fn try_from(value: IStr) -> Result<Self> {169		Ok(Self::Str(value))170	}171}172173impl Typed for String {174	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);175}176impl TryFrom<Val> for String {177	type Error = LocError;178179	fn try_from(value: Val) -> Result<Self> {180		<Self as Typed>::TYPE.check(&value)?;181		match value {182			Val::Str(s) => Ok(s.to_string()),183			_ => unreachable!(),184		}185	}186}187impl TryFrom<String> for Val {188	type Error = LocError;189190	fn try_from(value: String) -> Result<Self> {191		Ok(Self::Str(value.into()))192	}193}194195impl Typed for char {196	const TYPE: &'static ComplexValType = &ComplexValType::Char;197}198impl TryFrom<Val> for char {199	type Error = LocError;200201	fn try_from(value: Val) -> Result<Self> {202		<Self as Typed>::TYPE.check(&value)?;203		match value {204			Val::Str(s) => Ok(s.chars().next().unwrap()),205			_ => unreachable!(),206		}207	}208}209impl TryFrom<char> for Val {210	type Error = LocError;211212	fn try_from(value: char) -> Result<Self> {213		Ok(Self::Str(value.to_string().into()))214	}215}216217impl<T> Typed for Vec<T>218where219	T: Typed,220	T: TryFrom<Val, Error = LocError>,221	T: TryInto<Val, Error = LocError>,222{223	const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);224}225impl<T> TryFrom<Val> for Vec<T>226where227	T: Typed,228	T: TryFrom<Val, Error = LocError>,229	T: TryInto<Val, Error = LocError>,230{231	type Error = LocError;232233	fn try_from(value: Val) -> Result<Self> {234		<Self as Typed>::TYPE.check(&value)?;235		match value {236			Val::Arr(a) => {237				let mut o = Self::with_capacity(a.len());238				for i in a.iter() {239					o.push(T::try_from(i?)?);240				}241				Ok(o)242			}243			_ => unreachable!(),244		}245	}246}247impl<T> TryFrom<Vec<T>> for Val248where249	T: Typed,250	T: TryFrom<Self, Error = LocError>,251	T: TryInto<Self, Error = LocError>,252{253	type Error = LocError;254255	fn try_from(value: Vec<T>) -> Result<Self> {256		let mut o = Vec::with_capacity(value.len());257		for i in value {258			o.push(i.try_into()?);259		}260		Ok(Self::Arr(o.into()))261	}262}263264/// To be used in Vec<Any>265/// Regular Val can't be used here, because it has wrong TryFrom::Error type266#[derive(Clone)]267pub struct Any(pub Val);268269impl Typed for Any {270	const TYPE: &'static ComplexValType = &ComplexValType::Any;271}272impl TryFrom<Val> for Any {273	type Error = LocError;274275	fn try_from(value: Val) -> Result<Self> {276		Ok(Self(value))277	}278}279impl TryFrom<Any> for Val {280	type Error = LocError;281282	fn try_from(value: Any) -> Result<Self> {283		Ok(value.0)284	}285}286287/// Specialization, provides faster TryFrom<VecVal> for Val288pub struct VecVal(pub Vec<Val>);289290impl Typed for VecVal {291	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);292}293impl TryFrom<Val> for VecVal {294	type Error = LocError;295296	fn try_from(value: Val) -> Result<Self> {297		<Self as Typed>::TYPE.check(&value)?;298		match value {299			Val::Arr(a) => Ok(Self(a.evaluated()?.to_vec())),300			_ => unreachable!(),301		}302	}303}304impl TryFrom<VecVal> for Val {305	type Error = LocError;306307	fn try_from(value: VecVal) -> Result<Self> {308		Ok(Self::Arr(value.0.into()))309	}310}311312/// Specialization313pub struct Bytes(pub Rc<[u8]>);314315impl Typed for Bytes {316	const TYPE: &'static ComplexValType =317		&ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));318}319impl TryFrom<Val> for Bytes {320	type Error = LocError;321322	fn try_from(value: Val) -> Result<Self> {323		match value {324			Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),325			_ => {326				<Self as Typed>::TYPE.check(&value)?;327				match value {328					Val::Arr(a) => {329						let mut out = Vec::with_capacity(a.len());330						for e in a.iter() {331							let r = e?;332							out.push(u8::try_from(r)?);333						}334						Ok(Self(out.into()))335					}336					_ => unreachable!(),337				}338			}339		}340	}341}342impl TryFrom<Bytes> for Val {343	type Error = LocError;344345	fn try_from(value: Bytes) -> Result<Self> {346		Ok(Self::Arr(ArrValue::Bytes(value.0)))347	}348}349350pub struct M1;351impl Typed for M1 {352	const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));353}354impl TryFrom<Val> for M1 {355	type Error = LocError;356357	fn try_from(value: Val) -> Result<Self> {358		<Self as Typed>::TYPE.check(&value)?;359		Ok(Self)360	}361}362impl TryFrom<M1> for Val {363	type Error = LocError;364365	fn try_from(_: M1) -> Result<Self> {366		Ok(Self::Num(-1.0))367	}368}369370macro_rules! decl_either {371	($($name: ident, $($id: ident)*);*) => {$(372		pub enum $name<$($id),*> {373			$($id($id)),*374		}375		impl<$($id),*> Typed for $name<$($id),*>376		where377			$($id: Typed,)*378		{379			const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);380		}381		impl<$($id),*> TryFrom<Val> for $name<$($id),*>382		where383			$($id: Typed,)*384		{385			type Error = LocError;386387			fn try_from(value: Val) -> Result<Self> {388				$(389					if $id::TYPE.check(&value).is_ok() {390						$id::try_from(value).map(Self::$id)391					} else392				)* {393					<Self as Typed>::TYPE.check(&value)?;394					unreachable!()395				}396			}397		}398		impl<$($id),*> TryFrom<$name<$($id),*>> for Val399		where400			$($id: Typed,)*401		{402			type Error = LocError;403			fn try_from(value: $name<$($id),*>) -> Result<Self> {404				match value {$(405					$name::$id(v) => v.try_into()406				),*}407			}408		}409	)*}410}411decl_either!(412	Either1, A;413	Either2, A B;414	Either3, A B C;415	Either4, A B C D;416	Either5, A B C D E;417	Either6, A B C D E F;418	Either7, A B C D E F G419);420#[macro_export]421macro_rules! Either {422	($a:ty) => {Either1<$a>};423	($a:ty, $b:ty) => {Either2<$a, $b>};424	($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};425	($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};426	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};427	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};428	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};429}430431pub type MyType = Either![u32, f64, String];432433impl Typed for ArrValue {434	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);435}436impl TryFrom<Val> for ArrValue {437	type Error = LocError;438439	fn try_from(value: Val) -> Result<Self> {440		<Self as Typed>::TYPE.check(&value)?;441		match value {442			Val::Arr(a) => Ok(a),443			_ => unreachable!(),444		}445	}446}447impl TryFrom<ArrValue> for Val {448	type Error = LocError;449450	fn try_from(value: ArrValue) -> Result<Self> {451		Ok(Self::Arr(value))452	}453}454455impl Typed for FuncVal {456	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);457}458impl TryFrom<Val> for FuncVal {459	type Error = LocError;460461	fn try_from(value: Val) -> Result<Self> {462		<Self as Typed>::TYPE.check(&value)?;463		match value {464			Val::Func(a) => Ok(a),465			_ => unreachable!(),466		}467	}468}469impl TryFrom<FuncVal> for Val {470	type Error = LocError;471472	fn try_from(value: FuncVal) -> Result<Self> {473		Ok(Self::Func(value))474	}475}476477impl Typed for Cc<FuncDesc> {478	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);479}480impl TryFrom<Val> for Cc<FuncDesc> {481	type Error = LocError;482483	fn try_from(value: Val) -> Result<Self, Self::Error> {484		<Self as Typed>::TYPE.check(&value)?;485		match value {486			Val::Func(FuncVal::Normal(desc)) => Ok(desc),487			Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),488			_ => unreachable!(),489		}490	}491}492impl TryFrom<Cc<FuncDesc>> for Val {493	type Error = LocError;494495	fn try_from(value: Cc<FuncDesc>) -> Result<Self, Self::Error> {496		Ok(Self::Func(FuncVal::Normal(value)))497	}498}499500impl Typed for ObjValue {501	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);502}503impl TryFrom<Val> for ObjValue {504	type Error = LocError;505506	fn try_from(value: Val) -> Result<Self> {507		<Self as Typed>::TYPE.check(&value)?;508		match value {509			Val::Obj(a) => Ok(a),510			_ => unreachable!(),511		}512	}513}514impl TryFrom<ObjValue> for Val {515	type Error = LocError;516517	fn try_from(value: ObjValue) -> Result<Self> {518		Ok(Self::Obj(value))519	}520}521522impl Typed for bool {523	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);524}525impl TryFrom<Val> for bool {526	type Error = LocError;527528	fn try_from(value: Val) -> Result<Self> {529		<Self as Typed>::TYPE.check(&value)?;530		match value {531			Val::Bool(a) => Ok(a),532			_ => unreachable!(),533		}534	}535}536impl TryFrom<bool> for Val {537	type Error = LocError;538539	fn try_from(value: bool) -> Result<Self> {540		Ok(Self::Bool(value))541	}542}543544impl Typed for IndexableVal {545	const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[546		&ComplexValType::Simple(ValType::Arr),547		&ComplexValType::Simple(ValType::Str),548	]);549}550impl TryFrom<Val> for IndexableVal {551	type Error = LocError;552553	fn try_from(value: Val) -> Result<Self> {554		<Self as Typed>::TYPE.check(&value)?;555		value.into_indexable()556	}557}558impl TryFrom<IndexableVal> for Val {559	type Error = LocError;560561	fn try_from(value: IndexableVal) -> Result<Self> {562		match value {563			IndexableVal::Str(s) => Ok(Self::Str(s)),564			IndexableVal::Arr(a) => Ok(Self::Arr(a)),565		}566	}567}568569pub struct Null;570impl Typed for Null {571	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);572}573impl TryFrom<Val> for Null {574	type Error = LocError;575576	fn try_from(value: Val) -> Result<Self> {577		<Self as Typed>::TYPE.check(&value)?;578		Ok(Self)579	}580}581impl TryFrom<Null> for Val {582	type Error = LocError;583584	fn try_from(_: Null) -> Result<Self> {585		Ok(Self::Null)586	}587}
after · crates/jrsonnet-evaluator/src/typed/conversions.rs
1use std::{2	convert::{TryFrom, TryInto},3	rc::Rc,4};56use gcmodule::Cc;7use jrsonnet_interner::IStr;8pub use jrsonnet_macros::Typed;9use jrsonnet_types::{ComplexValType, ValType};1011use crate::{12	error::{Error::*, LocError, Result},13	throw,14	typed::CheckType,15	ArrValue, FuncDesc, FuncVal, IndexableVal, ObjValue, ObjValueBuilder, Val,16};1718pub trait TypedObj: Typed {19	fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;20	fn parse(obj: &ObjValue) -> Result<Self>;21	fn into_object(self) -> Result<ObjValue> {22		let mut builder = ObjValueBuilder::new();23		self.serialize(&mut builder)?;24		Ok(builder.build())25	}26}2728pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {29	const TYPE: &'static ComplexValType;30}3132macro_rules! impl_int {33	($($ty:ty)*) => {$(34		impl Typed for $ty {35			const TYPE: &'static ComplexValType =36				&ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));37		}38		impl TryFrom<Val> for $ty {39			type Error = LocError;4041			fn try_from(value: Val) -> Result<Self> {42				<Self as Typed>::TYPE.check(&value)?;43				match value {44					Val::Num(n) => {45						if n.trunc() != n {46							throw!(RuntimeError(47								format!(48									"cannot convert number with fractional part to {}",49									stringify!($ty)50								)51								.into()52							))53						}54						Ok(n as Self)55					}56					_ => unreachable!(),57				}58			}59		}60		impl TryFrom<$ty> for Val {61			type Error = LocError;6263			fn try_from(value: $ty) -> Result<Self> {64				Ok(Self::Num(value as f64))65			}66		}67	)*};68}6970impl_int!(i8 u8 i16 u16 i32 u32);7172impl Typed for f64 {73	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);74}75impl TryFrom<Val> for f64 {76	type Error = LocError;7778	fn try_from(value: Val) -> Result<Self> {79		<Self as Typed>::TYPE.check(&value)?;80		match value {81			Val::Num(n) => Ok(n),82			_ => unreachable!(),83		}84	}85}86impl TryFrom<f64> for Val {87	type Error = LocError;8889	fn try_from(value: f64) -> Result<Self> {90		Ok(Self::Num(value))91	}92}9394pub struct PositiveF64(pub f64);95impl Typed for PositiveF64 {96	const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);97}98impl TryFrom<Val> for PositiveF64 {99	type Error = LocError;100101	fn try_from(value: Val) -> Result<Self> {102		<Self as Typed>::TYPE.check(&value)?;103		match value {104			Val::Num(n) => Ok(Self(n)),105			_ => unreachable!(),106		}107	}108}109impl TryFrom<PositiveF64> for Val {110	type Error = LocError;111112	fn try_from(value: PositiveF64) -> Result<Self> {113		Ok(Self::Num(value.0))114	}115}116117impl Typed for usize {118	// It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility119	const TYPE: &'static ComplexValType =120		&ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));121}122impl TryFrom<Val> for usize {123	type Error = LocError;124125	fn try_from(value: Val) -> Result<Self> {126		<Self as Typed>::TYPE.check(&value)?;127		match value {128			Val::Num(n) => {129				if n.trunc() != n {130					throw!(RuntimeError(131						"cannot convert number with fractional part to usize".into()132					))133				}134				Ok(n as Self)135			}136			_ => unreachable!(),137		}138	}139}140impl TryFrom<usize> for Val {141	type Error = LocError;142143	fn try_from(value: usize) -> Result<Self> {144		if value > u32::MAX as usize {145			throw!(RuntimeError("number is too large".into()))146		}147		Ok(Self::Num(value as f64))148	}149}150151impl Typed for IStr {152	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);153}154impl TryFrom<Val> for IStr {155	type Error = LocError;156157	fn try_from(value: Val) -> Result<Self> {158		<Self as Typed>::TYPE.check(&value)?;159		match value {160			Val::Str(s) => Ok(s),161			_ => unreachable!(),162		}163	}164}165impl TryFrom<IStr> for Val {166	type Error = LocError;167168	fn try_from(value: IStr) -> Result<Self> {169		Ok(Self::Str(value))170	}171}172173impl Typed for String {174	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);175}176impl TryFrom<Val> for String {177	type Error = LocError;178179	fn try_from(value: Val) -> Result<Self> {180		<Self as Typed>::TYPE.check(&value)?;181		match value {182			Val::Str(s) => Ok(s.to_string()),183			_ => unreachable!(),184		}185	}186}187impl TryFrom<String> for Val {188	type Error = LocError;189190	fn try_from(value: String) -> Result<Self> {191		Ok(Self::Str(value.into()))192	}193}194195impl Typed for char {196	const TYPE: &'static ComplexValType = &ComplexValType::Char;197}198impl TryFrom<Val> for char {199	type Error = LocError;200201	fn try_from(value: Val) -> Result<Self> {202		<Self as Typed>::TYPE.check(&value)?;203		match value {204			Val::Str(s) => Ok(s.chars().next().unwrap()),205			_ => unreachable!(),206		}207	}208}209impl TryFrom<char> for Val {210	type Error = LocError;211212	fn try_from(value: char) -> Result<Self> {213		Ok(Self::Str(value.to_string().into()))214	}215}216217impl<T> Typed for Vec<T>218where219	T: Typed,220	T: TryFrom<Val, Error = LocError>,221	T: TryInto<Val, Error = LocError>,222{223	const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);224}225impl<T> TryFrom<Val> for Vec<T>226where227	T: Typed,228	T: TryFrom<Val, Error = LocError>,229	T: TryInto<Val, Error = LocError>,230{231	type Error = LocError;232233	fn try_from(value: Val) -> Result<Self> {234		<Self as Typed>::TYPE.check(&value)?;235		match value {236			Val::Arr(a) => {237				let mut o = Self::with_capacity(a.len());238				for i in a.iter() {239					o.push(T::try_from(i?)?);240				}241				Ok(o)242			}243			_ => unreachable!(),244		}245	}246}247impl<T> TryFrom<Vec<T>> for Val248where249	T: Typed,250	T: TryFrom<Self, Error = LocError>,251	T: TryInto<Self, Error = LocError>,252{253	type Error = LocError;254255	fn try_from(value: Vec<T>) -> Result<Self> {256		let mut o = Vec::with_capacity(value.len());257		for i in value {258			o.push(i.try_into()?);259		}260		Ok(Self::Arr(o.into()))261	}262}263264/// To be used in Vec<Any>265/// Regular Val can't be used here, because it has wrong TryFrom::Error type266#[derive(Clone)]267pub struct Any(pub Val);268269impl Typed for Any {270	const TYPE: &'static ComplexValType = &ComplexValType::Any;271}272impl TryFrom<Val> for Any {273	type Error = LocError;274275	fn try_from(value: Val) -> Result<Self> {276		Ok(Self(value))277	}278}279impl TryFrom<Any> for Val {280	type Error = LocError;281282	fn try_from(value: Any) -> Result<Self> {283		Ok(value.0)284	}285}286287/// Specialization, provides faster TryFrom<VecVal> for Val288pub struct VecVal(pub Cc<Vec<Val>>);289290impl Typed for VecVal {291	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);292}293impl TryFrom<Val> for VecVal {294	type Error = LocError;295296	fn try_from(value: Val) -> Result<Self> {297		<Self as Typed>::TYPE.check(&value)?;298		match value {299			Val::Arr(a) => Ok(Self(a.evaluated()?)),300			_ => unreachable!(),301		}302	}303}304impl TryFrom<VecVal> for Val {305	type Error = LocError;306307	fn try_from(value: VecVal) -> Result<Self> {308		Ok(Self::Arr(ArrValue::Eager(value.0)))309	}310}311312/// Specialization313pub struct Bytes(pub Rc<[u8]>);314315impl Typed for Bytes {316	const TYPE: &'static ComplexValType =317		&ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));318}319impl TryFrom<Val> for Bytes {320	type Error = LocError;321322	fn try_from(value: Val) -> Result<Self> {323		match value {324			Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),325			_ => {326				<Self as Typed>::TYPE.check(&value)?;327				match value {328					Val::Arr(a) => {329						let mut out = Vec::with_capacity(a.len());330						for e in a.iter() {331							let r = e?;332							out.push(u8::try_from(r)?);333						}334						Ok(Self(out.into()))335					}336					_ => unreachable!(),337				}338			}339		}340	}341}342impl TryFrom<Bytes> for Val {343	type Error = LocError;344345	fn try_from(value: Bytes) -> Result<Self> {346		Ok(Self::Arr(ArrValue::Bytes(value.0)))347	}348}349350pub struct M1;351impl Typed for M1 {352	const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));353}354impl TryFrom<Val> for M1 {355	type Error = LocError;356357	fn try_from(value: Val) -> Result<Self> {358		<Self as Typed>::TYPE.check(&value)?;359		Ok(Self)360	}361}362impl TryFrom<M1> for Val {363	type Error = LocError;364365	fn try_from(_: M1) -> Result<Self> {366		Ok(Self::Num(-1.0))367	}368}369370macro_rules! decl_either {371	($($name: ident, $($id: ident)*);*) => {$(372		pub enum $name<$($id),*> {373			$($id($id)),*374		}375		impl<$($id),*> Typed for $name<$($id),*>376		where377			$($id: Typed,)*378		{379			const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);380		}381		impl<$($id),*> TryFrom<Val> for $name<$($id),*>382		where383			$($id: Typed,)*384		{385			type Error = LocError;386387			fn try_from(value: Val) -> Result<Self> {388				$(389					if $id::TYPE.check(&value).is_ok() {390						$id::try_from(value).map(Self::$id)391					} else392				)* {393					<Self as Typed>::TYPE.check(&value)?;394					unreachable!()395				}396			}397		}398		impl<$($id),*> TryFrom<$name<$($id),*>> for Val399		where400			$($id: Typed,)*401		{402			type Error = LocError;403			fn try_from(value: $name<$($id),*>) -> Result<Self> {404				match value {$(405					$name::$id(v) => v.try_into()406				),*}407			}408		}409	)*}410}411decl_either!(412	Either1, A;413	Either2, A B;414	Either3, A B C;415	Either4, A B C D;416	Either5, A B C D E;417	Either6, A B C D E F;418	Either7, A B C D E F G419);420#[macro_export]421macro_rules! Either {422	($a:ty) => {Either1<$a>};423	($a:ty, $b:ty) => {Either2<$a, $b>};424	($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};425	($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};426	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};427	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};428	($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};429}430431pub type MyType = Either![u32, f64, String];432433impl Typed for ArrValue {434	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);435}436impl TryFrom<Val> for ArrValue {437	type Error = LocError;438439	fn try_from(value: Val) -> Result<Self> {440		<Self as Typed>::TYPE.check(&value)?;441		match value {442			Val::Arr(a) => Ok(a),443			_ => unreachable!(),444		}445	}446}447impl TryFrom<ArrValue> for Val {448	type Error = LocError;449450	fn try_from(value: ArrValue) -> Result<Self> {451		Ok(Self::Arr(value))452	}453}454455impl Typed for FuncVal {456	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);457}458impl TryFrom<Val> for FuncVal {459	type Error = LocError;460461	fn try_from(value: Val) -> Result<Self> {462		<Self as Typed>::TYPE.check(&value)?;463		match value {464			Val::Func(a) => Ok(a),465			_ => unreachable!(),466		}467	}468}469impl TryFrom<FuncVal> for Val {470	type Error = LocError;471472	fn try_from(value: FuncVal) -> Result<Self> {473		Ok(Self::Func(value))474	}475}476477impl Typed for Cc<FuncDesc> {478	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);479}480impl TryFrom<Val> for Cc<FuncDesc> {481	type Error = LocError;482483	fn try_from(value: Val) -> Result<Self, Self::Error> {484		<Self as Typed>::TYPE.check(&value)?;485		match value {486			Val::Func(FuncVal::Normal(desc)) => Ok(desc),487			Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),488			_ => unreachable!(),489		}490	}491}492impl TryFrom<Cc<FuncDesc>> for Val {493	type Error = LocError;494495	fn try_from(value: Cc<FuncDesc>) -> Result<Self, Self::Error> {496		Ok(Self::Func(FuncVal::Normal(value)))497	}498}499500impl Typed for ObjValue {501	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);502}503impl TryFrom<Val> for ObjValue {504	type Error = LocError;505506	fn try_from(value: Val) -> Result<Self> {507		<Self as Typed>::TYPE.check(&value)?;508		match value {509			Val::Obj(a) => Ok(a),510			_ => unreachable!(),511		}512	}513}514impl TryFrom<ObjValue> for Val {515	type Error = LocError;516517	fn try_from(value: ObjValue) -> Result<Self> {518		Ok(Self::Obj(value))519	}520}521522impl Typed for bool {523	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);524}525impl TryFrom<Val> for bool {526	type Error = LocError;527528	fn try_from(value: Val) -> Result<Self> {529		<Self as Typed>::TYPE.check(&value)?;530		match value {531			Val::Bool(a) => Ok(a),532			_ => unreachable!(),533		}534	}535}536impl TryFrom<bool> for Val {537	type Error = LocError;538539	fn try_from(value: bool) -> Result<Self> {540		Ok(Self::Bool(value))541	}542}543544impl Typed for IndexableVal {545	const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[546		&ComplexValType::Simple(ValType::Arr),547		&ComplexValType::Simple(ValType::Str),548	]);549}550impl TryFrom<Val> for IndexableVal {551	type Error = LocError;552553	fn try_from(value: Val) -> Result<Self> {554		<Self as Typed>::TYPE.check(&value)?;555		value.into_indexable()556	}557}558impl TryFrom<IndexableVal> for Val {559	type Error = LocError;560561	fn try_from(value: IndexableVal) -> Result<Self> {562		match value {563			IndexableVal::Str(s) => Ok(Self::Str(s)),564			IndexableVal::Arr(a) => Ok(Self::Arr(a)),565		}566	}567}568569pub struct Null;570impl Typed for Null {571	const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);572}573impl TryFrom<Val> for Null {574	type Error = LocError;575576	fn try_from(value: Val) -> Result<Self> {577		<Self as Typed>::TYPE.check(&value)?;578		Ok(Self)579	}580}581impl TryFrom<Null> for Val {582	type Error = LocError;583584	fn try_from(_: Null) -> Result<Self> {585		Ok(Self::Null)586	}587}
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -178,11 +178,17 @@
 	Lazy(Cc<Vec<LazyVal>>),
 	Eager(Cc<Vec<Val>>),
 	Extended(Box<(Self, Self)>),
+	Range(i32, i32),
+	Reversed(Box<Self>),
 }
 impl ArrValue {
 	pub fn new_eager() -> Self {
 		Self::Eager(Cc::new(Vec::new()))
 	}
+	pub fn new_range(a: i32, b: i32) -> Self {
+		assert!(a <= b);
+		Self::Range(a, b)
+	}
 
 	pub fn len(&self) -> usize {
 		match self {
@@ -190,6 +196,8 @@
 			Self::Lazy(l) => l.len(),
 			Self::Eager(e) => e.len(),
 			Self::Extended(v) => v.0.len() + v.1.len(),
+			Self::Range(a, b) => a.abs_diff(*b) as usize,
+			Self::Reversed(i) => i.len(),
 		}
 	}
 
@@ -218,6 +226,19 @@
 					v.1.get(index - a_len)
 				}
 			}
+			Self::Range(a, _) => {
+				if index >= self.len() {
+					return Ok(None);
+				}
+				Ok(Some(Val::Num(((*a as isize) + index as isize) as f64)))
+			}
+			Self::Reversed(v) => {
+				let len = v.len();
+				if index >= len {
+					return Ok(None);
+				}
+				v.get(len - index - 1)
+			}
 		}
 	}
 
@@ -236,6 +257,21 @@
 					v.1.get_lazy(index - a_len)
 				}
 			}
+			Self::Range(a, _) => {
+				if index >= self.len() {
+					return None;
+				}
+				Some(LazyVal::new_resolved(Val::Num(
+					((*a as isize) + index as isize) as f64,
+				)))
+			}
+			Self::Reversed(v) => {
+				let len = v.len();
+				if index >= len {
+					return None;
+				}
+				v.get_lazy(len - index - 1)
+			}
 		}
 	}
 
@@ -263,46 +299,50 @@
 				}
 				Cc::new(out)
 			}
+			Self::Range(a, b) => {
+				let mut out = Vec::with_capacity(self.len());
+				for i in *a..*b {
+					out.push(Val::Num(i as f64));
+				}
+				Cc::new(out)
+			}
+			Self::Reversed(r) => {
+				let mut r = r.evaluated()?;
+				Cc::update_with(&mut r, |v| v.reverse());
+				r
+			}
 		})
 	}
 
 	pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
-		(0..self.len()).map(move |idx| match self {
+		// if let Self::Reversed(v) = self {
+		// 	return v.iter().rev();
+		// }
+		let len = self.len();
+		(0..len).map(move |idx| match self {
 			Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),
 			Self::Lazy(l) => l[idx].evaluate(),
 			Self::Eager(e) => Ok(e[idx].clone()),
 			Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),
+			Self::Range(..) => self.get(idx).map(|e| e.unwrap()),
+			Self::Reversed(..) => self.get(len - idx - 1).map(|e| e.unwrap()),
 		})
 	}
 
 	pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
-		(0..self.len()).map(move |idx| match self {
+		let len = self.len();
+		(0..len).map(move |idx| match self {
 			Self::Bytes(b) => LazyVal::new_resolved(Val::Num(b[idx] as f64)),
 			Self::Lazy(l) => l[idx].clone(),
 			Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
 			Self::Extended(_) => self.get_lazy(idx).unwrap(),
+			Self::Range(..) => self.get_lazy(idx).unwrap(),
+			Self::Reversed(..) => self.get_lazy(len - idx - 1).unwrap(),
 		})
 	}
 
 	pub fn reversed(self) -> Self {
-		match self {
-			Self::Bytes(b) => {
-				let mut out = b.to_vec();
-				out.reverse();
-				Self::Bytes(out.into())
-			}
-			Self::Lazy(vec) => {
-				let mut out = (&vec as &Vec<_>).clone();
-				out.reverse();
-				Self::Lazy(Cc::new(out))
-			}
-			Self::Eager(vec) => {
-				let mut out = (&vec as &Vec<_>).clone();
-				out.reverse();
-				Self::Eager(Cc::new(out))
-			}
-			Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
-		}
+		Self::Reversed(Box::new(self))
 	}
 
 	pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {