difftreelog
refactor remove manual ThunkValue implementations
in: master
3 files changed
crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth1use hashbrown::HashMap;2use jrsonnet_gcmodule::Trace;3use jrsonnet_interner::IStr;4use jrsonnet_parser::{ArgsDesc, LocExpr};56use crate::{evaluate, gc::GcHashMap, typed::Typed, val::ThunkValue, Context, Result, Thunk, Val};78/// Marker for arguments, which can be evaluated with context set to None9pub trait OptionalContext {}1011#[derive(Trace)]12struct EvaluateThunk {13 ctx: Context,14 expr: LocExpr,15}16impl ThunkValue for EvaluateThunk {17 type Output = Val;18 fn get(self: Box<Self>) -> Result<Val> {19 evaluate(self.ctx, &self.expr)20 }21}2223pub trait ArgLike {24 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;25}2627impl ArgLike for &LocExpr {28 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {29 Ok(if tailstrict {30 Thunk::evaluated(evaluate(ctx, self)?)31 } else {32 Thunk::new(EvaluateThunk {33 ctx,34 expr: (*self).clone(),35 })36 })37 }38}3940impl<T> ArgLike for T41where42 T: Typed + Clone,43{44 fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {45 if T::provides_lazy() && !tailstrict {46 return Ok(T::into_lazy_untyped(self.clone()));47 }48 let val = T::into_untyped(self.clone())?;49 Ok(Thunk::evaluated(val))50 }51}52impl<T> OptionalContext for T where T: Typed + Clone {}5354#[derive(Clone, Trace)]55pub enum TlaArg {56 String(IStr),57 Code(LocExpr),58 Val(Val),59 Lazy(Thunk<Val>),60}61impl ArgLike for TlaArg {62 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {63 match self {64 Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),65 Self::Code(code) => Ok(if tailstrict {66 Thunk::evaluated(evaluate(ctx, code)?)67 } else {68 Thunk::new(EvaluateThunk {69 ctx,70 expr: code.clone(),71 })72 }),73 Self::Val(val) => Ok(Thunk::evaluated(val.clone())),74 Self::Lazy(lazy) => Ok(lazy.clone()),75 }76 }77}7879pub trait ArgsLike {80 fn unnamed_len(&self) -> usize;81 fn unnamed_iter(82 &self,83 ctx: Context,84 tailstrict: bool,85 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,86 ) -> Result<()>;87 fn named_iter(88 &self,89 ctx: Context,90 tailstrict: bool,91 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,92 ) -> Result<()>;93 fn named_names(&self, handler: &mut dyn FnMut(&IStr));94 fn is_empty(&self) -> bool;95}9697impl ArgsLike for Vec<Val> {98 fn unnamed_len(&self) -> usize {99 self.len()100 }101 fn unnamed_iter(102 &self,103 _ctx: Context,104 _tailstrict: bool,105 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,106 ) -> Result<()> {107 for (idx, el) in self.iter().enumerate() {108 handler(idx, Thunk::evaluated(el.clone()))?;109 }110 Ok(())111 }112 fn named_iter(113 &self,114 _ctx: Context,115 _tailstrict: bool,116 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,117 ) -> Result<()> {118 Ok(())119 }120 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}121 fn is_empty(&self) -> bool {122 self.is_empty()123 }124}125126impl ArgsLike for ArgsDesc {127 fn unnamed_len(&self) -> usize {128 self.unnamed.len()129 }130131 fn unnamed_iter(132 &self,133 ctx: Context,134 tailstrict: bool,135 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,136 ) -> Result<()> {137 for (id, arg) in self.unnamed.iter().enumerate() {138 handler(139 id,140 if tailstrict {141 Thunk::evaluated(evaluate(ctx.clone(), arg)?)142 } else {143 Thunk::new(EvaluateThunk {144 ctx: ctx.clone(),145 expr: arg.clone(),146 })147 },148 )?;149 }150 Ok(())151 }152153 fn named_iter(154 &self,155 ctx: Context,156 tailstrict: bool,157 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,158 ) -> Result<()> {159 for (name, arg) in &self.named {160 handler(161 name,162 if tailstrict {163 Thunk::evaluated(evaluate(ctx.clone(), arg)?)164 } else {165 Thunk::new(EvaluateThunk {166 ctx: ctx.clone(),167 expr: arg.clone(),168 })169 },170 )?;171 }172 Ok(())173 }174175 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {176 for (name, _) in &self.named {177 handler(name);178 }179 }180181 fn is_empty(&self) -> bool {182 self.unnamed.is_empty() && self.named.is_empty()183 }184}185186impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {187 fn unnamed_len(&self) -> usize {188 0189 }190191 fn unnamed_iter(192 &self,193 _ctx: Context,194 _tailstrict: bool,195 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,196 ) -> Result<()> {197 Ok(())198 }199200 fn named_iter(201 &self,202 ctx: Context,203 tailstrict: bool,204 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,205 ) -> Result<()> {206 for (name, value) in self {207 handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;208 }209 Ok(())210 }211212 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {213 for (name, _) in self {214 handler(name);215 }216 }217218 fn is_empty(&self) -> bool {219 self.is_empty()220 }221}222impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}223224impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {225 fn unnamed_len(&self) -> usize {226 self.0.unnamed_len()227 }228229 fn unnamed_iter(230 &self,231 ctx: Context,232 tailstrict: bool,233 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,234 ) -> Result<()> {235 self.0.unnamed_iter(ctx, tailstrict, handler)236 }237238 fn named_iter(239 &self,240 ctx: Context,241 tailstrict: bool,242 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,243 ) -> Result<()> {244 self.0.named_iter(ctx, tailstrict, handler)245 }246247 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {248 self.0.named_names(handler);249 }250251 fn is_empty(&self) -> bool {252 self.0.is_empty()253 }254}255256macro_rules! impl_args_like {257 ($count:expr; $($gen:ident)*) => {258 impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {259 fn unnamed_len(&self) -> usize {260 $count261 }262 #[allow(non_snake_case, unused_assignments)]263 fn unnamed_iter(264 &self,265 ctx: Context,266 tailstrict: bool,267 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,268 ) -> Result<()> {269 let mut i = 0usize;270 let ($($gen,)*) = self;271 $(272 handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;273 i+=1;274 )*275 Ok(())276 }277 fn named_iter(278 &self,279 _ctx: Context,280 _tailstrict: bool,281 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,282 ) -> Result<()> {283 Ok(())284 }285 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}286287 fn is_empty(&self) -> bool {288 // impl_args_like only implements non-empty tuples.289 false290 }291 }292 impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}293 };294 ($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {295 impl_args_like!($count; $($cur)*);296 impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);297 };298 ($count:expr; $($cur:ident)* @) => {299 impl_args_like!($count; $($cur)*);300 }301}302impl_args_like! {303 // First argument is already in position, so count starts from 1304 1usize; A @ B C D E F G H I J K L305}306307impl ArgsLike for () {308 fn unnamed_len(&self) -> usize {309 0310 }311312 fn unnamed_iter(313 &self,314 _ctx: Context,315 _tailstrict: bool,316 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,317 ) -> Result<()> {318 Ok(())319 }320321 fn named_iter(322 &self,323 _ctx: Context,324 _tailstrict: bool,325 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,326 ) -> Result<()> {327 Ok(())328 }329330 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}331 fn is_empty(&self) -> bool {332 true333 }334}335impl OptionalContext for () {}crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -12,24 +12,9 @@
evaluate_named,
function::builtin::ParamDefault,
gc::GcHashMap,
- val::ThunkValue,
Context, Pending, Thunk, Val,
};
-
-#[derive(Trace)]
-struct EvaluateNamedThunk {
- ctx: Pending<Context>,
- name: IStr,
- value: LocExpr,
-}
-impl ThunkValue for EvaluateNamedThunk {
- type Output = Val;
- fn get(self: Box<Self>) -> Result<Val> {
- evaluate_named(self.ctx.unwrap(), &self.value, self.name)
- }
-}
-
/// Creates correct [context](Context) for function body evaluation returning error on invalid call.
///
/// ## Parameters
@@ -105,11 +90,12 @@
destruct(
¶m.0,
- Thunk::new(EvaluateNamedThunk {
- ctx: fctx.clone(),
- name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
- value: param.1.clone().expect("default exists"),
- }),
+ {
+ let ctx = fctx.clone();
+ let name = param.0.name().unwrap_or_else(|| "<destruct>".into());
+ let value = param.1.clone().expect("default exists");
+ Thunk!(move || evaluate_named(ctx.unwrap(), &value, name))
+ },
fctx.clone(),
&mut defaults,
)?;
@@ -241,11 +227,12 @@
if let Some(v) = ¶m.1 {
destruct(
¶m.0.clone(),
- Thunk::new(EvaluateNamedThunk {
- ctx: fctx.clone(),
- name: param.0.name().unwrap_or_else(|| "<destruct>".into()),
- value: v.clone(),
- }),
+ {
+ let ctx = fctx.clone();
+ let name = param.0.name().unwrap_or_else(|| "<destruct>".into());
+ let value = v.clone();
+ Thunk!(move || evaluate_named(ctx.unwrap(), &value, name))
+ },
fctx.clone(),
&mut bindings,
)?;
nix/benchmarks.nixdiffbeforeafterboth--- a/nix/benchmarks.nix
+++ b/nix/benchmarks.nix
@@ -52,6 +52,7 @@
mkdir -p $out
cp -r ${src}/* $out/
cd $out
+ chmod u+w jsonnetfile.lock.json
mkdir vendor
${jsonnet-bundler}/bin/jb install
'';
@@ -125,7 +126,7 @@
go-jsonnet $path > generated.jsonnet
path=generated.jsonnet
''}
- hyperfine -N -w4 -m20 --output=pipe --style=basic --export-markdown result.md \
+ hyperfine -N -w4 -m20 --output=pipe --style=basic --export-asciidoc result.adoc \
${concatStringsSep " " (forEach jrsonnetVariants (
variant: "\"${variant.drv}/bin/jrsonnet $path${optionalString (vendor != "") " -J${vendor}"}\" -n \"Rust${
if variant.name != ""
@@ -137,7 +138,7 @@
${optionalString (skipGo == "") "\"go-jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Go\""} \
${optionalString (skipScala == "") "\"sjsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"Scala\""} \
${optionalString (skipCpp == "") "\"jsonnet $path${optionalString (vendor != "") " -J ${vendor}"}\" -n \"C++\""}
- cat result.md >> $out
+ cat result.adoc >> $out
'';
in ''
set -oux