From 027693dbe6bda02314cd28113033759f347996f6 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sun, 13 Aug 2023 12:22:30 +0000 Subject: [PATCH] refactor: reduce boilerplate by automatic conversions --- --- a/bindings/jsonnet/src/native.rs +++ b/bindings/jsonnet/src/native.rs @@ -69,10 +69,7 @@ ctx: *const c_void, mut raw_params: *const *const c_char, ) { - let name = CStr::from_ptr(name) - .to_str() - .expect("name is not utf-8") - .into(); + let name = CStr::from_ptr(name).to_str().expect("name is not utf-8"); let mut params = Vec::new(); loop { if (*raw_params).is_null() { --- a/bindings/jsonnet/src/val_make.rs +++ b/bindings/jsonnet/src/val_make.rs @@ -5,10 +5,7 @@ os::raw::{c_char, c_double, c_int}, }; -use jrsonnet_evaluator::{ - val::{ArrValue, StrValue}, - ObjValue, Val, -}; +use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val}; use crate::VM; @@ -21,7 +18,7 @@ pub unsafe extern "C" fn jsonnet_json_make_string(_vm: &VM, val: *const c_char) -> *mut Val { let val = CStr::from_ptr(val); let val = val.to_str().expect("string is not utf-8"); - Box::into_raw(Box::new(Val::Str(StrValue::Flat(val.into())))) + Box::into_raw(Box::new(Val::string(val))) } /// Convert the given double to a `JsonnetJsonValue`. --- a/bindings/jsonnet/src/val_modify.rs +++ b/bindings/jsonnet/src/val_modify.rs @@ -5,7 +5,6 @@ use std::{ffi::CStr, os::raw::c_char}; use jrsonnet_evaluator::{val::ArrValue, Thunk, Val}; -use jrsonnet_gcmodule::Cc; use crate::VM; --- a/crates/jrsonnet-cli/src/stdlib.rs +++ b/crates/jrsonnet-cli/src/stdlib.rs @@ -1,7 +1,7 @@ use std::{fs::read_to_string, str::FromStr}; use clap::Parser; -use jrsonnet_evaluator::{error::Result, trace::PathResolver, State}; +use jrsonnet_evaluator::{trace::PathResolver, Result, State}; use jrsonnet_stdlib::ContextInitializer; #[derive(Clone)] --- a/crates/jrsonnet-evaluator/src/arr/spec.rs +++ b/crates/jrsonnet-evaluator/src/arr/spec.rs @@ -6,12 +6,8 @@ use super::ArrValue; use crate::{ - error::ErrorKind::InfiniteRecursionDetected, - evaluate, - function::FuncVal, - typed::Typed, - val::{StrValue, ThunkValue}, - Context, Error, ObjValue, Result, Thunk, Val, + error::ErrorKind::InfiniteRecursionDetected, evaluate, function::FuncVal, typed::Typed, + val::ThunkValue, Context, Error, ObjValue, Result, Thunk, Val, }; pub trait ArrayLike: Any + Trace + Debug { @@ -101,9 +97,7 @@ } fn get_cheap(&self, index: usize) -> Option { - self.0 - .get(index) - .map(|v| Val::Str(StrValue::Flat(IStr::from(*v)))) + self.0.get(index).map(|v| Val::string(*v)) } fn is_cheap(&self) -> bool { true --- a/crates/jrsonnet-evaluator/src/ctx.rs +++ b/crates/jrsonnet-evaluator/src/ctx.rs @@ -87,9 +87,9 @@ } #[must_use] - pub fn with_var(self, name: IStr, value: Val) -> Self { + pub fn with_var(self, name: impl Into, value: Val) -> Self { let mut new_bindings = GcHashMap::with_capacity(1); - new_bindings.insert(name, Thunk::evaluated(value)); + new_bindings.insert(name.into(), Thunk::evaluated(value)); self.extend(new_bindings, None, None, None) } @@ -161,8 +161,8 @@ } /// # Panics /// If `name` is already bound - pub fn bind(&mut self, name: IStr, value: Thunk) -> &mut Self { - let old = self.bindings.insert(name, value); + pub fn bind(&mut self, name: impl Into, value: Thunk) -> &mut Self { + let old = self.bindings.insert(name.into(), value); assert!(old.is_none(), "variable bound twice in single context call"); self } --- a/crates/jrsonnet-evaluator/src/dynamic.rs +++ b/crates/jrsonnet-evaluator/src/dynamic.rs @@ -52,9 +52,3 @@ Self::new() } } - -impl From> for Thunk { - fn from(value: Pending) -> Self { - Self::new(value) - } -} --- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs @@ -36,7 +36,7 @@ } } Some(match &*expr.0 { - Expr::Str(s) => Val::Str(StrValue::Flat(s.clone())), + Expr::Str(s) => Val::string(s.clone()), Expr::Num(n) => Val::Num(*n), Expr::Literal(LiteralType::False) => Val::Bool(false), Expr::Literal(LiteralType::True) => Val::Bool(true), @@ -135,7 +135,7 @@ let fctx = Pending::new(); let mut new_bindings = GcHashMap::with_capacity(var.capacity_hint()); let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![ - Thunk::evaluated(Val::Str(StrValue::Flat(field.clone()))), + Thunk::evaluated(Val::string(field.clone())), Thunk::new(ObjectFieldThunk { field: field.clone(), obj: obj.clone(), @@ -226,7 +226,7 @@ } builder - .member(name.clone()) + .field(name.clone()) .with_add(*plus) .with_visibility(*visibility) .with_location(value.1.clone()) @@ -262,7 +262,7 @@ } builder - .member(name.clone()) + .field(name.clone()) .with_visibility(*visibility) .with_location(value.1.clone()) .bindable(UnboundMethod { @@ -437,7 +437,7 @@ Literal(LiteralType::False) => Val::Bool(false), Literal(LiteralType::Null) => Val::Null, Parened(e) => evaluate(ctx, e)?, - Str(v) => Val::Str(StrValue::Flat(v.clone())), + Str(v) => Val::string(v.clone()), Num(v) => Val::new_checked_num(*v)?, BinaryOp(v1, o, v2) => evaluate_binary_op_special(ctx, v1, *o, v2)?, UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(ctx, v)?)?, @@ -672,7 +672,7 @@ || format!("import {:?}", path.clone()), || s.import_resolved(resolved_path), )?, - ImportStr(_) => Val::Str(StrValue::Flat(s.import_resolved_str(resolved_path)?)), + ImportStr(_) => Val::string(s.import_resolved_str(resolved_path)?), ImportBin(_) => Val::Arr(ArrValue::bytes(s.import_resolved_bin(resolved_path)?)), _ => unreachable!(), } --- a/crates/jrsonnet-evaluator/src/evaluate/operator.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/operator.rs @@ -30,18 +30,12 @@ Ok(match (a, b) { (Str(v1), Str(v2)) => Str(StrValue::concat(v1.clone(), v2.clone())), - (Num(a), Str(b)) => Str(StrValue::Flat(format!("{a}{b}").into())), - (Str(a), Num(b)) => Str(StrValue::Flat(format!("{a}{b}").into())), + (Num(a), Str(b)) => Val::string(format!("{a}{b}")), + (Str(a), Num(b)) => Val::string(format!("{a}{b}")), - (Str(a), o) | (o, Str(a)) if a.is_empty() => { - Val::Str(StrValue::Flat(o.clone().to_string()?)) - } - (Str(a), o) => Str(StrValue::Flat( - format!("{a}{}", o.clone().to_string()?).into(), - )), - (o, Str(a)) => Str(StrValue::Flat( - format!("{}{a}", o.clone().to_string()?).into(), - )), + (Str(a), o) | (o, Str(a)) if a.is_empty() => Val::string(o.clone().to_string()?), + (Str(a), o) => Val::string(format!("{a}{}", o.clone().to_string()?)), + (o, Str(a)) => Val::string(format!("{}{a}", o.clone().to_string()?)), (Obj(v1), Obj(v2)) => Obj(v2.extend_from(v1.clone())), (Arr(a), Arr(b)) => Val::Arr(ArrValue::extended(a.clone(), b.clone())), @@ -149,7 +143,7 @@ (Str(a), In, Obj(obj)) => Bool(obj.has_field_ex(a.clone().into_flat(), true)), (a, Mod, b) => evaluate_mod_op(a, b)?, - (Str(v1), Mul, Num(v2)) => Str(StrValue::Flat(v1.to_string().repeat(*v2 as usize).into())), + (Str(v1), Mul, Num(v2)) => Val::string(v1.to_string().repeat(*v2 as usize)), // Bool X Bool (Bool(a), And, Bool(b)) => Bool(*a && *b), --- a/crates/jrsonnet-evaluator/src/function/arglike.rs +++ b/crates/jrsonnet-evaluator/src/function/arglike.rs @@ -61,7 +61,7 @@ impl ArgLike for TlaArg { fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result> { match self { - TlaArg::String(s) => Ok(Thunk::evaluated(Val::Str(StrValue::Flat(s.clone())))), + TlaArg::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))), TlaArg::Code(code) => Ok(if tailstrict { Thunk::evaluated(evaluate(ctx, code)?) } else { --- a/crates/jrsonnet-evaluator/src/function/mod.rs +++ b/crates/jrsonnet-evaluator/src/function/mod.rs @@ -12,7 +12,10 @@ native::NativeDesc, parse::{parse_default_function_call, parse_function_call}, }; -use crate::{evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, Val}; +use crate::{ + evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, + Val, +}; pub mod arglike; pub mod builtin; @@ -124,6 +127,9 @@ pub fn builtin(builtin: impl Builtin) -> Self { Self::Builtin(Cc::new(tb!(builtin))) } + pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self { + Self::StaticBuiltin(static_builtin) + } pub fn params(&self) -> Vec { match self { @@ -239,3 +245,17 @@ } } } + +impl From for FuncVal +where + T: Builtin, +{ + fn from(value: T) -> Self { + Self::builtin(value) + } +} +impl From<&'static dyn StaticBuiltin> for FuncVal { + fn from(value: &'static dyn StaticBuiltin) -> Self { + Self::static_builtin(value) + } +} --- a/crates/jrsonnet-evaluator/src/function/native.rs +++ b/crates/jrsonnet-evaluator/src/function/native.rs @@ -2,7 +2,7 @@ arglike::{ArgLike, OptionalContext}, FuncVal, }; -use crate::{error::Result, typed::Typed}; +use crate::{typed::Typed, Result}; pub trait NativeDesc { type Value; --- a/crates/jrsonnet-evaluator/src/gc.rs +++ b/crates/jrsonnet-evaluator/src/gc.rs @@ -117,9 +117,7 @@ } #[derive(Debug)] -pub struct GcHashMap( - pub HashMap> -); +pub struct GcHashMap(pub HashMap>); impl GcHashMap { pub fn new() -> Self { Self(HashMap::default()) --- a/crates/jrsonnet-evaluator/src/integrations/serde.rs +++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs @@ -11,10 +11,8 @@ }; use crate::{ - arr::ArrValue, - error::{Error as JrError, ErrorKind, Result}, - val::StrValue, - ObjValue, ObjValueBuilder, State, Val, + arr::ArrValue, runtime_error, Error as JrError, ObjValue, ObjValueBuilder, + Result, State, Val, }; impl<'de> Deserialize<'de> for Val { @@ -57,7 +55,7 @@ where E: serde::de::Error, { - Ok(Val::Str(StrValue::Flat(v.into()))) + Ok(Val::string(v)) } // visit_num! { @@ -138,7 +136,7 @@ while let Some((k, v)) = map.next_entry::, Val>()? { // Jsonnet ignores duplicate keys - out.member(k.into()).value_unchecked(v); + out.field(k).value(v); } Ok(Val::Obj(out.build())) @@ -264,7 +262,7 @@ let inner = Val::Arr(ArrValue::eager(self.data)); if let Some(variant) = self.variant { let mut out = ObjValue::builder_with_capacity(1); - out.member(variant).value_unchecked(inner); + out.field(variant).value(inner); Ok(Val::Obj(out.build())) } else { Ok(inner) @@ -365,7 +363,7 @@ { let key = self.key.take().expect("no serialize_key called"); let value = value.serialize(IntoValSerializer)?; - self.data.member(key).value(value)?; + self.data.field(key).try_value(value)?; Ok(()) } @@ -378,7 +376,7 @@ let key = key.serialize(IntoValSerializer)?; let key = key.to_string()?; let value = value.serialize(IntoValSerializer)?; - self.data.member(key).value(value)?; + self.data.field(key).try_value(value)?; Ok(()) } @@ -386,7 +384,7 @@ let inner = Val::Obj(self.data.build()); if let Some(variant) = self.variant { let mut out = ObjValue::builder_with_capacity(1); - out.member(variant).value_unchecked(inner); + out.field(variant).value(inner); Ok(Val::Obj(out.build())) } else { Ok(inner) @@ -550,7 +548,7 @@ { let mut out = ObjValue::builder_with_capacity(1); let value = value.serialize(self)?; - out.member(variant.into()).value_unchecked(value); + out.field(variant).value(value); Ok(Val::Obj(out.build())) } --- a/crates/jrsonnet-evaluator/src/lib.rs +++ b/crates/jrsonnet-evaluator/src/lib.rs @@ -498,7 +498,7 @@ pub struct InitialUnderscore(pub Thunk); impl ContextInitializer for InitialUnderscore { fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) { - builder.bind("_".into(), self.0.clone()); + builder.bind("_", self.0.clone()); } fn as_any(&self) -> &dyn Any { --- a/crates/jrsonnet-evaluator/src/manifest.rs +++ b/crates/jrsonnet-evaluator/src/manifest.rs @@ -174,11 +174,13 @@ Val::Str(s) => escape_string_json_buf(&s.clone().into_flat(), buf), Val::Num(n) => write!(buf, "{n}").unwrap(), #[cfg(feature = "exp-bigint")] - Val::BigInt(n) => if options.preserve_bigints { - write!(buf, "{n}").unwrap() - } else { - write!(buf, "{:?}", n.to_string()).unwrap() - }, + Val::BigInt(n) => { + if options.preserve_bigints { + write!(buf, "{n}").unwrap() + } else { + write!(buf, "{:?}", n.to_string()).unwrap() + } + } Val::Arr(items) => { buf.push('['); if !items.is_empty() { --- a/crates/jrsonnet-evaluator/src/obj.rs +++ b/crates/jrsonnet-evaluator/src/obj.rs @@ -15,7 +15,7 @@ arr::{PickObjectKeyValues, PickObjectValues}, bail, error::{suggest_object_fields, Error, ErrorKind::*}, - function::CallLocation, + function::{CallLocation, FuncVal}, gc::{GcHashMap, GcHashSet, TraceBox}, operator::evaluate_add_op, tb, @@ -345,7 +345,7 @@ pub(crate) fn extend_with_raw_member(self, key: IStr, value: ObjMember) -> Self { let mut out = ObjValueBuilder::with_capacity(1); out.with_super(self); - let mut member = out.member(key); + let mut member = out.field(key); if value.flags.add() { member = member.add() } @@ -848,11 +848,27 @@ self.assertions.push(tb!(assertion)); self } - pub fn member(&mut self, name: IStr) -> ObjMemberBuilder> { + pub fn field(&mut self, name: impl Into) -> ObjMemberBuilder> { let field_index = self.next_field_index; self.next_field_index = self.next_field_index.next(); - ObjMemberBuilder::new(ValueBuilder(self), name, field_index) + ObjMemberBuilder::new(ValueBuilder(self), name.into(), field_index) } + /// Preset for common method definiton pattern: + /// Create a hidden field with the function value. + /// + /// `.field(name).hide().value(Val::function(value))` + pub fn method(&mut self, name: impl Into, value: impl Into) -> &mut Self { + self.field(name).hide().value(Val::Func(value.into())); + self + } + pub fn try_method( + &mut self, + name: impl Into, + value: impl Into, + ) -> Result<&mut Self> { + self.field(name).hide().try_value(Val::Func(value.into()))?; + Ok(self) + } pub fn build(self) -> ObjValue { if self.sup.is_none() && self.map.is_empty() && self.assertions.is_empty() { @@ -930,18 +946,19 @@ pub struct ValueBuilder<'v>(&'v mut ObjValueBuilder); impl ObjMemberBuilder> { /// Inserts value, replacing if it is already defined - pub fn value_unchecked(self, value: Val) { + pub fn value(self, value: impl Into) { let (receiver, name, member) = - self.build_member(MaybeUnbound::Bound(Thunk::evaluated(value))); + self.build_member(MaybeUnbound::Bound(Thunk::evaluated(value.into()))); let entry = receiver.0.map.entry(name); entry.insert(member); } - pub fn value(self, value: Val) -> Result<()> { - self.thunk(Thunk::evaluated(value)) + /// Tries to insert value, returns an error if it was already defined + pub fn try_value(self, value: impl Into) -> Result<()> { + self.thunk(Thunk::evaluated(value.into())) } - pub fn thunk(self, value: Thunk) -> Result<()> { - self.binding(MaybeUnbound::Bound(value)) + pub fn thunk(self, value: impl Into>) -> Result<()> { + self.binding(MaybeUnbound::Bound(value.into())) } pub fn bindable(self, bindable: impl Unbound) -> Result<()> { self.binding(MaybeUnbound::Unbound(Cc::new(tb!(bindable)))) @@ -963,8 +980,8 @@ pub struct ExtendBuilder<'v>(&'v mut ObjValue); impl ObjMemberBuilder> { - pub fn value(self, value: Val) { - self.binding(MaybeUnbound::Bound(Thunk::evaluated(value))); + pub fn value(self, value: impl Into) { + self.binding(MaybeUnbound::Bound(Thunk::evaluated(value.into()))); } pub fn bindable(self, bindable: TraceBox>) { self.binding(MaybeUnbound::Unbound(Cc::new(bindable))); --- a/crates/jrsonnet-evaluator/src/typed/conversions.rs +++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs @@ -276,7 +276,7 @@ const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str); fn into_untyped(value: Self) -> Result { - Ok(Val::Str(StrValue::Flat(value))) + Ok(Val::string(value)) } fn from_untyped(value: Val) -> Result { @@ -292,7 +292,7 @@ const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str); fn into_untyped(value: Self) -> Result { - Ok(Val::Str(StrValue::Flat(value.into()))) + Ok(Val::string(value)) } fn from_untyped(value: Val) -> Result { @@ -308,7 +308,7 @@ const TYPE: &'static ComplexValType = &ComplexValType::Char; fn into_untyped(value: Self) -> Result { - Ok(Val::Str(StrValue::Flat(value.to_string().into()))) + Ok(Val::string(value)) } fn from_untyped(value: Val) -> Result { @@ -356,7 +356,7 @@ bail!("map key should serialize to string"); }; let value = V::into_untyped(v)?; - out.member(key).value_unchecked(value); + out.field(key).value(value); } Ok(Val::Obj(out.build())) } @@ -611,7 +611,7 @@ fn into_untyped(value: Self) -> Result { match value { - IndexableVal::Str(s) => Ok(Val::Str(StrValue::Flat(s))), + IndexableVal::Str(s) => Ok(Val::string(s)), IndexableVal::Arr(a) => Ok(Val::Arr(a)), } } --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -142,6 +142,14 @@ } } } +impl From for Thunk +where + T: ThunkValue, +{ + fn from(value: T) -> Self { + Thunk::new(value) + } +} impl Default for Thunk { fn default() -> Self { @@ -323,21 +331,14 @@ } } } -impl From<&str> for StrValue { - fn from(value: &str) -> Self { - Self::Flat(value.into()) - } -} -impl From for StrValue { - fn from(value: String) -> Self { - Self::Flat(value.into()) +impl From for StrValue +where + IStr: From, +{ + fn from(value: T) -> Self { + Self::Flat(IStr::from(value)) } } -impl From for StrValue { - fn from(value: IStr) -> Self { - Self::Flat(value) - } -} impl Display for StrValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -401,7 +402,7 @@ impl From for Val { fn from(v: IndexableVal) -> Self { match v { - IndexableVal::Str(s) => Self::Str(StrValue::Flat(s)), + IndexableVal::Str(s) => Self::string(s), IndexableVal::Arr(a) => Self::Arr(a), } } @@ -499,6 +500,34 @@ _ => bail!(ValueIsNotIndexable(self.value_type())), }) } + + pub fn function(function: impl Into) -> Self { + Self::Func(function.into()) + } + pub fn string(string: impl Into) -> Self { + Self::Str(string.into()) + } +} + +impl From for Val { + fn from(value: IStr) -> Self { + Self::string(value) + } +} +impl From for Val { + fn from(value: String) -> Self { + Self::string(value) + } +} +impl From<&str> for Val { + fn from(value: &str) -> Self { + Self::string(value) + } +} +impl From for Val { + fn from(value: ObjValue) -> Self { + Self::Obj(value) + } } const fn is_function_like(val: &Val) -> bool { --- a/crates/jrsonnet-macros/src/lib.rs +++ b/crates/jrsonnet-macros/src/lib.rs @@ -567,18 +567,18 @@ if self.is_option { quote! { if let Some(value) = self.#ident { - out.member(#name.into()) + out.field(#name) #hide #add - .value(<#ty as Typed>::into_untyped(value)?)?; + .try_value(<#ty as Typed>::into_untyped(value)?)?; } } } else { quote! { - out.member(#name.into()) + out.field(#name) #hide #add - .value(<#ty as Typed>::into_untyped(self.#ident)?)?; + .try_value(<#ty as Typed>::into_untyped(self.#ident)?)?; } } } else if self.is_option { --- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -36,7 +36,7 @@ #[builtin] pub fn builtin_repeat(what: Either![IStr, ArrValue], count: usize) -> Result { Ok(match what { - Either2::A(s) => Val::Str(StrValue::Flat(s.repeat(count).into())), + Either2::A(s) => Val::string(s.repeat(count)), Either2::B(arr) => Val::Arr( ArrValue::repeated(arr, count) .ok_or_else(|| runtime_error!("repeated length overflow"))?, --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -6,13 +6,12 @@ use jrsonnet_evaluator::{ error::{ErrorKind::*, Result}, - function::{builtin::Builtin, CallLocation, FuncVal, TlaArg}, - gc::TraceBox, + function::{CallLocation, FuncVal, TlaArg}, tb, trace::PathResolver, ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val, }; -use jrsonnet_gcmodule::{Cc, Trace}; +use jrsonnet_gcmodule::Trace; use jrsonnet_parser::Source; mod expr; @@ -182,38 +181,24 @@ .iter() .cloned() { - builder - .member(name.into()) - .hide() - .value(Val::Func(FuncVal::StaticBuiltin(builtin))) - .expect("no conflict"); + builder.method(name, builtin); } - builder - .member("extVar".into()) - .hide() - .value(Val::Func(FuncVal::builtin(builtin_ext_var { + builder.method( + "extVar", + builtin_ext_var { settings: settings.clone(), - }))) - .expect("no conflict"); - builder - .member("native".into()) - .hide() - .value(Val::Func(FuncVal::builtin(builtin_native { + }, + ); + builder.method( + "native", + builtin_native { settings: settings.clone(), - }))) - .expect("no conflict"); - builder - .member("trace".into()) - .hide() - .value(Val::Func(FuncVal::builtin(builtin_trace { settings }))) - .expect("no conflict"); + }, + ); + builder.method("trace", builtin_trace { settings }); - builder - .member("id".into()) - .hide() - .value(Val::Func(FuncVal::Id)) - .expect("no conflict"); + builder.method("id", FuncVal::Id); builder.build() } @@ -293,7 +278,7 @@ #[cfg(not(feature = "legacy-this-file"))] context: { let mut context = ContextBuilder::with_capacity(_s, 1); - context.bind("std".into(), stdlib_thunk.clone()); + context.bind("std", stdlib_thunk.clone()); context.build() }, #[cfg(not(feature = "legacy-this-file"))] @@ -338,10 +323,10 @@ .insert(name.into(), TlaArg::Code(parsed)); Ok(()) } - pub fn add_native(&self, name: IStr, cb: impl Builtin) { + pub fn add_native(&self, name: impl Into, cb: impl Into) { self.settings_mut() .ext_natives - .insert(name, Cc::new(tb!(cb))); + .insert(name.into(), cb.into()); } } impl jrsonnet_evaluator::ContextInitializer for ContextInitializer { @@ -354,7 +339,7 @@ } #[cfg(not(feature = "legacy-this-file"))] fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) { - builder.bind("std".into(), self.stdlib_thunk.clone()); + builder.bind("std", self.stdlib_thunk.clone()); } #[cfg(feature = "legacy-this-file")] fn populate(&self, source: Source, builder: &mut ContextBuilder) { @@ -362,14 +347,14 @@ let mut std = ObjValueBuilder::new(); std.with_super(self.stdlib_obj.clone()); - std.member("thisFile".into()) + std.field("thisFile".into()) .hide() - .value(Val::Str(StrValue::Flat( + .value(Val::string( match source.source_path().path() { Some(p) => self.settings().path_resolver.resolve(p).into(), None => source.source_path().to_string().into(), }, - ))) + )) .expect("this object builder is empty"); let stdlib_with_this_file = std.build(); --- a/crates/jrsonnet-stdlib/src/misc.rs +++ b/crates/jrsonnet-stdlib/src/misc.rs @@ -47,7 +47,7 @@ .ext_natives .get(&x) .cloned() - .map_or(Val::Null, |v| Val::Func(FuncVal::Builtin(v))) + .map_or(Val::Null, |v| Val::Func(v)) } #[builtin(fields( --- a/crates/jrsonnet-stdlib/src/objects.rs +++ b/crates/jrsonnet-stdlib/src/objects.rs @@ -122,7 +122,7 @@ if k == key { continue; } - new_obj.member(k).value_unchecked(v.unwrap()) + new_obj.field(k).value(v.unwrap()) } new_obj.build() --- a/crates/jrsonnet-stdlib/src/operator.rs +++ b/crates/jrsonnet-stdlib/src/operator.rs @@ -16,7 +16,7 @@ evaluate_mod_op( &match a { A(v) => Val::Num(v), - B(s) => Val::Str(StrValue::Flat(s)), + B(s) => Val::string(s), }, &b, ) --- a/crates/jrsonnet-stdlib/src/sets.rs +++ b/crates/jrsonnet-stdlib/src/sets.rs @@ -1,11 +1,10 @@ use std::cmp::Ordering; use jrsonnet_evaluator::{ - error::Result, function::{builtin, FuncVal}, operator::evaluate_compare_op, val::ArrValue, - Thunk, Val, + Result, Thunk, Val, }; use jrsonnet_parser::BinaryOpType; @@ -108,7 +107,7 @@ } }; } - while let Some(ac) = &ak { + while let Some(_ac) = &ak { // In a, but not in b out.push(av.clone().expect("ak != None")); av = a.next(); --- a/crates/jrsonnet-stdlib/src/strings.rs +++ b/crates/jrsonnet-stdlib/src/strings.rs @@ -3,7 +3,7 @@ error::{ErrorKind::*, Result}, function::builtin, typed::{Either2, M1}, - val::{ArrValue, StrValue}, + val::ArrValue, Either, IStr, Val, }; @@ -41,14 +41,8 @@ pub fn builtin_splitlimit(str: IStr, c: IStr, maxsplits: Either![usize, M1]) -> ArrValue { use Either2::*; match maxsplits { - A(n) => str - .splitn(n + 1, &c as &str) - .map(|s| Val::Str(StrValue::Flat(s.into()))) - .collect(), - B(_) => str - .split(&c as &str) - .map(|s| Val::Str(StrValue::Flat(s.into()))) - .collect(), + A(n) => str.splitn(n + 1, &c as &str).map(Val::string).collect(), + B(_) => str.split(&c as &str).map(Val::string).collect(), } } --- a/tests/tests/builtin.rs +++ b/tests/tests/builtin.rs @@ -36,7 +36,7 @@ s.with_stdlib(); s.add_global( "nativeAdd".into(), - Thunk::evaluated(Val::Func(FuncVal::StaticBuiltin(native_add::INST))), + Thunk::evaluated(Val::function(native_add::INST)), ); let v = s.evaluate_snippet( @@ -69,7 +69,7 @@ s.with_stdlib(); s.add_global( "curryAdd".into(), - Thunk::evaluated(Val::Func(FuncVal::StaticBuiltin(curry_add::INST))), + Thunk::evaluated(Val::function(curry_add::INST)), ); let v = s.evaluate_snippet( --- a/tests/tests/common.rs +++ b/tests/tests/common.rs @@ -77,12 +77,8 @@ #[allow(dead_code)] pub fn with_test(s: &State) { let mut bobj = ObjValueBuilder::new(); - bobj.member("assertThrow".into()) - .hide() - .value_unchecked(Val::Func(FuncVal::StaticBuiltin(assert_throw::INST))); - bobj.member("paramNames".into()) - .hide() - .value_unchecked(Val::Func(FuncVal::StaticBuiltin(param_names::INST))); + bobj.method("assertThrow", assert_throw::INST); + bobj.method("paramNames", param_names::INST); s.add_global("test".into(), Thunk::evaluated(Val::Obj(bobj.build()))) } -- gitstuff