mirror of
https://github.com/typst/typst
synced 2025-06-22 21:32:52 +08:00
Support for generating native functions at runtime
This commit is contained in:
parent
15302dbe7a
commit
3602d06a15
@ -307,7 +307,7 @@ impl Func {
|
||||
) -> SourceResult<Value> {
|
||||
match &self.repr {
|
||||
Repr::Native(native) => {
|
||||
let value = (native.function)(engine, context, &mut args)?;
|
||||
let value = (native.function.0)(engine, context, &mut args)?;
|
||||
args.finish()?;
|
||||
Ok(value)
|
||||
}
|
||||
@ -491,8 +491,8 @@ pub trait NativeFunc {
|
||||
/// Defines a native function.
|
||||
#[derive(Debug)]
|
||||
pub struct NativeFuncData {
|
||||
/// Invokes the function from Typst.
|
||||
pub function: fn(&mut Engine, Tracked<Context>, &mut Args) -> SourceResult<Value>,
|
||||
/// The implementation of the function.
|
||||
pub function: NativeFuncPtr,
|
||||
/// The function's normal name (e.g. `align`), as exposed to Typst.
|
||||
pub name: &'static str,
|
||||
/// The function's title case name (e.g. `Align`).
|
||||
@ -504,11 +504,11 @@ pub struct NativeFuncData {
|
||||
/// Whether this function makes use of context.
|
||||
pub contextual: bool,
|
||||
/// Definitions in the scope of the function.
|
||||
pub scope: LazyLock<Scope>,
|
||||
pub scope: DynLazyLock<Scope>,
|
||||
/// A list of parameter information for each parameter.
|
||||
pub params: LazyLock<Vec<ParamInfo>>,
|
||||
pub params: DynLazyLock<Vec<ParamInfo>>,
|
||||
/// Information about the return value of this function.
|
||||
pub returns: LazyLock<CastInfo>,
|
||||
pub returns: DynLazyLock<CastInfo>,
|
||||
}
|
||||
|
||||
cast! {
|
||||
@ -516,6 +516,28 @@ cast! {
|
||||
self => Func::from(self).into_value(),
|
||||
}
|
||||
|
||||
/// A pointer to a native function's implementation.
|
||||
pub struct NativeFuncPtr(pub &'static NativeFuncSignature);
|
||||
|
||||
/// The signature of a native function's implementation.
|
||||
type NativeFuncSignature =
|
||||
dyn Fn(&mut Engine, Tracked<Context>, &mut Args) -> SourceResult<Value> + Send + Sync;
|
||||
|
||||
impl Debug for NativeFuncPtr {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.pad("NativeFuncPtr(..)")
|
||||
}
|
||||
}
|
||||
|
||||
/// A `LazyLock` that uses a static closure for initialization instead of only
|
||||
/// working with function pointers.
|
||||
///
|
||||
/// Can be created from a normal function or closure by prepending with a `&`,
|
||||
/// e.g. `LazyLock::new(&|| "hello")`. Can be created from a dynamic closure
|
||||
/// by allocating and then leaking it. This is equivalent to having it
|
||||
/// statically allocated, but allows for it to be generated at runtime.
|
||||
type DynLazyLock<T> = LazyLock<T, &'static (dyn Fn() -> T + Send + Sync)>;
|
||||
|
||||
/// Describes a function parameter.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParamInfo {
|
||||
|
@ -315,15 +315,15 @@ fn create_func_data(func: &Func) -> TokenStream {
|
||||
|
||||
quote! {
|
||||
#foundations::NativeFuncData {
|
||||
function: #closure,
|
||||
function: #foundations::NativeFuncPtr(&#closure),
|
||||
name: #name,
|
||||
title: #title,
|
||||
docs: #docs,
|
||||
keywords: &[#(#keywords),*],
|
||||
contextual: #contextual,
|
||||
scope: ::std::sync::LazyLock::new(|| #scope),
|
||||
params: ::std::sync::LazyLock::new(|| ::std::vec![#(#params),*]),
|
||||
returns: ::std::sync::LazyLock::new(|| <#returns as #foundations::Reflect>::output()),
|
||||
scope: ::std::sync::LazyLock::new(&|| #scope),
|
||||
params: ::std::sync::LazyLock::new(&|| ::std::vec![#(#params),*]),
|
||||
returns: ::std::sync::LazyLock::new(&|| <#returns as #foundations::Reflect>::output()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user