There are basically three ways to do meta programming in nim. Simple replacement of tokens:
const debug = true
template log(msg: string) =
if debug: stdout.writeLine(msg)
You could also use other concrete types, generics and type checked or unchecked expressions instead of string.
Macros are syntax tree transformations, similar to rust compiler plugins:
import macros, strutils
macro readCfgAndBuildSource(cfgFilename: string): typed =
let inputString = slurp(cfgFilename.strVal)
result = newStmtList()
for line in inputString.splitLines:
# Ignore empty lines
if line.len < 1: continue
var chunks = line.split(',')
if chunks.len != 2:
error("Input needs comma split values, got: " & line)
let entry = quote do:
const cfg`chunks[0]` = "`chunks[1]`"
result.add(entry)
if result.len < 1: error("Input file empty!")
readCfgAndBuildSource("data.cfg")
This reads a file and creates constants from it at compile time.
Emit is a tad more complex. Nim is compiled to another language like c, c++ or llvm. Emit lets you emit code in the host language, mostly to wrap libraries. Don't think there is any way to make that typesafe.