git.delta.rocks / jrsonnet / refs/commits / 027693dbe6bd

difftreelog

refactor reduce boilerplate by automatic conversions

Yaroslav Bolyukin2023-08-13parent: #dad6c32.patch.diff
in: master

29 files changed

modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
72 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() {
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
6};6};
77
8use jrsonnet_evaluator::{8use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};
9 val::{ArrValue, StrValue},
10 ObjValue, Val,
11};
129
13use 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}
2623
27/// Convert the given double to a `JsonnetJsonValue`.24/// Convert the given double to a `JsonnetJsonValue`.
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
5use std::{ffi::CStr, os::raw::c_char};5use std::{ffi::CStr, os::raw::c_char};
66
7use jrsonnet_evaluator::{val::ArrValue, Thunk, Val};7use jrsonnet_evaluator::{val::ArrValue, Thunk, Val};
8use jrsonnet_gcmodule::Cc;
98
10use crate::VM;9use crate::VM;
1110
modifiedcrates/jrsonnet-cli/src/stdlib.rsdiffbeforeafterboth
1use std::{fs::read_to_string, str::FromStr};1use std::{fs::read_to_string, str::FromStr};
22
3use 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;
66
7#[derive(Clone)]7#[derive(Clone)]
modifiedcrates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth
10 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};
1612
101 }97 }
10298
103 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 true
modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
87 }87 }
8888
89 #[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 }
9595
161 }161 }
162 /// # Panics162 /// # Panics
163 /// If `name` is already bound163 /// If `name` is already bound
164 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 self
168 }168 }
modifiedcrates/jrsonnet-evaluator/src/dynamic.rsdiffbeforeafterboth
53 }53 }
54}54}
55
56impl<T: Trace + Clone> From<Pending<T>> for Thunk<T> {
57 fn from(value: Pending<T>) -> Self {
58 Self::new(value)
59 }
60}
6155
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
36 }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 }
227227
228 builder228 builder
229 .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 }
263263
264 builder264 builder
265 .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 }
modifiedcrates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth
30 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())),
3232
33 (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}")),
3535
36 (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 )),
4539
46 (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)?,
151145
152 (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)),
153147
154 // Bool X Bool148 // Bool X Bool
155 (Bool(a), And, Bool(b)) => Bool(*a && *b),149 (Bool(a), And, Bool(b)) => Bool(*a && *b),
modifiedcrates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth
61impl 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 {
modifiedcrates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth
14};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};
1619
17pub 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 }
127133
128 pub fn params(&self) -> Vec<BuiltinParam> {134 pub fn params(&self) -> Vec<BuiltinParam> {
129 match self {135 match self {
240 }246 }
241}247}
248
249impl<T> From<T> for FuncVal
250where
251 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}
242262
modifiedcrates/jrsonnet-evaluator/src/function/native.rsdiffbeforeafterboth
2 arglike::{ArgLike, OptionalContext},2 arglike::{ArgLike, OptionalContext},
3 FuncVal,3 FuncVal,
4};4};
5use crate::{error::Result, typed::Typed};5use crate::{typed::Typed, Result};
66
7pub trait NativeDesc {7pub trait NativeDesc {
8 type Value;8 type Value;
modifiedcrates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth

no syntactic changes

modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
11};11};
1212
13use 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};
1917
20impl<'de> Deserialize<'de> for Val {18impl<'de> Deserialize<'de> for Val {
57 where55 where
58 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 }
6260
63 // visit_num! {61 // visit_num! {
138136
139 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 keys
141 out.member(k.into()).value_unchecked(v);139 out.field(k).value(v);
142 }140 }
143141
144 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 }
371369
378 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 }
384382
385 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 }
556554
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
498pub 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 }
503503
504 fn as_any(&self) -> &dyn Any {504 fn as_any(&self) -> &dyn Any {
modifiedcrates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth
174 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() {
modifiedcrates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth
15 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 self
850 }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 self
863 }
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 }
856872
857 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 defined
933 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 }
939955
956 /// Tries to insert value, returns an error if it was already defined
940 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))))
963980
964pub 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)));
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
276 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);276 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);
277277
278 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 }
281281
282 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);
293293
294 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 }
297297
298 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;
309309
310 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 }
313313
314 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 }
611611
612 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 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
142 }142 }
143 }143 }
144}144}
145impl<T, V: Trace> From<T> for Thunk<V>
146where
147 T: ThunkValue<Output = V>,
148{
149 fn from(value: T) -> Self {
150 Thunk::new(value)
151 }
152}
145153
146impl<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 StrValue
327 fn from(value: &str) -> Self {335where
328 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 }
503
504 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}
511
512impl 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}
503532
504const 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(_))
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
567 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 #hide
572 #add572 #add
573 .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 #hide
580 #add580 #add
581 .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 {
modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
36#[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"))?,
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
66
7use 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;
1716
18mod 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 }
191186
192 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");
211200
212 builder201 builder.method("id", FuncVal::Id);
213 .member("id".into())
214 .hide()
215 .value(Val::Func(FuncVal::Id))
216 .expect("no conflict");
217202
218 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_natives
344 .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;
362347
363 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();
375360
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
47 .ext_natives47 .ext_natives
48 .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}
5252
53#[builtin(fields(53#[builtin(fields(
modifiedcrates/jrsonnet-stdlib/src/objects.rsdiffbeforeafterboth
122 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 }
127127
128 new_obj.build()128 new_obj.build()
modifiedcrates/jrsonnet-stdlib/src/operator.rsdiffbeforeafterboth
16 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 )
modifiedcrates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth
1use std::cmp::Ordering;1use std::cmp::Ordering;
22
3use 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;
1110
108 }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 b
113 out.push(av.clone().expect("ak != None"));112 out.push(av.clone().expect("ak != None"));
114 av = a.next();113 av = a.next();
modifiedcrates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth
3 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};
99
41pub 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}
modifiedtests/tests/builtin.rsdiffbeforeafterboth
36 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 );
4141
42 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 );
7474
75 let v = s.evaluate_snippet(75 let v = s.evaluate_snippet(
modifiedtests/tests/common.rsdiffbeforeafterboth
77#[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)));
8682
87 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}