Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> I'm not following you here.

Any marginally non-trivial macro is a compiler, by definition.

> The macro gets expanded at compile-time into 'normal' source code, by the compiler.

Macro expands a DSL inside it into the underlying host meta-language code. In other words, it compiles this DSL into the host language.

For example, a macro which defines a parser. Inside it is a BNF (or PEG), a very high level language. Macro must compile this language into Rust, and, since it is a very high level language, there are tons of optimisation opportunities that would be totally missed by the underlying Rust and LLVM because they lack this domain-specific knowledge.

Your macro will compile this source DSL in multiple stages (well, because this is the only sane approach to compilation anyway, read about the Nanopass framework for more details). First it will operate on an AST level, do some analysis, error reporting, inlining, may annotate the detected left recursive nodes and binary expression nodes. Then you'd lower it down into the trivial Packrat building blocks - still a tree. But now you notice that there is a lot of redundant reads from the input stream, and if you flatten this tree into an SSA you can optimise them all away.

Alas, after such an optimisation you'd have to promote it back to tree in order to generate Rust, because there is no `goto`.

And this is only one trivial example. In my practice there were dozens such DSLs. For example, same story is with an optimising WAM-based embedded Prolog DSL, multiple querying DSLs, tree walking DSLs (which are essential for implementing macros efficiently).



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: