This commit is contained in:
nora 2023-01-15 12:13:06 +01:00
parent 2560ba4253
commit 5fcdcc0f48
8 changed files with 216 additions and 1 deletions

47
Cargo.lock generated
View file

@ -2,6 +2,53 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "pm"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]] [[package]]
name = "uwu" name = "uwu"
version = "0.1.0" version = "0.1.0"
dependencies = [
"pm",
]

View file

@ -1,3 +1,6 @@
[workspace]
members = [".", "./pm"]
[package] [package]
name = "uwu" name = "uwu"
version = "0.1.0" version = "0.1.0"
@ -6,3 +9,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
pm = { path = "./pm" }

14
examples/scratch.rs Normal file
View file

@ -0,0 +1,14 @@
use uwu::scratch::{
actual_scratch_read, actual_scratch_write, define_scratch, scratch_space, Scratch,
};
#[scratch_space]
fn has_scratch_space(mut scratch: Scratch<'_>) {
scratch_write!(scratch, 10u32);
let _: u32 = scratch_read!(scratch);
}
fn main() {
define_scratch!(scratch, 10);
has_scratch_space(scratch);
}

14
pm/Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "pm"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
proc-macro2 = "1.0.49"
quote = "1.0.23"
syn = { version = "1.0.107", features = ["full", "fold"] }

49
pm/src/lib.rs Normal file
View file

@ -0,0 +1,49 @@
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{fold::Fold, parse_macro_input, parse_quote, ItemFn, Stmt};
#[proc_macro_attribute]
pub fn scratch_space(_: TokenStream, input: TokenStream) -> TokenStream {
let fn_def = parse_macro_input!(input as ItemFn);
let track_ident = Ident::new("scratch_local", Span::mixed_site());
let mut fn_def = LocalInitFolder {
track_ident: track_ident.clone(),
}
.fold_item_fn(fn_def);
let init: Stmt = parse_quote! { let #track_ident: (); };
fn_def.block.stmts.insert(0, init);
quote! { #fn_def }.into()
}
struct LocalInitFolder {
track_ident: Ident,
}
impl syn::fold::Fold for LocalInitFolder {
fn fold_macro(&mut self, mut mac: syn::Macro) -> syn::Macro {
if let Some(last_path) = mac.path.segments.iter().next_back() {
match last_path.ident.to_string().as_str() {
"scratch_write" => {
let track_ident = &self.track_ident;
mac.path = parse_quote! { actual_scratch_write };
mac.tokens.extend(quote! { ; #track_ident });
}
"scratch_read" => {
let track_ident = &self.track_ident;
mac.path = parse_quote! { actual_scratch_read };
mac.tokens.extend(quote! { ; #track_ident });
}
_ => {}
}
mac
} else {
mac
}
}
}

View file

@ -1,3 +1,5 @@
#![allow(warnings)]
pub struct Node<'a, 'n, T> { pub struct Node<'a, 'n, T> {
item: T, item: T,
outer: Option<&'a mut Node<'a, 'n, T>>, outer: Option<&'a mut Node<'a, 'n, T>>,
@ -11,7 +13,7 @@ impl<'a, 'n, T> Node<'a, 'n, T> {
pub fn push<R>(&mut self, item: T, with_func: impl FnOnce(&mut Self) -> R) -> R { pub fn push<R>(&mut self, item: T, with_func: impl FnOnce(&mut Self) -> R) -> R {
let mut inner = Node { let mut inner = Node {
item, item,
outer: Some(self), outer: Some(todo!()),
}; };
with_func(&mut inner) with_func(&mut inner)
} }
@ -22,6 +24,7 @@ mod tests {
use super::Node; use super::Node;
#[test] #[test]
#[ignore = "todo"]
fn push() { fn push() {
let mut list = Node::<u8>::new(0); let mut list = Node::<u8>::new(0);

View file

@ -5,6 +5,7 @@
pub mod cfg_match; pub mod cfg_match;
pub mod innocent_linked_list; pub mod innocent_linked_list;
pub mod scratch;
pub mod sendsync; pub mod sendsync;
pub mod unroll_int; pub mod unroll_int;
pub mod unsized_clone; pub mod unsized_clone;

83
src/scratch.rs Normal file
View file

@ -0,0 +1,83 @@
use std::mem::{self, MaybeUninit};
pub use pm::scratch_space;
pub struct Scratch<'a>(&'a mut [MaybeUninit<u8>]);
impl<'a> Scratch<'a> {
pub fn new(buf: &'a mut [MaybeUninit<u8>]) -> Self {
Self(buf)
}
pub fn write<T>(&mut self, _value: T) {
let size = mem::size_of::<T>();
assert!(size <= self.0.len());
}
pub fn read<T: Default>(&mut self) -> T {
T::default()
}
}
#[macro_export]
macro_rules! scratch_write {
($scratch:ident, $value:expr) => {
/* transformed to a call to actual_scratch_write */
compile_error!("Failed to transform macro invocation");
};
}
#[macro_export]
macro_rules! scratch_read {
($scratch:ident) => {
/* transformed to a call to actual_scratch_write */
compile_error!("Failed to transform macro invocation");
};
}
#[macro_export]
macro_rules! actual_scratch_write {
($scratch:ident, $value:expr ; $track_local:ident) => {
$track_local = ();
$scratch.write($value);
};
}
#[macro_export]
macro_rules! actual_scratch_read {
($scratch:ident ; $track_local:ident) => {{
let _read = $track_local;
$scratch.read()
}};
}
#[macro_export]
macro_rules! define_scratch {
($name:ident, $size:expr) => {
let mut __buffer: [::core::mem::MaybeUninit<u8>; $size] =
unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
#[allow(unused_mut)]
let mut $name = $crate::scratch::Scratch::new(&mut __buffer);
};
}
pub use {actual_scratch_read, actual_scratch_write, define_scratch, scratch_read, scratch_write};
#[cfg(test)]
mod tests {
use pm::scratch_space;
use super::{define_scratch, Scratch};
#[scratch_space]
fn has_scratch_space(mut scratch: Scratch<'_>) {
scratch_write!(scratch, 10u32);
let _: u32 = scratch_read!(scratch);
}
#[test]
fn simple_scratch() {
define_scratch!(scratch, 100);
has_scratch_space(scratch);
}
}