mirror of
https://github.com/typst/typst
synced 2025-05-13 12:36:23 +08:00
More efficient function representation
This commit is contained in:
parent
ab43bd802e
commit
30d6c070c1
@ -115,8 +115,8 @@ fn create(func: &Func) -> TokenStream {
|
|||||||
let params = params.iter().map(create_param_info);
|
let params = params.iter().map(create_param_info);
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #docs]
|
#[doc = #docs]
|
||||||
#vis fn #ident() -> ::typst::eval::NativeFunc {
|
#vis fn #ident() -> &'static ::typst::eval::NativeFunc {
|
||||||
::typst::eval::NativeFunc {
|
static FUNC: ::typst::eval::NativeFunc = ::typst::eval::NativeFunc {
|
||||||
func: |vm, args| {
|
func: |vm, args| {
|
||||||
#(#handlers)*
|
#(#handlers)*
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
@ -130,7 +130,8 @@ fn create(func: &Func) -> TokenStream {
|
|||||||
returns: ::std::vec![#(#returns),*],
|
returns: ::std::vec![#(#returns),*],
|
||||||
category: #category,
|
category: #category,
|
||||||
}),
|
}),
|
||||||
}
|
};
|
||||||
|
&FUNC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,42 +20,42 @@ use crate::World;
|
|||||||
#[derive(Clone, Hash)]
|
#[derive(Clone, Hash)]
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
/// The internal representation.
|
/// The internal representation.
|
||||||
repr: Arc<Prehashed<Repr>>,
|
repr: Repr,
|
||||||
/// The span with which errors are reported when this function is called.
|
/// The span with which errors are reported when this function is called.
|
||||||
span: Span,
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The different kinds of function representations.
|
/// The different kinds of function representations.
|
||||||
#[derive(Hash)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
enum Repr {
|
enum Repr {
|
||||||
/// A native Rust function.
|
/// A native Rust function.
|
||||||
Native(NativeFunc),
|
Native(&'static NativeFunc),
|
||||||
/// A function for an element.
|
/// A function for an element.
|
||||||
Elem(ElemFunc),
|
Elem(ElemFunc),
|
||||||
/// A user-defined closure.
|
/// A user-defined closure.
|
||||||
Closure(Closure),
|
Closure(Arc<Prehashed<Closure>>),
|
||||||
/// A nested function with pre-applied arguments.
|
/// A nested function with pre-applied arguments.
|
||||||
With(Func, Args),
|
With(Arc<(Func, Args)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Func {
|
impl Func {
|
||||||
/// The name of the function.
|
/// The name of the function.
|
||||||
pub fn name(&self) -> Option<&str> {
|
pub fn name(&self) -> Option<&str> {
|
||||||
match &**self.repr {
|
match &self.repr {
|
||||||
Repr::Native(native) => Some(native.info.name),
|
Repr::Native(native) => Some(native.info.name),
|
||||||
Repr::Elem(func) => Some(func.info().name),
|
Repr::Elem(func) => Some(func.info().name),
|
||||||
Repr::Closure(closure) => closure.name.as_deref(),
|
Repr::Closure(closure) => closure.name.as_deref(),
|
||||||
Repr::With(func, _) => func.name(),
|
Repr::With(arc) => arc.0.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract details the function.
|
/// Extract details the function.
|
||||||
pub fn info(&self) -> Option<&FuncInfo> {
|
pub fn info(&self) -> Option<&FuncInfo> {
|
||||||
match &**self.repr {
|
match &self.repr {
|
||||||
Repr::Native(native) => Some(&native.info),
|
Repr::Native(native) => Some(&native.info),
|
||||||
Repr::Elem(func) => Some(func.info()),
|
Repr::Elem(func) => Some(func.info()),
|
||||||
Repr::With(func, _) => func.info(),
|
Repr::Closure(_) => None,
|
||||||
_ => None,
|
Repr::With(arc) => arc.0.info(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,10 +74,10 @@ impl Func {
|
|||||||
|
|
||||||
/// The number of positional arguments this function takes, if known.
|
/// The number of positional arguments this function takes, if known.
|
||||||
pub fn argc(&self) -> Option<usize> {
|
pub fn argc(&self) -> Option<usize> {
|
||||||
match &**self.repr {
|
match &self.repr {
|
||||||
Repr::Closure(closure) => closure.argc(),
|
Repr::Closure(closure) => closure.argc(),
|
||||||
Repr::With(wrapped, applied) => Some(wrapped.argc()?.saturating_sub(
|
Repr::With(arc) => Some(arc.0.argc()?.saturating_sub(
|
||||||
applied.items.iter().filter(|arg| arg.name.is_none()).count(),
|
arc.1.items.iter().filter(|arg| arg.name.is_none()).count(),
|
||||||
)),
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ impl Func {
|
|||||||
|
|
||||||
/// Call the function with the given arguments.
|
/// Call the function with the given arguments.
|
||||||
pub fn call_vm(&self, vm: &mut Vm, mut args: Args) -> SourceResult<Value> {
|
pub fn call_vm(&self, vm: &mut Vm, mut args: Args) -> SourceResult<Value> {
|
||||||
match &**self.repr {
|
match &self.repr {
|
||||||
Repr::Native(native) => {
|
Repr::Native(native) => {
|
||||||
let value = (native.func)(vm, &mut args)?;
|
let value = (native.func)(vm, &mut args)?;
|
||||||
args.finish()?;
|
args.finish()?;
|
||||||
@ -113,9 +113,9 @@ impl Func {
|
|||||||
args,
|
args,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Repr::With(wrapped, applied) => {
|
Repr::With(arc) => {
|
||||||
args.items = applied.items.iter().cloned().chain(args.items).collect();
|
args.items = arc.1.items.iter().cloned().chain(args.items).collect();
|
||||||
return wrapped.call_vm(vm, args);
|
return arc.0.call_vm(vm, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,15 +137,12 @@ impl Func {
|
|||||||
/// Apply the given arguments to the function.
|
/// Apply the given arguments to the function.
|
||||||
pub fn with(self, args: Args) -> Self {
|
pub fn with(self, args: Args) -> Self {
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
Self {
|
Self { repr: Repr::With(Arc::new((self, args))), span }
|
||||||
repr: Arc::new(Prehashed::new(Repr::With(self, args))),
|
|
||||||
span,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the element function, if it is one.
|
/// Extract the element function, if it is one.
|
||||||
pub fn element(&self) -> Option<ElemFunc> {
|
pub fn element(&self) -> Option<ElemFunc> {
|
||||||
match **self.repr {
|
match self.repr {
|
||||||
Repr::Elem(func) => Some(func),
|
Repr::Elem(func) => Some(func),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@ -169,10 +166,7 @@ impl PartialEq for Func {
|
|||||||
|
|
||||||
impl From<Repr> for Func {
|
impl From<Repr> for Func {
|
||||||
fn from(repr: Repr) -> Self {
|
fn from(repr: Repr) -> Self {
|
||||||
Self {
|
Self { repr, span: Span::detached() }
|
||||||
repr: Arc::new(Prehashed::new(repr)),
|
|
||||||
span: Span::detached(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,28 +184,32 @@ pub struct NativeFunc {
|
|||||||
pub info: Lazy<FuncInfo>,
|
pub info: Lazy<FuncInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for NativeFunc {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.func as usize == other.func as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for NativeFunc {}
|
||||||
|
|
||||||
impl Hash for NativeFunc {
|
impl Hash for NativeFunc {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
(self.func as usize).hash(state);
|
(self.func as usize).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NativeFunc> for Func {
|
impl From<&'static NativeFunc> for Func {
|
||||||
fn from(native: NativeFunc) -> Self {
|
fn from(native: &'static NativeFunc) -> Self {
|
||||||
Repr::Native(native).into()
|
Repr::Native(native).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cast_to_value! {
|
|
||||||
v: NativeFunc => Value::Func(v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> From<F> for Value
|
impl<F> From<F> for Value
|
||||||
where
|
where
|
||||||
F: Fn() -> NativeFunc,
|
F: Fn() -> &'static NativeFunc,
|
||||||
{
|
{
|
||||||
fn from(f: F) -> Self {
|
fn from(f: F) -> Self {
|
||||||
f().into()
|
Value::Func(f().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +292,7 @@ impl Closure {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
mut args: Args,
|
mut args: Args,
|
||||||
) -> SourceResult<Value> {
|
) -> SourceResult<Value> {
|
||||||
let closure = match &**this.repr {
|
let closure = match &this.repr {
|
||||||
Repr::Closure(closure) => closure,
|
Repr::Closure(closure) => closure,
|
||||||
_ => panic!("`this` must be a closure"),
|
_ => panic!("`this` must be a closure"),
|
||||||
};
|
};
|
||||||
@ -347,7 +345,7 @@ impl Closure {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number of positional arguments this function takes, if known.
|
/// The number of positional arguments this closure takes, if known.
|
||||||
fn argc(&self) -> Option<usize> {
|
fn argc(&self) -> Option<usize> {
|
||||||
if self.sink.is_some() {
|
if self.sink.is_some() {
|
||||||
return None;
|
return None;
|
||||||
@ -359,7 +357,7 @@ impl Closure {
|
|||||||
|
|
||||||
impl From<Closure> for Func {
|
impl From<Closure> for Func {
|
||||||
fn from(closure: Closure) -> Self {
|
fn from(closure: Closure) -> Self {
|
||||||
Repr::Closure(closure).into()
|
Repr::Closure(Arc::new(Prehashed::new(closure))).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,12 +88,6 @@ impl Debug for ElemFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for ElemFunc {
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
state.write_usize(self.0 as *const _ as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for ElemFunc {}
|
impl Eq for ElemFunc {}
|
||||||
|
|
||||||
impl PartialEq for ElemFunc {
|
impl PartialEq for ElemFunc {
|
||||||
@ -102,6 +96,12 @@ impl PartialEq for ElemFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for ElemFunc {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_usize(self.0 as *const _ as usize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cast_from_value! {
|
cast_from_value! {
|
||||||
ElemFunc,
|
ElemFunc,
|
||||||
v: Func => v.element().ok_or("expected element function")?,
|
v: Func => v.element().ok_or("expected element function")?,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user