Skip to content

Instantly share code, notes, and snippets.

@mjendrusch
Created October 12, 2016 20:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjendrusch/1bed6eb2de838aea59ae1fd1d0c29fc2 to your computer and use it in GitHub Desktop.
Save mjendrusch/1bed6eb2de838aea59ae1fd1d0c29fc2 to your computer and use it in GitHub Desktop.
Macro to bind proc to JavaScript method
import macros
# Macro to build a lambda using JavaScript's `this`
# from a proc, `this` being the first argument.
macro bindMethod*(procedure: typed): auto =
var
rawProc = getImpl(procedure.symbol)
args = rawProc[3]
thisType = args[1][1]
params = newNimNode(nnkFormalParams).add(args[0])
body = newNimNode(nnkLambda)
this = newIdentNode("this")
# construct the `this` parameter:
thisQuote = quote do:
var `this` {. nodecl, importc .} : `thisType`
call = newNimNode(nnkCall).add(rawProc[0], thisQuote[0][0][0][0])
# construct the procedure call inside the method
if args.len > 2:
for idx in 2..args.len-1:
params.add(args[idx])
call.add(args[idx][0])
body.add(
newNimNode(nnkEmpty)
).add(rawProc[1]).add(rawProc[2]).add(
params
).add(rawProc[4]).add(rawProc[5]).add(
newNimNode(nnkStmtList).add(
thisQuote[0],
newNimNode(nnkAsgn).add(
newIdentNode("result"),
call
)
)
)
result = body
# Usage example
type Foo = object
# A method
mt {.exportc.}: proc(a: string): cstring
x: int
proc testMethod(a: Foo, b: string): cstring =
cstring($a & b)
var test: Foo
test.mt = bindMethod(testMethod)
test.x = 42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment