Skip to content

Commit

Permalink
support arrays with enum indices (#3)
Browse files Browse the repository at this point in the history
* switch to balls
* rm submodules
* rm remaining module directories
  • Loading branch information
disruptek authored Jan 24, 2021
1 parent 1cef56f commit 1f9b213
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
deps
nim.cfg
bin/
nimblemeta.json
Expand Down
24 changes: 0 additions & 24 deletions .gitmodules

This file was deleted.

1 change: 0 additions & 1 deletion criterion
Submodule criterion deleted from 83a49e
1 change: 0 additions & 1 deletion eminim
Submodule eminim deleted from 86d93d
1 change: 0 additions & 1 deletion grok
Submodule grok deleted from eb313f
59 changes: 45 additions & 14 deletions jason.nim
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ proc jasonSquare(a: NimNode): NimNode =
macro jason*[I, T](a: array[I, T]): Jason =
## Render any Nim array as a series of JSON values.
# make sure the array ast has the form we expect
let typ = a.getTypeImpl
let typ = a.getType
# support for nim-1.2
if typ.kind == nnkBracket:
return jasonSquare a
Expand All @@ -203,28 +203,59 @@ macro jason*[I, T](a: array[I, T]): Jason =
else:
# take a look at the range definition for the array
let ranger = typ[1]
expectKind(ranger, nnkInfix) # infix
expectKind(ranger[0], nnkIdent) # ident".."
expectKind(ranger[1], nnkIntLit) # 0
expectKind(ranger[2], nnkIntLit) # 10
if $ranger[0] != "..":
error "unexpected infix range:\n" & treeRepr(ranger)
when false:
if ranger.kind == nnkBracketExpr:
echo treeRepr(ranger)
echo "get type1: ", treeRepr(ranger.getType)
echo "get inst1: ", treeRepr(ranger.getTypeInst)
echo "get impl1: ", treeRepr(ranger.getTypeImpl)
var ranger = ranger.getTypeInst
echo "get type2: ", treeRepr(ranger.getType)
echo "get inst2: ", treeRepr(ranger.getTypeInst)
echo "get impl2: ", treeRepr(ranger.getTypeImpl)

# okay, let's do this thing
let js = ident"jason"
let s = genSym(nskVar, "jason")
var list = newStmtList()

# we'll make adding strings to our accumulating string easier...
template addString(x: typed): NimNode {.dirty.} =
# also cast the argument to a string just for correctness
list.add newCall(newDotExpr(s, bindSym"add"), newCall(ident"string", x))
# iterate over the array by index and add each item to the string
add list:
s.newDotExpr(bindSym"add").newCall:
ident"string".newCall x

template composeIt(iter: typed; body: untyped) {.dirty.} =
var first = true
for it {.inject.} in iter:
#var it {.inject.} = it
if first:
first = false
else:
addString newLit"," # comma between each element
let index = body
# s.add jason(a[index])
addString js.newCall(nnkBracketExpr.newTree(a, index))

list.add newVarStmt(s, newLit"[")
for index in ranger[1].intVal .. ranger[2].intVal:
if index != 0:
addString newLit"," # comma between each element
# s.add jason(a[index])
addString js.newCall(nnkBracketExpr.newTree(a, newLit index))

# iterate over the array by index and add each item to the string
case ranger.kind
of nnkBracketExpr, nnkInfix, nnkSym:
# type A = array[0..10, string]
# type A = array[foo..bar, string]
expectKind(ranger[1], nnkIntLit) # 0
expectKind(ranger[2], nnkIntLit) # 10
composeIt ranger[1].intVal .. ranger[2].intVal:
newLit it.int
of nnkEnumTy:
# type A = array[Enum, string]
composeIt 1 ..< ranger.len:
ranger[it]
else:
error "expected infix or enum:\n" & treeRepr(ranger)

addString newLit"]"
list.add s # final value of the stmtlist is the string itself
result = newCall(ident"Jason", list)
Expand Down
6 changes: 3 additions & 3 deletions jason.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ description = "compile-time json"
license = "MIT"

when not defined(release):
requires "https://github.com/disruptek/testes >= 1.0.0 & < 2.0.0"
requires "https://github.com/disruptek/balls >= 2.0.0 & < 3.0.0"
requires "https://github.com/disruptek/criterion < 1.0.0"

task test, "run tests for ci":
when defined(windows):
exec "testes.cmd"
exec "balls.cmd"
else:
exec findExe"testes"
exec findExe"balls"

task demo, "generate benchmarks":
exec """demo docs/bench.svg "nim c --out=\$1 --panics:on --gc:arc --define:danger tests/bench.nim""""
Expand Down
1 change: 0 additions & 1 deletion jsony
Submodule jsony deleted from 80c902
1 change: 0 additions & 1 deletion packedjson
Submodule packedjson deleted from 580132
1 change: 0 additions & 1 deletion testes
Submodule testes deleted from e6ddd9
22 changes: 20 additions & 2 deletions tests/test.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import std/options

import testes
import balls
import jason

type
Expand Down Expand Up @@ -36,7 +36,7 @@ type
func `==`(js: Jason or string; s: Jason or string): bool =
system.`==`(js.string, s.string)

testes:
suite "sweet json":
test "string":
check jason"hello" == """"hello""""

Expand Down Expand Up @@ -164,3 +164,21 @@ testes:
dj = $jason(d)
check cj == """{"foo":3,"bar":4.0,"bif":0,"baz":true,"bin":["e","f","g","h"]}"""
check dj == """{"foo":2,"bar":8.0,"bif":1,"boz":{"a":6,"b":7.0},"bin":["i","j","k","l"]}"""

test "arrays with enum indices":
type
E = enum one, two, three, four
B = array[E, string]
let y: B = [one: "a", two: "b", three: "c", four: "d"]
check $jason(y) == """["a","b","c","d"]"""

test "arrays with subset of enum indices":
when true:
skip"does not work yet; broken typed macro ast?"
else:
type
E = enum one, two, three, four
A = array[two..four, string]
let x: A = [two: "b", three: "c", four: "d"]
checkpoint $jason(x)
check $jason(x) == """["b","c","d"]"""

0 comments on commit 1f9b213

Please sign in to comment.