1use std::any::Any;23use jrsonnet_gcmodule::{cc_dyn, Trace, TraceBox};4use jrsonnet_parser::function::{FunctionSignature, ParamDefault, ParamName, ParamParse};56use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};7use crate::{Context, Result, Val};89#[macro_export]10macro_rules! params {11 (@name unnamed) => { ParamName::Unnamed };12 (@name named $name:literal) => { ParamName::Named($crate::IStr::from($name)) };13 ($($(#[$meta:meta])* [$kind:ident $(($lit:literal))? => $default:expr]),* $(,)?) => {14 thread_local! {15 static PARAMS: FunctionSignature = FunctionSignature::new([16 $($(#[$meta])* ParamParse::new(params!(@name $kind $($lit)?), $default)),*17 ].into());18 }19 };20}2122cc_dyn!(23 #[derive(Clone)]24 BuiltinFunc,25 Builtin,26 pub(crate) fn new() {...}27);28impl Builtin for BuiltinFunc {29 fn name(&self) -> &str {30 self.0.name()31 }3233 fn params(&self) -> FunctionSignature {34 self.0.params()35 }3637 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {38 self.0.call(ctx, loc, args)39 }4041 fn as_any(&self) -> &dyn Any {42 self.0.as_any()43 }44}4546474849pub trait Builtin: Trace {50 51 fn name(&self) -> &str;52 53 fn params(&self) -> FunctionSignature;54 55 fn call(&self, ctx: Context, loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val>;5657 fn as_any(&self) -> &dyn Any;58}5960pub trait StaticBuiltin: Builtin + Send + Sync61where62 Self: 'static,63{64 65 66}6768#[derive(Trace)]69pub struct NativeCallback {70 pub(crate) params: FunctionSignature,71 handler: TraceBox<dyn NativeCallbackHandler>,72}73impl NativeCallback {74 #[deprecated = "prefer using builtins directly, use this interface only for bindings"]75 pub fn new(params: Vec<String>, handler: impl NativeCallbackHandler) -> Self {76 Self {77 params: FunctionSignature::new(78 params79 .into_iter()80 .map(|n| ParamParse::new(ParamName::Named(n.into()), ParamDefault::None))81 .collect(),82 ),83 handler: TraceBox(Box::new(handler)),84 }85 }86}8788impl Builtin for NativeCallback {89 fn name(&self) -> &'static str {90 91 92 "<native>"93 }9495 fn params(&self) -> FunctionSignature {96 self.params.clone()97 }9899 fn call(&self, ctx: Context, _loc: CallLocation<'_>, args: &dyn ArgsLike) -> Result<Val> {100 let args = parse_builtin_call(ctx, self.params.clone(), args, true)?;101 let args = args102 .into_iter()103 .map(|a| a.expect("legacy natives have no default params"))104 .map(|a| a.evaluate())105 .collect::<Result<Vec<Val>>>()?;106 self.handler.call(&args)107 }108109 fn as_any(&self) -> &dyn Any {110 self111 }112}113114pub trait NativeCallbackHandler: Trace {115 fn call(&self, args: &[Val]) -> Result<Val>;116}