Skip to content

Commit 67a7569

Browse files
committed
Basic memoization
1 parent f6e7c92 commit 67a7569

File tree

5 files changed

+69
-98
lines changed

5 files changed

+69
-98
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ edition = "2021"
55

66
[dependencies]
77
comemo-macros = { path = "./macros" }
8+
siphasher = "0.3"
9+
once_cell = "1"

macros/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod memoize;
1313
mod track;
1414

1515
use proc_macro::TokenStream;
16+
use proc_macro2::Span;
1617
use quote::{quote, quote_spanned};
1718
use syn::spanned::Spanned;
1819
use syn::{parse_quote, Error, Result};

macros/src/memoize.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ pub fn expand(mut func: syn::ItemFn) -> Result<proc_macro2::TokenStream> {
55
let name = func.sig.ident.to_string();
66

77
let mut args = vec![];
8-
let mut asserts = vec![];
98
for input in &func.sig.inputs {
109
let typed = match input {
1110
syn::FnArg::Typed(typed) => typed,
@@ -19,15 +18,68 @@ pub fn expand(mut func: syn::ItemFn) -> Result<proc_macro2::TokenStream> {
1918
_ => bail!(typed.pat, "only simple identifiers are supported"),
2019
};
2120

22-
asserts.push(quote_spanned! { ident.span() => assert_hash(&#ident); });
2321
args.push(ident);
2422
}
2523

26-
func.block.stmts.insert(0, parse_quote! { {
27-
println!("calling {}", #name);
28-
fn assert_hash<T: std::hash::Hash>(_: &T) {}
29-
// #(#asserts)*
30-
} });
24+
let mut inner = func.clone();
25+
inner.sig.ident = syn::Ident::new("inner", Span::call_site());
26+
27+
let asserts = args.iter().map(|ident| {
28+
quote_spanned! {
29+
ident.span() =>
30+
argument_must_be_hash_or_tracked(&#ident);
31+
}
32+
});
33+
34+
let hashes = args.iter().map(|ident| {
35+
quote! {
36+
#ident.hash(&mut state);
37+
}
38+
});
39+
40+
func.block = parse_quote! { { #inner {
41+
fn argument_must_be_hash_or_tracked<T: std::hash::Hash>(_: &T) {}
42+
#(#asserts)*
43+
44+
use std::collections::HashMap;
45+
use std::hash::Hash;
46+
use std::sync::atomic::{AtomicUsize, Ordering};
47+
use std::sync::Mutex;
48+
use comemo::once_cell::sync::Lazy;
49+
use comemo::siphasher::sip128::{Hasher128, SipHasher};
50+
51+
static NR: AtomicUsize = AtomicUsize::new(1);
52+
static MAP: Lazy<Mutex<HashMap<u128, String>>> =
53+
Lazy::new(|| Mutex::new(HashMap::new()));
54+
55+
let nr = NR.fetch_add(1, Ordering::SeqCst);
56+
let hash = {
57+
let mut state = SipHasher::new();
58+
#(#hashes)*
59+
state.finish128().as_u128()
60+
};
61+
62+
let mut hit = true;
63+
let result = MAP
64+
.lock()
65+
.unwrap()
66+
.entry(hash)
67+
.or_insert_with(|| {
68+
hit = false;
69+
inner(#(#args),*)
70+
})
71+
.clone();
72+
73+
println!(
74+
"{} {} {} {}",
75+
#name,
76+
nr,
77+
if hit { "[hit]: " } else { "[miss]:" },
78+
result,
79+
);
80+
81+
result
82+
} } };
3183

3284
Ok(quote! { #func })
3385
}

src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Tracked memoization.
44

55
pub use comemo_macros::{memoize, track};
66

7+
// This is an implementation detail, which shouldn't directly be used.
8+
#[doc(hidden)]
9+
pub use {once_cell, siphasher};
10+
711
use std::ops::Deref;
812

913
/// Tracks accesses to a value.
@@ -30,15 +34,14 @@ pub trait Track: Sized {
3034
Tracked(self)
3135
}
3236

37+
// Everything below is an implementation detail.
38+
// You shouldn't use that stuff directly.
39+
3340
/// The tracked API surface of the type.
34-
///
35-
/// This is an implementation detail, which shouldn't directly be used.
3641
#[doc(hidden)]
3742
type Surface;
3843

3944
/// Access the tracked API surface.
40-
///
41-
/// This is an implementation detail, which shouldn't directly be used.
4245
#[doc(hidden)]
4346
fn surface(&self) -> &Self::Surface;
4447
}

src/main.rs

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)