git.delta.rocks / jrsonnet / refs/commits / b3f009bb7b2e

difftreelog

source

crates/jrsonnet-evaluator/src/function/builtin.rs2.9 KiBsourcehistory
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}4546/// Description of function defined by native code47///48/// Prefer to use #[builtin] macro, instead of manual implementation of this trait49pub trait Builtin: Trace {50	/// Function name to be used in stack traces51	fn name(&self) -> &str;52	/// Parameter names for named calls53	fn params(&self) -> FunctionSignature;54	/// Call the builtin55	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	// In impl, to make it object safe:65	// const INST: &'static Self;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		// TODO: standard natives gets their names from definition91		// But builitins should already have them92		"<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}