difftreelog
style fix formatting
in: master
4 files changed
crates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth1use std::fmt::Debug;23pub use arglike::{ArgLike, ArgsLike, TlaArg};4use jrsonnet_gcmodule::{Cc, Trace};5use jrsonnet_interner::IStr;6pub use jrsonnet_macros::builtin;7use jrsonnet_parser::{Destruct, Expr, ExprLocation, LocExpr, ParamsDesc};89use self::{10 arglike::OptionalContext,11 builtin::{Builtin, BuiltinParam, ParamName, StaticBuiltin},12 native::NativeDesc,13 parse::{parse_default_function_call, parse_function_call},14};15use crate::{16 evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result,17 Val,18};1920pub mod arglike;21pub mod builtin;22pub mod native;23pub mod parse;2425/// Function callsite location.26/// Either from other jsonnet code, specified by expression location, or from native (without location).27#[derive(Clone, Copy)]28pub struct CallLocation<'l>(pub Option<&'l ExprLocation>);29impl<'l> CallLocation<'l> {30 /// Construct new location for calls coming from specified jsonnet expression location.31 pub const fn new(loc: &'l ExprLocation) -> Self {32 Self(Some(loc))33 }34}35impl CallLocation<'static> {36 /// Construct new location for calls coming from native code.37 pub const fn native() -> Self {38 Self(None)39 }40}4142/// Represents Jsonnet function defined in code.43#[derive(Debug, PartialEq, Trace)]44pub struct FuncDesc {45 /// # Example46 ///47 /// In expressions like this, deducted to `a`, unspecified otherwise.48 /// ```jsonnet49 /// local a = function() ...50 /// local a() ...51 /// { a: function() ... }52 /// { a() = ... }53 /// ```54 pub name: IStr,55 /// Context, in which this function was evaluated.56 ///57 /// # Example58 /// In59 /// ```jsonnet60 /// local a = 2;61 /// function() ...62 /// ```63 /// context will contain `a`.64 pub ctx: Context,6566 /// Function parameter definition67 pub params: ParamsDesc,68 /// Function body69 pub body: LocExpr,70}71impl FuncDesc {72 /// Create body context, but fill arguments without defaults with lazy error73 pub fn default_body_context(&self) -> Result<Context> {74 parse_default_function_call(self.ctx.clone(), &self.params)75 }7677 /// Create context, with which body code will run78 pub fn call_body_context(79 &self,80 call_ctx: Context,81 args: &dyn ArgsLike,82 tailstrict: bool,83 ) -> Result<Context> {84 parse_function_call(call_ctx, self.ctx.clone(), &self.params, args, tailstrict)85 }8687 pub fn evaluate_trivial(&self) -> Option<Val> {88 evaluate_trivial(&self.body)89 }90}9192/// Represents a Jsonnet function value, including plain functions and user-provided builtins.93#[allow(clippy::module_name_repetitions)]94#[derive(Trace, Clone)]95pub enum FuncVal {96 /// Identity function, kept this way for comparsions.97 Id,98 /// Plain function implemented in jsonnet.99 Normal(Cc<FuncDesc>),100 /// Standard library function.101 StaticBuiltin(#[trace(skip)] &'static dyn StaticBuiltin),102 /// User-provided function.103 Builtin(Cc<TraceBox<dyn Builtin>>),104}105106impl Debug for FuncVal {107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {108 match self {109 Self::Id => f.debug_tuple("Id").finish(),110 Self::Normal(arg0) => f.debug_tuple("Normal").field(arg0).finish(),111 Self::StaticBuiltin(arg0) => {112 f.debug_tuple("StaticBuiltin").field(&arg0.name()).finish()113 }114 Self::Builtin(arg0) => f.debug_tuple("Builtin").field(&arg0.name()).finish(),115 }116 }117}118119#[allow(clippy::unnecessary_wraps)]120#[builtin]121const fn builtin_id(x: Val) -> Val {122 x123}124static ID: &builtin_id = &builtin_id {};125126impl FuncVal {127 pub fn builtin(builtin: impl Builtin) -> Self {128 Self::Builtin(Cc::new(tb!(builtin)))129 }130 pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self {131 Self::StaticBuiltin(static_builtin)132 }133134 pub fn params(&self) -> Vec<BuiltinParam> {135 match self {136 Self::Id => ID.params().to_vec(),137 Self::StaticBuiltin(i) => i.params().to_vec(),138 Self::Builtin(i) => i.params().to_vec(),139 Self::Normal(p) => p140 .params141 .iter()142 .map(|p| {143 BuiltinParam::new(144 p.0.name()145 .as_ref()146 .map(IStr::to_string)147 .map_or(ParamName::ANONYMOUS, ParamName::new_dynamic),148 p.1.is_some(),149 )150 })151 .collect(),152 }153 }154 /// Amount of non-default required arguments155 pub fn params_len(&self) -> usize {156 match self {157 Self::Id => 1,158 Self::Normal(n) => n.params.iter().filter(|p| p.1.is_none()).count(),159 Self::StaticBuiltin(i) => i.params().iter().filter(|p| !p.has_default()).count(),160 Self::Builtin(i) => i.params().iter().filter(|p| !p.has_default()).count(),161 }162 }163 /// Function name, as defined in code.164 pub fn name(&self) -> IStr {165 match self {166 Self::Id => "id".into(),167 Self::Normal(normal) => normal.name.clone(),168 Self::StaticBuiltin(builtin) => builtin.name().into(),169 Self::Builtin(builtin) => builtin.name().into(),170 }171 }172 /// Call function using arguments evaluated in specified `call_ctx` [`Context`].173 ///174 /// If `tailstrict` is specified - then arguments will be evaluated before being passed to function body.175 pub fn evaluate(176 &self,177 call_ctx: Context,178 loc: CallLocation<'_>,179 args: &dyn ArgsLike,180 tailstrict: bool,181 ) -> Result<Val> {182 match self {183 Self::Id => ID.call(call_ctx, loc, args),184 Self::Normal(func) => {185 let body_ctx = func.call_body_context(call_ctx, args, tailstrict)?;186 evaluate(body_ctx, &func.body)187 }188 Self::StaticBuiltin(b) => b.call(call_ctx, loc, args),189 Self::Builtin(b) => b.call(call_ctx, loc, args),190 }191 }192 pub fn evaluate_simple<A: ArgsLike + OptionalContext>(193 &self,194 args: &A,195 tailstrict: bool,196 ) -> Result<Val> {197 self.evaluate(198 ContextBuilder::dangerous_empty_state().build(),199 CallLocation::native(),200 args,201 tailstrict,202 )203 }204 /// Convert jsonnet function to plain `Fn` value.205 pub fn into_native<D: NativeDesc>(self) -> D::Value {206 D::into_native(self)207 }208209 /// Is this function an indentity function.210 ///211 /// Currently only works for builtin `std.id`, aka `Self::Id` value, and `function(x) x`.212 ///213 /// This function should only be used for optimization, not for the conditional logic, i.e code should work with syntetic identity function too214 pub fn is_identity(&self) -> bool {215 match self {216 Self::Id => true,217 Self::Normal(desc) => {218 if desc.params.len() != 1 {219 return false;220 }221 let param = &desc.params[0];222 if param.1.is_some() {223 return false;224 }225 #[allow(clippy::infallible_destructuring_match)]226 let id = match ¶m.0 {227 Destruct::Full(id) => id,228 #[cfg(feature = "exp-destruct")]229 _ => return false,230 };231 &desc.body.0 as &Expr == &Expr::Var(id.clone())232 }233 _ => false,234 }235 }236 /// Identity function value.237 pub const fn identity() -> Self {238 Self::Id239 }240241 pub fn evaluate_trivial(&self) -> Option<Val> {242 match self {243 FuncVal::Normal(n) => n.evaluate_trivial(),244 _ => None,245 }246 }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}1use std::fmt::Debug;23pub use arglike::{ArgLike, ArgsLike, TlaArg};4use jrsonnet_gcmodule::{Cc, Trace};5use jrsonnet_interner::IStr;6pub use jrsonnet_macros::builtin;7use jrsonnet_parser::{Destruct, Expr, ExprLocation, LocExpr, ParamsDesc};89use self::{10 arglike::OptionalContext,11 builtin::{Builtin, BuiltinParam, ParamName, StaticBuiltin},12 native::NativeDesc,13 parse::{parse_default_function_call, parse_function_call},14};15use crate::{evaluate, evaluate_trivial, gc::TraceBox, tb, Context, ContextBuilder, Result, Val};1617pub mod arglike;18pub mod builtin;19pub mod native;20pub mod parse;2122/// Function callsite location.23/// Either from other jsonnet code, specified by expression location, or from native (without location).24#[derive(Clone, Copy)]25pub struct CallLocation<'l>(pub Option<&'l ExprLocation>);26impl<'l> CallLocation<'l> {27 /// Construct new location for calls coming from specified jsonnet expression location.28 pub const fn new(loc: &'l ExprLocation) -> Self {29 Self(Some(loc))30 }31}32impl CallLocation<'static> {33 /// Construct new location for calls coming from native code.34 pub const fn native() -> Self {35 Self(None)36 }37}3839/// Represents Jsonnet function defined in code.40#[derive(Debug, PartialEq, Trace)]41pub struct FuncDesc {42 /// # Example43 ///44 /// In expressions like this, deducted to `a`, unspecified otherwise.45 /// ```jsonnet46 /// local a = function() ...47 /// local a() ...48 /// { a: function() ... }49 /// { a() = ... }50 /// ```51 pub name: IStr,52 /// Context, in which this function was evaluated.53 ///54 /// # Example55 /// In56 /// ```jsonnet57 /// local a = 2;58 /// function() ...59 /// ```60 /// context will contain `a`.61 pub ctx: Context,6263 /// Function parameter definition64 pub params: ParamsDesc,65 /// Function body66 pub body: LocExpr,67}68impl FuncDesc {69 /// Create body context, but fill arguments without defaults with lazy error70 pub fn default_body_context(&self) -> Result<Context> {71 parse_default_function_call(self.ctx.clone(), &self.params)72 }7374 /// Create context, with which body code will run75 pub fn call_body_context(76 &self,77 call_ctx: Context,78 args: &dyn ArgsLike,79 tailstrict: bool,80 ) -> Result<Context> {81 parse_function_call(call_ctx, self.ctx.clone(), &self.params, args, tailstrict)82 }8384 pub fn evaluate_trivial(&self) -> Option<Val> {85 evaluate_trivial(&self.body)86 }87}8889/// Represents a Jsonnet function value, including plain functions and user-provided builtins.90#[allow(clippy::module_name_repetitions)]91#[derive(Trace, Clone)]92pub enum FuncVal {93 /// Identity function, kept this way for comparsions.94 Id,95 /// Plain function implemented in jsonnet.96 Normal(Cc<FuncDesc>),97 /// Standard library function.98 StaticBuiltin(#[trace(skip)] &'static dyn StaticBuiltin),99 /// User-provided function.100 Builtin(Cc<TraceBox<dyn Builtin>>),101}102103impl Debug for FuncVal {104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {105 match self {106 Self::Id => f.debug_tuple("Id").finish(),107 Self::Normal(arg0) => f.debug_tuple("Normal").field(arg0).finish(),108 Self::StaticBuiltin(arg0) => {109 f.debug_tuple("StaticBuiltin").field(&arg0.name()).finish()110 }111 Self::Builtin(arg0) => f.debug_tuple("Builtin").field(&arg0.name()).finish(),112 }113 }114}115116#[allow(clippy::unnecessary_wraps)]117#[builtin]118const fn builtin_id(x: Val) -> Val {119 x120}121static ID: &builtin_id = &builtin_id {};122123impl FuncVal {124 pub fn builtin(builtin: impl Builtin) -> Self {125 Self::Builtin(Cc::new(tb!(builtin)))126 }127 pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self {128 Self::StaticBuiltin(static_builtin)129 }130131 pub fn params(&self) -> Vec<BuiltinParam> {132 match self {133 Self::Id => ID.params().to_vec(),134 Self::StaticBuiltin(i) => i.params().to_vec(),135 Self::Builtin(i) => i.params().to_vec(),136 Self::Normal(p) => p137 .params138 .iter()139 .map(|p| {140 BuiltinParam::new(141 p.0.name()142 .as_ref()143 .map(IStr::to_string)144 .map_or(ParamName::ANONYMOUS, ParamName::new_dynamic),145 p.1.is_some(),146 )147 })148 .collect(),149 }150 }151 /// Amount of non-default required arguments152 pub fn params_len(&self) -> usize {153 match self {154 Self::Id => 1,155 Self::Normal(n) => n.params.iter().filter(|p| p.1.is_none()).count(),156 Self::StaticBuiltin(i) => i.params().iter().filter(|p| !p.has_default()).count(),157 Self::Builtin(i) => i.params().iter().filter(|p| !p.has_default()).count(),158 }159 }160 /// Function name, as defined in code.161 pub fn name(&self) -> IStr {162 match self {163 Self::Id => "id".into(),164 Self::Normal(normal) => normal.name.clone(),165 Self::StaticBuiltin(builtin) => builtin.name().into(),166 Self::Builtin(builtin) => builtin.name().into(),167 }168 }169 /// Call function using arguments evaluated in specified `call_ctx` [`Context`].170 ///171 /// If `tailstrict` is specified - then arguments will be evaluated before being passed to function body.172 pub fn evaluate(173 &self,174 call_ctx: Context,175 loc: CallLocation<'_>,176 args: &dyn ArgsLike,177 tailstrict: bool,178 ) -> Result<Val> {179 match self {180 Self::Id => ID.call(call_ctx, loc, args),181 Self::Normal(func) => {182 let body_ctx = func.call_body_context(call_ctx, args, tailstrict)?;183 evaluate(body_ctx, &func.body)184 }185 Self::StaticBuiltin(b) => b.call(call_ctx, loc, args),186 Self::Builtin(b) => b.call(call_ctx, loc, args),187 }188 }189 pub fn evaluate_simple<A: ArgsLike + OptionalContext>(190 &self,191 args: &A,192 tailstrict: bool,193 ) -> Result<Val> {194 self.evaluate(195 ContextBuilder::dangerous_empty_state().build(),196 CallLocation::native(),197 args,198 tailstrict,199 )200 }201 /// Convert jsonnet function to plain `Fn` value.202 pub fn into_native<D: NativeDesc>(self) -> D::Value {203 D::into_native(self)204 }205206 /// Is this function an indentity function.207 ///208 /// Currently only works for builtin `std.id`, aka `Self::Id` value, and `function(x) x`.209 ///210 /// This function should only be used for optimization, not for the conditional logic, i.e code should work with syntetic identity function too211 pub fn is_identity(&self) -> bool {212 match self {213 Self::Id => true,214 Self::Normal(desc) => {215 if desc.params.len() != 1 {216 return false;217 }218 let param = &desc.params[0];219 if param.1.is_some() {220 return false;221 }222 #[allow(clippy::infallible_destructuring_match)]223 let id = match ¶m.0 {224 Destruct::Full(id) => id,225 #[cfg(feature = "exp-destruct")]226 _ => return false,227 };228 &desc.body.0 as &Expr == &Expr::Var(id.clone())229 }230 _ => false,231 }232 }233 /// Identity function value.234 pub const fn identity() -> Self {235 Self::Id236 }237238 pub fn evaluate_trivial(&self) -> Option<Val> {239 match self {240 FuncVal::Normal(n) => n.evaluate_trivial(),241 _ => None,242 }243 }244}245246impl<T> From<T> for FuncVal247where248 T: Builtin,249{250 fn from(value: T) -> Self {251 Self::builtin(value)252 }253}254impl From<&'static dyn StaticBuiltin> for FuncVal {255 fn from(value: &'static dyn StaticBuiltin) -> Self {256 Self::static_builtin(value)257 }258}crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -11,8 +11,7 @@
};
use crate::{
- arr::ArrValue, runtime_error, Error as JrError, ObjValue, ObjValueBuilder,
- Result, State, Val,
+ arr::ArrValue, runtime_error, Error as JrError, ObjValue, ObjValueBuilder, Result, State, Val,
};
impl<'de> Deserialize<'de> for Val {
crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -635,13 +635,11 @@
el!(
Index {
indexable: el!(Var("std".into()), 1, 4),
- parts: vec![
- IndexPart {
- value: el!(Str("deepJoin".into()), 5, 13),
- #[cfg(feature = "exp-null-coaelse")]
- null_coaelse: false,
- },
- ],
+ parts: vec![IndexPart {
+ value: el!(Str("deepJoin".into()), 5, 13),
+ #[cfg(feature = "exp-null-coaelse")]
+ null_coaelse: false,
+ }],
},
1,
13
crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -349,12 +349,10 @@
std.with_super(self.stdlib_obj.clone());
std.field("thisFile".into())
.hide()
- .value(Val::string(
- match source.source_path().path() {
- Some(p) => self.settings().path_resolver.resolve(p).into(),
- None => source.source_path().to_string().into(),
- },
- ))
+ .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();