git.delta.rocks / jrsonnet / refs/commits / 76f0cfd3dd2f

difftreelog

feat --exp-apply argument

Yaroslav Bolyukin2023-07-26parent: #0f5ef44.patch.diff
in: master

3 files changed

modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
8edition = "2021"8edition = "2021"
99
10[features]10[features]
11experimental = ["exp-preserve-order", "exp-destruct"]11experimental = ["exp-preserve-order", "exp-destruct", "exp-null-coaelse", "exp-object-iteration", "exp-bigint", "exp-apply"]
12# Use mimalloc as allocator12# Use mimalloc as allocator
13mimalloc = ["mimallocator"]13mimalloc = ["mimallocator"]
14# Experimental feature, which allows to preserve order of object fields14# Experimental feature, which allows to preserve order of object fields
22exp-object-iteration = ["jrsonnet-evaluator/exp-object-iteration"]22exp-object-iteration = ["jrsonnet-evaluator/exp-object-iteration"]
23# Bigint type23# Bigint type
24exp-bigint = ["jrsonnet-evaluator/exp-bigint", "jrsonnet-cli/exp-bigint"]24exp-bigint = ["jrsonnet-evaluator/exp-bigint", "jrsonnet-cli/exp-bigint"]
25# obj?.field, obj?.['field']
26exp-null-coaelse = ["jrsonnet-evaluator/exp-null-coaelse", "jrsonnet-parser/exp-null-coaelse"]
27# --exp-apply
28exp-apply = []
2529
26# std.thisFile support30# std.thisFile support
27legacy-this-file = ["jrsonnet-cli/legacy-this-file"]31legacy-this-file = ["jrsonnet-cli/legacy-this-file"]
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
44 /// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself44 /// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself
45 pub input: Option<String>,45 pub input: Option<String>,
46
47 /// After executing input, apply specified code.
48 /// Output of the initial input will be accessible using `$`
49 #[cfg(feature = "exp-apply")]
50 #[clap(long)]
51 pub exp_apply: Vec<String>,
46}52}
4753
48/// Jsonnet commandline interpreter (Rust implementation)54/// Jsonnet commandline interpreter (Rust implementation)
181 };187 };
182188
183 let tla = opts.tla.tla_opts()?;189 let tla = opts.tla.tla_opts()?;
190 #[allow(unused_mut)]
184 let val = apply_tla(s.clone(), &tla, val)?;191 let mut val = apply_tla(s.clone(), &tla, val)?;
192
193 #[cfg(feature = "exp-apply")]
194 for apply in opts.input.exp_apply {
195 use jrsonnet_evaluator::{InitialUnderscore, Thunk};
196 val = s.evaluate_snippet_with(
197 "<exp_apply>".to_owned(),
198 &apply,
199 InitialUnderscore(Thunk::evaluated(val)),
200 )?;
201 }
185202
186 let manifest_format = opts.manifest.manifest_format();203 let manifest_format = opts.manifest.manifest_format();
187 if let Some(multi) = opts.output.multi {204 if let Some(multi) = opts.output.multi {
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
154 }154 }
155}155}
156
157macro_rules! impl_context_initializer {
158 ($($gen:ident)*) => {
159 #[allow(non_snake_case)]
160 impl<$($gen: ContextInitializer + Trace,)*> ContextInitializer for ($($gen,)*) {
161 fn reserve_vars(&self) -> usize {
162 let mut out = 0;
163 let ($($gen,)*) = self;
164 $(out += $gen.reserve_vars();)*
165 out
166 }
167 fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {
168 let ($($gen,)*) = self;
169 $($gen.populate(for_file.clone(), builder);)*
170 }
171 fn as_any(&self) -> &dyn Any {
172 self
173 }
174 }
175 };
176 ($($cur:ident)* @ $c:ident $($rest:ident)*) => {
177 impl_context_initializer!($($cur)*);
178 impl_context_initializer!($($cur)* $c @ $($rest)*);
179 };
180 ($($cur:ident)* @) => {
181 impl_context_initializer!($($cur)*);
182 }
183}
184impl_context_initializer! {
185 A B @ C D E
186}
156187
157/// Dynamically reconfigurable evaluation settings188/// Dynamically reconfigurable evaluation settings
158#[derive(Trace)]189#[derive(Trace)]
361 context_initializer.initialize(self.clone(), source)392 context_initializer.initialize(self.clone(), source)
362 }393 }
394
395 /// Creates context with all passed global variables, calling custom modifier
396 pub fn create_default_context_with(
397 &self,
398 source: Source,
399 context_initializer: impl ContextInitializer,
400 ) -> Context {
401 let default_initializer = &self.settings().context_initializer;
402 let mut builder = ContextBuilder::with_capacity(
403 self.clone(),
404 default_initializer.reserve_vars() + context_initializer.reserve_vars(),
405 );
406 default_initializer.populate(source.clone(), &mut builder);
407 context_initializer.populate(source, &mut builder);
408
409 builder.build()
410 }
363411
364 /// Executes code creating a new stack frame412 /// Executes code creating a new stack frame
365 pub fn push<T>(413 pub fn push<T>(
428 }476 }
429 let mut settings = self.settings_mut();477 let mut settings = self.settings_mut();
430 let initializer = &mut settings.context_initializer;478 let initializer = &mut settings.context_initializer;
431 match initializer.as_any().downcast_ref::<GlobalsCtx>() {479 if let Some(global) = initializer.as_any().downcast_ref::<GlobalsCtx>() {
432 Some(glob) => {480 global.globals.borrow_mut().insert(name, value);
433 glob.globals.borrow_mut().insert(name, value);
434 }481 } else {
435 None => {
436 let inner = std::mem::replace(&mut settings.context_initializer, tb!(()));482 let inner = std::mem::replace(&mut settings.context_initializer, tb!(()));
437 settings.context_initializer = tb!(GlobalsCtx {483 settings.context_initializer = tb!(GlobalsCtx {
438 globals: {484 globals: {
441 RefCell::new(out)487 RefCell::new(out)
442 },488 },
443 inner489 inner
444 })490 });
445 }491 }
446 }
447 }492 }
448}493}
494
495#[derive(Trace)]
496pub struct InitialUnderscore(pub Thunk<Val>);
497impl ContextInitializer for InitialUnderscore {
498 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {
499 builder.bind("_".into(), self.0.clone());
500 }
501
502 fn as_any(&self) -> &dyn Any {
503 self
504 }
505}
449506
450/// Raw methods evaluate passed values but don't perform TLA execution507/// Raw methods evaluate passed values but don't perform TLA execution
451impl State {508impl State {
465 })?;522 })?;
466 evaluate(self.create_default_context(source), &parsed)523 evaluate(self.create_default_context(source), &parsed)
467 }524 }
525 /// Parses and evaluates the given snippet with custom context modifier
526 pub fn evaluate_snippet_with(
527 &self,
528 name: impl Into<IStr>,
529 code: impl Into<IStr>,
530 context_initializer: impl ContextInitializer,
531 ) -> Result<Val> {
532 let code = code.into();
533 let source = Source::new_virtual(name.into(), code.clone());
534 let parsed = jrsonnet_parser::parse(
535 &code,
536 &ParserSettings {
537 source: source.clone(),
538 },
539 )
540 .map_err(|e| ImportSyntaxError {
541 path: source.clone(),
542 error: Box::new(e),
543 })?;
544 evaluate(
545 self.create_default_context_with(source, context_initializer),
546 &parsed,
547 )
548 }
468}549}
469550
470/// Settings utilities551/// Settings utilities