From 0170913d5413aab4c1f2bd7d56b9b7138f676012 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 25 May 2022 21:31:12 +0200 Subject: [PATCH] Rebrand queries as memoization --- macros/src/lib.rs | 1 + src/eval/mod.rs | 1 + src/export/render.rs | 3 +-- src/lib.rs | 2 +- src/{query.rs => memo.rs} | 34 ++++++++++++++++++---------------- src/model/layout.rs | 3 +-- 6 files changed, 23 insertions(+), 21 deletions(-) rename src/{query.rs => memo.rs} (72%) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 496238346..029a1adb3 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -8,6 +8,7 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{Error, Ident, Result}; +/// Turn a struct into a node / a function with settable properties. #[proc_macro_attribute] pub fn node(stream: TokenStream, item: TokenStream) -> TokenStream { let impl_block = syn::parse_macro_input!(item as syn::ItemImpl); diff --git a/src/eval/mod.rs b/src/eval/mod.rs index e403c3cba..e54dfce42 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -26,6 +26,7 @@ pub use func::*; pub use machine::*; pub use raw::*; pub use scope::*; +pub use typst_macros::node; pub use value::*; use std::collections::BTreeMap; diff --git a/src/export/render.rs b/src/export/render.rs index 9c37791e1..aa60e67e6 100644 --- a/src/export/render.rs +++ b/src/export/render.rs @@ -12,7 +12,6 @@ use crate::geom::{ self, Geometry, Length, Paint, PathElement, Shape, Size, Stroke, Transform, }; use crate::image::{Image, RasterImage, Svg}; -use crate::query::query_ref; use crate::Context; /// Export a frame into a rendered image. @@ -244,7 +243,7 @@ fn render_outline_glyph( // Rasterize the glyph with `pixglyph`. // Try to retrieve a prepared glyph or prepare it from scratch if it // doesn't exist, yet. - let bitmap = query_ref( + let bitmap = crate::memo::memoized_ref( (&ctx.fonts, text.face_id, id), |(fonts, face_id, id)| pixglyph::Glyph::load(fonts.get(face_id).ttf(), id), |glyph| glyph.as_ref().map(|g| g.rasterize(ts.tx, ts.ty, ppem)), diff --git a/src/lib.rs b/src/lib.rs index 7d848c53c..17225b328 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,9 +45,9 @@ pub mod frame; pub mod image; pub mod library; pub mod loading; +pub mod memo; pub mod model; pub mod parse; -pub mod query; pub mod source; pub mod syntax; diff --git a/src/query.rs b/src/memo.rs similarity index 72% rename from src/query.rs rename to src/memo.rs index 97af01399..6545ebcc8 100644 --- a/src/query.rs +++ b/src/memo.rs @@ -1,4 +1,4 @@ -//! Query caching. +//! Function memoization. use std::any::Any; use std::cell::RefCell; @@ -7,7 +7,7 @@ use std::fmt::{self, Display, Formatter}; use std::hash::Hash; thread_local! { - /// The thread-local query cache. + /// The thread-local cache. static CACHE: RefCell = RefCell::default(); } @@ -22,37 +22,39 @@ where CACHE.with(|cell| f(&mut cell.borrow_mut())) } -/// An entry in the query cache. +/// An entry in the cache. struct CacheEntry { - /// The query's results. + /// The memoized function's result. data: Box, /// How many evictions have passed since the entry has been last used. age: usize, } -/// Execute a query. +/// Execute a memoized function call. /// -/// This hashes all inputs to the query and then either returns a cached version -/// from the thread-local query cache or executes the query and saves a copy of -/// the results in the cache. +/// This hashes all inputs to the function and then either returns a cached +/// version from the thread-local cache or executes the function and saves a +/// copy of the results in the cache. /// /// Note that `f` must be a pure function. -pub fn query(input: I, f: fn(input: I) -> O) -> O +pub fn memoized(input: I, f: fn(input: I) -> O) -> O where I: Hash, O: Clone + 'static, { - query_ref(input, f, Clone::clone) + memoized_ref(input, f, Clone::clone) } -/// Execute a query and then call a function with a reference to the result. +/// Execute a function and then call another function with a reference to the +/// result. /// -/// This hashes all inputs to the query and then either call `g` with a cached -/// version from the thread-local query cache or executes the query, calls `g` -/// with the fresh version and saves the result in the cache. +/// This hashes all inputs to the function and then either +/// - calls `g` with a cached version from the thread-local cache, +/// - or executes `f`, calls `g` with the fresh version and saves the result in +/// the cache. /// /// Note that `f` must be a pure function, while `g` does not need to be pure. -pub fn query_ref(input: I, f: fn(input: I) -> O, g: G) -> R +pub fn memoized_ref(input: I, f: fn(input: I) -> O, g: G) -> R where I: Hash, O: 'static, @@ -74,7 +76,7 @@ where }) } -/// Garbage-collect the thread-local query cache. +/// Garbage-collect the thread-local cache. /// /// This deletes elements which haven't been used in a while and returns details /// about the eviction. diff --git a/src/model/layout.rs b/src/model/layout.rs index 1933fca10..6dfbcb90e 100644 --- a/src/model/layout.rs +++ b/src/model/layout.rs @@ -14,7 +14,6 @@ use crate::geom::{ }; use crate::library::graphics::MoveNode; use crate::library::layout::{AlignNode, PadNode}; -use crate::query::query; use crate::util::Prehashed; use crate::Context; @@ -222,7 +221,7 @@ impl Layout for LayoutNode { regions: &Regions, styles: StyleChain, ) -> TypResult>> { - query( + crate::memo::memoized( (self, ctx, regions, styles), |(node, ctx, regions, styles)| { let entry = StyleEntry::Barrier(Barrier::new(node.id()));