difftreelog
refactor move state to global
in: master
9 files changed
bindings/jsonnet/src/lib.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -247,7 +247,7 @@
match vm
.state
.import(filename)
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val.manifest(&vm.manifest_format))
{
Ok(v) => {
@@ -282,7 +282,7 @@
match vm
.state
.evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val.manifest(&vm.manifest_format))
{
Ok(v) => {
@@ -340,7 +340,7 @@
match vm
.state
.import(filename)
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val_to_multi(val, &vm.manifest_format))
{
Ok(v) => {
@@ -369,7 +369,7 @@
match vm
.state
.evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val_to_multi(val, &vm.manifest_format))
{
Ok(v) => {
@@ -422,7 +422,7 @@
match vm
.state
.import(filename)
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val_to_stream(val, &vm.manifest_format))
{
Ok(v) => {
@@ -451,7 +451,7 @@
match vm
.state
.evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())
- .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
+ .and_then(|val| apply_tla(&vm.tla_args, val))
.and_then(|val| val_to_stream(val, &vm.manifest_format))
{
Ok(v) => {
cmds/jrsonnet/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -173,6 +173,7 @@
let mut s = State::builder();
s.import_resolver(import_resolver).context_initializer(std);
let s = s.build();
+ let _s = s.enter();
let input = opts.input.input.ok_or(Error::MissingInputArgument)?;
let val = if opts.input.exec {
@@ -192,7 +193,7 @@
unused_mut,
clippy::redundant_clone,
)]
- let mut val = apply_tla(s.clone(), &tla, val)?;
+ let mut val = apply_tla(&tla, val)?;
#[cfg(feature = "exp-apply")]
for apply in opts.input.exp_apply {
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -6,12 +6,11 @@
use crate::{
error::ErrorKind::*, gc::WithCapacityExt as _, map::LayeredHashMap, ObjValue, Pending, Result,
- State, Thunk, Val,
+ Thunk, Val,
};
#[derive(Trace)]
struct ContextInternals {
- state: Option<State>,
dollar: Option<ObjValue>,
sup: Option<ObjValue>,
this: Option<ObjValue>,
@@ -33,13 +32,6 @@
Pending::new()
}
- pub fn state(&self) -> &State {
- self.0
- .state
- .as_ref()
- .expect("used state from dummy context")
- }
-
pub fn dollar(&self) -> Option<&ObjValue> {
self.0.dollar.as_ref()
}
@@ -112,7 +104,6 @@
ctx.bindings.clone().extend(new_bindings)
};
Self(Cc::new(ContextInternals {
- state: ctx.state.clone(),
dollar,
sup,
this,
@@ -128,34 +119,22 @@
}
pub struct ContextBuilder {
- state: Option<State>,
bindings: FxHashMap<IStr, Thunk<Val>>,
extend: Option<Context>,
}
impl ContextBuilder {
- /// # Panics
- /// Panics aren't directly caused by this function, but if state from resulting context is used
- pub fn dangerous_empty_state() -> Self {
- Self {
- state: None,
- bindings: FxHashMap::new(),
- extend: None,
- }
+ pub fn new() -> Self {
+ Self::with_capacity(0)
}
- pub fn new(state: State) -> Self {
- Self::with_capacity(state, 0)
- }
- pub fn with_capacity(state: State, capacity: usize) -> Self {
+ pub fn with_capacity(capacity: usize) -> Self {
Self {
- state: Some(state),
bindings: FxHashMap::with_capacity(capacity),
extend: None,
}
}
pub fn extend(parent: Context) -> Self {
Self {
- state: parent.0.state.clone(),
bindings: FxHashMap::new(),
extend: Some(parent),
}
@@ -173,7 +152,6 @@
parent.extend(self.bindings, None, None, None)
} else {
Context(Cc::new(ContextInternals {
- state: self.state,
bindings: LayeredHashMap::new(self.bindings),
dollar: None,
sup: None,
crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth1use std::collections::HashMap;23use jrsonnet_gcmodule::Trace;4use jrsonnet_interner::IStr;5use jrsonnet_parser::{ArgsDesc, LocExpr, SourceFifo, SourcePath};67use crate::{evaluate, typed::Typed, Context, Result, Thunk, Val};89/// Marker for arguments, which can be evaluated with context set to None10pub trait OptionalContext {}1112pub trait ArgLike {13 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>>;14}1516impl ArgLike for &LocExpr {17 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {18 Ok(if tailstrict {19 Thunk::evaluated(evaluate(ctx, self)?)20 } else {21 let expr = (*self).clone();22 Thunk!(move || evaluate(ctx, &expr))23 })24 }25}2627impl<T> ArgLike for T28where29 T: Typed + Clone,30{31 fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {32 if T::provides_lazy() && !tailstrict {33 return Ok(T::into_lazy_untyped(self.clone()));34 }35 let val = T::into_untyped(self.clone())?;36 Ok(Thunk::evaluated(val))37 }38}39impl<T> OptionalContext for T where T: Typed + Clone {}4041#[derive(Clone, Trace)]42pub enum TlaArg {43 String(IStr),44 Val(Val),45 Lazy(Thunk<Val>),46 Import(String),47 ImportStr(String),48 InlineCode(String),49}50impl ArgLike for TlaArg {51 fn evaluate_arg(&self, ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {52 match self {53 Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),54 Self::Val(val) => Ok(Thunk::evaluated(val.clone())),55 Self::Lazy(lazy) => Ok(lazy.clone()),56 Self::Import(p) => {57 let resolved = ctx.state().resolve_from_default(&p.as_str())?;58 Ok(Thunk!(move || ctx.state().import_resolved(resolved)))59 }60 Self::ImportStr(p) => {61 let resolved = ctx.state().resolve_from_default(&p.as_str())?;62 Ok(Thunk!(move || ctx63 .state()64 .import_resolved_str(resolved)65 .map(Val::string)))66 }67 Self::InlineCode(p) => {68 let resolved =69 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));70 Ok(Thunk!(move || ctx.state().import_resolved(resolved)))71 }72 }73 }74}7576pub trait ArgsLike {77 fn unnamed_len(&self) -> usize;78 fn unnamed_iter(79 &self,80 ctx: Context,81 tailstrict: bool,82 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,83 ) -> Result<()>;84 fn named_iter(85 &self,86 ctx: Context,87 tailstrict: bool,88 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,89 ) -> Result<()>;90 fn named_names(&self, handler: &mut dyn FnMut(&IStr));91 fn is_empty(&self) -> bool;92}9394impl ArgsLike for Vec<Val> {95 fn unnamed_len(&self) -> usize {96 self.len()97 }98 fn unnamed_iter(99 &self,100 _ctx: Context,101 _tailstrict: bool,102 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,103 ) -> Result<()> {104 for (idx, el) in self.iter().enumerate() {105 handler(idx, Thunk::evaluated(el.clone()))?;106 }107 Ok(())108 }109 fn named_iter(110 &self,111 _ctx: Context,112 _tailstrict: bool,113 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,114 ) -> Result<()> {115 Ok(())116 }117 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}118 fn is_empty(&self) -> bool {119 self.is_empty()120 }121}122123impl ArgsLike for ArgsDesc {124 fn unnamed_len(&self) -> usize {125 self.unnamed.len()126 }127128 fn unnamed_iter(129 &self,130 ctx: Context,131 tailstrict: bool,132 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,133 ) -> Result<()> {134 for (id, arg) in self.unnamed.iter().enumerate() {135 handler(136 id,137 if tailstrict {138 Thunk::evaluated(evaluate(ctx.clone(), arg)?)139 } else {140 let ctx = ctx.clone();141 let arg = arg.clone();142143 Thunk!(move || evaluate(ctx, &arg))144 },145 )?;146 }147 Ok(())148 }149150 fn named_iter(151 &self,152 ctx: Context,153 tailstrict: bool,154 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,155 ) -> Result<()> {156 for (name, arg) in &self.named {157 handler(158 name,159 if tailstrict {160 Thunk::evaluated(evaluate(ctx.clone(), arg)?)161 } else {162 let ctx = ctx.clone();163 let arg = arg.clone();164165 Thunk!(move || evaluate(ctx, &arg))166 },167 )?;168 }169 Ok(())170 }171172 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {173 for (name, _) in &self.named {174 handler(name);175 }176 }177178 fn is_empty(&self) -> bool {179 self.unnamed.is_empty() && self.named.is_empty()180 }181}182183impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {184 fn unnamed_len(&self) -> usize {185 0186 }187188 fn unnamed_iter(189 &self,190 _ctx: Context,191 _tailstrict: bool,192 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,193 ) -> Result<()> {194 Ok(())195 }196197 fn named_iter(198 &self,199 ctx: Context,200 tailstrict: bool,201 handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,202 ) -> Result<()> {203 for (name, value) in self {204 handler(name, value.evaluate_arg(ctx.clone(), tailstrict)?)?;205 }206 Ok(())207 }208209 fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {210 for (name, _) in self {211 handler(name);212 }213 }214215 fn is_empty(&self) -> bool {216 self.is_empty()217 }218}219impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}220221macro_rules! impl_args_like {222 ($count:expr; $($gen:ident)*) => {223 impl<$($gen: ArgLike,)*> ArgsLike for ($($gen,)*) {224 fn unnamed_len(&self) -> usize {225 $count226 }227 #[allow(non_snake_case, unused_assignments)]228 fn unnamed_iter(229 &self,230 ctx: Context,231 tailstrict: bool,232 handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,233 ) -> Result<()> {234 let mut i = 0usize;235 let ($($gen,)*) = self;236 $(237 handler(i, $gen.evaluate_arg(ctx.clone(), tailstrict)?)?;238 i+=1;239 )*240 Ok(())241 }242 fn named_iter(243 &self,244 _ctx: Context,245 _tailstrict: bool,246 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,247 ) -> Result<()> {248 Ok(())249 }250 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}251252 fn is_empty(&self) -> bool {253 // impl_args_like only implements non-empty tuples.254 false255 }256 }257 impl<$($gen: ArgLike,)*> OptionalContext for ($($gen,)*) where $($gen: OptionalContext),* {}258 };259 ($count:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {260 impl_args_like!($count; $($cur)*);261 impl_args_like!($count + 1usize; $($cur)* $c @ $($rest)*);262 };263 ($count:expr; $($cur:ident)* @) => {264 impl_args_like!($count; $($cur)*);265 }266}267impl_args_like! {268 // First argument is already in position, so count starts from 1269 1usize; A @ B C D E F G H I J K L270}271272impl ArgsLike for () {273 fn unnamed_len(&self) -> usize {274 0275 }276277 fn unnamed_iter(278 &self,279 _ctx: Context,280 _tailstrict: bool,281 _handler: &mut dyn FnMut(usize, Thunk<Val>) -> Result<()>,282 ) -> Result<()> {283 Ok(())284 }285286 fn named_iter(287 &self,288 _ctx: Context,289 _tailstrict: bool,290 _handler: &mut dyn FnMut(&IStr, Thunk<Val>) -> Result<()>,291 ) -> Result<()> {292 Ok(())293 }294295 fn named_names(&self, _handler: &mut dyn FnMut(&IStr)) {}296 fn is_empty(&self) -> bool {297 true298 }299}300impl OptionalContext for () {}crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/mod.rs
+++ b/crates/jrsonnet-evaluator/src/function/mod.rs
@@ -207,7 +207,7 @@
tailstrict: bool,
) -> Result<Val> {
self.evaluate(
- ContextBuilder::dangerous_empty_state().build(),
+ ContextBuilder::new().build(),
CallLocation::native(),
args,
tailstrict,
crates/jrsonnet-evaluator/src/tla.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/tla.rs
+++ b/crates/jrsonnet-evaluator/src/tla.rs
@@ -1,21 +1,24 @@
use jrsonnet_interner::IStr;
use jrsonnet_parser::Source;
+use rustc_hash::FxHashMap;
use crate::{
- function::{ArgsLike, CallLocation},
- in_description_frame, Result, State, Val,
+ function::{CallLocation, TlaArg},
+ in_description_frame, with_state, Result, Val,
};
-pub fn apply_tla<A: ArgsLike>(s: State, args: &A, val: Val) -> Result<Val> {
+pub fn apply_tla(args: &FxHashMap<IStr, TlaArg>, val: Val) -> Result<Val> {
Ok(if let Val::Func(func) = val {
in_description_frame(
|| "during TLA call".to_owned(),
|| {
func.evaluate(
- s.create_default_context(Source::new_virtual(
- "<top-level-arg>".into(),
- IStr::empty(),
- )),
+ with_state(|s| {
+ s.create_default_context(Source::new_virtual(
+ "<top-level-arg>".into(),
+ IStr::empty(),
+ ))
+ }),
CallLocation::native(),
args,
false,
crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -335,11 +335,6 @@
pub path_resolver: PathResolver,
}
-fn extvar_source(name: &str, code: impl Into<IStr>) -> Source {
- let source_name = format!("<extvar:{name}>");
- Source::new_virtual(source_name.into(), code.into())
-}
-
#[derive(Trace, Clone)]
pub struct ContextInitializer {
/// std without applied thisFile overlay
crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -3,15 +3,15 @@
use jrsonnet_evaluator::{
bail,
error::{ErrorKind::*, Result},
- function::{builtin, ArgLike, CallLocation, FuncVal},
+ function::{builtin, CallLocation, FuncVal},
manifest::JsonFormat,
typed::{Either2, Either4},
val::{equals, ArrValue},
- Context, Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,
+ Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,
};
use jrsonnet_gcmodule::Cc;
-use crate::{extvar_source, Settings};
+use crate::Settings;
#[builtin]
pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {
@@ -50,16 +50,14 @@
#[builtin(fields(
settings: Cc<RefCell<Settings>>,
))]
-pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Val> {
- let ctx = ctx.state().create_default_context(extvar_source(&x, ""));
+pub fn builtin_ext_var(this: &builtin_ext_var, x: IStr) -> Result<Val> {
this.settings
.borrow()
.ext_vars
.get(&x)
.cloned()
.ok_or_else(|| UndefinedExternalVariable(x))?
- .evaluate_arg(ctx, true)?
- .evaluate()
+ .evaluate_tailstrict()
}
#[builtin(fields(
tests/tests/builtin.rsdiffbeforeafterboth--- a/tests/tests/builtin.rs
+++ b/tests/tests/builtin.rs
@@ -19,7 +19,7 @@
fn basic_function() -> Result<()> {
let a: a = a {};
let v = u32::from_untyped(a.call(
- ContextBuilder::dangerous_empty_state().build(),
+ ContextBuilder::new().build(),
CallLocation::native(),
&(),
)?)?;