mast
A simple DSL for defining abstract syntax trees in Nim.
This project was directly inspired by the breeze library.
Overview
This library provides another way to write Nim macros more closely following the output of treeRepr
.
Showcase
Please see tests for examples of most features. This section provides an incomplete summary of the core functionality.
Basic example
The following is an example usage:
import mast
macro makeMain(body: untyped) =
ast:
ProcDef:
`main`
Empty
Empty
FormalParams:
Empty
Empty
Empty
(body)
makeMain:
echo "Hello world!"
# `makeMain` expands to:
proc main() =
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
Identifiers
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.
Installing
The package can be installed by following the nimble instructions here.
Usage
Simply import mast into your module to start using it.
Contributing
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!