Here is a problem I am trying to solve. I have multiple procedural macro functions that generate tables of pre-computed values. Currently my procedural macro functions take parameters in the form of literal integers. I would like to be able to pass these parameters from a configuration file. I could re-write my functions to load parameters from macro themselves. However, I want to keep configuration from a top level crate, like in this example:
top-level-crate/
config/
params.yaml
macro1-crate/
macro2-crate/
Since the input into a macro function is syntax tokens not run-time values, I am not able to load a file from top-level-crate and pass params.
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(500, 123, 499);
const TABLE2: [f32;100] = gen_table2!(1, 3);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
I would like to be able to pass params to gen_table1 and gen_table2 from a configuration file like this:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
// Load values PARAM1, PARAM2, PARAM3, PARAM4, PARAM5
const TABLE1: [f32;100] = gen_table1!(PARAM1, PARAM2, PARAM3);
const TABLE2: [f32;100] = gen_table2!(PARAM4, PARAM5);
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
The obvious problem is that PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 are runtime values, and proc macros rely on build time information to generate tables.
One option I am considering is to create yet another proc macro specifically to load configuration into some sort of data-structure built using quote!
tokens. Then feed this into macros. However, this feels hackish and the configuration file needs to be loaded several times. Also the params data structure need to be tightly coupled across macros. The code might look like this:
use macro1_crate::gen_table1;
use macro2_crate::gen_table2;
const TABLE1: [f32;100] = gen_table1!(myparams!());
const TABLE2: [f32;100] = gen_table2!(myparams!());
fn main() {
// use TABLE1 and TABLE2 to do further computation.
}
Any improvements or further suggestions?