1use std::any::Any;2use std::fmt;34use jrsonnet_gcmodule::{cc_dyn, Acyclic, Trace, TraceBox};5use jrsonnet_interner::IStr;6use jrsonnet_parser::function::{FunctionSignature, ParamDefault, ParamName, ParamParse};78use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};9use crate::{Context, Result, Val};1011#[macro_export]12macro_rules! params {13 (@name unnamed) => { ParamName::ANONYMOUS };14 (@name named $name:literal) => { ParamName::new($crate::IStr::from($name)) };15 ($($(#[$meta:meta])* [$kind:ident $(($lit:literal))? => $default:expr]),* $(,)?) => {16 thread_local! {17 static PARAMS: FunctionSignature = FunctionSignature::new([18 $($(#[$meta])* ParamParse::new(params!(@name $kind $($lit)?), $default)),*19 ].into());20 }21 };22}2324cc_dyn!(25 #[derive(Clone)]26 BuiltinFunc,27 Builtin,28 pub(crate) fn new() {...}29);30impl Builtin for BuiltinFunc {31 fn name(&self) -> &str {32 self.0.name()33 }3435 fn params(&self) -> FunctionSignature {36 self.0.params()37 }3839 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {40 self.0.call(ctx, loc, args)41 }4243 fn as_any(&self) -> &dyn Any {44 self.0.as_any()45 }46}4748495051pub trait Builtin: Trace {52 53 fn name(&self) -> &str;54 55 fn params(&self) -> FunctionSignature;56 57 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val>;5859 fn as_any(&self) -> &dyn Any;60}6162pub trait StaticBuiltin: Builtin + Send + Sync63where64 Self: 'static,65{66 67 68}6970#[derive(Trace)]71pub struct NativeCallback {72 pub(crate) params: FunctionSignature,73 handler: TraceBox<dyn NativeCallbackHandler>,74}75impl NativeCallback {76 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]77 pub fn new(params: Vec<String>, handler: impl NativeCallbackHandler) -> Self {78 Self {79 params: FunctionSignature::new(80 params81 .into_iter()82 .map(|n| ParamParse::new(ParamName::new(n.into()), ParamDefault::None))83 .collect(),84 ),85 handler: TraceBox(Box::new(handler)),86 }87 }88}8990impl Builtin for NativeCallback {91 fn name(&self) -> &str {92 93 94 "<native>"95 }9697 fn params(&self) -> FunctionSignature {98 self.params.clone()99 }100101 fn call(&self, ctx: Context, _loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {102 let args = parse_builtin_call(ctx, self.params.clone(), args, true)?;103 let args = args104 .into_iter()105 .map(|a| a.expect("legacy natives have no default params"))106 .map(|a| a.evaluate())107 .collect::<Result<Vec<Val>>>()?;108 self.handler.call(&args)109 }110111 fn as_any(&self) -> &dyn Any {112 self113 }114}115116pub trait NativeCallbackHandler: Trace {117 fn call(&self, args: &[Val]) -> Result<Val>;118}