1use std::collections::HashMap;23use gcmodule::Trace;4use jrsonnet_interner::IStr;5use jrsonnet_parser::{ArgsDesc, LocExpr};67use crate::{8 error::Result, evaluate, gc::TraceBox, typed::Typed, val::LazyValValue, Context, LazyVal,9 State, Val,10};1112#[derive(Trace)]13struct EvaluateLazyVal {14 ctx: Context,15 expr: LocExpr,16}17impl LazyValValue for EvaluateLazyVal {18 fn get(self: Box<Self>, s: State) -> Result<Val> {19 evaluate(s, self.ctx, &self.expr)20 }21}2223pub trait ArgLike {24 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal>;25}2627impl ArgLike for &LocExpr {28 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {29 Ok(if tailstrict {30 LazyVal::new_resolved(evaluate(s, ctx, self)?)31 } else {32 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {33 ctx,34 expr: (*self).clone(),35 })))36 })37 }38}3940impl<T> ArgLike for T41where42 T: Typed + Clone,43{44 fn evaluate_arg(&self, s: State, _ctx: Context, _tailstrict: bool) -> Result<LazyVal> {45 let val = T::into_untyped(self.clone(), s)?;46 Ok(LazyVal::new_resolved(val))47 }48}4950pub enum TlaArg {51 String(IStr),52 Code(LocExpr),53 Val(Val),54}55impl ArgLike for TlaArg {56 fn evaluate_arg(&self, s: State, ctx: Context, tailstrict: bool) -> Result<LazyVal> {57 match self {58 TlaArg::String(s) => Ok(LazyVal::new_resolved(Val::Str(s.clone()))),59 TlaArg::Code(code) => Ok(if tailstrict {60 LazyVal::new_resolved(evaluate(s, ctx, code)?)61 } else {62 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {63 ctx,64 expr: code.clone(),65 })))66 }),67 TlaArg::Val(val) => Ok(LazyVal::new_resolved(val.clone())),68 }69 }70}7172mod sealed {73 74 pub trait Unnamed {}75 76 pub trait Named {}77}7879pub trait ArgsLike {80 fn unnamed_len(&self) -> usize;81 fn unnamed_iter(82 &self,83 s: State,84 ctx: Context,85 tailstrict: bool,86 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,87 ) -> Result<()>;88 fn named_iter(89 &self,90 s: State,91 ctx: Context,92 tailstrict: bool,93 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,94 ) -> Result<()>;95 fn named_names(&self, handler: &mut dyn FnMut(&IStr));96}9798impl ArgsLike for ArgsDesc {99 fn unnamed_len(&self) -> usize {100 self.unnamed.len()101 }102103 fn unnamed_iter(104 &self,105 s: State,106 ctx: Context,107 tailstrict: bool,108 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,109 ) -> Result<()> {110 for (id, arg) in self.unnamed.iter().enumerate() {111 handler(112 id,113 if tailstrict {114 LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)115 } else {116 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {117 ctx: ctx.clone(),118 expr: arg.clone(),119 })))120 },121 )?;122 }123 Ok(())124 }125126 fn named_iter(127 &self,128 s: State,129 ctx: Context,130 tailstrict: bool,131 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,132 ) -> Result<()> {133 for (name, arg) in &self.named {134 handler(135 name,136 if tailstrict {137 LazyVal::new_resolved(evaluate(s.clone(), ctx.clone(), arg)?)138 } else {139 LazyVal::new(TraceBox(Box::new(EvaluateLazyVal {140 ctx: ctx.clone(),141 expr: arg.clone(),142 })))143 },144 )?;145 }146 Ok(())147 }148149 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {150 for (name, _) in &self.named {151 handler(name);152 }153 }154}155156impl<A: ArgLike, S> sealed::Named for HashMap<IStr, A, S> {}157impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {158 fn unnamed_len(&self) -> usize {159 0160 }161162 fn unnamed_iter(163 &self,164 _s: State,165 _ctx: Context,166 _tailstrict: bool,167 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,168 ) -> Result<()> {169 Ok(())170 }171172 fn named_iter(173 &self,174 s: State,175 ctx: Context,176 tailstrict: bool,177 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,178 ) -> Result<()> {179 for (name, value) in self.iter() {180 handler(181 name,182 value.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?,183 )?;184 }185 Ok(())186 }187188 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {189 for (name, _) in self.iter() {190 handler(name);191 }192 }193}194195macro_rules! impl_args_like {196 ($count:expr; $($gen:ident)*) => {197 impl<$($gen: ArgLike,)*> sealed::Unnamed for ($($gen,)*) {}198 impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {199 fn unnamed_len(&self) -> usize {200 $count201 }202 #[allow(non_snake_case, unused_assignments)]203 fn unnamed_iter(204 &self,205 s: State,206 ctx: Context,207 tailstrict: bool,208 handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,209 ) -> Result<()> {210 let mut i = 0usize;211 let ($($gen,)*) = self;212 $(213 handler(i, $gen.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;214 i+=1;215 )*216 Ok(())217 }218 fn named_iter(219 &self,220 _s: State,221 _ctx: Context,222 _tailstrict: bool,223 _handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,224 ) -> Result<()> {225 Ok(())226 }227 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}228 }229 impl<$($gen: ArgLike,)*> sealed::Named for ($((IStr, $gen),)*) {}230 impl<$($gen: ArgLike,)*> ArgsLike for ($((IStr, $gen),)*) {231 fn unnamed_len(&self) -> usize {232 0233 }234 fn unnamed_iter(235 &self,236 _s: State,237 _ctx: Context,238 _tailstrict: bool,239 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,240 ) -> Result<()> {241 Ok(())242 }243 #[allow(non_snake_case)]244 fn named_iter(245 &self,246 s: State,247 ctx: Context,248 tailstrict: bool,249 handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,250 ) -> Result<()> {251 let ($($gen,)*) = self;252 $(253 handler(&$gen.0, $gen.1.evaluate_arg(s.clone(), ctx.clone(), tailstrict)?)?;254 )*255 Ok(())256 }257 #[allow(non_snake_case)]258 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {259 let ($($gen,)*) = self;260 $(261 handler(&$gen.0);262 )*263 }264 }265 };266 ($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {267 impl_args_like!($count; $($cur)*);268 impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);269 };270 ($count:expr; $($cur:ident)* @) => {271 impl_args_like!($count; $($cur)*);272 }273}274impl_args_like! {275 0usize; A @ B C D E F G H I J K L276}277278impl ArgsLike for () {279 fn unnamed_len(&self) -> usize {280 0281 }282283 fn unnamed_iter(284 &self,285 _s: State,286 _ctx: Context,287 _tailstrict: bool,288 _handler: &mut dyn FnMut(usize, LazyVal) -> Result<()>,289 ) -> Result<()> {290 Ok(())291 }292293 fn named_iter(294 &self,295 _s: State,296 _ctx: Context,297 _tailstrict: bool,298 _handler: &mut dyn FnMut(&IStr, LazyVal) -> Result<()>,299 ) -> Result<()> {300 Ok(())301 }302303 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}304}