1use std::any::Any;23use jrsonnet_gcmodule::{cc_dyn, Trace, TraceBox};4use jrsonnet_parser::function::{FunctionSignature, ParamDefault, ParamName, ParamParse};56use super::CallLocation;7use crate::{Result, Thunk, 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, loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val> {38 self.0.call(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, loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> 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, _loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val> {100 let args = args101 .into_iter()102 .map(|a| a.as_ref().expect("legacy natives have no default params"))103 .map(|a| a.evaluate())104 .collect::<Result<Vec<Val>>>()?;105 self.handler.call(&args)106 }107108 fn as_any(&self) -> &dyn Any {109 self110 }111}112113pub trait NativeCallbackHandler: Trace {114 fn call(&self, args: &[Val]) -> Result<Val>;115}