1use crate::{2 builtin::{3 call_builtin,4 manifest::{5 manifest_json_ex, manifest_yaml_ex, ManifestJsonOptions, ManifestType,6 ManifestYamlOptions,7 },8 },9 cc_ptr_eq,10 error::{Error::*, LocError},11 evaluate,12 function::{parse_function_call, parse_function_call_map, place_args},13 gc::TraceBox,14 native::NativeCallback,15 throw, Context, ObjValue, Result,16};17use gcmodule::{Cc, Trace};18use jrsonnet_interner::IStr;19use jrsonnet_parser::{ArgsDesc, ExprLocation, LocExpr, ParamsDesc};20use jrsonnet_types::ValType;21use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};2223pub trait LazyValValue: Trace {24 fn get(self: Box<Self>) -> Result<Val>;25}2627#[derive(Trace)]28enum LazyValInternals {29 Computed(Val),30 Errored(LocError),31 Waiting(TraceBox<dyn LazyValValue>),32 Pending,33}3435#[derive(Clone, Trace)]36pub struct LazyVal(Cc<RefCell<LazyValInternals>>);37impl LazyVal {38 pub fn new(f: TraceBox<dyn LazyValValue>) -> Self {39 Self(Cc::new(RefCell::new(LazyValInternals::Waiting(f))))40 }41 pub fn new_resolved(val: Val) -> Self {42 Self(Cc::new(RefCell::new(LazyValInternals::Computed(val))))43 }44 pub fn evaluate(&self) -> Result<Val> {45 match &*self.0.borrow() {46 LazyValInternals::Computed(v) => return Ok(v.clone()),47 LazyValInternals::Errored(e) => return Err(e.clone()),48 LazyValInternals::Pending => return Err(RecursiveLazyValueEvaluation.into()),49 _ => (),50 };51 let value = if let LazyValInternals::Waiting(value) =52 std::mem::replace(&mut *self.0.borrow_mut(), LazyValInternals::Pending)53 {54 value55 } else {56 unreachable!()57 };58 let new_value = match value.0.get() {59 Ok(v) => v,60 Err(e) => {61 *self.0.borrow_mut() = LazyValInternals::Errored(e.clone());62 return Err(e);63 }64 };65 *self.0.borrow_mut() = LazyValInternals::Computed(new_value.clone());66 Ok(new_value)67 }68}6970impl Debug for LazyVal {71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {72 write!(f, "Lazy")73 }74}75impl PartialEq for LazyVal {76 fn eq(&self, other: &Self) -> bool {77 cc_ptr_eq(&self.0, &other.0)78 }79}8081#[derive(Debug, PartialEq, Trace)]82pub struct FuncDesc {83 pub name: IStr,84 pub ctx: Context,85 pub params: ParamsDesc,86 pub body: LocExpr,87}8889#[derive(Debug, Trace)]90pub enum FuncVal {91 92 Normal(FuncDesc),93 94 Intrinsic(IStr),95 96 NativeExt(IStr, Cc<NativeCallback>),97}9899impl PartialEq for FuncVal {100 fn eq(&self, other: &Self) -> bool {101 match (self, other) {102 (Self::Normal(a), Self::Normal(b)) => a == b,103 (Self::Intrinsic(an), Self::Intrinsic(bn)) => an == bn,104 (Self::NativeExt(an, _), Self::NativeExt(bn, _)) => an == bn,105 (..) => false,106 }107 }108}109impl FuncVal {110 pub fn is_ident(&self) -> bool {111 matches!(&self, Self::Intrinsic(n) if n as &str == "id")112 }113 pub fn name(&self) -> IStr {114 match self {115 Self::Normal(normal) => normal.name.clone(),116 Self::Intrinsic(name) => format!("std.{}", name).into(),117 Self::NativeExt(n, _) => format!("native.{}", n).into(),118 }119 }120 pub fn evaluate(121 &self,122 call_ctx: Context,123 loc: &ExprLocation,124 args: &ArgsDesc,125 tailstrict: bool,126 ) -> Result<Val> {127 match self {128 Self::Normal(func) => {129 let ctx = parse_function_call(130 call_ctx,131 func.ctx.clone(),132 &func.params,133 args,134 tailstrict,135 )?;136 evaluate(ctx, &func.body)137 }138 Self::Intrinsic(name) => call_builtin(call_ctx, loc, name, args),139 Self::NativeExt(_name, handler) => {140 let args =141 parse_function_call(call_ctx, Context::new(), &handler.params, args, true)?;142 let mut out_args = Vec::with_capacity(handler.params.len());143 for p in handler.params.0.iter() {144 out_args.push(args.binding(p.0.clone())?.evaluate()?);145 }146 Ok(handler.call(loc.0.clone(), &out_args)?)147 }148 }149 }150151 pub fn evaluate_map(152 &self,153 call_ctx: Context,154 args: &HashMap<IStr, Val>,155 tailstrict: bool,156 ) -> Result<Val> {157 match self {158 Self::Normal(func) => {159 let ctx = parse_function_call_map(160 call_ctx,161 Some(func.ctx.clone()),162 &func.params,163 args,164 tailstrict,165 )?;166 evaluate(ctx, &func.body)167 }168 Self::Intrinsic(_) => todo!(),169 Self::NativeExt(_, _) => todo!(),170 }171 }172173 pub fn evaluate_values(&self, call_ctx: Context, args: &[Val]) -> Result<Val> {174 match self {175 Self::Normal(func) => {176 let ctx = place_args(call_ctx, Some(func.ctx.clone()), &func.params, args)?;177 evaluate(ctx, &func.body)178 }179 Self::Intrinsic(_) => todo!(),180 Self::NativeExt(_, _) => todo!(),181 }182 }183}184185#[derive(Clone)]186pub enum ManifestFormat {187 YamlStream(Box<ManifestFormat>),188 Yaml(usize),189 Json(usize),190 ToString,191 String,192}193194#[derive(Debug, Clone, Trace)]195#[force_tracking]196pub enum ArrValue {197 Lazy(Cc<Vec<LazyVal>>),198 Eager(Cc<Vec<Val>>),199 Extended(Box<(Self, Self)>),200}201impl ArrValue {202 pub fn new_eager() -> Self {203 Self::Eager(Cc::new(Vec::new()))204 }205206 pub fn len(&self) -> usize {207 match self {208 Self::Lazy(l) => l.len(),209 Self::Eager(e) => e.len(),210 Self::Extended(v) => v.0.len() + v.1.len(),211 }212 }213214 pub fn is_empty(&self) -> bool {215 self.len() == 0216 }217218 pub fn get(&self, index: usize) -> Result<Option<Val>> {219 match self {220 Self::Lazy(vec) => {221 if let Some(v) = vec.get(index) {222 Ok(Some(v.evaluate()?))223 } else {224 Ok(None)225 }226 }227 Self::Eager(vec) => Ok(vec.get(index).cloned()),228 Self::Extended(v) => {229 let a_len = v.0.len();230 if a_len > index {231 v.0.get(index)232 } else {233 v.1.get(index - a_len)234 }235 }236 }237 }238239 pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {240 match self {241 Self::Lazy(vec) => vec.get(index).cloned(),242 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),243 Self::Extended(v) => {244 let a_len = v.0.len();245 if a_len > index {246 v.0.get_lazy(index)247 } else {248 v.1.get_lazy(index - a_len)249 }250 }251 }252 }253254 pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {255 Ok(match self {256 Self::Lazy(vec) => {257 let mut out = Vec::with_capacity(vec.len());258 for item in vec.iter() {259 out.push(item.evaluate()?);260 }261 Cc::new(out)262 }263 Self::Eager(vec) => vec.clone(),264 Self::Extended(_v) => {265 let mut out = Vec::with_capacity(self.len());266 for item in self.iter() {267 out.push(item?);268 }269 Cc::new(out)270 }271 })272 }273274 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {275 (0..self.len()).map(move |idx| match self {276 Self::Lazy(l) => l[idx].evaluate(),277 Self::Eager(e) => Ok(e[idx].clone()),278 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),279 })280 }281282 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {283 (0..self.len()).map(move |idx| match self {284 Self::Lazy(l) => l[idx].clone(),285 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),286 Self::Extended(_) => self.get_lazy(idx).unwrap(),287 })288 }289290 pub fn reversed(self) -> Self {291 match self {292 Self::Lazy(vec) => {293 let mut out = (&vec as &Vec<_>).clone();294 out.reverse();295 Self::Lazy(Cc::new(out))296 }297 Self::Eager(vec) => {298 let mut out = (&vec as &Vec<_>).clone();299 out.reverse();300 Self::Eager(Cc::new(out))301 }302 Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),303 }304 }305306 pub fn map(self, mapper: impl Fn(Val) -> Result<Val>) -> Result<Self> {307 let mut out = Vec::with_capacity(self.len());308309 for value in self.iter() {310 out.push(mapper(value?)?);311 }312313 Ok(Self::Eager(Cc::new(out)))314 }315316 pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {317 let mut out = Vec::with_capacity(self.len());318319 for value in self.iter() {320 let value = value?;321 if filter(&value)? {322 out.push(value);323 }324 }325326 Ok(Self::Eager(Cc::new(out)))327 }328329 pub fn ptr_eq(a: &Self, b: &Self) -> bool {330 match (a, b) {331 (Self::Lazy(a), Self::Lazy(b)) => cc_ptr_eq(a, b),332 (Self::Eager(a), Self::Eager(b)) => cc_ptr_eq(a, b),333 _ => false,334 }335 }336}337338impl From<Vec<LazyVal>> for ArrValue {339 fn from(v: Vec<LazyVal>) -> Self {340 Self::Lazy(Cc::new(v))341 }342}343344impl From<Vec<Val>> for ArrValue {345 fn from(v: Vec<Val>) -> Self {346 Self::Eager(Cc::new(v))347 }348}349350pub enum IndexableVal {351 Str(IStr),352 Arr(ArrValue),353}354355#[derive(Debug, Clone, Trace)]356pub enum Val {357 Bool(bool),358 Null,359 Str(IStr),360 Num(f64),361 Arr(ArrValue),362 Obj(ObjValue),363 Func(Cc<FuncVal>),364}365366macro_rules! matches_unwrap {367 ($e: expr, $p: pat, $r: expr) => {368 match $e {369 $p => $r,370 _ => panic!("no match"),371 }372 };373}374impl Val {375 376 377 pub fn new_checked_num(num: f64) -> Result<Self> {378 if num.is_finite() {379 Ok(Self::Num(num))380 } else {381 throw!(RuntimeError("overflow".into()))382 }383 }384385 pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {386 let this_type = self.value_type();387 if this_type != val_type {388 throw!(TypeMismatch(context, vec![val_type], this_type))389 } else {390 Ok(())391 }392 }393 pub fn unwrap_num(self) -> Result<f64> {394 Ok(matches_unwrap!(self, Self::Num(v), v))395 }396 pub fn unwrap_str(self) -> Result<IStr> {397 Ok(matches_unwrap!(self, Self::Str(v), v))398 }399 pub fn unwrap_arr(self) -> Result<ArrValue> {400 Ok(matches_unwrap!(self, Self::Arr(v), v))401 }402 pub fn unwrap_func(self) -> Result<Cc<FuncVal>> {403 Ok(matches_unwrap!(self, Self::Func(v), v))404 }405 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {406 self.assert_type(context, ValType::Bool)?;407 Ok(matches_unwrap!(self, Self::Bool(v), v))408 }409 pub fn try_cast_str(self, context: &'static str) -> Result<IStr> {410 self.assert_type(context, ValType::Str)?;411 Ok(matches_unwrap!(self, Self::Str(v), v))412 }413 pub fn try_cast_num(self, context: &'static str) -> Result<f64> {414 self.assert_type(context, ValType::Num)?;415 self.unwrap_num()416 }417 pub fn try_cast_nullable_num(self, context: &'static str) -> Result<Option<f64>> {418 Ok(match self {419 Val::Null => None,420 Val::Num(num) => Some(num),421 _ => throw!(TypeMismatch(422 context,423 vec![ValType::Null, ValType::Num],424 self.value_type()425 )),426 })427 }428 pub const fn value_type(&self) -> ValType {429 match self {430 Self::Str(..) => ValType::Str,431 Self::Num(..) => ValType::Num,432 Self::Arr(..) => ValType::Arr,433 Self::Obj(..) => ValType::Obj,434 Self::Bool(_) => ValType::Bool,435 Self::Null => ValType::Null,436 Self::Func(..) => ValType::Func,437 }438 }439440 pub fn to_string(&self) -> Result<IStr> {441 Ok(match self {442 Self::Bool(true) => "true".into(),443 Self::Bool(false) => "false".into(),444 Self::Null => "null".into(),445 Self::Str(s) => s.clone(),446 v => manifest_json_ex(447 v,448 &ManifestJsonOptions {449 padding: "",450 mtype: ManifestType::ToString,451 },452 )?453 .into(),454 })455 }456457 458 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {459 let obj = match self {460 Self::Obj(obj) => obj,461 _ => throw!(MultiManifestOutputIsNotAObject),462 };463 let keys = obj.fields();464 let mut out = Vec::with_capacity(keys.len());465 for key in keys {466 let value = obj467 .get(key.clone())?468 .expect("item in object")469 .manifest(ty)?;470 out.push((key, value));471 }472 Ok(out)473 }474475 476 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {477 let arr = match self {478 Self::Arr(a) => a,479 _ => throw!(StreamManifestOutputIsNotAArray),480 };481 let mut out = Vec::with_capacity(arr.len());482 for i in arr.iter() {483 out.push(i?.manifest(ty)?);484 }485 Ok(out)486 }487488 pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {489 Ok(match ty {490 ManifestFormat::YamlStream(format) => {491 let arr = match self {492 Self::Arr(a) => a,493 _ => throw!(StreamManifestOutputIsNotAArray),494 };495 let mut out = String::new();496497 match format as &ManifestFormat {498 ManifestFormat::YamlStream(_) => throw!(StreamManifestOutputCannotBeRecursed),499 ManifestFormat::String => throw!(StreamManifestCannotNestString),500 _ => {}501 };502503 if !arr.is_empty() {504 for v in arr.iter() {505 out.push_str("---\n");506 out.push_str(&v?.manifest(format)?);507 out.push('\n');508 }509 out.push_str("...");510 }511512 out.into()513 }514 ManifestFormat::Yaml(padding) => self.to_yaml(*padding)?,515 ManifestFormat::Json(padding) => self.to_json(*padding)?,516 ManifestFormat::ToString => self.to_string()?,517 ManifestFormat::String => match self {518 Self::Str(s) => s.clone(),519 _ => throw!(StringManifestOutputIsNotAString),520 },521 })522 }523524 525 pub fn to_json(&self, padding: usize) -> Result<IStr> {526 manifest_json_ex(527 self,528 &ManifestJsonOptions {529 padding: &" ".repeat(padding),530 mtype: if padding == 0 {531 ManifestType::Minify532 } else {533 ManifestType::Manifest534 },535 },536 )537 .map(|s| s.into())538 }539540 541 pub fn to_std_json(&self, padding: usize) -> Result<Rc<str>> {542 manifest_json_ex(543 self,544 &ManifestJsonOptions {545 padding: &" ".repeat(padding),546 mtype: ManifestType::Std,547 },548 )549 .map(|s| s.into())550 }551552 pub fn to_yaml(&self, padding: usize) -> Result<IStr> {553 let padding = &" ".repeat(padding);554 manifest_yaml_ex(555 self,556 &ManifestYamlOptions {557 padding,558 arr_element_padding: padding,559 },560 )561 .map(|s| s.into())562 }563 pub fn into_indexable(self) -> Result<IndexableVal> {564 Ok(match self {565 Val::Str(s) => IndexableVal::Str(s),566 Val::Arr(arr) => IndexableVal::Arr(arr),567 _ => throw!(ValueIsNotIndexable(self.value_type())),568 })569 }570}571572const fn is_function_like(val: &Val) -> bool {573 matches!(val, Val::Func(_))574}575576577pub fn primitive_equals(val_a: &Val, val_b: &Val) -> Result<bool> {578 Ok(match (val_a, val_b) {579 (Val::Bool(a), Val::Bool(b)) => a == b,580 (Val::Null, Val::Null) => true,581 (Val::Str(a), Val::Str(b)) => a == b,582 (Val::Num(a), Val::Num(b)) => (a - b).abs() <= f64::EPSILON,583 (Val::Arr(_), Val::Arr(_)) => throw!(RuntimeError(584 "primitiveEquals operates on primitive types, got array".into(),585 )),586 (Val::Obj(_), Val::Obj(_)) => throw!(RuntimeError(587 "primitiveEquals operates on primitive types, got object".into(),588 )),589 (a, b) if is_function_like(a) && is_function_like(b) => {590 throw!(RuntimeError("cannot test equality of functions".into()))591 }592 (_, _) => false,593 })594}595596597pub fn equals(val_a: &Val, val_b: &Val) -> Result<bool> {598 if val_a.value_type() != val_b.value_type() {599 return Ok(false);600 }601 match (val_a, val_b) {602 (Val::Arr(a), Val::Arr(b)) => {603 if ArrValue::ptr_eq(a, b) {604 return Ok(true);605 }606 if a.len() != b.len() {607 return Ok(false);608 }609 for (a, b) in a.iter().zip(b.iter()) {610 if !equals(&a?, &b?)? {611 return Ok(false);612 }613 }614 Ok(true)615 }616 (Val::Obj(a), Val::Obj(b)) => {617 if ObjValue::ptr_eq(a, b) {618 return Ok(true);619 }620 let fields = a.fields();621 if fields != b.fields() {622 return Ok(false);623 }624 for field in fields {625 if !equals(&a.get(field.clone())?.unwrap(), &b.get(field)?.unwrap())? {626 return Ok(false);627 }628 }629 Ok(true)630 }631 (a, b) => Ok(primitive_equals(a, b)?),632 }633}