Skip to content

Commit 1d78ec3

Browse files
committed
Rename Tracker to Constraint
1 parent b20d4b7 commit 1d78ec3

File tree

9 files changed

+81
-115
lines changed

9 files changed

+81
-115
lines changed

macros/src/lib.rs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ use quote::quote;
1717
use syn::{parse_quote, Error, Result};
1818

1919
/// Memoize a pure function.
20-
///
21-
/// ```
22-
/// #[memoize]
23-
/// fn describe(image: Tracked<Image>) -> String {
24-
/// let w = image.width();
25-
/// let h = image.height();
26-
/// format!("The image is {w}x{h} pixels.")
27-
/// }
28-
/// ```
2920
#[proc_macro_attribute]
3021
pub fn memoize(_: TokenStream, stream: TokenStream) -> TokenStream {
3122
let func = syn::parse_macro_input!(stream as syn::ItemFn);
@@ -35,28 +26,6 @@ pub fn memoize(_: TokenStream, stream: TokenStream) -> TokenStream {
3526
}
3627

3728
/// Make a type trackable.
38-
///
39-
/// ```
40-
/// /// A decoded raster image.
41-
/// pub struct Image {
42-
/// width: u32,
43-
/// height: u32,
44-
/// pixels: Vec<u8>,
45-
/// }
46-
///
47-
/// #[track]
48-
/// impl Image {
49-
/// fn width(&self) -> u32 {
50-
/// self.width
51-
/// }
52-
///
53-
/// fn height(&self) -> u32 {
54-
/// self.height
55-
/// }
56-
/// }
57-
/// ```
58-
///
59-
/// [`Track`]: ../comemo/trait.Track.html
6029
#[proc_macro_attribute]
6130
pub fn track(_: TokenStream, stream: TokenStream) -> TokenStream {
6231
let block = syn::parse_macro_input!(stream as syn::ItemImpl);

macros/src/memoize.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ pub fn expand(func: &syn::ItemFn) -> Result<proc_macro2::TokenStream> {
2828
}
2929

3030
let arg = args[0];
31-
/*
3231
let ty = types[0];
33-
let track = match ty {
32+
let _inner = match ty {
3433
syn::Type::Path(path) => {
3534
let segs = &path.path.segments;
3635
if segs.len() != 1 {
@@ -50,7 +49,6 @@ pub fn expand(func: &syn::ItemFn) -> Result<proc_macro2::TokenStream> {
5049
}
5150
_ => bail!(ty, "expected type of the form `Tracked<_>`"),
5251
};
53-
*/
5452

5553
let mut outer = func.clone();
5654
outer.block = parse_quote! { {

macros/src/track.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn expand(block: &syn::ItemImpl) -> Result<proc_macro2::TokenStream> {
1616
syn::ReturnType::Default => unreachable!(),
1717
syn::ReturnType::Type(_, ty) => ty.as_ref(),
1818
};
19-
quote! { #name: ::comemo::internal::AccessTracker<#ty>, }
19+
quote! { #name: ::comemo::internal::HashConstraint<#ty>, }
2020
});
2121

2222
let tracked_methods = methods.iter().map(|method| {
@@ -26,10 +26,10 @@ pub fn expand(block: &syn::ItemImpl) -> Result<proc_macro2::TokenStream> {
2626
method.vis = parse_quote! { pub(super) };
2727
}
2828
method.block = parse_quote! { {
29-
let (inner, tracker) = ::comemo::internal::to_parts(self.0);
29+
let (inner, constraint) = ::comemo::internal::to_parts(self.0);
3030
let output = inner.#name();
31-
if let Some(tracker) = &tracker {
32-
tracker.#name.track(&output);
31+
if let Some(constraint) = &constraint {
32+
constraint.#name.set(&output);
3333
}
3434
output
3535
} };
@@ -39,7 +39,7 @@ pub fn expand(block: &syn::ItemImpl) -> Result<proc_macro2::TokenStream> {
3939
let tracked_valids = methods.iter().map(|method| {
4040
let name = &method.sig.ident;
4141
quote! {
42-
tracker.#name.valid(&self.#name())
42+
constraint.#name.valid(&self.#name())
4343
}
4444
});
4545

@@ -48,10 +48,10 @@ pub fn expand(block: &syn::ItemImpl) -> Result<proc_macro2::TokenStream> {
4848

4949
impl ::comemo::Track for #ty {}
5050
impl ::comemo::internal::Trackable for #ty {
51-
type Tracker = Tracker;
51+
type Constraint = Constraint;
5252
type Surface = SurfaceFamily;
5353

54-
fn valid(&self, tracker: &Self::Tracker) -> bool {
54+
fn valid(&self, constraint: &Self::Constraint) -> bool {
5555
#(#tracked_valids)&&*
5656
}
5757

@@ -77,7 +77,7 @@ pub fn expand(block: &syn::ItemImpl) -> Result<proc_macro2::TokenStream> {
7777
}
7878

7979
#[derive(Default)]
80-
pub struct Tracker {
80+
pub struct Constraint {
8181
#(#tracked_fields)*
8282
}
8383
};

src/cache.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub struct Cache {
1616
}
1717

1818
/// An entry in the cache.
19-
struct Entry<Tracker, R> {
20-
tracker: Tracker,
19+
struct Entry<C, R> {
20+
constraint: C,
2121
output: R,
2222
}
2323

@@ -30,18 +30,18 @@ impl Cache {
3030
R: Debug + Clone + 'static,
3131
{
3232
let mut hit = true;
33-
let output = self.lookup(tracked).unwrap_or_else(|| {
34-
let tracker = T::Tracker::default();
33+
let output = self.lookup::<T, R>(tracked).unwrap_or_else(|| {
34+
let constraint = T::Constraint::default();
3535
let (inner, _) = to_parts(tracked);
36-
let tracked = from_parts(inner, Some(&tracker));
36+
let tracked = from_parts(inner, Some(&constraint));
3737
let output = f(tracked);
38-
self.insert::<T, R>(tracker, output.clone());
38+
self.insert::<T, R>(constraint, output.clone());
3939
hit = false;
4040
output
4141
});
4242

43-
let label = if hit { "[hit]: " } else { "[miss]:" };
44-
eprintln!("{name} {label} {output:?}");
43+
let label = if hit { "[hit]" } else { "[miss]" };
44+
eprintln!("{name:<9} {label:<7} {output:?}");
4545

4646
output
4747
}
@@ -56,18 +56,18 @@ impl Cache {
5656
self.map
5757
.borrow()
5858
.iter()
59-
.filter_map(|boxed| boxed.downcast_ref::<Entry<T::Tracker, R>>())
60-
.find(|entry| Trackable::valid(inner, &entry.tracker))
59+
.filter_map(|boxed| boxed.downcast_ref::<Entry<T::Constraint, R>>())
60+
.find(|entry| Trackable::valid(inner, &entry.constraint))
6161
.map(|entry| entry.output.clone())
6262
}
6363

6464
/// Insert an entry into the cache.
65-
fn insert<T, R>(&self, tracker: T::Tracker, output: R)
65+
fn insert<T, R>(&self, constraint: T::Constraint, output: R)
6666
where
6767
T: Track,
6868
R: 'static,
6969
{
70-
let entry = Entry { tracker, output };
70+
let entry = Entry { constraint, output };
7171
self.map.borrow_mut().push(Box::new(entry));
7272
}
7373
}

src/hash.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
use std::cell::Cell;
12
use std::hash::Hash;
3+
use std::marker::PhantomData;
4+
use std::num::NonZeroU128;
25

36
use siphasher::sip128::{Hasher128, SipHasher};
4-
use std::num::NonZeroU128;
57

68
/// Produce a non zero 128-bit hash of a value.
79
pub fn siphash<T: Hash>(value: &T) -> NonZeroU128 {
@@ -13,3 +15,22 @@ pub fn siphash<T: Hash>(value: &T) -> NonZeroU128 {
1315
.try_into()
1416
.unwrap_or(NonZeroU128::new(u128::MAX).unwrap())
1517
}
18+
19+
/// Defines a constraint for a value through its hash.
20+
#[derive(Default)]
21+
pub struct HashConstraint<T: Hash> {
22+
cell: Cell<Option<NonZeroU128>>,
23+
marker: PhantomData<T>,
24+
}
25+
26+
impl<T: Hash> HashConstraint<T> {
27+
/// Set the constraint for the value.
28+
pub fn set(&self, value: &T) {
29+
self.cell.set(Some(siphash(value)));
30+
}
31+
32+
/// Whether the value fulfills the constraint.
33+
pub fn valid(&self, value: &T) -> bool {
34+
self.cell.get().map_or(true, |v| v == siphash(value))
35+
}
36+
}

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ pub use comemo_macros::{memoize, track};
1111
#[doc(hidden)]
1212
pub mod internal {
1313
pub use crate::cache::CACHE;
14-
pub use crate::track::{from_parts, to_parts, AccessTracker, Family, Trackable};
14+
pub use crate::hash::HashConstraint;
15+
pub use crate::track::{to_parts, Family, Trackable};
1516
}

src/main.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,17 @@ fn describe(image: Tracked<Image>) -> &'static str {
4242
}
4343

4444
const _: () = {
45-
mod inner {
45+
mod private {
4646
use super::*;
4747

4848
impl ::comemo::Track for Image {}
4949
impl ::comemo::internal::Trackable for Image {
50-
type Tracker = Tracker;
50+
type Constraint = Constraint;
5151
type Surface = SurfaceFamily;
5252

53-
fn valid(&self, tracker: &Self::Tracker) -> bool {
54-
tracker.width.valid(&self.width()) && tracker.height.valid(&self.height())
53+
fn valid(&self, constraint: &Self::Constraint) -> bool {
54+
constraint.width.valid(&self.width())
55+
&& constraint.height.valid(&self.height())
5556
}
5657

5758
fn surface<'a, 'r>(tracked: &'r Tracked<'a, Image>) -> &'r Surface<'a>
@@ -73,28 +74,28 @@ const _: () = {
7374

7475
impl<'a> Surface<'a> {
7576
pub(super) fn width(&self) -> u32 {
76-
let (inner, tracker) = ::comemo::internal::to_parts(self.0);
77+
let (inner, constraint) = ::comemo::internal::to_parts(self.0);
7778
let output = inner.width();
78-
if let Some(tracker) = &tracker {
79-
tracker.width.track(&output);
79+
if let Some(constraint) = &constraint {
80+
constraint.width.set(&output);
8081
}
8182
output
8283
}
8384

8485
pub(super) fn height(&self) -> u32 {
85-
let (inner, tracker) = ::comemo::internal::to_parts(self.0);
86+
let (inner, constraint) = ::comemo::internal::to_parts(self.0);
8687
let output = inner.height();
87-
if let Some(tracker) = &tracker {
88-
tracker.height.track(&output);
88+
if let Some(constraint) = &constraint {
89+
constraint.height.set(&output);
8990
}
9091
output
9192
}
9293
}
9394

9495
#[derive(Default)]
95-
pub struct Tracker {
96-
width: ::comemo::internal::AccessTracker<u32>,
97-
height: ::comemo::internal::AccessTracker<u32>,
96+
pub struct Constraint {
97+
width: ::comemo::internal::HashConstraint<u32>,
98+
height: ::comemo::internal::HashConstraint<u32>,
9899
}
99100
}
100101
};

src/track.rs

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,22 @@
1-
use std::cell::Cell;
2-
use std::hash::Hash;
3-
use std::marker::PhantomData;
4-
use std::num::NonZeroU128;
51
use std::ops::Deref;
62

7-
use crate::hash::siphash;
8-
93
/// Tracks accesses to a value.
104
///
11-
/// Encapsulates a reference to a value and tracks all accesses to it.
12-
/// The only methods accessible on `Tracked<T>` are those defined in an impl
13-
/// block for `T` annotated with [`#[track]`](track).
14-
///
15-
/// ```
16-
/// use comemo::Track;
17-
///
18-
/// let image = Image::random(20, 40);
19-
/// let sentence = describe(image.track());
20-
/// println!("{sentence}");
21-
/// ```
5+
/// Encapsulates a reference to a value and tracks all accesses to it. The only
6+
/// methods accessible on `Tracked<T>` are those defined in an implementation
7+
/// block for `T` annotated with [`#[track]`](macro@crate::track).
228
pub struct Tracked<'a, T>
239
where
2410
T: Track + ?Sized,
2511
{
2612
/// A reference to the tracked value.
2713
inner: &'a T,
28-
/// A tracker which stores constraints for T. It is filled by the tracked
29-
/// methods on T's generated surface type.
14+
/// A constraint that is generated for T by the tracked methods on T's
15+
/// surface type.
3016
///
31-
/// Starts out as `None` and is set to a stack-stored tracker in the
17+
/// Starts out as `None` and is set to a stack-stored constraint in the
3218
/// preamble of memoized functions.
33-
tracker: Option<&'a T::Tracker>,
19+
constraint: Option<&'a T::Constraint>,
3420
}
3521

3622
// The type `Tracked<T>` automatically dereferences to T's generated surface
@@ -59,42 +45,45 @@ where
5945
}
6046

6147
/// Destructure a `Tracked<_>` into its parts.
62-
pub fn to_parts<T>(tracked: Tracked<T>) -> (&T, Option<&T::Tracker>)
48+
pub fn to_parts<T>(tracked: Tracked<T>) -> (&T, Option<&T::Constraint>)
6349
where
6450
T: Track,
6551
{
66-
(tracked.inner, tracked.tracker)
52+
(tracked.inner, tracked.constraint)
6753
}
6854

6955
/// Create a `Tracked<_>` from its parts.
70-
pub fn from_parts<'a, T>(inner: &'a T, tracker: Option<&'a T::Tracker>) -> Tracked<'a, T>
56+
pub fn from_parts<'a, T>(
57+
inner: &'a T,
58+
constraint: Option<&'a T::Constraint>,
59+
) -> Tracked<'a, T>
7160
where
7261
T: Track,
7362
{
74-
Tracked { inner, tracker }
63+
Tracked { inner, constraint }
7564
}
7665

7766
/// A trackable type.
7867
///
7968
/// This is implemented by types that have an implementation block annoted with
80-
/// [`#[track]`](track).
69+
/// [`#[track]`](macro@crate::track).
8170
pub trait Track: Trackable {
8271
/// Start tracking a value.
8372
fn track(&self) -> Tracked<Self> {
84-
Tracked { inner: self, tracker: None }
73+
Tracked { inner: self, constraint: None }
8574
}
8675
}
8776

8877
/// Non-exposed parts of the `Track` trait.
8978
pub trait Trackable {
90-
/// Keeps track of accesses to the value.
91-
type Tracker: Default + 'static;
79+
/// Describes an instance of type.
80+
type Constraint: Default + 'static;
9281

9382
/// The tracked API surface of this type.
9483
type Surface: for<'a> Family<'a>;
9584

96-
/// Whether an instance fulfills the given tracker's constraints.
97-
fn valid(&self, tracker: &Self::Tracker) -> bool;
85+
/// Whether an instance fulfills the given constraint.
86+
fn valid(&self, constraint: &Self::Constraint) -> bool;
9887

9988
/// Cast a reference from `Tracked` to this type's surface.
10089
fn surface<'a, 'r>(
@@ -109,17 +98,3 @@ pub trait Family<'a> {
10998
/// The surface with lifetime.
11099
type Out;
111100
}
112-
113-
/// Tracks accesses to a value.
114-
#[derive(Default)]
115-
pub struct AccessTracker<T: Hash>(Cell<Option<NonZeroU128>>, PhantomData<T>);
116-
117-
impl<T: Hash> AccessTracker<T> {
118-
pub fn track(&self, value: &T) {
119-
self.0.set(Some(siphash(value)));
120-
}
121-
122-
pub fn valid(&self, value: &T) -> bool {
123-
self.0.get().map_or(true, |v| v == siphash(value))
124-
}
125-
}

0 commit comments

Comments
 (0)