Skip to content

Commit

Permalink
Version 0.4.3
Browse files Browse the repository at this point in the history
Some fixes to be compatible with Nim 0.19.x
  • Loading branch information
xomachine committed Dec 9, 2018
2 parents 17d75f0 + aa6eafa commit b28a2e5
Show file tree
Hide file tree
Showing 24 changed files with 185 additions and 89 deletions.
60 changes: 25 additions & 35 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
image: gcc

build:compiler:
stage: build
.build:compiler: &nimbuild
cache:
key: nim-compiler
key: nim-${NIMBRANCH}
paths:
- nim-devel
- nim-master
artifacts:
expire_in: 1h
paths:
- nim-*
script:
- nim-${NIMBRANCH}
before_script:
- |
for BRANCH in master devel; do
if [ ! -x nim-$BRANCH/bin/nim ]; then
git clone -b $BRANCH --depth 1 git://github.com/nim-lang/nim nim-$BRANCH/
cd nim-$BRANCH
if [ ! -x nim-${NIMBRANCH}/bin/nim ]; then
git clone -b ${NIMBRANCH} --depth 1 git://github.com/nim-lang/nim nim-${NIMBRANCH}/
cd nim-${NIMBRANCH}
git clone --depth 1 git://github.com/nim-lang/csources csources/
cd csources
sh build.sh
Expand All @@ -26,7 +19,7 @@ build:compiler:
./koch boot -d:release
./koch nimble
else
cd nim-$BRANCH
cd nim-${NIMBRANCH}
git fetch origin
if ! git merge FETCH_HEAD | grep "Already up-to-date"; then
bin/nim c koch
Expand All @@ -35,39 +28,36 @@ build:compiler:
fi
fi
cd ..
done
export PATH="nim-${NIMBRANCH}/bin${PATH:+:$PATH}"
test:devel:
.test: &testscript
stage: test
dependencies:
- build:compiler
except:
- gh-pages
script:
- export PATH="nim-devel/bin${PATH:+:$PATH}"
- nimble -v
- nim -v
- nimble tests

test:devel:
variables:
NIMBRANCH: devel
allow_failure: true
except:
- gh-pages
<<: *nimbuild
<<: *testscript

test:master:
stage: test
dependencies:
- build:compiler
script:
- export PATH="nim-master/bin${PATH:+:$PATH}"
- nimble -v
- nim -v
- nimble tests
except:
- gh-pages
variables:
NIMBRANCH: master
<<: *nimbuild
<<: *testscript

pages:
stage: deploy
dependencies:
- build:compiler
variables:
NIMBRANCH: master
<<: *nimbuild
script:
- export PATH="nim-master/bin${PATH:+:$PATH}"
- mkdir -p public
- nimble docs
- cp index.html public/index.html
Expand Down
29 changes: 20 additions & 9 deletions nesm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,27 @@ from sequtils import toSeq
from tables import contains, `[]`, `[]=`
from streams import Stream

from nesm.typesinfo import TypeChunk, Context, initContext
from nesm.generator import genTypeChunk
from nesm.settings import applyOptions, splitSettingsExpr
from nesm/typesinfo import TypeChunk, Context, initContext
from nesm/generator import genTypeChunk
from nesm/settings import applyOptions, splitSettingsExpr
when defined(nimdoc):
# Workaround to make nimdoc happy
proc generateProcs(ctx: Context, n: NimNode): NimNode = discard
include nesm.documentation
include nesm/documentation
else:
from nesm.procgen import generateProcs
from nesm/procgen import generateProcs

const NimCumulativeVersion = NimMajor * 10000 + NimMinor * 100 + NimPatch
when NimCumulativeVersion >= 1801:
from nesm/cache import storeContext, getContext
else:
static:
var ctx = initContext()
proc storeContext(context: Context) {.compileTime.} =
ctx = initContext()
ctx.declared = context.declared
proc getContext(): Context {.compileTime.} = ctx

static:
var ctx = initContext()
proc prepare(context: var Context, statements: NimNode
): NimNode {.compileTime.} =
result = newStmtList()
Expand Down Expand Up @@ -78,6 +86,7 @@ proc cleanupTypeDeclaration(declaration: NimNode): NimNode =

macro nonIntrusiveBody(typename: typed, o: untyped, de: static[bool]): untyped =
let typebody = getTypeImpl(typename)
let ctx = getContext()
when defined(debug):
hint("Deserialize? " & $de)
hint(typebody.treeRepr)
Expand Down Expand Up @@ -120,14 +129,15 @@ macro toSerializable*(typedecl: typed, settings: varargs[untyped]): untyped =
## * **endian** - set the endian of serialized object
## * **dynamic** - if set to 'false' then object treated as **static**
result = newStmtList()
let ctx = getContext()
when defined(debug):
hint(typedecl.symbol.getImpl().treeRepr())
var ast = typedecl.symbol.getImpl()
var newctx = ctx.applyOptions(settings)
when defined(debug):
hint(ast.treeRepr)
result.add(newctx.prepare(ast))
ctx.declared = newctx.declared
newctx.storeContext()
when defined(debug):
hint(result.repr)

Expand All @@ -141,10 +151,11 @@ macro serializable*(typedecl: untyped): untyped =
## # Type declaration
##
result = cleanupTypeDeclaration(typedecl)
var ctx = getContext()
when defined(debug):
hint(typedecl.treeRepr)
when not defined(nimdoc):
result.add(ctx.prepare(typedecl))
when defined(debug):
hint(result.repr)

ctx.storeContext()
14 changes: 10 additions & 4 deletions nesm/basics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ proc genBasic*(context: Context, size: int): TypeChunk {.compileTime.}
proc genSerialize*(name: NimNode, size: NimNode): NimNode {.compileTime.}
proc genDeserialize*(name: NimNode, size: NimNode): NimNode {.compileTime.}

from generator import STREAM_NAME
from generator import getStreamName
from endians import swapEndian16, swapEndian32, swapEndian64
from streams import writeData, readData
# FIXME: workaround for https://github.com/nim-lang/Nim/issues/7889
proc readData() = discard

proc genDeserialize*(name: NimNode, size: NimNode): NimNode =
let STREAM_NAME = getStreamName()
quote do:
assert(`size` ==
doAssert(`size` ==
`STREAM_NAME`.readData(`name`.unsafeAddr, `size`),
"Stream was not provided enough data")
"Stream has not provided enough data")

proc genSwapCall(size: int): NimNode {.compileTime.} =
case size
Expand All @@ -29,21 +32,24 @@ proc genDeserializeSwap(name: NimNode,
size: int): NimNode {.compileTime.} =
let isize = newIntLitNode(size)
let swapcall = genSwapCall(size)
let STREAM_NAME = getStreamName()
quote do:
var thedata = newString(`isize`)
assert(`STREAM_NAME`.readData(thedata.addr, `isize`) ==
doAssert(`STREAM_NAME`.readData(thedata.addr, `isize`) ==
`isize`,
"Stream has not provided enough data")
`swapcall`(`name`.unsafeAddr, thedata.addr)

proc genSerialize*(name: NimNode, size: NimNode): NimNode =
let STREAM_NAME = getStreamName()
quote do:
`STREAM_NAME`.writeData(`name`.unsafeAddr, `size`)

proc genSerializeSwap(name: NimNode,
size: int): NimNode {.compileTime.} =
let isize = newIntLitNode(size)
let swapcall = genSwapCall(size)
let STREAM_NAME = getStreamName()
quote do:
var thedata = newString(`isize`)
`swapcall`(thedata.addr, `name`.unsafeAddr)
Expand Down
86 changes: 86 additions & 0 deletions nesm/cache.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from typesinfo import Context, initContext, TypeChunk

proc getContext*(): Context {.compileTime.}
proc storeContext*(context: Context) {.compileTime.}

import macrocache
import macros
from tables import `[]`, `[]=`, pairs
const ctxTable = CacheTable("nesm.nesm.context")
const SOURCENAME = "aliassource"
type ContextEntry {.pure.} = enum
size
serialize
deserialize
dynamic
has_hidden
maxcount

proc contains(self: CacheTable, key: string): bool {.compileTime.} =
for k, v in self:
if k == key:
return true
return false

proc storeContext(context: Context) =
let THESOURCENAME = newTree(nnkBracketExpr, newIdentNode(SOURCENAME))
for newfield in context.newfields:
let chunk = context.declared[newfield]
let sizecode = chunk.size(THESOURCENAME)
let serializecode = chunk.serialize(THESOURCENAME)
let deserializecode = chunk.deserialize(THESOURCENAME)
let dynamic = chunk.dynamic.int.newLit()
let has_hidden = chunk.has_hidden.int.newLit()
let maxcount =
if chunk.nodekind == nnkEnumTy:
chunk.maxcount.newLit()
else:
false.newLit()
if newfield notin ctxTable:
when declared(debug):
hint("Adding key: " & newfield)
ctxTable[newfield] = newStmtList()
for i in ContextEntry:
ctxTable[newfield].add(newEmptyNode())
else:
when declared(debug):
hint("Modifying key: " & newfield)
ctxTable[newfield][ContextEntry.size.ord] = newBlockStmt(sizecode)
ctxTable[newfield][ContextEntry.serialize.ord] = newBlockStmt(serializecode)
ctxTable[newfield][ContextEntry.deserialize.ord] = newBlockStmt(deserializecode)
ctxTable[newfield][ContextEntry.dynamic.ord] = dynamic
ctxTable[newfield][ContextEntry.has_hidden.ord] = has_hidden
ctxTable[newfield][ContextEntry.maxcount.ord] = maxcount

proc getContext(): Context =
let THESOURCENAME = newIdentNode(SOURCENAME)
result = initContext()
for k, v in ctxTable:
var tc: TypeChunk
when declared(debug):
hint("Extracting key: " & k)
# >[0]<block "Name"[0]: >[1]<
let sizecode = v[ContextEntry.size.ord][1]
let serializecode = v[ContextEntry.serialize.ord][1]
let deserializecode = v[ContextEntry.deserialize.ord][1]
tc.size = proc(source: NimNode): NimNode =
quote do:
block:
let `THESOURCENAME` = `source`.unsafeAddr
`sizecode`
tc.deserialize = proc(source: NimNode): NimNode =
quote do:
block:
let `THESOURCENAME` = `source`.unsafeAddr
`deserializecode`
tc.serialize = proc(source: NimNode): NimNode =
quote do:
block:
let `THESOURCENAME` = `source`.unsafeAddr
`serializecode`
tc.dynamic = v[ContextEntry.dynamic.ord].intVal.bool
tc.has_hidden = v[ContextEntry.has_hidden.ord].intVal.bool
if v[ContextEntry.maxcount.ord].kind == nnkUInt64Lit:
tc.nodekind = nnkEnumTy
tc.maxcount = cast[uint64](v[ContextEntry.maxcount.ord].intVal)
result.declared[k] = tc
6 changes: 3 additions & 3 deletions nesm/documentation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@
## discard
## assert(4 ==
## thestream.readData(result.weight.unsafeAddr, 4),
## "Stream was not provided enough data")
## "Stream has not provided enough data")
## assert(4 ==
## thestream.readData(result.diameter.unsafeAddr, 4),
## "Stream was not provided enough data")
## "Stream has not provided enough data")
## assert(1 ==
## thestream.readData(result.isHollow.unsafeAddr, 1),
## "Stream was not provided enough data")
## "Stream has not provided enough data")
##
## As you may see from the code above, the macro generates three kinds
## of procedures: serializer, deserializer and size estimator.
Expand Down
10 changes: 4 additions & 6 deletions nesm/enums.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@ proc getCount(declaration: NimNode): uint64 =

proc estimateEnumSize(highest: uint64): int {.compileTime.} =
let maxvalue = ((highest) shr 1).int64
case maxvalue
of 0..int8.high: 1
of (-int8.low)..int16.high: 2
of (-int16.low)..int32.high: 4
of (-int32.low)..int64.high: 8
if maxvalue in 0'i64..int8.high.int64: 1
elif maxvalue in (int8.high.int64+1)..int16.high.int64: 2
elif maxvalue in (int16.high.int64+1)..int32.high.int64: 4
elif maxvalue in (int32.high.int64+1)..int64.high: 8
else: 0


proc genEnum(context: Context, declaration: NimNode): TypeChunk =
let count = getCount(declaration)
let sizeOverrides = len(context.overrides.size)
Expand Down
12 changes: 6 additions & 6 deletions nesm/generator.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ from typesinfo import TypeChunk, Context
proc genTypeChunk*(immutableContext: Context,
thetype: NimNode): TypeChunk {.compileTime.}

static:
let STREAM_NAME* = newIdentNode("thestream")
proc getStreamName*(): NimNode {.compileTime.} =
newIdentNode("thestream")

from tables import Table, contains, `[]`, `[]=`, initTable, pairs
from sequtils import mapIt, foldl, toSeq, filterIt
Expand Down Expand Up @@ -76,9 +76,9 @@ proc genTypeChunk(immutableContext: Context, thetype: NimNode): TypeChunk =
case context.overrides.sizeof.len:
of 0: discard
of 1:
assert(not context.is_static,
doAssert(not context.is_static,
"Sizeof option is not allowed in the static context!")
assert(plaintype[0..2] in ["uin", "int"],
doAssert(plaintype[0..2] in ["uin", "int"],
"The sizeof field must be an integer type!")
let prev_serialize = result.serialize
let capture = context.overrides.sizeof[0]
Expand Down Expand Up @@ -110,7 +110,7 @@ proc genTypeChunk(immutableContext: Context, thetype: NimNode): TypeChunk =
elif thetype.repr == "string":
if context.is_static:
error("Strings are not allowed in static context")
assert(context.overrides.size.len in 0..1, "To many 'size' options")
doAssert(context.overrides.size.len in 0..1, "To many 'size' options")
if context.overrides.size.len > 0:
result = context.handleSizeOption()
else:
Expand Down Expand Up @@ -169,7 +169,7 @@ proc genTypeChunk(immutableContext: Context, thetype: NimNode): TypeChunk =
result = context.genObject(thetype)
of nnkObjectTy:
expectMinLen(thetype, 3)
assert(thetype[1].kind == nnkEmpty,
doAssert(thetype[1].kind == nnkEmpty,
"Inheritence not supported in serializable")
return context.genTypeChunk(thetype[2])
of nnkRefTy:
Expand Down
2 changes: 1 addition & 1 deletion nesm/objects.nim
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ proc genObject(context: Context, thetype: NimNode): TypeChunk =
# problem when accessing to field under case.
let fchunk = newContext.genFields(declaration[0])
result.has_hidden = result.has_hidden or fchunk.has_hidden
assert fchunk.entries.len == 1
doAssert fchunk.entries.len == 1
let name = fchunk.entries[0].name
let chunk = fchunk.entries[0].chunk
elems.add((name, chunk.caseWorkaround()))
Expand Down
Loading

0 comments on commit b28a2e5

Please sign in to comment.