1#![feature(box_syntax, box_patterns)]2#![feature(type_alias_impl_trait)]3#![feature(debug_non_exhaustive)]4#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]5mod ctx;6mod dynamic;7mod error;8mod evaluate;9mod obj;10mod val;1112use closure::closure;13pub use ctx::*;14pub use dynamic::*;15pub use error::*;16pub use evaluate::*;17use jsonnet_parser::*;18pub use obj::*;19use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc};20pub use val::*;2122rc_fn_helper!(23 Binding,24 binding,25 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<Val>26);27rc_fn_helper!(28 LazyBinding,29 lazy_binding,30 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Result<LazyVal>31);32rc_fn_helper!(FunctionRhs, function_rhs, dyn Fn(Context) -> Result<Val>);33rc_fn_helper!(34 FunctionDefault,35 function_default,36 dyn Fn(Context, LocExpr) -> Result<Val>37);3839pub struct FileData(String, LocExpr, Option<Val>);40#[derive(Default)]41pub struct EvaluationStateInternals {42 43 stack: RefCell<Vec<StackTraceElement>>,44 45 46 files: RefCell<HashMap<PathBuf, FileData>>,47 globals: RefCell<HashMap<String, Val>>,48}4950thread_local! {51 pub static EVAL_STATE: RefCell<Option<EvaluationState>> = RefCell::new(None)52}53pub(crate) fn with_state<T>(f: impl FnOnce(&EvaluationState) -> T) -> T {54 EVAL_STATE.with(|s| f(s.borrow().as_ref().unwrap()))55}56pub(crate) fn create_error<T>(err: Error) -> Result<T> {57 with_state(|s| s.error(err))58}59pub(crate) fn push<T>(e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {60 with_state(|s| s.push(e, comment, f))61}6263#[derive(Default, Clone)]64pub struct EvaluationState(Rc<EvaluationStateInternals>);65impl EvaluationState {66 pub fn add_file(&self, name: PathBuf, code: String) -> std::result::Result<(), ParseError> {67 self.0.files.borrow_mut().insert(68 name.clone(),69 FileData(70 code.clone(),71 parse(72 &code,73 &ParserSettings {74 file_name: name,75 loc_data: true,76 },77 )?,78 None,79 ),80 );8182 Ok(())83 }84 pub fn add_parsed_file(85 &self,86 name: PathBuf,87 code: String,88 parsed: LocExpr,89 ) -> std::result::Result<(), ()> {90 self.091 .files92 .borrow_mut()93 .insert(name, FileData(code, parsed, None));9495 Ok(())96 }97 pub fn get_source(&self, name: &PathBuf) -> Option<String> {98 let ro_map = self.0.files.borrow();99 ro_map.get(name).map(|value| value.0.clone())100 }101 pub fn evaluate_file(&self, name: &PathBuf) -> Result<Val> {102 self.begin_state();103 let expr: LocExpr = {104 let ro_map = self.0.files.borrow();105 let value = ro_map106 .get(name)107 .unwrap_or_else(|| panic!("file not added: {:?}", name));108 if value.2.is_some() {109 return Ok(value.2.clone().unwrap());110 }111 value.1.clone()112 };113 let value = evaluate(self.create_default_context()?, &expr)?;114 {115 self.0116 .files117 .borrow_mut()118 .get_mut(name)119 .unwrap()120 .2121 .replace(value.clone());122 }123 self.end_state();124 Ok(value)125 }126127 pub fn parse_evaluate_raw(&self, code: &str) -> Result<Val> {128 let parsed = parse(129 &code,130 &ParserSettings {131 file_name: PathBuf::from("raw.jsonnet"),132 loc_data: true,133 },134 );135 self.begin_state();136 let value = evaluate(self.create_default_context()?, &parsed.unwrap());137 self.end_state();138 value139 }140141 pub fn add_global(&self, name: String, value: Val) {142 self.0.globals.borrow_mut().insert(name, value);143 }144145 pub fn add_stdlib(&self) {146 self.begin_state();147 use jsonnet_stdlib::STDLIB_STR;148 if cfg!(feature = "serialized-stdlib") {149 self.add_parsed_file(150 PathBuf::from("std.jsonnet"),151 STDLIB_STR.to_owned(),152 bincode::deserialize(include_bytes!(concat!(env!("OUT_DIR"), "/stdlib.bincode")))153 .expect("deserialize stdlib"),154 )155 .unwrap();156 } else {157 self.add_file(PathBuf::from("std.jsonnet"), STDLIB_STR.to_owned())158 .unwrap();159 }160 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();161 self.add_global("std".to_owned(), val);162 self.end_state();163 }164165 pub fn create_default_context(&self) -> Result<Context> {166 let globals = self.0.globals.borrow();167 let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();168 for (name, value) in globals.iter() {169 new_bindings.insert(170 name.clone(),171 lazy_binding!(172 closure!(clone value, |_self, _super_obj| Ok(lazy_val!(closure!(clone value, ||Ok(value.clone())))))173 ),174 );175 }176 Context::new().extend(new_bindings, None, None, None)177 }178179 pub fn push<T>(&self, e: LocExpr, comment: String, f: impl FnOnce() -> Result<T>) -> Result<T> {180 {181 let mut stack = self.0.stack.borrow_mut();182 if stack.len() > 5000 {183 drop(stack);184 return self.error(Error::StackOverflow);185 } else {186 stack.push(StackTraceElement(e, comment));187 }188 }189 let result = f();190 self.0.stack.borrow_mut().pop();191 result192 }193 pub fn print_stack_trace(&self) {194 for e in self.stack_trace().0 {195 println!("{:?} - {:?}", e.0, e.1)196 }197 }198 pub fn stack_trace(&self) -> StackTrace {199 StackTrace(self.0.stack.borrow().iter().rev().cloned().collect())200 }201 pub fn error<T>(&self, err: Error) -> Result<T> {202 Err(LocError(err, self.stack_trace()))203 }204205 fn begin_state(&self) {206 EVAL_STATE.with(|v| v.borrow_mut().replace(self.clone()));207 }208 fn end_state(&self) {209 EVAL_STATE.with(|v| v.borrow_mut().take());210 }211}212213#[cfg(test)]214pub mod tests {215 use super::Val;216 use crate::EvaluationState;217 use jsonnet_parser::*;218 use std::path::PathBuf;219220 #[test]221 fn eval_state_stacktrace() {222 let state = EvaluationState::default();223 state224 .push(225 loc_expr!(226 Expr::Num(0.0),227 true,228 (PathBuf::from("test1.jsonnet"), 10, 20)229 ),230 "outer".to_owned(),231 || {232 state.push(233 loc_expr!(234 Expr::Num(0.0),235 true,236 (PathBuf::from("test2.jsonnet"), 30, 40)237 ),238 "inner".to_owned(),239 || {240 state.print_stack_trace();241 Ok(())242 },243 )?;244 Ok(())245 },246 )247 .unwrap();248 }249250 #[test]251 fn eval_state_standard() {252 let state = EvaluationState::default();253 state.add_stdlib();254 assert_eq!(255 state256 .parse_evaluate_raw(r#"std.assertEqual(std.base64("test"), "dGVzdA==")"#)257 .unwrap(),258 Val::Bool(true)259 );260 }261262 macro_rules! eval {263 ($str: expr) => {264 evaluate(265 Context::new(),266 EvaluationState::default(),267 &parse(268 $str,269 &ParserSettings {270 loc_data: true,271 file_name: "test.jsonnet".to_owned(),272 },273 )274 .unwrap(),275 )276 };277 }278279 macro_rules! eval_stdlib {280 ($str: expr) => {{281 let std = "local std = ".to_owned() + jsonnet_stdlib::STDLIB_STR + ";";282 evaluate(283 Context::new(),284 EvaluationState::default(),285 &parse(286 &(std + $str),287 &ParserSettings {288 loc_data: true,289 file_name: "test.jsonnet".to_owned(),290 },291 )292 .unwrap(),293 )294 }};295 }296297 macro_rules! assert_eval {298 ($str: expr) => {299 assert_eq!(300 evaluate(301 Context::new(),302 EvaluationState::default(),303 &parse(304 $str,305 &ParserSettings {306 loc_data: true,307 file_name: "test.jsonnet".to_owned(),308 }309 )310 .unwrap()311 ),312 Val::Bool(true)313 )314 };315 }316 macro_rules! assert_json {317 ($str: expr, $out: expr) => {318 assert_eq!(319 format!(320 "{}",321 evaluate(322 Context::new(),323 EvaluationState::default(),324 &parse(325 $str,326 &ParserSettings {327 loc_data: true,328 file_name: "test.jsonnet".to_owned(),329 }330 )331 .unwrap()332 )333 ),334 $out335 )336 };337 }338 macro_rules! assert_json_stdlib {339 ($str: expr, $out: expr) => {340 assert_eq!(format!("{}", eval_stdlib!($str)), $out)341 };342 }343 macro_rules! assert_eval_neg {344 ($str: expr) => {345 assert_eq!(346 evaluate(347 Context::new(),348 EvaluationState::default(),349 &parse(350 $str,351 &ParserSettings {352 loc_data: true,353 file_name: "test.jsonnet".to_owned(),354 }355 )356 .unwrap()357 ),358 Val::Bool(false)359 )360 };361 }362363 364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574}