Skip to content

Instantly share code, notes, and snippets.

@zacharycarter
Last active August 9, 2019 06:54
Show Gist options
  • Save zacharycarter/2b4a6fc3740f33a8be18ea24d8c03d7b to your computer and use it in GitHub Desktop.
Save zacharycarter/2b4a6fc3740f33a8be18ea24d8c03d7b to your computer and use it in GitHub Desktop.
macro for vm hooks
# from https://github.com/Serenitor/embeddedNimScript/blob/master/scripts/api.nim
template builtin = discard
proc add (a, b: int): int = builtin
proc modifyState (str: string) = builtin
proc fooBar (foo: var Foo) = builtin
# from https://github.com/Serenitor/embeddedNimScript/blob/master/embeddedNims/apiImpl.nim
from compiler/idents import IdentCache
from compiler/vmdef import registerCallback, VmArgs, PCtx
from compiler/modulegraphs import ModuleGraph
from compiler/vm import
# Getting values from VmArgs
getInt, getFloat, getString, getBool, getNode,
# Setting result (return value)
setResult
from compiler/ast import
# Types
PSym, PNode, TNodeKind,
# Getting values from PNodes
getInt, getFloat,
# Creating new PNodes
newNode, newFloatNode, addSon, newTree
from os import splitFile
from threadpool import FlowVar
# Assume location of shared state type in ../state
import ../state
type
Script* = ref object
filename*: string
moduleName*: string
mainModule*: PSym
graph*: ModuleGraph
context*: PCtx
watcher*: FlowVar[int]
Foo = object
bar: string
proc exposeScriptApi* (script: Script) =
bindObject(Foo) # here we invoke our theoretical macro
template expose (procName, procBody: untyped) {.dirty.} =
script.context.registerCallback script.moduleName & "." & astToStr(procName),
proc (a: VmArgs) =
procBody
expose add:
# We need to use procs like getInt to retrieve the argument values from VmArgs
# Instead of using the return statement we need to use setResult
setResult(a,
getInt(a, 0) +
getInt(a, 1))
expose modifyState:
modifyMe = getString(a, 0)
echo "`", script.moduleName, "` has changed state.modifyMe to `", modifyMe, "`"
expose fooBar: # here we are adding a new callback to the VM hooks
foo = getFoo(a, 0) # here we call the getFoo proc that our macro generates - a: VmArgs, 0: index into register
echo foo.bar # this should print "intial value"
foo.bar = "modified value"
setFoo(foo) # here we call the setFoo proc that our macro generates which will in turn create a PNode and call setResult
var foo = Foo(bar: "initial value")
fooBar(foo)
echo foo.bar # should print "modified value"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment