difftreelog
feat impl ArgLike for Thunk<Val>
in: master
1 file 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::{7 error::Result,8 evaluate,9 gc::GcHashMap,10 typed::Typed,11 val::{StrValue, ThunkValue},12 Context, Thunk, Val,13};1415/// Marker for arguments, which can be evaluated with context set to None16pub trait OptionalContext {}1718#[derive(Trace)]19struct EvaluateThunk {20 ctx: Context,21 expr: LocExpr,22}23impl ThunkValue for EvaluateThunk {24 type Output = Val;25 fn get(self: Box<Self>) -> Result<Val> {26 evaluate(self.ctx, &self.expr)27 }28}2930pub trait ArgLike {31 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;32}3334impl ArgLike for &LocExpr {35 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {36 Ok(if tailstrict {37 Thunk::evaluated(evaluate(ctx, self)?)38 } else {39 Thunk::new(EvaluateThunk {40 ctx,41 expr: (*self).clone(),42 })43 })44 }45}4647impl<T> ArgLike for T48where49 T: Typed + Clone,50{51 fn evaluate_arg(&self, _ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {52 let val = T::into_untyped(self.clone())?;53 Ok(Thunk::evaluated(val))54 }55}56impl<T> OptionalContext for T where T: Typed + Clone {}5758#[derive(Clone, Trace)]59pub enum TlaArg {60 String(IStr),61 Code(LocExpr),62 Val(Val),63}64impl ArgLike for TlaArg {65 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {66 match self {67 TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))),68 TlaArg::Code(code) => Ok(if tailstrict {69 Thunk::evaluated(evaluate(ctx, code)?)70 } else {71 Thunk::new(EvaluateThunk {72 ctx,73 expr: code.clone(),74 })75 }),76 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),77 }78 }79}8081mod sealed {82 /// Implemented for `ArgsLike`, where only unnamed arguments present83 pub trait Unnamed {}84 /// Implemented for `ArgsLike`, where only named arguments present85 pub trait Named {}86}8788pub trait ArgsLike {89 fn unnamed_len(&self) -> usize;90 fn unnamed_iter(91 &self,92 ctx: Context,93 tailstrict: bool,94 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,95 ) -> Result<()>;96 fn named_iter(97 &self,98 ctx: Context,99 tailstrict: bool,100 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,101 ) -> Result<()>;102 fn named_names(&self, handler: &mut dyn FnMut(&IStr));103}104105impl ArgsLike for Vec<Val> {106 fn unnamed_len(&self) -> usize {107 self.len()108 }109 fn unnamed_iter(110 &self,111 _ctx: Context,112 _tailstrict: bool,113 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,114 ) -> Result<()> {115 for (idx, el) in self.iter().enumerate() {116 handler(idx, Thunk::evaluated(el.clone()))?;117 }118 Ok(())119 }120 fn named_iter(121 &self,122 _ctx: Context,123 _tailstrict: bool,124 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,125 ) -> Result<()> {126 Ok(())127 }128 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}129}130131impl ArgsLike for ArgsDesc {132 fn unnamed_len(&self) -> usize {133 self.unnamed.len()134 }135136 fn unnamed_iter(137 &self,138 ctx: Context,139 tailstrict: bool,140 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,141 ) -> Result<()> {142 for (id, arg) in self.unnamed.iter().enumerate() {143 handler(144 id,145 if tailstrict {146 Thunk::evaluated(evaluate(ctx.clone(), arg)?)147 } else {148 Thunk::new(EvaluateThunk {149 ctx: ctx.clone(),150 expr: arg.clone(),151 })152 },153 )?;154 }155 Ok(())156 }157158 fn named_iter(159 &self,160 ctx: Context,161 tailstrict: bool,162 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,163 ) -> Result<()> {164 for (name, arg) in &self.named {165 handler(166 name,167 if tailstrict {168 Thunk::evaluated(evaluate(ctx.clone(), arg)?)169 } else {170 Thunk::new(EvaluateThunk {171 ctx: ctx.clone(),172 expr: arg.clone(),173 })174 },175 )?;176 }177 Ok(())178 }179180 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {181 for (name, _) in &self.named {182 handler(name);183 }184 }185}186187impl<V: ArgLike, S> sealed::Named for HashMap<IStr, V, S> {}188impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {189 fn unnamed_len(&self) -> usize {190 0191 }192193 fn unnamed_iter(194 &self,195 _ctx: Context,196 _tailstrict: bool,197 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,198 ) -> Result<()> {199 Ok(())200 }201202 fn named_iter(203 &self,204 ctx: Context,205 tailstrict: bool,206 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,207 ) -> Result<()> {208 for (name, value) in self.iter() {209 handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;210 }211 Ok(())212 }213214 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {215 for (name, _) in self.iter() {216 handler(name);217 }218 }219}220impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}221222impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {223 fn unnamed_len(&self) -> usize {224 self.0.unnamed_len()225 }226227 fn unnamed_iter(228 &self,229 ctx: Context,230 tailstrict: bool,231 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,232 ) -> Result<()> {233 self.0.unnamed_iter(ctx, tailstrict, handler)234 }235236 fn named_iter(237 &self,238 ctx: Context,239 tailstrict: bool,240 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,241 ) -> Result<()> {242 self.0.named_iter(ctx, tailstrict, handler)243 }244245 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {246 self.0.named_names(handler);247 }248}249250macro_rules! impl_args_like {251 ($count:expr; $($gen:ident)*) => {252 impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}253 impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {254 fn unnamed_len(&self) -> usize {255 $count256 }257 #[allow(non_snake_case, unused_assignments)]258 fn unnamed_iter(259 &self,260 ctx: Context,261 tailstrict: bool,262 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,263 ) -> Result<()> {264 let mut i = 0usize;265 let ($($gen,)*) = self;266 $(267 handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;268 i+=1;269 )*270 Ok(())271 }272 fn named_iter(273 &self,274 _ctx: Context,275 _tailstrict: bool,276 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,277 ) -> Result<()> {278 Ok(())279 }280 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}281 }282 impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}283284 impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}285 impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {286 fn unnamed_len(&self) -> usize {287 0288 }289 fn unnamed_iter(290 &self,291 _ctx: Context,292 _tailstrict: bool,293 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,294 ) -> Result<()> {295 Ok(())296 }297 #[allow(non_snake_case)]298 fn named_iter(299 &self,300 ctx: Context,301 tailstrict: bool,302 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,303 ) -> Result<()> {304 let ($($gen,)*) = self;305 $(306 handler(&$gen.0, $gen.1.evaluate_arg(ctx.clone(), tailstrict)?)?;307 )*308 Ok(())309 }310 #[allow(non_snake_case)]311 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {312 let ($($gen,)*) = self;313 $(314 handler(&$gen.0);315 )*316 }317 }318 impl<$($gen: ArgLike,)*> OptionalContext for ($((IStr, $gen),)*) where $($gen: OptionalContext),* {}319 };320 ($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {321 impl_args_like!($count; $($cur)*);322 impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);323 };324 ($count:expr; $($cur:ident)* @) => {325 impl_args_like!($count; $($cur)*);326 }327}328impl_args_like! {329 // First argument is already in position, so count starts from 1330 1usize; A @ B C D E F G H I J K L331}332333impl ArgsLike for () {334 fn unnamed_len(&self) -> usize {335 0336 }337338 fn unnamed_iter(339 &self,340 _ctx: Context,341 _tailstrict: bool,342 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,343 ) -> Result<()> {344 Ok(())345 }346347 fn named_iter(348 &self,349 _ctx: Context,350 _tailstrict: bool,351 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,352 ) -> Result<()> {353 Ok(())354 }355356 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}357}358impl OptionalContext for () {}1use hashbrown::HashMap;2use jrsonnet_gcmodule::Trace;3use jrsonnet_interner::IStr;4use jrsonnet_parser::{ArgsDesc, LocExpr};56use crate::{7 error::Result,8 evaluate,9 gc::GcHashMap,10 typed::Typed,11 val::{StrValue, ThunkValue},12 Context, Thunk, Val,13};1415/// Marker for arguments, which can be evaluated with context set to None16pub trait OptionalContext {}1718#[derive(Trace)]19struct EvaluateThunk {20 ctx: Context,21 expr: LocExpr,22}23impl ThunkValue for EvaluateThunk {24 type Output = Val;25 fn get(self: Box<Self>) -> Result<Val> {26 evaluate(self.ctx, &self.expr)27 }28}2930pub trait ArgLike {31 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;32}3334impl ArgLike for &LocExpr {35 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {36 Ok(if tailstrict {37 Thunk::evaluated(evaluate(ctx, self)?)38 } else {39 Thunk::new(EvaluateThunk {40 ctx,41 expr: (*self).clone(),42 })43 })44 }45}4647impl<T> ArgLike for T48where49 T: Typed + Clone,50{51 fn evaluate_arg(&self, _ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {52 let val = T::into_untyped(self.clone())?;53 Ok(Thunk::evaluated(val))54 }55}56impl<T> OptionalContext for T where T: Typed + Clone {}5758impl ArgLike for Thunk<Val> {59 fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {60 if tailstrict {61 self.force()?;62 }63 Ok(self.clone())64 }65}66impl OptionalContext for Thunk<Val> {}6768#[derive(Clone, Trace)]69pub enum TlaArg {70 String(IStr),71 Code(LocExpr),72 Val(Val),73}74impl ArgLike for TlaArg {75 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {76 match self {77 TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))),78 TlaArg::Code(code) => Ok(if tailstrict {79 Thunk::evaluated(evaluate(ctx, code)?)80 } else {81 Thunk::new(EvaluateThunk {82 ctx,83 expr: code.clone(),84 })85 }),86 TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())),87 }88 }89}9091mod sealed {92 /// Implemented for `ArgsLike`, where only unnamed arguments present93 pub trait Unnamed {}94 /// Implemented for `ArgsLike`, where only named arguments present95 pub trait Named {}96}9798pub trait ArgsLike {99 fn unnamed_len(&self) -> usize;100 fn unnamed_iter(101 &self,102 ctx: Context,103 tailstrict: bool,104 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,105 ) -> Result<()>;106 fn named_iter(107 &self,108 ctx: Context,109 tailstrict: bool,110 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,111 ) -> Result<()>;112 fn named_names(&self, handler: &mut dyn FnMut(&IStr));113}114115impl ArgsLike for Vec<Val> {116 fn unnamed_len(&self) -> usize {117 self.len()118 }119 fn unnamed_iter(120 &self,121 _ctx: Context,122 _tailstrict: bool,123 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,124 ) -> Result<()> {125 for (idx, el) in self.iter().enumerate() {126 handler(idx, Thunk::evaluated(el.clone()))?;127 }128 Ok(())129 }130 fn named_iter(131 &self,132 _ctx: Context,133 _tailstrict: bool,134 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,135 ) -> Result<()> {136 Ok(())137 }138 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}139}140141impl ArgsLike for ArgsDesc {142 fn unnamed_len(&self) -> usize {143 self.unnamed.len()144 }145146 fn unnamed_iter(147 &self,148 ctx: Context,149 tailstrict: bool,150 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,151 ) -> Result<()> {152 for (id, arg) in self.unnamed.iter().enumerate() {153 handler(154 id,155 if tailstrict {156 Thunk::evaluated(evaluate(ctx.clone(), arg)?)157 } else {158 Thunk::new(EvaluateThunk {159 ctx: ctx.clone(),160 expr: arg.clone(),161 })162 },163 )?;164 }165 Ok(())166 }167168 fn named_iter(169 &self,170 ctx: Context,171 tailstrict: bool,172 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,173 ) -> Result<()> {174 for (name, arg) in &self.named {175 handler(176 name,177 if tailstrict {178 Thunk::evaluated(evaluate(ctx.clone(), arg)?)179 } else {180 Thunk::new(EvaluateThunk {181 ctx: ctx.clone(),182 expr: arg.clone(),183 })184 },185 )?;186 }187 Ok(())188 }189190 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {191 for (name, _) in &self.named {192 handler(name);193 }194 }195}196197impl<V: ArgLike, S> sealed::Named for HashMap<IStr, V, S> {}198impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {199 fn unnamed_len(&self) -> usize {200 0201 }202203 fn unnamed_iter(204 &self,205 _ctx: Context,206 _tailstrict: bool,207 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,208 ) -> Result<()> {209 Ok(())210 }211212 fn named_iter(213 &self,214 ctx: Context,215 tailstrict: bool,216 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,217 ) -> Result<()> {218 for (name, value) in self.iter() {219 handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;220 }221 Ok(())222 }223224 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {225 for (name, _) in self.iter() {226 handler(name);227 }228 }229}230impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}231232impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {233 fn unnamed_len(&self) -> usize {234 self.0.unnamed_len()235 }236237 fn unnamed_iter(238 &self,239 ctx: Context,240 tailstrict: bool,241 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,242 ) -> Result<()> {243 self.0.unnamed_iter(ctx, tailstrict, handler)244 }245246 fn named_iter(247 &self,248 ctx: Context,249 tailstrict: bool,250 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,251 ) -> Result<()> {252 self.0.named_iter(ctx, tailstrict, handler)253 }254255 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {256 self.0.named_names(handler);257 }258}259260macro_rules! impl_args_like {261 ($count:expr; $($gen:ident)*) => {262 impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}263 impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {264 fn unnamed_len(&self) -> usize {265 $count266 }267 #[allow(non_snake_case, unused_assignments)]268 fn unnamed_iter(269 &self,270 ctx: Context,271 tailstrict: bool,272 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,273 ) -> Result<()> {274 let mut i = 0usize;275 let ($($gen,)*) = self;276 $(277 handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;278 i+=1;279 )*280 Ok(())281 }282 fn named_iter(283 &self,284 _ctx: Context,285 _tailstrict: bool,286 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,287 ) -> Result<()> {288 Ok(())289 }290 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}291 }292 impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}293294 impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}295 impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {296 fn unnamed_len(&self) -> usize {297 0298 }299 fn unnamed_iter(300 &self,301 _ctx: Context,302 _tailstrict: bool,303 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,304 ) -> Result<()> {305 Ok(())306 }307 #[allow(non_snake_case)]308 fn named_iter(309 &self,310 ctx: Context,311 tailstrict: bool,312 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,313 ) -> Result<()> {314 let ($($gen,)*) = self;315 $(316 handler(&$gen.0, $gen.1.evaluate_arg(ctx.clone(), tailstrict)?)?;317 )*318 Ok(())319 }320 #[allow(non_snake_case)]321 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {322 let ($($gen,)*) = self;323 $(324 handler(&$gen.0);325 )*326 }327 }328 impl<$($gen: ArgLike,)*> OptionalContext for ($((IStr, $gen),)*) where $($gen: OptionalContext),* {}329 };330 ($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {331 impl_args_like!($count; $($cur)*);332 impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);333 };334 ($count:expr; $($cur:ident)* @) => {335 impl_args_like!($count; $($cur)*);336 }337}338impl_args_like! {339 // First argument is already in position, so count starts from 1340 1usize; A @ B C D E F G H I J K L341}342343impl ArgsLike for () {344 fn unnamed_len(&self) -> usize {345 0346 }347348 fn unnamed_iter(349 &self,350 _ctx: Context,351 _tailstrict: bool,352 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,353 ) -> Result<()> {354 Ok(())355 }356357 fn named_iter(358 &self,359 _ctx: Context,360 _tailstrict: bool,361 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,362 ) -> Result<()> {363 Ok(())364 }365366 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}367}368impl OptionalContext for () {}