diff options
Diffstat (limited to 'tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim')
-rw-r--r-- | tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim new file mode 100644 index 000000000..d91f1cb35 --- /dev/null +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -0,0 +1,287 @@ +import macros, macro_dsl, estreams +from strutils import format + +template newLenName() = + let lenName {.inject.} = ^("len" & $lenNames) + inc(lenNames) + +template defPacketImports*() {.dirty.} = + import macros, macro_dsl, estreams + from strutils import format + +macro defPacket*(typeNameN: untyped, typeFields: untyped): untyped = + result = newNimNode(nnkStmtList) + let + typeName = quoted2ident(typeNameN) + packetID = ^"p" + streamID = ^"s" + var + constructorParams = newNimNode(nnkFormalParams).und(typeName) + constructor = newNimNode(nnkProcDef).und( + postfix(^("new" & $typeName.ident), "*"), + emptyNode(), + emptyNode(), + constructorParams, + emptyNode(), + emptyNode()) + pack = newNimNode(nnkProcDef).und( + postfix(^"pack", "*"), + emptyNode(), + emptyNode(), + newNimNode(nnkFormalParams).und( + emptyNode(), # : void + newNimNode(nnkIdentDefs).und( + streamID, # s: PBuffer + ^"PBuffer", + newNimNode(nnkNilLit)), + newNimNode(nnkIdentDefs).und( + packetID, # p: var typeName + newNimNode(nnkVarTy).und(typeName), + emptyNode())), + emptyNode(), + emptyNode()) + read = newNimNode(nnkProcDef).und( + newIdentNode("read" & $typeName.ident).postfix("*"), + emptyNode(), + emptyNode(), + newNimNode(nnkFormalParams).und( + typeName, #result type + newNimNode(nnkIdentDefs).und( + streamID, # s: PBuffer = nil + ^"PBuffer", + newNimNode(nnkNilLit))), + emptyNode(), + emptyNode()) + constructorBody = newNimNode(nnkStmtList) + packBody = newNimNode(nnkStmtList) + readBody = newNimNode(nnkStmtList) + lenNames = 0 + for i in 0.. typeFields.len - 1: + let + name = typeFields[i][0] + dotName = packetID.dot(name) + resName = newIdentNode("result").dot(name) + case typeFields[i][1].kind + of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type] + case $typeFields[i][1][0].ident + of "seq": + ## let lenX = readInt16(s) + newLenName() + let + item = ^"item" ## item name in our iterators + seqType = typeFields[i][1][1] ## type of seq + readName = newIdentNode("read" & $seqType.ident) + readBody.add(newNimNode(nnkLetSection).und( + newNimNode(nnkIdentDefs).und( + lenName, + newNimNode(nnkEmpty), + newCall("readInt16", streamID)))) + readBody.add( ## result.name = @[] + resName := ("@".prefix(newNimNode(nnkBracket))), + newNimNode(nnkForStmt).und( ## for item in 1..len: + item, + infix(1.lit, "..", lenName), + newNimNode(nnkStmtList).und( + newCall( ## add(result.name, unpack[seqType](stream)) + "add", resName, newNimNode(nnkCall).und(readName, streamID) + ) ) ) ) + packbody.add( + newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und( + lenName, ## var lenName = int16(len(p.name)) + newIdentNode("int16"), + newCall("int16", newCall("len", dotName)))), + newCall("writeBE", streamID, lenName), + newNimNode(nnkForStmt).und( ## for item in 0..length - 1: pack(p.name[item], stream) + item, + infix(0.lit, "..", infix(lenName, "-", 1.lit)), + newNimNode(nnkStmtList).und( + newCall("echo", item, ": ".lit), + newCall("pack", streamID, dotName[item])))) + #set the default value to @[] (new sequence) + typeFields[i][2] = "@".prefix(newNimNode(nnkBracket)) + else: + error("Unknown type: " & treeRepr(typeFields[i])) + of nnkIdent: ##normal type + case $typeFields[i][1].ident + of "string": # length encoded string + packBody.add(newCall("write", streamID, dotName)) + readBody.add(resName := newCall("readStr", streamID)) + of "int8", "int16", "int32", "float32", "float64", "char", "bool": + packBody.add(newCall( + "writeBE", streamID, dotName)) + readBody.add(resName := newCall("read" & $typeFields[i][1].ident, streamID)) + else: ## hopefully the type you specified was another defpacket() type + packBody.add(newCall("pack", streamID, dotName)) + readBody.add(resName := newCall("read" & $typeFields[i][1].ident, streamID)) + else: + error("I don't know what to do with: " & treerepr(typeFields[i])) + + var + toStringFunc = newNimNode(nnkProcDef).und( + newNimNode(nnkPostfix).und( + ^"*", + newNimNode(nnkAccQuoted).und(^"$")), + emptyNode(), + emptyNode(), + newNimNode(nnkFormalParams).und( + ^"string", + newNimNode(nnkIdentDefs).und( + packetID, # p: typeName + typeName, + emptyNode())), + emptyNode(), + emptyNode(), + newNimNode(nnkStmtList).und(# [6] + newNimNode(nnkAsgn).und( + ^"result", ## result = + newNimNode(nnkCall).und(# [6][0][1] + ^"format", ## format + emptyNode())))) ## "[TypeName $1 $2]" + formatStr = "[" & $typeName.ident + + const emptyFields = {nnkEmpty, nnkNilLit} + var objFields = newNimNode(nnkRecList) + for i in 0 ..< len(typeFields): + let fname = typeFields[i][0] + constructorParams.add(newNimNode(nnkIdentDefs).und( + fname, + typeFields[i][1], + typeFields[i][2])) + constructorBody.add((^"result").dot(fname) := fname) + #export the name + typeFields[i][0] = fname.postfix("*") + if not(typeFields[i][2].kind in emptyFields): + ## empty the type default for the type def + typeFields[i][2] = newNimNode(nnkEmpty) + objFields.add(typeFields[i]) + toStringFunc[6][0][1].add( + prefix("$", packetID.dot(fname))) + formatStr.add " $" + formatStr.add($(i + 1)) + + formatStr.add ']' + toStringFunc[6][0][1][1] = formatStr.lit() + + result.add( + newNimNode(nnkTypeSection).und( + newNimNode(nnkTypeDef).und( + typeName.postfix("*"), + newNimNode(nnkEmpty), + newNimNode(nnkObjectTy).und( + newNimNode(nnkEmpty), #not sure what this is + newNimNode(nnkEmpty), #parent: OfInherit(Ident(!"SomeObj")) + objFields)))) + result.add(constructor.und(constructorBody)) + result.add(pack.und(packBody)) + result.add(read.und(readBody)) + result.add(toStringFunc) + when defined(GenPacketShowOutput): + echo(repr(result)) + +proc newProc*(name: NimNode; params: varargs[NimNode]; resultType: NimNode): NimNode {.compileTime.} = + result = newNimNode(nnkProcDef).und( + name, + emptyNode(), + emptyNode(), + newNimNode(nnkFormalParams).und(resultType), + emptyNode(), + emptyNode(), + newNimNode(nnkStmtList)) + result[3].add(params) + +proc body*(procNode: NimNode): NimNode {.compileTime.} = + assert procNode.kind == nnkProcDef and procNode[6].kind == nnkStmtList + result = procNode[6] + +proc iddefs*(a, b: string; c: NimNode): NimNode {.compileTime.} = + result = newNimNode(nnkIdentDefs).und(^a, ^b, c) +proc iddefs*(a: string; b: NimNode): NimNode {.compileTime.} = + result = newNimNode(nnkIdentDefs).und(^a, b, emptyNode()) +proc varTy*(a: NimNode): NimNode {.compileTime.} = + result = newNimNode(nnkVarTy).und(a) + +macro forwardPacket*(typeName: untyped, underlyingType: untyped): untyped = + var + packetID = ^"p" + streamID = ^"s" + result = newNimNode(nnkStmtList).und( + newProc( + (^("read" & $typeName.ident)).postfix("*"), + [ iddefs("s", "PBuffer", newNimNode(nnkNilLit)) ], + typeName), + newProc( + (^"pack").postfix("*"), + [ iddefs("s", "PBuffer", newNimNode(nnkNilLit)), + iddefs("p", varTy(typeName)) ], + emptyNode())) + var + readBody = result[0][6] + packBody = result[1][6] + resName = ^"result" + + case underlyingType.kind + of nnkBracketExpr: + case $underlyingType[0].ident + of "array": + for i in underlyingType[1][1].intval.int .. underlyingType[1][2].intval.int: + readBody.add( + newCall("read", ^"s", resName[lit(i)])) + packBody.add( + newCall("writeBE", ^"s", packetID[lit(i)])) + else: + echo "Unknown type: ", repr(underlyingtype) + else: + echo "unknown type:", repr(underlyingtype) + echo(repr(result)) + +template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} = + proc `read typeName`*(buffer: PBuffer): typeName = + #discard readData(s, addr result, sizeof(result)) + var res: underlyingType + buffer.read(res) + result = typeName(res) + proc `pack`*(buffer: PBuffer; ord: var typeName) = + #writeData(s, addr p, sizeof(p)) + buffer.write(underlyingType(ord)) + +when false: + type + SomeEnum = enum + A = 0'i8, + B, C + forwardPacket(SomeEnum, int8) + + + defPacket(Foo, tuple[x: array[0..4, int8]]) + var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8]) + var s2 = newStringStream("") + f.pack(s2) + assert s2.data == "\4\3\2\1\0" + + var s = newStringStream() + s.flushImpl = proc(s: PStream) = + var z = PStringStream(s) + z.setPosition(0) + z.data.setLen(0) + + + s.setPosition(0) + s.data.setLen(0) + var o = B + o.pack(s) + o = A + o.pack(s) + o = C + o.pack(s) + assert s.data == "\1\0\2" + s.flush + + defPacket(Y, tuple[z: int8]) + proc `$`(z: Y): string = result = "Y(" & $z.z & ")" + defPacket(TestPkt, tuple[x: seq[Y]]) + var test = newTestPkt() + test.x.add([newY(5), newY(4), newY(3), newY(2), newY(1)]) + for itm in test.x: + echo(itm) + test.pack(s) + echo(repr(s.data)) |