11extern crate proc_macro;
22
3- use proc_macro:: TokenStream ;
3+ use proc_macro:: TokenStream ;
4+ use quote:: { quote, ToTokens } ;
5+ use syn:: {
6+ Ident , LitFloat , LitInt , LitStr , Result , Token , parse:: { Parse , ParseStream } , parse_macro_input
7+ } ;
8+
9+ #[ derive( Debug , Clone ) ]
10+ struct ExpLutMacroInput {
11+ start : f32 ,
12+ end : f32 ,
13+ steps : usize ,
14+ }
15+
16+ impl Parse for ExpLutMacroInput {
17+ fn parse ( input : ParseStream ) -> Result < Self > {
18+ let key1: Ident = input. parse ( ) ?;
19+ input. parse :: < Token ! [ : ] > ( ) ?;
20+ let lit1: LitFloat = input. parse ( ) ?;
21+ let value1: & str = lit1. base10_digits ( ) ;
22+
23+ input. parse :: < Token ! [ , ] > ( ) ?;
24+
25+ let key2: Ident = input. parse ( ) ?;
26+ input. parse :: < Token ! [ : ] > ( ) ?;
27+ let lit2: LitFloat = input. parse ( ) ?;
28+ let value2: & str = lit2. base10_digits ( ) ;
29+
30+ input. parse :: < Token ! [ , ] > ( ) ?;
31+
32+ let key3: Ident = input. parse ( ) ?;
33+ input. parse :: < Token ! [ : ] > ( ) ?;
34+ let lit3: LitInt = input. parse ( ) ?;
35+ let value3: & str = lit3. base10_digits ( ) ;
36+
37+ let mut input = ExpLutMacroInput {
38+ start : 0.0 ,
39+ end : 0.0 ,
40+ steps : 0 ,
41+ } ;
42+
43+ for ( key, value) in [ ( key1, value1) , ( key2, value2) , ( key3, value3) ] {
44+ if key == "start" {
45+ input. start = value. parse :: < f32 > ( ) . unwrap ( ) ;
46+ } else if key == "end" {
47+ input. end = value. parse :: < f32 > ( ) . unwrap ( ) ;
48+ } else if key == "steps" {
49+ input. steps = value. parse :: < usize > ( ) . unwrap ( ) ;
50+ }
51+ }
52+
53+ Ok ( input)
54+ }
55+ }
56+
57+ #[ proc_macro]
58+ pub fn exp_lut_macro ( input : TokenStream ) -> TokenStream {
59+ let input = parse_macro_input ! ( input as ExpLutMacroInput ) ;
60+
61+ if input. steps < 2 {
62+ panic ! ( "EXP_LOOKUP_STEPS must be >= 2" ) ;
63+ }
64+
65+ if input. end <= input. start {
66+ panic ! ( "EXP_LOOKUP_END must be > EXP_LOOKUP_START" ) ;
67+ }
68+
69+ let steps: usize = input. steps ;
70+ let start: f32 = input. start ;
71+ let end: f32 = input. end ;
72+ let step_size: f32 = ( end - start) / steps as f32 ;
73+
74+ let expanded = quote ! {
75+ const LUT : [ f32 ; #steps] = core:: array:: from_fn( |i| {
76+ let x = #start + ( i as f32 * #step_size) ;
77+ x. exp( )
78+ } ) ;
79+ } ;
80+
81+ TokenStream :: from ( expanded)
82+ }
0 commit comments