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

difftreelog

source

crates/jrsonnet-evaluator/src/function/builtin.rs3.0 KiBsourcehistory
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}4748/// Description of function defined by native code49///50/// Prefer to use #[builtin] macro, instead of manual implementation of this trait51pub trait Builtin: Trace {52	/// Function name to be used in stack traces53	fn name(&self) -> &str;54	/// Parameter names for named calls55	fn params(&self) -> FunctionSignature;56	/// Call the builtin57	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	// In impl, to make it object safe:67	// const INST: &'static Self;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		// TODO: standard natives gets their names from definition93		// But builitins should already have them94		"<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}