difftreelog
refactor reduce boilerplate by automatic conversions
in: master
29 files changed
bindings/jsonnet/src/native.rsdiffbeforeafterboth72 let name = CStr::from_ptr(name)72 let name = CStr::from_ptr(name).to_str().expect("name is not utf-8");73 .to_str()74 .expect("name is not utf-8")75 .into();76 let mut params = Vec::new();73 let mut params = Vec::new();77 loop {74 loop {78 if (*raw_params).is_null() {75 if (*raw_params).is_null() {bindings/jsonnet/src/val_make.rsdiffbeforeafterboth6};6};778use jrsonnet_evaluator::{8use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};9 val::{ArrValue, StrValue},10 ObjValue, Val,11};12913use crate::VM;10use crate::VM;21pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {18pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val {22 let val = CStr::from_ptr(val);19 let val = CStr::from_ptr(val);23 let val = val.to_str().expect("string is not utf-8");20 let val = val.to_str().expect("string is not utf-8");24 Box::into_raw(Box::new(Val::Str(StrValue::Flat(val.into()))))21 Box::into_raw(Box::new(Val::string(val)))25}22}262327/// Convert the given double to a `JsonnetJsonValue`.24/// Convert the given double to a `JsonnetJsonValue`.bindings/jsonnet/src/val_modify.rsdiffbeforeafterboth5use std::{ffi::CStr, os::raw::c_char};5use std::{ffi::CStr, os::raw::c_char};667use jrsonnet_evaluator::{val::ArrValue, Thunk, Val};7use jrsonnet_evaluator::{val::ArrValue, Thunk, Val};8use jrsonnet_gcmodule::Cc;9810use crate::VM;9use crate::VM;1110crates/jrsonnet-cli/src/stdlib.rsdiffbeforeafterboth1use std::{fs::read_to_string, str::FromStr};1use std::{fs::read_to_string, str::FromStr};223use clap::Parser;3use clap::Parser;4use jrsonnet_evaluator::{error::Result, trace::PathResolver, State};4use jrsonnet_evaluator::{trace::PathResolver, Result, State};5use jrsonnet_stdlib::ContextInitializer;5use jrsonnet_stdlib::ContextInitializer;667#[derive(Clone)]7#[derive(Clone)]crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth10 evaluate,11 function::FuncVal,12 typed::Typed,13 val::{StrValue, ThunkValue},10 val::ThunkValue, Context, Error, ObjValue, Result, Thunk, Val,14 Context, Error, ObjValue, Result, Thunk, Val,15};11};1612101 }97 }10298103 fn get_cheap(&self, index: usize) -> Option<Val> {99 fn get_cheap(&self, index: usize) -> Option<Val> {104 self.0100 self.0.get(index).map(|v| Val::string(*v))105 .get(index)106 .map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))107 }101 }108 fn is_cheap(&self) -> bool {102 fn is_cheap(&self) -> bool {109 true103 truecrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth87 }87 }888889 #[must_use]89 #[must_use]90 pub fn with_var(self, name: IStr, value: Val) -> Self {90 pub fn with_var(self, name: impl Into<IStr>, value: Val) -> Self {91 let mut new_bindings = GcHashMap::with_capacity(1);91 let mut new_bindings = GcHashMap::with_capacity(1);92 new_bindings.insert(name, Thunk::evaluated(value));92 new_bindings.insert(name.into(), Thunk::evaluated(value));93 self.extend(new_bindings, None, None, None)93 self.extend(new_bindings, None, None, None)94 }94 }9595161 }161 }162 /// # Panics162 /// # Panics163 /// If `name` is already bound163 /// If `name` is already bound164 pub fn bind(&mut self, name: IStr, value: Thunk<Val>) -> &mut Self {164 pub fn bind(&mut self, name: impl Into<IStr>, value: Thunk<Val>) -> &mut Self {165 let old = self.bindings.insert(name, value);165 let old = self.bindings.insert(name.into(), value);166 assert!(old.is_none(), "variable bound twice in single context call");166 assert!(old.is_none(), "variable bound twice in single context call");167 self167 self168 }168 }crates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth53 }53 }54}54}5556impl<T: Trace + Clone> From<Pending<T>> for Thunk<T> {57 fn from(value: Pending<T>) -> Self {58 Self::new(value)59 }60}6155crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth36 }36 }37 }37 }38 Some(match &*expr.0 {38 Some(match &*expr.0 {39 Expr::Str(s) => Val::Str(StrValue::Flat(s.clone())),39 Expr::Str(s) => Val::string(s.clone()),40 Expr::Num(n) => Val::Num(*n),40 Expr::Num(n) => Val::Num(*n),41 Expr::Literal(LiteralType::False) => Val::Bool(false),41 Expr::Literal(LiteralType::False) => Val::Bool(false),42 Expr::Literal(LiteralType::True) => Val::Bool(true),42 Expr::Literal(LiteralType::True) => Val::Bool(true),135 let fctx = Pending::new();135 let fctx = Pending::new();136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());136 let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint());137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![137 let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![138 Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))),138 Thunk::evaluated(Val::string(field.clone())),139 Thunk::new(ObjectFieldThunk {139 Thunk::new(ObjectFieldThunk {140 field: field.clone(),140 field: field.clone(),141 obj: obj.clone(),141 obj: obj.clone(),226 }226 }227227228 builder228 builder229 .member(name.clone())229 .field(name.clone())230 .with_add(*plus)230 .with_add(*plus)231 .with_visibility(*visibility)231 .with_visibility(*visibility)232 .with_location(value.1.clone())232 .with_location(value.1.clone())262 }262 }263263264 builder264 builder265 .member(name.clone())265 .field(name.clone())266 .with_visibility(*visibility)266 .with_visibility(*visibility)267 .with_location(value.1.clone())267 .with_location(value.1.clone())268 .bindable(UnboundMethod {268 .bindable(UnboundMethod {437 Literal(LiteralType::False) => Val::Bool(false),437 Literal(LiteralType::False) => Val::Bool(false),438 Literal(LiteralType::Null) => Val::Null,438 Literal(LiteralType::Null) => Val::Null,439 Parened(e) => evaluate(ctx, e)?,439 Parened(e) => evaluate(ctx, e)?,440 Str(v) => Val::Str(StrValue::Flat(v.clone())),440 Str(v) => Val::string(v.clone()),441 Num(v) => Val::new_checked_num(*v)?,441 Num(v) => Val::new_checked_num(*v)?,442 BinaryOp(v1, o, v2) => evaluate_binary_op_special(ctx, v1, *o, v2)?,442 BinaryOp(v1, o, v2) => evaluate_binary_op_special(ctx, v1, *o, v2)?,443 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(ctx, v)?)?,443 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(ctx, v)?)?,672 || format!("import {:?}", path.clone()),672 || format!("import {:?}", path.clone()),673 || s.import_resolved(resolved_path),673 || s.import_resolved(resolved_path),674 )?,674 )?,675 ImportStr(_) => Val::Str(StrValue::Flat(s.import_resolved_str(resolved_path)?)),675 ImportStr(_) => Val::string(s.import_resolved_str(resolved_path)?),676 ImportBin(_) => Val::Arr(ArrValue::bytes(s.import_resolved_bin(resolved_path)?)),676 ImportBin(_) => Val::Arr(ArrValue::bytes(s.import_resolved_bin(resolved_path)?)),677 _ => unreachable!(),677 _ => unreachable!(),678 }678 }crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth30 Ok(match (a, b) {30 Ok(match (a, b) {31 (Str(v1), Str(v2)) => Str(StrValue::concat(v1.clone(), v2.clone())),31 (Str(v1), Str(v2)) => Str(StrValue::concat(v1.clone(), v2.clone())),323233 (Num(a), Str(b)) => Str(StrValue::Flat(format!("{a}{b}").into())),33 (Num(a), Str(b)) => Val::string(format!("{a}{b}")),34 (Str(a), Num(b)) => Str(StrValue::Flat(format!("{a}{b}").into())),34 (Str(a), Num(b)) => Val::string(format!("{a}{b}")),353536 (Str(a), o) | (o, Str(a)) if a.is_empty() => {36 (Str(a), o) | (o, Str(a)) if a.is_empty() => Val::string(o.clone().to_string()?),37 Val::Str(StrValue::Flat(o.clone().to_string()?))38 }39 (Str(a), o) => Str(StrValue::Flat(37 (Str(a), o) => Val::string(format!("{a}{}", o.clone().to_string()?)),40 format!("{a}{}", o.clone().to_string()?).into(),41 )),42 (o, Str(a)) => Str(StrValue::Flat(38 (o, Str(a)) => Val::string(format!("{}{a}", o.clone().to_string()?)),43 format!("{}{a}", o.clone().to_string()?).into(),44 )),453946 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),40 (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())),47 (Arr(a), Arr(b)) => Val::Arr(ArrValue::extended(a.clone(), b.clone())),41 (Arr(a), Arr(b)) => Val::Arr(ArrValue::extended(a.clone(), b.clone())),149 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)),143 (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)),150 (a, Mod, b) => evaluate_mod_op(a, b)?,144 (a, Mod, b) => evaluate_mod_op(a, b)?,151145152 (Str(v1), Mul, Num(v2)) => Str(StrValue::Flat(v1.to_string().repeat(*v2 as usize).into())),146 (Str(v1), Mul, Num(v2)) => Val::string(v1.to_string().repeat(*v2 as usize)),153147154 // Bool X Bool148 // Bool X Bool155 (Bool(a), And, Bool(b)) => Bool(*a && *b),149 (Bool(a), And, Bool(b)) => Bool(*a && *b),crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth61impl ArgLike for TlaArg {61impl ArgLike for TlaArg {62 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {62 fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result<Thunk<Val>> {63 match self {63 match self {64 TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))),64 TlaArg::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))),65 TlaArg::Code(code) => Ok(if tailstrict {65 TlaArg::Code(code) => Ok(if tailstrict {66 Thunk::evaluated(evaluate(ctx, code)?)66 Thunk::evaluated(evaluate(ctx, code)?)67 } else {67 } else {crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth14};14};15use crate::{evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, Val};15use crate::{16 evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result,17 Val,18};161917pub mod arglike;20pub mod arglike;124 pub fn builtin(builtin: impl Builtin) -> Self {127 pub fn builtin(builtin: impl Builtin) -> Self {125 Self::Builtin(Cc::new(tb!(builtin)))128 Self::Builtin(Cc::new(tb!(builtin)))126 }129 }130 pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self {131 Self::StaticBuiltin(static_builtin)132 }127133128 pub fn params(&self) -> Vec<BuiltinParam> {134 pub fn params(&self) -> Vec<BuiltinParam> {129 match self {135 match self {240 }246 }241}247}248249impl<T> From<T> for FuncVal250where251 T: Builtin,252{253 fn from(value: T) -> Self {254 Self::builtin(value)255 }256}257impl From<&'static dyn StaticBuiltin> for FuncVal {258 fn from(value: &'static dyn StaticBuiltin) -> Self {259 Self::static_builtin(value)260 }261}242262crates/jrsonnet-evaluator/src/function/native.rsdiffbeforeafterboth2 arglike::{ArgLike, OptionalContext},2 arglike::{ArgLike, OptionalContext},3 FuncVal,3 FuncVal,4};4};5use crate::{error::Result, typed::Typed};5use crate::{typed::Typed, Result};667pub trait NativeDesc {7pub trait NativeDesc {8 type Value;8 type Value;crates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterbothno syntactic changes
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth11};11};121213use crate::{13use crate::{14 arr::ArrValue,14 arr::ArrValue, runtime_error, Error as JrError, ObjValue, ObjValueBuilder,15 error::{Error as JrError, ErrorKind, Result},16 val::StrValue,17 ObjValue, ObjValueBuilder, State, Val,15 Result, State, Val,18};16};191720impl<'de> Deserialize<'de> for Val {18impl<'de> Deserialize<'de> for Val {57 where55 where58 E: serde::de::Error,56 E: serde::de::Error,59 {57 {60 Ok(Val::Str(StrValue::Flat(v.into())))58 Ok(Val::string(v))61 }59 }626063 // visit_num! {61 // visit_num! {138136139 while let Some((k, v)) = map.next_entry::<Cow<'de, str>, Val>()? {137 while let Some((k, v)) = map.next_entry::<Cow<'de, str>, Val>()? {140 // Jsonnet ignores duplicate keys138 // Jsonnet ignores duplicate keys141 out.member(k.into()).value_unchecked(v);139 out.field(k).value(v);142 }140 }143141144 Ok(Val::Obj(out.build()))142 Ok(Val::Obj(out.build()))264 let inner = Val::Arr(ArrValue::eager(self.data));262 let inner = Val::Arr(ArrValue::eager(self.data));265 if let Some(variant) = self.variant {263 if let Some(variant) = self.variant {266 let mut out = ObjValue::builder_with_capacity(1);264 let mut out = ObjValue::builder_with_capacity(1);267 out.member(variant).value_unchecked(inner);265 out.field(variant).value(inner);268 Ok(Val::Obj(out.build()))266 Ok(Val::Obj(out.build()))269 } else {267 } else {270 Ok(inner)268 Ok(inner)365 {363 {366 let key = self.key.take().expect("no serialize_key called");364 let key = self.key.take().expect("no serialize_key called");367 let value = value.serialize(IntoValSerializer)?;365 let value = value.serialize(IntoValSerializer)?;368 self.data.member(key).value(value)?;366 self.data.field(key).try_value(value)?;369 Ok(())367 Ok(())370 }368 }371369378 let key = key.serialize(IntoValSerializer)?;376 let key = key.serialize(IntoValSerializer)?;379 let key = key.to_string()?;377 let key = key.to_string()?;380 let value = value.serialize(IntoValSerializer)?;378 let value = value.serialize(IntoValSerializer)?;381 self.data.member(key).value(value)?;379 self.data.field(key).try_value(value)?;382 Ok(())380 Ok(())383 }381 }384382385 fn end(self) -> Result<Val> {383 fn end(self) -> Result<Val> {386 let inner = Val::Obj(self.data.build());384 let inner = Val::Obj(self.data.build());387 if let Some(variant) = self.variant {385 if let Some(variant) = self.variant {388 let mut out = ObjValue::builder_with_capacity(1);386 let mut out = ObjValue::builder_with_capacity(1);389 out.member(variant).value_unchecked(inner);387 out.field(variant).value(inner);390 Ok(Val::Obj(out.build()))388 Ok(Val::Obj(out.build()))391 } else {389 } else {392 Ok(inner)390 Ok(inner)550 {548 {551 let mut out = ObjValue::builder_with_capacity(1);549 let mut out = ObjValue::builder_with_capacity(1);552 let value = value.serialize(self)?;550 let value = value.serialize(self)?;553 out.member(variant.into()).value_unchecked(value);551 out.field(variant).value(value);554 Ok(Val::Obj(out.build()))552 Ok(Val::Obj(out.build()))555 }553 }556554crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth498pub struct InitialUnderscore(pub Thunk<Val>);498pub struct InitialUnderscore(pub Thunk<Val>);499impl ContextInitializer for InitialUnderscore {499impl ContextInitializer for InitialUnderscore {500 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {500 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {501 builder.bind("_".into(), self.0.clone());501 builder.bind("_", self.0.clone());502 }502 }503503504 fn as_any(&self) -> &dyn Any {504 fn as_any(&self) -> &dyn Any {crates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth174 Val::Str(s) => escape_string_json_buf(&s.clone().into_flat(), buf),174 Val::Str(s) => escape_string_json_buf(&s.clone().into_flat(), buf),175 Val::Num(n) => write!(buf, "{n}").unwrap(),175 Val::Num(n) => write!(buf, "{n}").unwrap(),176 #[cfg(feature = "exp-bigint")]176 #[cfg(feature = "exp-bigint")]177 Val::BigInt(n) => if options.preserve_bigints {177 Val::BigInt(n) => {178 if options.preserve_bigints {178 write!(buf, "{n}").unwrap()179 write!(buf, "{n}").unwrap()179 } else {180 } else {180 write!(buf, "{:?}", n.to_string()).unwrap()181 write!(buf, "{:?}", n.to_string()).unwrap()181 },182 }183 }182 Val::Arr(items) => {184 Val::Arr(items) => {183 buf.push('[');185 buf.push('[');184 if !items.is_empty() {186 if !items.is_empty() {crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth15 arr::{PickObjectKeyValues, PickObjectValues},15 arr::{PickObjectKeyValues, PickObjectValues},16 bail,16 bail,17 error::{suggest_object_fields, Error, ErrorKind::*},17 error::{suggest_object_fields, Error, ErrorKind::*},18 function::CallLocation,18 function::{CallLocation, FuncVal},19 gc::{GcHashMap, GcHashSet, TraceBox},19 gc::{GcHashMap, GcHashSet, TraceBox},20 operator::evaluate_add_op,20 operator::evaluate_add_op,21 tb,21 tb,345 pub(crate) fn extend_with_raw_member(self, key: IStr, value: ObjMember) -> Self {345 pub(crate) fn extend_with_raw_member(self, key: IStr, value: ObjMember) -> Self {346 let mut out = ObjValueBuilder::with_capacity(1);346 let mut out = ObjValueBuilder::with_capacity(1);347 out.with_super(self);347 out.with_super(self);348 let mut member = out.member(key);348 let mut member = out.field(key);349 if value.flags.add() {349 if value.flags.add() {350 member = member.add()350 member = member.add()351 }351 }848 self.assertions.push(tb!(assertion));848 self.assertions.push(tb!(assertion));849 self849 self850 }850 }851 pub fn member(&mut self, name: IStr) -> ObjMemberBuilder<ValueBuilder<'_>> {851 pub fn field(&mut self, name: impl Into<IStr>) -> ObjMemberBuilder<ValueBuilder<'_>> {852 let field_index = self.next_field_index;852 let field_index = self.next_field_index;853 self.next_field_index = self.next_field_index.next();853 self.next_field_index = self.next_field_index.next();854 ObjMemberBuilder::new(ValueBuilder(self), name, field_index)854 ObjMemberBuilder::new(ValueBuilder(self), name.into(), field_index)855 }855 }856 /// Preset for common method definiton pattern:857 /// Create a hidden field with the function value.858 ///859 /// `.field(name).hide().value(Val::function(value))`860 pub fn method(&mut self, name: impl Into<IStr>, value: impl Into<FuncVal>) -> &mut Self {861 self.field(name).hide().value(Val::Func(value.into()));862 self863 }864 pub fn try_method(865 &mut self,866 name: impl Into<IStr>,867 value: impl Into<FuncVal>,868 ) -> Result<&mut Self> {869 self.field(name).hide().try_value(Val::Func(value.into()))?;870 Ok(self)871 }856872857 pub fn build(self) -> ObjValue {873 pub fn build(self) -> ObjValue {858 if self.sup.is_none() && self.map.is_empty() && self.assertions.is_empty() {874 if self.sup.is_none() && self.map.is_empty() && self.assertions.is_empty() {930pub struct ValueBuilder<'v>(&'v mut ObjValueBuilder);946pub struct ValueBuilder<'v>(&'v mut ObjValueBuilder);931impl ObjMemberBuilder<ValueBuilder<'_>> {947impl ObjMemberBuilder<ValueBuilder<'_>> {932 /// Inserts value, replacing if it is already defined948 /// Inserts value, replacing if it is already defined933 pub fn value_unchecked(self, value: Val) {949 pub fn value(self, value: impl Into<Val>) {934 let (receiver, name, member) =950 let (receiver, name, member) =935 self.build_member(MaybeUnbound::Bound(Thunk::evaluated(value)));951 self.build_member(MaybeUnbound::Bound(Thunk::evaluated(value.into())));936 let entry = receiver.0.map.entry(name);952 let entry = receiver.0.map.entry(name);937 entry.insert(member);953 entry.insert(member);938 }954 }939955956 /// Tries to insert value, returns an error if it was already defined940 pub fn value(self, value: Val) -> Result<()> {957 pub fn try_value(self, value: impl Into<Val>) -> Result<()> {941 self.thunk(Thunk::evaluated(value))958 self.thunk(Thunk::evaluated(value.into()))942 }959 }943 pub fn thunk(self, value: Thunk<Val>) -> Result<()> {960 pub fn thunk(self, value: impl Into<Thunk<Val>>) -> Result<()> {944 self.binding(MaybeUnbound::Bound(value))961 self.binding(MaybeUnbound::Bound(value.into()))945 }962 }946 pub fn bindable(self, bindable: impl Unbound<Bound = Val>) -> Result<()> {963 pub fn bindable(self, bindable: impl Unbound<Bound = Val>) -> Result<()> {947 self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable))))964 self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable))))963980964pub struct ExtendBuilder<'v>(&'v mut ObjValue);981pub struct ExtendBuilder<'v>(&'v mut ObjValue);965impl ObjMemberBuilder<ExtendBuilder<'_>> {982impl ObjMemberBuilder<ExtendBuilder<'_>> {966 pub fn value(self, value: Val) {983 pub fn value(self, value: impl Into<Val>) {967 self.binding(MaybeUnbound::Bound(Thunk::evaluated(value)));984 self.binding(MaybeUnbound::Bound(Thunk::evaluated(value.into())));968 }985 }969 pub fn bindable(self, bindable: TraceBox<dyn Unbound<Bound = Val>>) {986 pub fn bindable(self, bindable: TraceBox<dyn Unbound<Bound = Val>>) {970 self.binding(MaybeUnbound::Unbound(Cc::new(bindable)));987 self.binding(MaybeUnbound::Unbound(Cc::new(bindable)));crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth276 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);276 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);277277278 fn into_untyped(value: Self) -> Result<Val> {278 fn into_untyped(value: Self) -> Result<Val> {279 Ok(Val::Str(StrValue::Flat(value)))279 Ok(Val::string(value))280 }280 }281281282 fn from_untyped(value: Val) -> Result<Self> {282 fn from_untyped(value: Val) -> Result<Self> {292 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);292 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);293293294 fn into_untyped(value: Self) -> Result<Val> {294 fn into_untyped(value: Self) -> Result<Val> {295 Ok(Val::Str(StrValue::Flat(value.into())))295 Ok(Val::string(value))296 }296 }297297298 fn from_untyped(value: Val) -> Result<Self> {298 fn from_untyped(value: Val) -> Result<Self> {308 const TYPE: &'static ComplexValType = &ComplexValType::Char;308 const TYPE: &'static ComplexValType = &ComplexValType::Char;309309310 fn into_untyped(value: Self) -> Result<Val> {310 fn into_untyped(value: Self) -> Result<Val> {311 Ok(Val::Str(StrValue::Flat(value.to_string().into())))311 Ok(Val::string(value))312 }312 }313313314 fn from_untyped(value: Val) -> Result<Self> {314 fn from_untyped(value: Val) -> Result<Self> {356 bail!("map key should serialize to string");356 bail!("map key should serialize to string");357 };357 };358 let value = V::into_untyped(v)?;358 let value = V::into_untyped(v)?;359 out.member(key).value_unchecked(value);359 out.field(key).value(value);360 }360 }361 Ok(Val::Obj(out.build()))361 Ok(Val::Obj(out.build()))362 }362 }611611612 fn into_untyped(value: Self) -> Result<Val> {612 fn into_untyped(value: Self) -> Result<Val> {613 match value {613 match value {614 IndexableVal::Str(s) => Ok(Val::Str(StrValue::Flat(s))),614 IndexableVal::Str(s) => Ok(Val::string(s)),615 IndexableVal::Arr(a) => Ok(Val::Arr(a)),615 IndexableVal::Arr(a) => Ok(Val::Arr(a)),616 }616 }617 }617 }crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth142 }142 }143 }143 }144}144}145impl<T, V: Trace> From<T> for Thunk<V>146where147 T: ThunkValue<Output = V>,148{149 fn from(value: T) -> Self {150 Thunk::new(value)151 }152}145153146impl<T: Trace + Default> Default for Thunk<T> {154impl<T: Trace + Default> Default for Thunk<T> {147 fn default() -> Self {155 fn default() -> Self {323 }331 }324 }332 }325}333}326impl From<&str> for StrValue {334impl<T> From<T> for StrValue327 fn from(value: &str) -> Self {335where328 Self::Flat(value.into())336 IStr: From<T>,329 }330}331impl From<String> for StrValue {332 fn from(value: String) -> Self {333 Self::Flat(value.into())334 }335}336impl From<IStr> for StrValue {337{337 fn from(value: IStr) -> Self {338 fn from(value: T) -> Self {338 Self::Flat(value)339 Self::Flat(IStr::from(value))339 }340 }340}341}341impl Display for StrValue {342impl Display for StrValue {401impl From<IndexableVal> for Val {402impl From<IndexableVal> for Val {402 fn from(v: IndexableVal) -> Self {403 fn from(v: IndexableVal) -> Self {403 match v {404 match v {404 IndexableVal::Str(s) => Self::Str(StrValue::Flat(s)),405 IndexableVal::Str(s) => Self::string(s),405 IndexableVal::Arr(a) => Self::Arr(a),406 IndexableVal::Arr(a) => Self::Arr(a),406 }407 }407 }408 }500 })501 })501 }502 }503504 pub fn function(function: impl Into<FuncVal>) -> Self {505 Self::Func(function.into())506 }507 pub fn string(string: impl Into<StrValue>) -> Self {508 Self::Str(string.into())509 }502}510}511512impl From<IStr> for Val {513 fn from(value: IStr) -> Self {514 Self::string(value)515 }516}517impl From<String> for Val {518 fn from(value: String) -> Self {519 Self::string(value)520 }521}522impl From<&str> for Val {523 fn from(value: &str) -> Self {524 Self::string(value)525 }526}527impl From<ObjValue> for Val {528 fn from(value: ObjValue) -> Self {529 Self::Obj(value)530 }531}503532504const fn is_function_like(val: &Val) -> bool {533const fn is_function_like(val: &Val) -> bool {505 matches!(val, Val::Func(_))534 matches!(val, Val::Func(_))crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth567 if self.is_option {567 if self.is_option {568 quote! {568 quote! {569 if let Some(value) = self.#ident {569 if let Some(value) = self.#ident {570 out.member(#name.into())570 out.field(#name)571 #hide571 #hide572 #add572 #add573 .value(<#ty as Typed>::into_untyped(value)?)?;573 .try_value(<#ty as Typed>::into_untyped(value)?)?;574 }574 }575 }575 }576 } else {576 } else {577 quote! {577 quote! {578 out.member(#name.into())578 out.field(#name)579 #hide579 #hide580 #add580 #add581 .value(<#ty as Typed>::into_untyped(self.#ident)?)?;581 .try_value(<#ty as Typed>::into_untyped(self.#ident)?)?;582 }582 }583 }583 }584 } else if self.is_option {584 } else if self.is_option {crates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth36#[builtin]36#[builtin]37pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {37pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result<Val> {38 Ok(match what {38 Ok(match what {39 Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())),39 Either2::A(s) => Val::string(s.repeat(count)),40 Either2::B(arr) => Val::Arr(40 Either2::B(arr) => Val::Arr(41 ArrValue::repeated(arr, count)41 ArrValue::repeated(arr, count)42 .ok_or_else(|| runtime_error!("repeated length overflow"))?,42 .ok_or_else(|| runtime_error!("repeated length overflow"))?,crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth667use jrsonnet_evaluator::{7use jrsonnet_evaluator::{8 error::{ErrorKind::*, Result},8 error::{ErrorKind::*, Result},9 function::{builtin::Builtin, CallLocation, FuncVal, TlaArg},9 function::{CallLocation, FuncVal, TlaArg},10 gc::TraceBox,11 tb,10 tb,12 trace::PathResolver,11 trace::PathResolver,13 ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,12 ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,14};13};15use jrsonnet_gcmodule::{Cc, Trace};14use jrsonnet_gcmodule::Trace;16use jrsonnet_parser::Source;15use jrsonnet_parser::Source;171618mod expr;17mod expr;182 .iter()181 .iter()183 .cloned()182 .cloned()184 {183 {185 builder184 builder.method(name, builtin);186 .member(name.into())187 .hide()188 .value(Val::Func(FuncVal::StaticBuiltin(builtin)))189 .expect("no conflict");190 }185 }191186192 builder187 builder.method(193 .member("extVar".into())188 "extVar",194 .hide()195 .value(Val::Func(FuncVal::builtin(builtin_ext_var {189 builtin_ext_var {196 settings: settings.clone(),190 settings: settings.clone(),197 })))191 },198 .expect("no conflict");192 );199 builder193 builder.method(200 .member("native".into())194 "native",201 .hide()202 .value(Val::Func(FuncVal::builtin(builtin_native {195 builtin_native {203 settings: settings.clone(),196 settings: settings.clone(),204 })))197 },205 .expect("no conflict");198 );206 builder199 builder.method("trace", builtin_trace { settings });207 .member("trace".into())208 .hide()209 .value(Val::Func(FuncVal::builtin(builtin_trace { settings })))210 .expect("no conflict");211200212 builder201 builder.method("id", FuncVal::Id);213 .member("id".into())214 .hide()215 .value(Val::Func(FuncVal::Id))216 .expect("no conflict");217202218 builder.build()203 builder.build()219}204}293 #[cfg(not(feature = "legacy-this-file"))]278 #[cfg(not(feature = "legacy-this-file"))]294 context: {279 context: {295 let mut context = ContextBuilder::with_capacity(_s, 1);280 let mut context = ContextBuilder::with_capacity(_s, 1);296 context.bind("std".into(), stdlib_thunk.clone());281 context.bind("std", stdlib_thunk.clone());297 context.build()282 context.build()298 },283 },299 #[cfg(not(feature = "legacy-this-file"))]284 #[cfg(not(feature = "legacy-this-file"))]338 .insert(name.into(), TlaArg::Code(parsed));323 .insert(name.into(), TlaArg::Code(parsed));339 Ok(())324 Ok(())340 }325 }341 pub fn add_native(&self, name: IStr, cb: impl Builtin) {326 pub fn add_native(&self, name: impl Into<IStr>, cb: impl Into<FuncVal>) {342 self.settings_mut()327 self.settings_mut()343 .ext_natives328 .ext_natives344 .insert(name, Cc::new(tb!(cb)));329 .insert(name.into(), cb.into());345 }330 }346}331}347impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {332impl jrsonnet_evaluator::ContextInitializer for ContextInitializer {354 }339 }355 #[cfg(not(feature = "legacy-this-file"))]340 #[cfg(not(feature = "legacy-this-file"))]356 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {341 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {357 builder.bind("std".into(), self.stdlib_thunk.clone());342 builder.bind("std", self.stdlib_thunk.clone());358 }343 }359 #[cfg(feature = "legacy-this-file")]344 #[cfg(feature = "legacy-this-file")]360 fn populate(&self, source: Source, builder: &mut ContextBuilder) {345 fn populate(&self, source: Source, builder: &mut ContextBuilder) {361 use jrsonnet_evaluator::val::StrValue;346 use jrsonnet_evaluator::val::StrValue;362347363 let mut std = ObjValueBuilder::new();348 let mut std = ObjValueBuilder::new();364 std.with_super(self.stdlib_obj.clone());349 std.with_super(self.stdlib_obj.clone());365 std.member("thisFile".into())350 std.field("thisFile".into())366 .hide()351 .hide()367 .value(Val::Str(StrValue::Flat(352 .value(Val::string(368 match source.source_path().path() {353 match source.source_path().path() {369 Some(p) => self.settings().path_resolver.resolve(p).into(),354 Some(p) => self.settings().path_resolver.resolve(p).into(),370 None => source.source_path().to_string().into(),355 None => source.source_path().to_string().into(),371 },356 },372 )))357 ))373 .expect("this object builder is empty");358 .expect("this object builder is empty");374 let stdlib_with_this_file = std.build();359 let stdlib_with_this_file = std.build();375360crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth47 .ext_natives47 .ext_natives48 .get(&x)48 .get(&x)49 .cloned()49 .cloned()50 .map_or(Val::Null, |v| Val::Func(FuncVal::Builtin(v)))50 .map_or(Val::Null, |v| Val::Func(v))51}51}525253#[builtin(fields(53#[builtin(fields(crates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth122 if k == key {122 if k == key {123 continue;123 continue;124 }124 }125 new_obj.member(k).value_unchecked(v.unwrap())125 new_obj.field(k).value(v.unwrap())126 }126 }127127128 new_obj.build()128 new_obj.build()crates/jrsonnet-stdlib/src/operator.rsdiffbeforeafterboth16 evaluate_mod_op(16 evaluate_mod_op(17 &match a {17 &match a {18 A(v) => Val::Num(v),18 A(v) => Val::Num(v),19 B(s) => Val::Str(StrValue::Flat(s)),19 B(s) => Val::string(s),20 },20 },21 &b,21 &b,22 )22 )crates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth1use std::cmp::Ordering;1use std::cmp::Ordering;223use jrsonnet_evaluator::{3use jrsonnet_evaluator::{4 error::Result,5 function::{builtin, FuncVal},4 function::{builtin, FuncVal},6 operator::evaluate_compare_op,5 operator::evaluate_compare_op,7 val::ArrValue,6 val::ArrValue,8 Thunk, Val,7 Result, Thunk, Val,9};8};10use jrsonnet_parser::BinaryOpType;9use jrsonnet_parser::BinaryOpType;1110108 }107 }109 };108 };110 }109 }111 while let Some(ac) = &ak {110 while let Some(_ac) = &ak {112 // In a, but not in b111 // In a, but not in b113 out.push(av.clone().expect("ak != None"));112 out.push(av.clone().expect("ak != None"));114 av = a.next();113 av = a.next();crates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth3 error::{ErrorKind::*, Result},3 error::{ErrorKind::*, Result},4 function::builtin,4 function::builtin,5 typed::{Either2, M1},5 typed::{Either2, M1},6 val::{ArrValue, StrValue},6 val::ArrValue,7 Either, IStr, Val,7 Either, IStr, Val,8};8};9941pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {41pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue {42 use Either2::*;42 use Either2::*;43 match maxsplits {43 match maxsplits {44 A(n) => str44 A(n) => str.splitn(n + 1, &c as &str).map(Val::string).collect(),45 .splitn(n + 1, &c as &str)46 .map(|s| Val::Str(StrValue::Flat(s.into())))47 .collect(),48 B(_) => str45 B(_) => str.split(&c as &str).map(Val::string).collect(),49 .split(&c as &str)50 .map(|s| Val::Str(StrValue::Flat(s.into())))51 .collect(),52 }46 }53}47}tests/tests/builtin.rsdiffbeforeafterboth36 s.with_stdlib();36 s.with_stdlib();37 s.add_global(37 s.add_global(38 "nativeAdd".into(),38 "nativeAdd".into(),39 Thunk::evaluated(Val::Func(FuncVal::StaticBuiltin(native_add::INST))),39 Thunk::evaluated(Val::function(native_add::INST)),40 );40 );414142 let v = s.evaluate_snippet(42 let v = s.evaluate_snippet(69 s.with_stdlib();69 s.with_stdlib();70 s.add_global(70 s.add_global(71 "curryAdd".into(),71 "curryAdd".into(),72 Thunk::evaluated(Val::Func(FuncVal::StaticBuiltin(curry_add::INST))),72 Thunk::evaluated(Val::function(curry_add::INST)),73 );73 );747475 let v = s.evaluate_snippet(75 let v = s.evaluate_snippet(tests/tests/common.rsdiffbeforeafterboth77#[allow(dead_code)]77#[allow(dead_code)]78pub fn with_test(s: &State) {78pub fn with_test(s: &State) {79 let mut bobj = ObjValueBuilder::new();79 let mut bobj = ObjValueBuilder::new();80 bobj.member("assertThrow".into())80 bobj.method("assertThrow", assert_throw::INST);81 .hide()82 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST)));83 bobj.member("paramNames".into())81 bobj.method("paramNames", param_names::INST);84 .hide()85 .value_unchecked(Val::Func(FuncVal::StaticBuiltin(param_names::INST)));868287 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))83 s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build())))88}84}