Skip to content

Instantly share code, notes, and snippets.

@planetis-m
Created October 3, 2019 13:33
Show Gist options
  • Save planetis-m/55ad5a4d8e361649670730b0f59ed95d to your computer and use it in GitHub Desktop.
Save planetis-m/55ad5a4d8e361649670730b0f59ed95d to your computer and use it in GitHub Desktop.
import macros, parsejson, streams
template loadArray() {.dirty.} =
if p.kind != jsonArrayStart: raiseParseErr(p, "'[' expected for an array")
next(p)
var i = 0
while p.kind != jsonArrayEnd and p.kind != jsonEof:
inc(i)
if p.kind == jsonArrayEnd: next(p)
else: raiseParseErr(p, "']' end of array expected")
template loadInt(param, baseTy) =
if p.kind == jsonInt:
param = baseTy(getInt(p))
next(p)
else: raiseParseErr(p, "int expected")
proc loadAny(nodeTy, param: NimNode): NimNode =
let baseTy = getTypeImpl(nodeTy)
case baseTy.typeKind
of ntyArray:
result = getAst(loadArray())
result[3][1].insert(0, loadAny(baseTy[2], nnkBracketExpr.newTree(param, ident"i")))
of ntyInt..ntyInt64, ntyUInt..ntyUInt64:
result = getAst(loadInt(param, baseTy))
else:
error("Unsupported type: " & nodeTy.repr)
template genParseProc(stream, param, data, dataTy, body: untyped): untyped {.dirty.} =
proc parse(s: Stream, param: var dataTy) =
var p: JsonParser
open(p, s, "unknown file")
next(p)
body
close(p)
parse(stream, data)
macro load(s: Stream, data: typed) =
let typeNode = getTypeImpl(data)
let param = genSym(nskParam, "d")
let body = loadAny(typeNode, param)
result = getAst(genParseProc(s, param, data, typeNode, body))
echo result.repr
when isMainModule:
let s = newStringStream("[1, 3, 5]")
var a: array[3, int]
load(s, a)
assert a == [1, 3, 5]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment