Skip to content

Instantly share code, notes, and snippets.

@flaviut
Last active December 30, 2022 13:25
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flaviut/b59ccbb3a1a71e79c686 to your computer and use it in GitHub Desktop.
Save flaviut/b59ccbb3a1a71e79c686 to your computer and use it in GitHub Desktop.
import macros
proc procToLambda(input: PNimrodNode): PNimrodNode {.compiletime.} =
# Ident !"foo"
# Empty
# Empty
# FormalParams
# Ident retType
# IdentDefs
# ...
# Pragma
# ...
# Empty
# StmtList
# ...
expectKind(input, nnkProcDef)
expectLen(input, 7)
result = newNimNode(nnkLambda)
result.add(newEmptyNode()) # name
result.add(newEmptyNode())
result.add(newEmptyNode())
result.add(input[3]) # params
result.add(newEmptyNode()) # pragmas
result.add(newEmptyNode())
result.add(input[6]) # body
proc callchainToProc(input, templat: PNimrodNode): PNimrodNode {.compiletime.} =
expectKind(templat, nnkProcDef)
var params: seq[PNimrodNode] = @[]
# FormalParams
# Ident retTypeName
# (IdentDefs
# (Ident paramName)*
# Ident typeName
# Empty)*
for i in 1.. <len(templat[3]):
let nextDefs = templat[3][i]
expectKind(nextDefs, nnkIdentDefs)
for pi in 0..(len(nextDefs)-3):
params.add(nextDefs[pi])
let resultCall = newCall(input, params)
result = copyNimTree(templat)
result[6] = quote do:
return `resultCall`
macro decorate*(vals: openarray[expr], input: stmt): stmt =
result = procToLambda(input)
for i in 0.. <len(vals): # Wrap the proc in each of the decorators
result = newCall(vals[i], result)
result = callchainToProc(result, input)
import decorators
proc timesTwo(input: proc(parm1: string): int): proc(p: string): int =
return proc (p: string): int =
return input(p) * 2
proc plusTwo(input: proc(parm1: string): int): proc(p: string): int =
return proc (p: string): int =
return input(p) + 2
proc foo(parm1: string): int {.decorate: [timesTwo, plusTwo].} =
return 2
echo foo("")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment