nim-chronicles/chronicles/scope_helpers.nim

79 lines
2.5 KiB
Nim

import
macros, tables, strformat, options
type
BindingsSet* = Table[string, NimNode]
FinalBindingsSet* = OrderedTable[string, NimNode]
proc id*(key: string, public = false): NimNode =
result = newIdentNode(key)
if public: result = postfix(result, "*")
iterator assignments*(n: NimNode, liftIdentifiers = true): (string, NimNode) =
# extract the assignment pairs from a block with assigments
# or a call-site with keyword arguments.
for child in n:
if child.kind in {nnkAsgn, nnkExprEqExpr}:
let name = $child[0]
let value = child[1]
yield (name, value)
elif child.kind == nnkIdent and liftIdentifiers:
yield ($child, child)
else:
error "A scope definitions should consist only of key-value assignments"
proc scopeAssignments*(scopeBody: NimNode): NimNode =
if scopeBody.len > 1:
result = scopeBody[1]
else:
result = newStmtList()
proc scopeRevision*(scopeBody: NimNode): int =
# get the revision number from a `activeChroniclesScope` body
var revisionNode = scopeBody[0]
result = int(revisionNode.intVal)
proc lastScopeBody*(scopes: NimNode): NimNode =
# get the most recent `activeChroniclesScope` body from a symChoice node
if scopes.kind in {nnkClosedSymChoice, nnkOpenSymChoice}:
var bestScopeRev = 0
assert scopes.len > 0
for scope in scopes:
let scopeBody = scope.getImpl.body
let rev = scopeBody.scopeRevision
if result == nil or rev > bestScopeRev:
result = scopeBody
bestScopeRev = rev
else:
result = scopes.getImpl.body
template finalLexicalBindings*(scopes: NimNode): NimNode =
scopes.lastScopeBody.scopeAssignments
proc handleUserStreamChoice*(n: NimNode): StreamSpec =
# XXX: This proc could use a lent result once the compiler supports it
if n.kind != nnkStrLit:
error "The stream name should be specified as a string literal", n
let streamName = $n
for s in config.streams:
if s.name == streamName:
return s
error &"'{streamName}' is not a configured stream name. " &
"Please refer to the documentation of 'chronicles_streams'", n
proc skipTypedesc*(n: NimNode): NimNode =
result = n
if result.kind == nnkBracketExpr and $result[0] in ["type", "typedesc"]:
result = result[1]
proc clearEmptyVarargs*(args: NimNode) =
# Nim will sometimes do something silly - it will convert our varargs
# into an empty array. We need to detect this case and handle it:
if args.len == 1 and args[0].kind == nnkHiddenStdConv:
args.del 0