git.delta.rocks / jrsonnet / refs/commits / 60607d2bef37

difftreelog

refactor drop special casing of StaticBuiltin and Id functions

lryppxxoYaroslav Bolyukin2026-04-04parent: #a10f2cf.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth
57 fn as_any(&self) -> &dyn Any;57 fn as_any(&self) -> &dyn Any;
58}58}
59
60pub trait StaticBuiltin: Builtin + Send + Sync
61where
62 Self: 'static,
63{
64 // In impl, to make it object safe:
65 // const INST: &'static Self;
66}
6759
68#[derive(Trace)]60#[derive(Trace)]
69pub struct NativeCallback {61pub struct NativeCallback {
modifiedcrates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth
7pub use jrsonnet_macros::builtin;7pub use jrsonnet_macros::builtin;
88
9use self::{9use self::{
10 builtin::{Builtin, StaticBuiltin},10 builtin::Builtin,
11 parse::{parse_builtin_call, parse_default_function_call, parse_function_call},11 parse::{parse_builtin_call, parse_default_function_call, parse_function_call},
12 prepared::{PreparedCall, parse_prepared_builtin_call, parse_prepared_function_call},12 prepared::{parse_prepared_builtin_call, parse_prepared_function_call, PreparedCall},
13};13};
14use crate::{14use crate::{
15 Context, Result, Thunk, Val, bail, error::ErrorKind::*, evaluate, evaluate_trivial,15 bail, error::ErrorKind::*, evaluate, evaluate_trivial, function::builtin::BuiltinFunc, Context,
16 function::builtin::BuiltinFunc,16 Result, Thunk, Val,
17};17};
1818
19pub mod builtin;19pub mod builtin;
97#[allow(clippy::module_name_repetitions)]97#[allow(clippy::module_name_repetitions)]
98#[derive(Trace, Clone)]98#[derive(Trace, Clone)]
99pub enum FuncVal {99pub enum FuncVal {
100 /// Identity function, kept this way for comparsions.
101 Id,
102 /// Plain function implemented in jsonnet.100 /// Plain function implemented in jsonnet.
103 Normal(Cc<FuncDesc>),101 Normal(Cc<FuncDesc>),
104 /// Function without arguments works just as a fancy thunk value.102 /// Function without arguments works just as a fancy thunk value.
105 Thunk(Thunk<Val>),103 Thunk(Thunk<Val>),
106 /// Standard library function.
107 StaticBuiltin(#[trace(skip)] &'static dyn StaticBuiltin),
108 /// User-provided function.104 /// User-provided function.
109 Builtin(BuiltinFunc),105 Builtin(BuiltinFunc),
110}106}
111107
112impl Debug for FuncVal {108impl Debug for FuncVal {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 match self {110 match self {
115 Self::Id => f.debug_tuple("Id").finish(),
116 Self::Thunk(arg0) => f.debug_tuple("Thunk").field(arg0).finish(),111 Self::Thunk(arg0) => f.debug_tuple("Thunk").field(arg0).finish(),
117 Self::Normal(arg0) => f.debug_tuple("Normal").field(arg0).finish(),112 Self::Normal(arg0) => f.debug_tuple("Normal").field(arg0).finish(),
118 Self::StaticBuiltin(arg0) => {
119 f.debug_tuple("StaticBuiltin").field(&arg0.name()).finish()
120 }
121 Self::Builtin(arg0) => f.debug_tuple("Builtin").field(&arg0.name()).finish(),113 Self::Builtin(arg0) => f.debug_tuple("Builtin").field(&arg0.name()).finish(),
122 }114 }
123 }115 }
124}116}
125117
126#[allow(clippy::unnecessary_wraps)]118#[allow(clippy::unnecessary_wraps)]
127#[builtin]119#[builtin]
128const fn builtin_id(x: Val) -> Val {120pub const fn builtin_id(x: Thunk<Val>) -> Thunk<Val> {
129 x121 x
130}122}
131static ID: &builtin_id = &builtin_id {};
132123
133impl FuncVal {124impl FuncVal {
134 pub fn builtin(builtin: impl Builtin) -> Self {125 pub fn builtin(builtin: impl Builtin) -> Self {
135 Self::Builtin(BuiltinFunc::new(builtin))126 Self::Builtin(BuiltinFunc::new(builtin))
136 }127 }
137 pub fn static_builtin(static_builtin: &'static dyn StaticBuiltin) -> Self {
138 Self::StaticBuiltin(static_builtin)
139 }
140128
141 pub fn params(&self) -> FunctionSignature {129 pub fn params(&self) -> FunctionSignature {
142 match self {130 match self {
143 Self::Id => ID.params(),
144 Self::StaticBuiltin(i) => i.params(),
145 Self::Builtin(i) => i.params(),131 Self::Builtin(i) => i.params(),
146 Self::Normal(p) => p.params.signature.clone(),132 Self::Normal(p) => p.params.signature.clone(),
147 Self::Thunk(_) => FunctionSignature::empty(),133 Self::Thunk(_) => FunctionSignature::empty(),
154 /// Function name, as defined in code.140 /// Function name, as defined in code.
155 pub fn name(&self) -> IStr {141 pub fn name(&self) -> IStr {
156 match self {142 match self {
157 Self::Id => "id".into(),
158 Self::Normal(normal) => normal.name.clone(),143 Self::Normal(normal) => normal.name.clone(),
159 Self::StaticBuiltin(builtin) => builtin.name().into(),
160 Self::Builtin(builtin) => builtin.name().into(),144 Self::Builtin(builtin) => builtin.name().into(),
161 Self::Thunk(_) => "thunk".into(),145 Self::Thunk(_) => "thunk".into(),
162 }146 }
182 }166 }
183 thunk.evaluate()167 thunk.evaluate()
184 }168 }
185 Self::Id => {
186 let args = parse_builtin_call(call_ctx, ID.params(), args, tailstrict)?;
187 ID.call(loc, &args)
188 }
189 Self::StaticBuiltin(b) => {
190 let args = parse_builtin_call(call_ctx, b.params(), args, tailstrict)?;
191 b.call(loc, &args)
192 }
193 Self::Builtin(b) => {169 Self::Builtin(b) => {
194 let args = parse_builtin_call(call_ctx, b.params(), args, tailstrict)?;170 let args = parse_builtin_call(call_ctx, b.params(), args, tailstrict)?;
195 b.call(loc, &args)171 b.call(loc, &args)
217 evaluate(body_ctx, &func.body)193 evaluate(body_ctx, &func.body)
218 }194 }
219 FuncVal::Thunk(t) => t.evaluate(),195 FuncVal::Thunk(t) => t.evaluate(),
220 FuncVal::Id => {
221 let args = parse_prepared_builtin_call(prepared, ID.params(), unnamed, named);
222 ID.call(loc, &args)
223 }
224 FuncVal::StaticBuiltin(b) => {
225 let args = parse_prepared_builtin_call(prepared, b.params(), unnamed, named);
226 b.call(loc, &args)
227 }
228 FuncVal::Builtin(b) => {196 FuncVal::Builtin(b) => {
229 let args = parse_prepared_builtin_call(prepared, b.params(), unnamed, named);197 let args = parse_prepared_builtin_call(prepared, b.params(), unnamed, named);
230 b.call(loc, &args)198 b.call(loc, &args)
239 /// This function should only be used for optimization, not for the conditional logic, i.e code should work with syntetic identity function too207 /// This function should only be used for optimization, not for the conditional logic, i.e code should work with syntetic identity function too
240 pub fn is_identity(&self) -> bool {208 pub fn is_identity(&self) -> bool {
241 match self {209 match self {
242 Self::Id => true,210 Self::Builtin(b) => b.as_any().downcast_ref::<builtin_id>().is_some(),
243 Self::Normal(desc) => {211 Self::Normal(desc) => {
244 if desc.params.len() != 1 {212 if desc.params.len() != 1 {
245 return false;213 return false;
257 };225 };
258 matches!(&*desc.body, Expr::Var(v) if &**v == id)226 matches!(&*desc.body, Expr::Var(v) if &**v == id)
259 }227 }
260 _ => false,228 Self::Thunk(_) => false,
261 }229 }
262 }230 }
263 /// Identity function value.
264 pub const fn identity() -> Self {
265 Self::Id
266 }
267231
268 pub fn evaluate_trivial(&self) -> Option<Val> {232 pub fn evaluate_trivial(&self) -> Option<Val> {
269 match self {233 match self {
281 Self::builtin(value)245 Self::builtin(value)
282 }246 }
283}247}
284impl From<&'static dyn StaticBuiltin> for FuncVal {
285 fn from(value: &'static dyn StaticBuiltin) -> Self {
286 Self::static_builtin(value)
287 }
288}
289248