difftreelog
refactor move state to global
in: master
9 files changed
bindings/jsonnet/src/lib.rsdiffbeforeafterboth247 match vm247 match vm248 .state248 .state249 .import(filename)249 .import(filename)250 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))250 .and_then(|val| apply_tla(&vm.tla_args, val))251 .and_then(|val| val.manifest(&vm.manifest_format))251 .and_then(|val| val.manifest(&vm.manifest_format))252 {252 {253 Ok(v) => {253 Ok(v) => {282 match vm282 match vm283 .state283 .state284 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())284 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())285 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))285 .and_then(|val| apply_tla(&vm.tla_args, val))286 .and_then(|val| val.manifest(&vm.manifest_format))286 .and_then(|val| val.manifest(&vm.manifest_format))287 {287 {288 Ok(v) => {288 Ok(v) => {340 match vm340 match vm341 .state341 .state342 .import(filename)342 .import(filename)343 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))343 .and_then(|val| apply_tla(&vm.tla_args, val))344 .and_then(|val| val_to_multi(val, &vm.manifest_format))344 .and_then(|val| val_to_multi(val, &vm.manifest_format))345 {345 {346 Ok(v) => {346 Ok(v) => {369 match vm369 match vm370 .state370 .state371 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())371 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())372 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))372 .and_then(|val| apply_tla(&vm.tla_args, val))373 .and_then(|val| val_to_multi(val, &vm.manifest_format))373 .and_then(|val| val_to_multi(val, &vm.manifest_format))374 {374 {375 Ok(v) => {375 Ok(v) => {422 match vm422 match vm423 .state423 .state424 .import(filename)424 .import(filename)425 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))425 .and_then(|val| apply_tla(&vm.tla_args, val))426 .and_then(|val| val_to_stream(val, &vm.manifest_format))426 .and_then(|val| val_to_stream(val, &vm.manifest_format))427 {427 {428 Ok(v) => {428 Ok(v) => {451 match vm451 match vm452 .state452 .state453 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())453 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())454 .and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))454 .and_then(|val| apply_tla(&vm.tla_args, val))455 .and_then(|val| val_to_stream(val, &vm.manifest_format))455 .and_then(|val| val_to_stream(val, &vm.manifest_format))456 {456 {457 Ok(v) => {457 Ok(v) => {cmds/jrsonnet/src/main.rsdiffbeforeafterboth173 let mut s = State::builder();173 let mut s = State::builder();174 s.import_resolver(import_resolver).context_initializer(std);174 s.import_resolver(import_resolver).context_initializer(std);175 let s = s.build();175 let s = s.build();176 let _s = s.enter();176177177 let input = opts.input.input.ok_or(Error::MissingInputArgument)?;178 let input = opts.input.input.ok_or(Error::MissingInputArgument)?;178 let val = if opts.input.exec {179 let val = if opts.input.exec {192 unused_mut,193 unused_mut,193 clippy::redundant_clone,194 clippy::redundant_clone,194 )]195 )]195 let mut val = apply_tla(s.clone(), &tla, val)?;196 let mut val = apply_tla(&tla, val)?;196197197 #[cfg(feature = "exp-apply")]198 #[cfg(feature = "exp-apply")]198 for apply in opts.input.exp_apply {199 for apply in opts.input.exp_apply {crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth667use crate::{7use crate::{8 error::ErrorKind::*, gc::WithCapacityExt as _, map::LayeredHashMap, ObjValue, Pending, Result,8 error::ErrorKind::*, gc::WithCapacityExt as _, map::LayeredHashMap, ObjValue, Pending, Result,9 State, Thunk, Val,9 Thunk, Val,10};10};111112#[derive(Trace)]12#[derive(Trace)]13struct ContextInternals {13struct ContextInternals {14 state: Option<State>,15 dollar: Option<ObjValue>,14 dollar: Option<ObjValue>,16 sup: Option<ObjValue>,15 sup: Option<ObjValue>,17 this: Option<ObjValue>,16 this: Option<ObjValue>,33 Pending::new()32 Pending::new()34 }33 }3536 pub fn state(&self) -> &State {37 self.038 .state39 .as_ref()40 .expect("used state from dummy context")41 }423443 pub fn dollar(&self) -> Option<&ObjValue> {35 pub fn dollar(&self) -> Option<&ObjValue> {44 self.0.dollar.as_ref()36 self.0.dollar.as_ref()112 ctx.bindings.clone().extend(new_bindings)104 ctx.bindings.clone().extend(new_bindings)113 };105 };114 Self(Cc::new(ContextInternals {106 Self(Cc::new(ContextInternals {115 state: ctx.state.clone(),116 dollar,107 dollar,117 sup,108 sup,118 this,109 this,128}119}129120130pub struct ContextBuilder {121pub struct ContextBuilder {131 state: Option<State>,132 bindings: FxHashMap<IStr, Thunk<Val>>,122 bindings: FxHashMap<IStr, Thunk<Val>>,133 extend: Option<Context>,123 extend: Option<Context>,134}124}135125136impl ContextBuilder {126impl ContextBuilder {137 /// # Panics138 /// Panics aren't directly caused by this function, but if state from resulting context is used139 pub fn dangerous_empty_state() -> Self {140 Self {141 state: None,142 bindings: FxHashMap::new(),143 extend: None,144 }145 }146 pub fn new(state: State) -> Self {127 pub fn new() -> Self {147 Self::with_capacity(state, 0)128 Self::with_capacity(0)148 }129 }149 pub fn with_capacity(state: State, capacity: usize) -> Self {130 pub fn with_capacity(capacity: usize) -> Self {150 Self {131 Self {151 state: Some(state),152 bindings: FxHashMap::with_capacity(capacity),132 bindings: FxHashMap::with_capacity(capacity),153 extend: None,133 extend: None,154 }134 }155 }135 }156 pub fn extend(parent: Context) -> Self {136 pub fn extend(parent: Context) -> Self {157 Self {137 Self {158 state: parent.0.state.clone(),159 bindings: FxHashMap::new(),138 bindings: FxHashMap::new(),160 extend: Some(parent),139 extend: Some(parent),161 }140 }173 parent.extend(self.bindings, None, None, None)152 parent.extend(self.bindings, None, None, None)174 } else {153 } else {175 Context(Cc::new(ContextInternals {154 Context(Cc::new(ContextInternals {176 state: self.state,177 bindings: LayeredHashMap::new(self.bindings),155 bindings: LayeredHashMap::new(self.bindings),178 dollar: None,156 dollar: None,179 sup: None,157 sup: None,crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth4use jrsonnet_interner::IStr;4use jrsonnet_interner::IStr;5use jrsonnet_parser::{ArgsDesc, LocExpr, SourceFifo, SourcePath};5use jrsonnet_parser::{ArgsDesc, LocExpr, SourceFifo, SourcePath};667use crate::{evaluate, typed::Typed, Context, Result, Thunk, Val};7use crate::{evaluate, typed::Typed, with_state, Context, Result, Thunk, Val};889/// Marker for arguments, which can be evaluated with context set to None9/// Marker for arguments, which can be evaluated with context set to None10pub trait OptionalContext {}10pub trait OptionalContext {}47 ImportStr(String),47 ImportStr(String),48 InlineCode(String),48 InlineCode(String),49}49}50impl ArgLike for TlaArg {50impl TlaArg {51 pub fn evaluate_tailstrict(&self) -> Result<Val> {52 match self {53 Self::String(s) => Ok(Val::string(s.clone())),54 Self::Val(val) => Ok(val.clone()),55 Self::Lazy(lazy) => Ok(lazy.evaluate()?),56 Self::Import(p) => with_state(|s| {57 let resolved = s.resolve_from_default(&p.as_str())?;58 s.import_resolved(resolved)59 }),60 Self::ImportStr(p) => with_state(|s| {61 let resolved = s.resolve_from_default(&p.as_str())?;62 s.import_resolved_str(resolved).map(Val::string)63 }),64 Self::InlineCode(p) => with_state(|s| {65 let resolved =66 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));67 s.import_resolved(resolved)68 }),69 }70 }51 fn evaluate_arg(&self, ctx: Context, _tailstrict: bool) -> Result<Thunk<Val>> {71 pub fn evaluate(&self) -> Result<Thunk<Val>> {52 match self {72 match self {53 Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),73 Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),54 Self::Val(val) => Ok(Thunk::evaluated(val.clone())),74 Self::Val(val) => Ok(Thunk::evaluated(val.clone())),55 Self::Lazy(lazy) => Ok(lazy.clone()),75 Self::Lazy(lazy) => Ok(lazy.clone()),56 Self::Import(p) => {76 Self::Import(p) => with_state(|s| {57 let resolved = ctx.state().resolve_from_default(&p.as_str())?;77 let resolved = s.resolve_from_default(&p.as_str())?;58 Ok(Thunk!(move || ctx.state().import_resolved(resolved)))78 Ok(Thunk!(move || s.import_resolved(resolved)))59 }79 }),60 Self::ImportStr(p) => {80 Self::ImportStr(p) => with_state(|s| {61 let resolved = ctx.state().resolve_from_default(&p.as_str())?;81 let resolved = s.resolve_from_default(&p.as_str())?;62 Ok(Thunk!(move || ctx82 Ok(Thunk!(move || s63 .state()64 .import_resolved_str(resolved)83 .import_resolved_str(resolved)65 .map(Val::string)))84 .map(Val::string)))66 }85 }),67 Self::InlineCode(p) => {86 Self::InlineCode(p) => with_state(|s| {68 let resolved =87 let resolved =69 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));88 SourcePath::new(SourceFifo("<inline code>".to_owned(), p.as_bytes().into()));70 Ok(Thunk!(move || ctx.state().import_resolved(resolved)))89 Ok(Thunk!(move || s.import_resolved(resolved)))71 }90 }),72 }91 }73 }92 }74}93}9495// TODO: Is this implementation really required, as there is no Context to use?96// Maybe something a bit stricter is possible to add, especially with precompiled calls?97impl ArgLike for TlaArg {98 fn evaluate_arg(&self, _ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {99 if tailstrict {100 self.evaluate_tailstrict().map(Thunk::evaluated)101 } else {102 self.evaluate()103 }104 }105}7510676pub trait ArgsLike {107pub trait ArgsLike {77 fn unnamed_len(&self) -> usize;108 fn unnamed_len(&self) -> usize;crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth207 tailstrict: bool,207 tailstrict: bool,208 ) -> Result<Val> {208 ) -> Result<Val> {209 self.evaluate(209 self.evaluate(210 ContextBuilder::dangerous_empty_state().build(),210 ContextBuilder::new().build(),211 CallLocation::native(),211 CallLocation::native(),212 args,212 args,213 tailstrict,213 tailstrict,crates/jrsonnet-evaluator/src/tla.rsdiffbeforeafterboth1use jrsonnet_interner::IStr;1use jrsonnet_interner::IStr;2use jrsonnet_parser::Source;2use jrsonnet_parser::Source;3use rustc_hash::FxHashMap;344use crate::{5use crate::{5 function::{ArgsLike, CallLocation},6 function::{CallLocation, TlaArg},6 in_description_frame, Result, State, Val,7 in_description_frame, with_state, Result, Val,7};8};899pub fn apply_tla<A: ArgsLike>(s: State, args: &A, val: Val) -> Result<Val> {10pub fn apply_tla(args: &FxHashMap<IStr, TlaArg>, val: Val) -> Result<Val> {10 Ok(if let Val::Func(func) = val {11 Ok(if let Val::Func(func) = val {11 in_description_frame(12 in_description_frame(12 || "during TLA call".to_owned(),13 || "during TLA call".to_owned(),13 || {14 || {14 func.evaluate(15 func.evaluate(16 with_state(|s| {15 s.create_default_context(Source::new_virtual(17 s.create_default_context(Source::new_virtual(16 "<top-level-arg>".into(),18 "<top-level-arg>".into(),17 IStr::empty(),19 IStr::empty(),18 )),20 ))21 }),19 CallLocation::native(),22 CallLocation::native(),20 args,23 args,21 false,24 false,crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth335 pub path_resolver: PathResolver,335 pub path_resolver: PathResolver,336}336}337338fn extvar_source(name: &str, code: impl Into<IStr>) -> Source {339 let source_name = format!("<extvar:{name}>");340 Source::new_virtual(source_name.into(), code.into())341}342337343#[derive(Trace, Clone)]338#[derive(Trace, Clone)]344pub struct ContextInitializer {339pub struct ContextInitializer {crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{4 bail,4 bail,5 error::{ErrorKind::*, Result},5 error::{ErrorKind::*, Result},6 function::{builtin, ArgLike, CallLocation, FuncVal},6 function::{builtin, CallLocation, FuncVal},7 manifest::JsonFormat,7 manifest::JsonFormat,8 typed::{Either2, Either4},8 typed::{Either2, Either4},9 val::{equals, ArrValue},9 val::{equals, ArrValue},10 Context, Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,10 Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,11};11};12use jrsonnet_gcmodule::Cc;12use jrsonnet_gcmodule::Cc;131314use crate::{extvar_source, Settings};14use crate::Settings;151516#[builtin]16#[builtin]17pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {17pub fn builtin_length(x: Either![IStr, ArrValue, ObjValue, FuncVal]) -> usize {50#[builtin(fields(50#[builtin(fields(51 settings: Cc<RefCell<Settings>>,51 settings: Cc<RefCell<Settings>>,52))]52))]53pub fn builtin_ext_var(this: &builtin_ext_var, ctx: Context, x: IStr) -> Result<Val> {53pub fn builtin_ext_var(this: &builtin_ext_var, x: IStr) -> Result<Val> {54 let ctx = ctx.state().create_default_context(extvar_source(&x, ""));55 this.settings54 this.settings56 .borrow()55 .borrow()57 .ext_vars56 .ext_vars58 .get(&x)57 .get(&x)59 .cloned()58 .cloned()60 .ok_or_else(|| UndefinedExternalVariable(x))?59 .ok_or_else(|| UndefinedExternalVariable(x))?61 .evaluate_arg(ctx, true)?62 .evaluate()60 .evaluate_tailstrict()63}61}646265#[builtin(fields(63#[builtin(fields(tests/tests/builtin.rsdiffbeforeafterboth19fn basic_function() -> Result<()> {19fn basic_function() -> Result<()> {20 let a: a = a {};20 let a: a = a {};21 let v = u32::from_untyped(a.call(21 let v = u32::from_untyped(a.call(22 ContextBuilder::dangerous_empty_state().build(),22 ContextBuilder::new().build(),23 CallLocation::native(),23 CallLocation::native(),24 &(),24 &(),25 )?)?;25 )?)?;