4
foo!(x, y, z);
// expands to
fn xx(self) -> T {..}
fn xy(self) -> T {..}
...
fn xxx(self) -> T {..}
fn xxy(self) -> T {..}
fn xyz(self) -> T {..}
fn xzx(self) -> T {..}
//and so on
...

Is it possible for macros to generate additional data? I would like to implement vector swizzling. There are many combinations for a Vector4. 4 + 2^2 + 3^3 + 4^4 = 291 combinations

I haven't done anything with macros besides simple substitution, so I am wondering if something like that could be expressed or do I need compiler plugins for that?

mattias
  • 2,079
  • 3
  • 20
  • 27
Maik Klein
  • 15,548
  • 27
  • 101
  • 197
  • "additional data" is a very generic concept. Are you really asking if a macro can make an arbitrary number of functions based on the macro input? – Shepmaster Jun 26 '16 at 19:17
  • @Shepmaster Yes I basically want to generate permutations of the macro input. – Maik Klein Jun 26 '16 at 19:18
  • 2
    Then the answer is [basically no](http://stackoverflow.com/q/27415011/155423). (Or [this](http://stackoverflow.com/q/24905160/155423)). (Or [this](http://stackoverflow.com/q/23061702/155423)). – Shepmaster Jun 26 '16 at 19:18
  • If you agree that this is a duplicate, feel free to mark it as whichever one was most useful. If you don't, [edit] your question to explain the differences. – Shepmaster Jun 27 '16 at 04:07
  • 1
    @Shepmaster: I note that none of the duplicates mentions the use of a build script (which, in Rust, is quite more handy than in other languages due to being integrated to the build system). It could potentially be a reasonable alternative... depending on the specifics of the problem. – Matthieu M. Jun 27 '16 at 06:55
  • @MatthieuM. a good point! The downside is that you are going to have to treat all the Rust code as plain text. I think you can feel free to add that answer here or on any of the others. – Shepmaster Jun 27 '16 at 21:47
  • @Shepmaster: The previous questions you linked present examples that are more "in situ" in the middle of existing code so I think I'll answer this one instead. – Matthieu M. Jun 28 '16 at 07:07

1 Answers1

1

Rust supports 3 methods of code generation:

  • macros declared with macro!
  • procedural macros relying on plugins (unstable)
  • build.rs

The latter is a built-in build script specifically supporting code generation/3rd-party libraries build (such as C libraries).

In your case, you are specifically interesting in the Code Generation part, which is simple enough (quoting the docs):

// build.rs

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("hello.rs");
    let mut f = File::create(&dest_path).unwrap();

    f.write_all(b"
        pub fn message() -> &'static str {
            \"Hello, World!\"
        }
    ").unwrap();
}

Given this, you can automatically generate any .rs file before the build starts without encountering the macro hygiene issue or having to rely on a nightly compiler.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722