A simple DSL for defining abstract syntax trees in Nim.
This project was directly inspired by the breeze library.
This library provides another way to write Nim macros
more closely following the output of treeRepr
.
Please see tests for examples of most features. This section provides an incomplete summary of the core functionality.
The following is an example usage:
import mast
macro makeMain(say: static string) =
ast:
ProcDef:
`main`
Empty
Empty
FormalParams:
Empty
Empty
Empty
StmtList:
Command:
`echo`
"Hello macro!"
Command:
`echo`
(lit say)
makeMain "Hello world!"
# `makeMain` expands to:
proc main() =
echo "Hello macro!"
echo "Hello world!"
Notice that most elements in the AST definition correspond to their nnk*
NimNode counterparts.
Exceptions to this pattern are the following:
- Identifiers which are enclosed in backticks ("`")
- Literals which are simply specified in the AST definition as-is
- External expressions which are embedded in the AST by enclosing them in parentheses
Under the hood mast uses the fmt
macro to parse identifier names. This means that identifier names can be
composed using the following syntax:
let i = 1
let newIdent = ast`ident{i}` # generates `Ident "ident1"`
Bound symbols can be specified by using the sym
macro:
let boundSym = ast (sym someDeclaredSymbol)
Lastly, new symbols can be generated using the following syntax:
let genSymed = ast (sym Proc`someProcSymbol`)
The Proc
symbol here corresponds to nskProc
,
and the symbol inside the backticks can be interpolated in the same way as
identifiers.
The package can be installed by following the nimble instructions here.
Simply import mast into your module to start using it.
This project is maintained during my free time, and serves as a tool for a game engine I am writing after work hours. Contributions are welcome, and I will merge them immediately if they serve to keep the project robust, simple, and maintainable.
Cheers and happy coding! 🍺