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

difftreelog

source

crates/jrsonnet-evaluator/src/function/builtin.rs3.0 KiBsourcehistory
1use std::any::Any;23use jrsonnet_gcmodule::{Trace, TraceBox, cc_dyn};4use jrsonnet_ir::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}2122#[macro_export]23macro_rules! names {24	($($name:ident: $val:literal),* $(,)?) => {25		struct Names {26			$($name: $crate::IStr,)*27		}28		thread_local! {29			static NAMES: Names = Names {30				$($name: $crate::IStr::from($val)),*31			};32		}33		$(pub fn $name() -> $crate::IStr {34			NAMES.with(|n| n.$name.clone())35		})*36	}37}3839cc_dyn!(40	#[derive(Clone)]41	BuiltinFunc,42	Builtin,43	pub(crate) fn new() {...}44);45impl Builtin for BuiltinFunc {46	fn name(&self) -> &str {47		self.0.name()48	}4950	fn params(&self) -> FunctionSignature {51		self.0.params()52	}5354	fn call(&self, loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val> {55		self.0.call(loc, args)56	}5758	fn as_any(&self) -> &dyn Any {59		self.0.as_any()60	}61}6263/// Description of function defined by native code64///65/// Prefer to use #[builtin] macro, instead of manual implementation of this trait66pub trait Builtin: Trace {67	/// Function name to be used in stack traces68	fn name(&self) -> &str;69	/// Parameter names for named calls70	fn params(&self) -> FunctionSignature;71	/// Call the builtin72	fn call(&self, loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val>;7374	fn as_any(&self) -> &dyn Any;75}7677#[derive(Trace)]78pub struct NativeCallback {79	pub(crate) params: FunctionSignature,80	handler: TraceBox<dyn NativeCallbackHandler>,81}82impl NativeCallback {83	#[deprecated = "prefer using builtins directly, use this interface only for bindings"]84	pub fn new(params: Vec<String>, handler: impl NativeCallbackHandler) -> Self {85		Self {86			params: FunctionSignature::new(87				params88					.into_iter()89					.map(|n| ParamParse::new(ParamName::Named(n.into()), ParamDefault::None))90					.collect(),91			),92			handler: TraceBox(Box::new(handler)),93		}94	}95}9697impl Builtin for NativeCallback {98	fn name(&self) -> &'static str {99		// TODO: standard natives gets their names from definition100		// But builitins should already have them101		"<native>"102	}103104	fn params(&self) -> FunctionSignature {105		self.params.clone()106	}107108	fn call(&self, _loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val> {109		let args = args110			.iter()111			.map(|a| a.as_ref().expect("legacy natives have no default params"))112			.map(Thunk::evaluate)113			.collect::<Result<Vec<Val>>>()?;114		self.handler.call(&args)115	}116117	fn as_any(&self) -> &dyn Any {118		self119	}120}121122pub trait NativeCallbackHandler: Trace {123	fn call(&self, args: &[Val]) -> Result<Val>;124}