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

difftreelog

feat varadic Either type

Yaroslav Bolyukin2021-12-27parent: #8f3ed48.patch.diff
in: master

2 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
@@ -1,12 +1,14 @@
 use crate::function::StaticBuiltin;
-use crate::typed::{Any, Either, Null, PositiveF64, VecVal, M1};
-use crate::{self as jrsonnet_evaluator, ObjValue};
+use crate::typed::{Any, Null, PositiveF64, VecVal, M1};
+use crate::{self as jrsonnet_evaluator, Either, ObjValue};
 use crate::{
 	builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},
 	equals,
 	error::{Error::*, Result},
 	operator::evaluate_mod_op,
-	primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal, IndexableVal, Val,
+	primitive_equals, push_frame, throw,
+	typed::{Either2, Either4},
+	with_state, ArrValue, Context, FuncVal, IndexableVal, Val,
 };
 use format::{format_arr, format_obj};
 use gcmodule::Cc;
@@ -140,16 +142,17 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_length(x: Either<IStr, Either<VecVal, Either<ObjValue, Cc<FuncVal>>>>) -> Result<usize> {
+fn builtin_length(x: Either![IStr, VecVal, ObjValue, Cc<FuncVal>]) -> Result<usize> {
+	use Either4::*;
 	Ok(match x {
-		Either::Left(x) => x.len(),
-		Either::Right(Either::Left(x)) => x.0.len(),
-		Either::Right(Either::Right(Either::Left(x))) => x
+		A(x) => x.len(),
+		B(x) => x.0.len(),
+		C(x) => x
 			.fields_visibility()
 			.into_iter()
 			.filter(|(_k, v)| *v)
 			.count(),
-		Either::Right(Either::Right(Either::Right(f))) => f.args_len(),
+		D(f) => f.args_len(),
 	})
 }
 
@@ -215,11 +218,11 @@
 #[jrsonnet_macros::builtin]
 fn builtin_slice(
 	indexable: IndexableVal,
-	index: Either<usize, Null>,
-	end: Either<usize, Null>,
-	step: Either<usize, Null>,
+	index: Option<usize>,
+	end: Option<usize>,
+	step: Option<usize>,
 ) -> Result<Any> {
-	std_slice(indexable, index.left(), end.left(), step.left()).map(Any)
+	std_slice(indexable, index, end, step).map(Any)
 }
 
 #[jrsonnet_macros::builtin]
@@ -243,11 +246,12 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_mod(a: Either<f64, IStr>, b: Any) -> Result<Any> {
+fn builtin_mod(a: Either![f64, IStr], b: Any) -> Result<Any> {
+	use Either2::*;
 	Ok(Any(evaluate_mod_op(
 		&match a {
-			Either::Left(v) => Val::Num(v),
-			Either::Right(s) => Val::Str(s),
+			A(v) => Val::Num(v),
+			B(s) => Val::Str(s),
 		},
 		&b.0,
 	)?))
@@ -481,10 +485,11 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_base64(input: Either<Vec<u8>, IStr>) -> Result<String> {
+fn builtin_base64(input: Either![Vec<u8>, IStr]) -> Result<String> {
+	use Either2::*;
 	Ok(match input {
-		Either::Left(a) => base64::encode(a),
-		Either::Right(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
+		A(a) => base64::encode(a),
+		B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
 	})
 }
 
@@ -607,10 +612,11 @@
 }
 
 #[jrsonnet_macros::builtin]
-fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either<usize, M1>) -> Result<VecVal> {
+fn builtin_splitlimit(str: IStr, c: char, maxsplits: Either![usize, M1]) -> Result<VecVal> {
+	use Either2::*;
 	Ok(VecVal(match maxsplits {
-		Either::Left(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),
-		Either::Right(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),
+		A(n) => str.splitn(n + 1, c).map(|s| Val::Str(s.into())).collect(),
+		B(_) => str.split(c).map(|s| Val::Str(s.into())).collect(),
 	}))
 }
 
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
315 }315 }
316}316}
317317
318pub enum Either<A, B> {318macro_rules! decl_either {
319 Left(A),319 ($($name: ident, $($id: ident)*);*) => {$(
320 Right(B),320 pub enum $name<$($id),*> {
321}321 $($id($id)),*
322322 }
323impl<A, B> Either<A, B> {
324 pub fn to_left(self, f: impl FnOnce(B) -> A) -> A {
325 match self {
326 Either::Left(l) => l,
327 Either::Right(r) => f(r),
328 }
329 }
330 #[allow(clippy::missing_const_for_fn)]
331 pub fn left(self) -> Option<A> {
332 match self {
333 Either::Left(a) => Some(a),
334 Either::Right(_) => None,
335 }
336 }
337}
338
339impl<A, B> Typed for Either<A, B>
340where
341 A: Typed,
342 B: Typed,
343{
344 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[A::TYPE, B::TYPE]);
345}
346impl<A, B> TryFrom<Val> for Either<A, B>323 impl<$($id),*> Typed for $name<$($id),*>
347where324 where
348 A: Typed,325 $($id: Typed,)*
326 {
327 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);
328 }
329 impl<$($id),*> TryFrom<Val> for $name<$($id),*>
330 where
349 B: Typed,331 $($id: Typed,)*
350{332 {
351 type Error = LocError;333 type Error = LocError;
352334
353 fn try_from(value: Val) -> Result<Self> {335 fn try_from(value: Val) -> Result<Self> {
354 if A::TYPE.check(&value).is_ok() {336 $(
355 A::try_from(value).map(Self::Left)
356 } else if B::TYPE.check(&value).is_ok() {337 if $id::TYPE.check(&value).is_ok() {
357 B::try_from(value).map(Self::Right)338 $id::try_from(value).map(Self::$id)
358 } else {339 } else
359 <Self as Typed>::TYPE.check(&value)?;340 )* {
360 unreachable!()341 <Self as Typed>::TYPE.check(&value)?;
361 }342 unreachable!()
343 }
362 }344 }
363}345 }
364impl<A, B> TryFrom<Either<A, B>> for Val346 impl<$($id),*> TryFrom<$name<$($id),*>> for Val
365where347 where
348 $($id: Typed,)*
349 {
350 type Error = LocError;
351 fn try_from(value: $name<$($id),*>) -> Result<Self> {
352 match value {$(
353 $name::$id(v) => v.try_into()
354 ),*}
355 }
356 }
357 )*}
358}
359decl_either!(
360 Either1, A;
361 Either2, A B;
362 Either3, A B C;
363 Either4, A B C D;
364 Either5, A B C D E;
365 Either6, A B C D E F;
366 Either7, A B C D E F G
367);
368#[macro_export]
369macro_rules! Either {
370 ($a:ty) => {Either1<$a>};
366 A: Typed,371 ($a:ty, $b:ty) => {Either2<$a, $b>};
367 B: Typed,
368{
369 type Error = LocError;
370
371 fn try_from(value: Either<A, B>) -> Result<Self> {372 ($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};
372 match value {
373 Either::Left(a) => a.try_into(),373 ($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};
374 Either::Right(b) => b.try_into(),374 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};
375 }375 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};
376 }376 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};
377}377}
378
379pub type MyType = Either![u32, f64, String];
378380
379impl Typed for ArrValue {381impl Typed for ArrValue {
380 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);382 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);