Last active
June 6, 2021 20:30
-
-
Save thomcc/11cc759d32389094250a503ab24e5f4f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! initial version courtesy of @danielhenrymantilla. | |
//! | |
//! extended to support fns with args/return types, | |
//! visibility, #[attributes], unsafe, const, async, | |
//! extern "abi" ... | |
//! | |
//! left as an exercise for later (cuz it sux): | |
//! - generics? | |
//! - where clauses? | |
//! - probably other shit im missing | |
//! - ... | |
//! | |
//! probably don't do stuff like this, honestly. | |
#[macro_export] | |
macro_rules! with_sections { | |
( | |
$(#[$m:meta])* | |
$v:vis | |
$(const $(@$const_:tt)?)? | |
$(async $(@$async_:tt)?)? | |
$(unsafe $(@$unsafe_:tt)?)? | |
$(extern $($abi:literal)?)? | |
fn $fname:ident ($($args:tt)*) -> $ret:ty { | |
$($contents:tt)* | |
} | |
) => (with_sections! { | |
// note: the "param" to `@__inner` is | |
// passed verbatim (as a `:tt`) until | |
// the end | |
@__inner ( | |
@name $fname | |
@vis ($v) | |
@args ($($args)*) | |
@ret ($ret) | |
@attrs ($(#[$m])*) | |
@abi ($(extern $($abi)?)?) | |
@unsafety ($(unsafe $(@$unsafe_)?)?) | |
@constitude ($(const $(@$const_)?)?) | |
@asynchrony ($(async $(@$async_)?)?) | |
) | |
@out [] | |
@in [{$($contents)*}] | |
}); | |
// `fn blah(...) {}` — no explicit return type, but we | |
// fake it with explicit `-> ()` | |
( | |
$(#[$m:meta])* | |
$v:vis | |
$(const $(@$const_:tt)?)? | |
$(async $(@$async_:tt)?)? | |
$(unsafe $(@$unsafe_:tt)?)? | |
$(extern $($abi:literal)?)? | |
fn $fname:ident ($($args:tt)*) $contents:tt | |
) => (with_sections! { | |
$(#[$m])* | |
$v | |
$(const $(@$const_)?)? | |
$(async $(@$async_)?)? | |
$(unsafe $(@$unsafe_)?)? | |
$(extern $($abi)?)? | |
fn $fname($($args)*) -> () $contents | |
}); | |
(@__inner $funcinfo:tt | |
@out $out:tt | |
@in [#[section($section:expr $(,)?)] $body:tt $($rest:tt)*] | |
) => (with_sections! { | |
@__inner $funcinfo | |
@out $out | |
@in [match Section::new($section) { _ => $body } $($rest)*] | |
}); | |
(@__inner $funcinfo:tt | |
@out $out:tt | |
@in [{ $($inner:tt)* } $($rest:tt)*] | |
) => (with_sections! { | |
@__inner $funcinfo | |
@out [$out] | |
@in [$($inner)* @end_brace $($rest)*] | |
}); | |
(@__inner $funcinfo:tt | |
@out [[$($out:tt)*] $($acc:tt)*] | |
@in [@end_brace $($rest:tt)*] | |
) => (with_sections! { | |
@__inner $funcinfo | |
@out [$($out)* { $($acc)* }] | |
@in [$($rest)*] | |
}); | |
(@__inner $funcinfo:tt | |
@out [$($out:tt)*] | |
@in [$current:tt $($rest:tt)*] | |
) => (with_sections! { | |
@__inner $funcinfo | |
@out [$($out)* $current] | |
@in [$($rest)*] | |
}); | |
( | |
@__inner ( | |
@name $fname:ident | |
@vis ($v:vis) | |
@args ($($args:tt)*) | |
@ret ($ret:ty) | |
@attrs ($(#[$m:meta])*) | |
@abi ($(extern $($abi:literal)?)?) | |
@unsafety ($(unsafe $(@$unsafe_:tt)?)?) | |
@constitude ($(const $(@$const_:tt)?)?) | |
@asynchrony ($(async $(@$async_:tt)?)?) | |
) | |
@out [$($out:tt)*] | |
@in [/* nothing */] | |
) => ( | |
$(#[$m])* | |
$v | |
$(const $(@$const_)?)? | |
$(async $(@$async_)?)? | |
$(unsafe $(@$unsafe_)?)? | |
$(extern $($abi)?)? | |
fn $fname($($args)*) -> $ret $($out)* | |
); | |
} | |
pub struct Section { | |
name: &'static str, | |
} | |
impl Section { | |
pub fn new(name: &'static str) -> Section { | |
println!("begin {}", name); | |
Self { name } | |
} | |
} | |
impl Drop for Section { | |
fn drop(&mut self) { | |
println!("end {}", self.name); | |
} | |
} | |
// rest of this is various kinds of test code. | |
// (most stuff got tested by modifying these in place) | |
with_sections! { | |
/// ``` | |
/// playground::doit(1); | |
/// ``` | |
pub fn doit(x: i32) { | |
println!("b4 everything {}", x); | |
#[section("foo")] | |
{ | |
println!("inside foo before bar"); | |
#[section("bar")] | |
{ | |
println!("inside bar") | |
} | |
println!("inside foo after bar"); | |
} | |
#[section("baz")] | |
{ | |
println!("inside baz") | |
} | |
println!("after everything"); | |
} | |
} | |
with_sections! { | |
// extern "C" | |
const unsafe fn no() -> i32 { | |
// println!("no"); | |
4 | |
} | |
} | |
with_sections! { | |
// extern "C" | |
async unsafe fn _ayes() { | |
println!("no"); | |
// 4 | |
} | |
} | |
fn main() { | |
fn type_name_of<T: 'static>(_: T) -> &'static str { | |
std::any::type_name::<T>() | |
} | |
doit(1); | |
// let _f: extern "C" fn() -> i32 = no; | |
unsafe { println!("{}", no()) }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment