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> {
|
) -> SourceResult<Value> {
|
||||||
match &self.repr {
|
match &self.repr {
|
||||||
Repr::Native(native) => {
|
Repr::Native(native) => {
|
||||||
let value = (native.function)(engine, context, &mut args)?;
|
let value = (native.function.0)(engine, context, &mut args)?;
|
||||||
args.finish()?;
|
args.finish()?;
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
@ -491,8 +491,8 @@ pub trait NativeFunc {
|
|||||||
/// Defines a native function.
|
/// Defines a native function.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NativeFuncData {
|
pub struct NativeFuncData {
|
||||||
/// Invokes the function from Typst.
|
/// The implementation of the function.
|
||||||
pub function: fn(&mut Engine, Tracked<Context>, &mut Args) -> SourceResult<Value>,
|
pub function: NativeFuncPtr,
|
||||||
/// The function's normal name (e.g. `align`), as exposed to Typst.
|
/// The function's normal name (e.g. `align`), as exposed to Typst.
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
/// The function's title case name (e.g. `Align`).
|
/// The function's title case name (e.g. `Align`).
|
||||||
@ -504,11 +504,11 @@ pub struct NativeFuncData {
|
|||||||
/// Whether this function makes use of context.
|
/// Whether this function makes use of context.
|
||||||
pub contextual: bool,
|
pub contextual: bool,
|
||||||
/// Definitions in the scope of the function.
|
/// Definitions in the scope of the function.
|
||||||
pub scope: LazyLock<Scope>,
|
pub scope: DynLazyLock<Scope>,
|
||||||
/// A list of parameter information for each parameter.
|
/// 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.
|
/// Information about the return value of this function.
|
||||||
pub returns: LazyLock<CastInfo>,
|
pub returns: DynLazyLock<CastInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
cast! {
|
cast! {
|
||||||
@ -516,6 +516,28 @@ cast! {
|
|||||||
self => Func::from(self).into_value(),
|
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.
|
/// Describes a function parameter.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ParamInfo {
|
pub struct ParamInfo {
|
||||||
|
@ -315,15 +315,15 @@ fn create_func_data(func: &Func) -> TokenStream {
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#foundations::NativeFuncData {
|
#foundations::NativeFuncData {
|
||||||
function: #closure,
|
function: #foundations::NativeFuncPtr(&#closure),
|
||||||
name: #name,
|
name: #name,
|
||||||
title: #title,
|
title: #title,
|
||||||
docs: #docs,
|
docs: #docs,
|
||||||
keywords: &[#(#keywords),*],
|
keywords: &[#(#keywords),*],
|
||||||
contextual: #contextual,
|
contextual: #contextual,
|
||||||
scope: ::std::sync::LazyLock::new(|| #scope),
|
scope: ::std::sync::LazyLock::new(&|| #scope),
|
||||||
params: ::std::sync::LazyLock::new(|| ::std::vec![#(#params),*]),
|
params: ::std::sync::LazyLock::new(&|| ::std::vec![#(#params),*]),
|
||||||
returns: ::std::sync::LazyLock::new(|| <#returns as #foundations::Reflect>::output()),
|
returns: ::std::sync::LazyLock::new(&|| <#returns as #foundations::Reflect>::output()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user