Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Last active August 29, 2015 14:17
Show Gist options
  • Save fowlmouth/48f3340b797c12cb3043 to your computer and use it in GitHub Desktop.
Save fowlmouth/48f3340b797c12cb3043 to your computer and use it in GitHub Desktop.
nim variadic templates
import macros
macro first (va_expr: expr): expr =
if va_expr.kind == nnkBracket:
return va_expr[0]
else:
return va_expr
macro rest (va_expr: expr): expr =
echo treerepr(va_expr)
va_expr.expectKind nnkBracket
result = newNimNode(va_expr.kind)
for i in 1 .. <len(va_expr):
echo i, ": ", va_expr[i].repr
result.add va_expr[i]
echo treerepr result
macro show (xs: expr): expr =
toStrLit(xs)
proc recurseApply (f:NimNode; xs:NimNode): NimNode{.compileTime.} =
result = newStmtList()
var xs = xs
while xs.len > 0:
let item = getAst(first(xs))
xs = getAst(rest(xs))
result.add quote do: `f`(`item`)
discard
echo repr(result)
macro `&&` (args:varargs[expr]): expr =
echo treerepr(args)
if args.kind == nnkBracket: return args
else: return newNimNode(nnkBracket).add(args)
macro cleanup(destructor; xs:varargs[expr]): stmt =
result = recurseApply(destructor, xs)
#bind destructor
#echo first(xs)
#echo len(xs)
#echo repr(xs)
#echo repr(rest(xs))
#destructor(first(xs))
#when len(xs) > 1:
# cleanup(destructor, getAst(rest(xs)))
proc destroy (i:int) =
echo "destroying ", i
proc destroy (f:float) =
echo "destroying ", f
let
i1 = 1
f1 = 2.0
i2 = 3
cleanup(destroy, i1, f1, i2)
import macros
macro first (va_expr: expr): expr =
if va_expr.kind == nnkBracket:
return va_expr[0]
else:
return va_expr
macro rest (va_expr: expr): expr =
echo treerepr(va_expr)
va_expr.expectKind nnkBracket
result = newNimNode(va_expr.kind)
for i in 1 .. <len(va_expr):
echo i, ": ", va_expr[i].repr
result.add va_expr[i]
echo treerepr result
template cleanup_tmpl (destructor; xs:varargs[expr]): stmt =
destructor(first(xs))
when len(xs) > 1:
cleanup_tmpl(destructor, rest(xs))
proc destroy (i:int) =
echo "destroying ", i
proc destroy (f:float) =
echo "destroying ", f
let
i1 = 1
f1 = 2.0
i2 = 3
cleanup_tmpl(destroy, i1, f1, i2)
#include <iostream>
using namespace std;
void destroy(int some)
{
cout << "destroying " << some << endl;
}
void destroy(float some)
{
cout << "destroying " << some << endl;
}
template <typename first, typename... rest>
void destroy(first& a, rest&... b)
{
destroy(a);
destroy(b...);
}
int main(void)
{
int a = 1, b = 2;
float c = 1.0/9.0;
destroy(a,c,b);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment