From 830f7683c2123dfa7863b18dd9e02ea6a0d55f20 Mon Sep 17 00:00:00 2001 From: treeform Date: Wed, 3 Aug 2022 18:23:27 -0700 Subject: [PATCH 1/3] progress --- src/genny.nim | 19 +- src/genny/languages/cpp.nim | 453 ++++++++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 src/genny/languages/cpp.nim diff --git a/src/genny.nim b/src/genny.nim index 964ecc0..00cb2a5 100644 --- a/src/genny.nim +++ b/src/genny.nim @@ -1,5 +1,6 @@ -import genny/internal, genny/languages/c, genny/languages/nim, - genny/languages/node, genny/languages/python, macros, strformat +import genny/internal, genny/languages/c, genny/languages/cpp, + genny/languages/nim, genny/languages/node, genny/languages/python, macros, + strformat template discard2(f: untyped): untyped = when(compiles do: discard f): @@ -36,6 +37,7 @@ macro exportConstsTyped(body: typed) = exportConstPy(sym) exportConstNode(sym) exportConstC(sym) + exportConstCpp(sym) template exportConsts*(body: untyped) = ## Exports a list of constants. @@ -58,6 +60,7 @@ macro exportEnumsTyped(body: typed) = exportEnumPy(sym) exportEnumNode(sym) exportEnumC(sym) + exportEnumCpp(sym) template exportEnums*(body: untyped) = ## Exports a list of enums. @@ -114,6 +117,7 @@ proc procTyped( exportProcPy(procSym, owner, prefixes) exportProcNode(procSym, owner, prefixes) exportProcC(procSym, owner, prefixes) + exportProcCpp(procSym, owner, prefixes) macro exportProcsUntyped(body: untyped) = result = newNimNode(nnkStmtList) @@ -124,6 +128,8 @@ macro exportProcsTyped(body: typed) = for entry in body.asStmtList: procTyped(entry) + exportFunctionCpp(procTypedSym(entry)) + template exportProcs*(body: untyped) = ## Exports a list of procs. ## Procs can just be a name `doX` or fully qualified with `doX(int): int`. @@ -173,6 +179,7 @@ macro exportObjectTyped(body: typed) = exportObjectPy(sym, constructor) exportObjectNode(sym, constructor) exportObjectC(sym, constructor) + exportObjectCpp(sym, constructor) if procsBlock[1].len > 0: var procsSeen: seq[string] @@ -191,6 +198,7 @@ macro exportObjectTyped(body: typed) = exportProcPy(procSym, sym, prefixes) exportProcNode(procSym, sym, prefixes) exportProcC(procSym, sym, prefixes) + exportProcCpp(procSym, sym, prefixes) template exportObject*(sym, body: untyped) = ## Exports an object, with these sections: @@ -225,6 +233,7 @@ macro exportSeqTyped(body: typed) = exportSeqPy(sym) exportSeqNode(sym) exportSeqC(sym) + exportSeqCpp(sym) for entry in body.asStmtList()[1 .. ^1]: procTyped(entry, sym) @@ -299,6 +308,7 @@ macro exportRefObjectTyped(body: typed) = exportRefObjectPy(sym, fields, constructor) exportRefObjectNode(sym, fields, constructor) exportRefObjectC(sym, fields, constructor) + exportRefObjectCpp(sym, fields, constructor) if procsBlock[1].len > 0: var procsSeen: seq[string] @@ -317,6 +327,10 @@ macro exportRefObjectTyped(body: typed) = exportProcPy(procSym, sym, prefixes) exportProcNode(procSym, sym, prefixes) exportProcC(procSym, sym, prefixes) + exportProcCpp(procSym, sym, prefixes) + exportMemberCpp(procSym, sym, prefixes) + + exportRefObjectCppDone() template exportRefObject*(sym, body: untyped) = ## Exports a ref object, with these sections: @@ -333,3 +347,4 @@ macro writeFiles*(dir, lib: static[string]) = writePy(dir, lib) writeNode(dir, lib) writeC(dir, lib) + writeCpp(dir, lib) diff --git a/src/genny/languages/cpp.nim b/src/genny/languages/cpp.nim new file mode 100644 index 0000000..e9921bb --- /dev/null +++ b/src/genny/languages/cpp.nim @@ -0,0 +1,453 @@ +import ../common, macros, strformat, strutils + +var + types {.compiletime.}: string + procs {.compiletime.}: string + classes {.compiletime.}: string + members {.compiletime.}: string + +proc unCapitalize(s: string): string = + s[0].toLowerAscii() & s[1 .. ^1] + +proc exportTypeCpp(sym: NimNode): string = + if sym.kind == nnkBracketExpr: + if sym[0].repr == "array": + let + entryCount = sym[1].repr + entryType = exportTypeCpp(sym[2]) + result = &"{entryType}[{entryCount}]" + elif sym[0].repr == "seq": + result = sym.getSeqName() + else: + error(&"Unexpected bracket expression {sym[0].repr}[") + else: + result = + case sym.repr: + of "string": "const char*" + of "bool": "bool" + of "byte": "char" + of "int8": "int8_t" + of "int16": "int16_t" + of "int32": "int32_t" + of "int64": "int64_t" + of "int": "int64_t" + of "uint8": "uint8_t" + of "uint16": "uint16_t" + of "uint32": "uint32_t" + of "uint64": "uint64_t" + of "uint": "uint64_t" + of "float32": "float" + of "float64": "double" + of "float": "double" + of "Rune": "int32_t" + of "Vec2": "Vector2" + of "Mat3": "Matrix3" + of "", "nil": "void" + of "None": "void" + else: + if sym.getType().kind == nnkBracketExpr: + sym.repr + else: + sym.repr + +proc exportTypeCpp(sym: NimNode, name: string): string = + if sym.kind == nnkBracketExpr: + if sym[0].repr == "array": + let + entryCount = sym[1].repr + entryType = exportTypeCpp(sym[2], &"{name}[{entryCount}]") + result = &"{entryType}" + elif sym[0].repr == "seq": + result = sym.getSeqName() & " " & name + else: + error(&"Unexpected bracket expression {sym[0].repr}[") + else: + result = exportTypeCpp(sym) & " " & name + +proc dllProc*(procName: string, args: openarray[string], restype: string) = + var argStr = "" + for arg in args: + argStr.add &"{arg}, " + argStr.removeSuffix ", " + procs.add &"{restype} {procName}({argStr});\n" + procs.add "\n" + +proc dllProc*(procName: string, args: openarray[(NimNode, NimNode)], restype: string) = + var argsConverted: seq[string] + for (argName, argType) in args: + argsConverted.add exportTypeCpp(argType, toSnakeCase(argName.getName())) + dllProc(procName, argsConverted, restype) + +proc dllProc*(procName: string, restype: string) = + var a: seq[(string)] + dllProc(procName, a, restype) + +proc exportConstCpp*(sym: NimNode) = + types.add &"#define {toCapSnakeCase(sym.repr)} {sym.getImpl()[2].repr}\n" + types.add "\n" + +proc exportEnumCpp*(sym: NimNode) = + types.add &"typedef char {sym.repr};\n" + for i, entry in sym.getImpl()[2][1 .. ^1]: + types.add &"#define {toCapSnakeCase(entry.repr)} {i}\n" + types.add "\n" + +proc exportProcCpp*( + sym: NimNode, + owner: NimNode = nil, + prefixes: openarray[NimNode] = [], + standAlone = false +) = + let + procName = sym.repr + procNameSnaked = toSnakeCase(procName) + procType = sym.getTypeInst() + procParams = procType[0][1 .. ^1] + procReturn = procType[0][0] + + var apiProcName = "" + if owner != nil: + apiProcName.add &"{toSnakeCase(owner.getName())}_" + for prefix in prefixes: + apiProcName.add &"{toSnakeCase(prefix.getName())}_" + apiProcName.add &"{procNameSnaked}" + + var defaults: seq[(string, NimNode)] + for identDefs in sym.getImpl()[3][1 .. ^1]: + let default = identDefs[^1] + for entry in identDefs[0 .. ^3]: + defaults.add((entry.repr, default)) + + # let comments = + # if sym.getImpl()[6][0].kind == nnkCommentStmt: + # sym.getImpl()[6][0].repr + # elif sym.getImpl[6].kind == nnkAsgn and + # sym.getImpl[6][1].kind == nnkStmtListExpr and + # sym.getImpl[6][1][0].kind == nnkCommentStmt: + # sym.getImpl[6][1][0].repr + # else: + # "" + # if comments != "": + # let lines = comments.replace("## ", "").split("\n") + # procs.add "/**\n" + # for line in lines: + # procs.add &" * {line}\n" + # procs.add " */\n" + + var dllParams: seq[(NimNode, NimNode)] + for param in procParams: + dllParams.add((param[0], param[1])) + dllProc(&"$lib_{apiProcName}", dllParams, exportTypeCpp(procReturn)) + + +proc exportFunctionCpp*( + sym: NimNode, +) = + let + procName = sym.repr + procNameSnaked = toSnakeCase(procName) + procType = sym.getTypeInst() + procParams = procType[0][1 .. ^1] + procReturn = procType[0][0] + + var apiProcName = procNameSnaked + + if procReturn.kind != nnkEmpty: + members.add exportTypeCpp(procReturn) + members.add " " + members.add procName + members.add "(" + for param in procParams: + members.add exportTypeCpp(param[1], param[0].getName()) + members.add ", " + members.removeSuffix ", " + members.add ") {\n" + members.add " " + if procReturn.kind != nnkEmpty: + members.add "return " + members.add &"$lib_{apiProcName}(" + for param in procParams: + members.add param[0].getName() + members.add ", " + members.removeSuffix ", " + members.add ");\n" + members.add "};\n\n" + + +proc exportMemberCpp*( + sym: NimNode, + owner: NimNode = nil, + prefixes: openarray[NimNode] = [] +) = + let + procName = sym.repr + procNameSnaked = toSnakeCase(procName) + procType = sym.getTypeInst() + procParams = procType[0][1 .. ^1] + procReturn = procType[0][0] + + var apiProcName = "" + if owner != nil: + apiProcName.add &"{toSnakeCase(owner.getName())}_" + for prefix in prefixes: + apiProcName.add &"{toSnakeCase(prefix.getName())}_" + apiProcName.add &"{procNameSnaked}" + + let comments = + if sym.getImpl()[6][0].kind == nnkCommentStmt: + sym.getImpl()[6][0].repr + elif sym.getImpl[6].kind == nnkAsgn and + sym.getImpl[6][1].kind == nnkStmtListExpr and + sym.getImpl[6][1][0].kind == nnkCommentStmt: + sym.getImpl[6][1][0].repr + else: + "" + if comments != "": + let lines = comments.replace("## ", "").split("\n") + classes.add " /**\n" + for line in lines: + classes.add &" * {line}\n" + classes.add " */\n" + + classes.add &" {exportTypeCpp(procReturn)} {procName}(" + for param in procParams[1..^1]: + classes.add exportTypeCpp(param[1], param[0].getName()) + classes.add ", " + classes.removeSuffix ", " + classes.add ");\n\n" + + + + members.add &"{exportTypeCpp(procReturn)} {owner.getName()}::{procName}(" + for param in procParams[1..^1]: + members.add exportTypeCpp(param[1], param[0].getName()) + members.add ", " + members.removeSuffix ", " + members.add ") " + members.add "{\n" + if procReturn.kind == nnkEmpty: + members.add &" " + else: + members.add &" return " + members.add &"$lib_{apiProcName}(" + members.add "*this, " + for param in procParams[1..^1]: + members.add param[0].getName() + members.add ", " + members.removeSuffix ", " + members.add ");\n" + members.add "};\n\n" + + +proc exportObjectCpp*(sym: NimNode, constructor: NimNode) = + let objName = sym.repr + + types.add &"struct {objName} " & "{\n" + for identDefs in sym.getImpl()[2][2]: + for property in identDefs[0 .. ^3]: + types.add &" {exportTypeCpp(identDefs[^2], toSnakeCase(property[1].repr))};\n" + types.add "};\n\n" + + if constructor != nil: + exportProcCpp(constructor) + exportFunctionCpp(constructor) + else: + procs.add &"{objName} $lib_{toSnakeCase(objName)}(" + for identDefs in sym.getImpl()[2][2]: + for property in identDefs[0 .. ^3]: + procs.add &"{exportTypeCpp(identDefs[^2], toSnakeCase(property[1].repr))}, " + procs.removeSuffix ", " + procs.add ");\n\n" + + members.add &"{objName} {objName.unCapitalize()}(" + for identDefs in sym.getImpl()[2][2]: + for property in identDefs[0 .. ^3]: + members.add &"{exportTypeCpp(identDefs[^2], property[1].repr)}" + members.add ", " + members.removeSuffix ", " + members.add ") " + members.add "{\n" + members.add &" return " + members.add &"$lib_{toSnakeCase(objName)}(" + for identDefs in sym.getImpl()[2][2]: + for property in identDefs[0 .. ^3]: + members.add property[1].repr + members.add ", " + members.removeSuffix ", " + members.add ");\n" + members.add "};\n\n" + + + dllProc(&"$lib_{toSnakeCase(objName)}_eq", [&"{objName} a", &"{objName} b"], "char") + +proc genRefObject(objName: string) = + + types.add &"struct {objName};\n\n" + + # types.add &"typedef uint64_t {objName};\n\n" + + # types.add &"struct {objName} {{ uint64_t ref; }};\n\n" + + let unrefLibProc = &"$lib_{toSnakeCase(objName)}_unref" + + dllProc(unrefLibProc, [objName & " " & toSnakeCase(objName)], "void") + +proc genSeqProcs(objName, procPrefix, selfSuffix: string, entryType: NimNode) = + let objArg = objName & " " & toSnakeCase(objName) + dllProc(&"{procPrefix}_len", [objArg], "int64_t") + dllProc(&"{procPrefix}_get", [objArg, "int64_t index"], exportTypeCpp(entryType)) + dllProc(&"{procPrefix}_set", [objArg, "int64_t index", exportTypeCpp(entryType, "value")], "void") + dllProc(&"{procPrefix}_delete", [objArg, "int64_t index"], "void") + dllProc(&"{procPrefix}_add", [objArg, exportTypeCpp(entryType, "value")], "void") + dllProc(&"{procPrefix}_clear", [objArg], "void") + +proc exportRefObjectCpp*( + sym: NimNode, + fields: seq[(string, NimNode)], + constructor: NimNode +) = + let + objName = sym.repr + objNameSnaked = toSnakeCase(objName) + objType = sym.getType()[1].getType() + + genRefObject(objName) + + classes.add &"struct {objName} " & "{\n\n" + classes.add &" private:\n\n" + classes.add &" uint64_t reference;\n\n" + classes.add &" public:\n\n" + + if constructor != nil: + let + constructorLibProc = &"$lib_{toSnakeCase(constructor.repr)}" + constructorType = constructor.getTypeInst() + constructorParams = constructorType[0][1 .. ^1] + constructorRaises = constructor.raises() + + classes.add &" {objName}(" + for param in constructorParams: + classes.add exportTypeCpp(param[1], param[0].getName()) + classes.add ", " + classes.removeSuffix ", " + classes.add ");\n\n" + + members.add &"{objName}::{objName}(" + for param in constructorParams: + members.add exportTypeCpp(param[1], param[0].getName()) + members.add ", " + members.removeSuffix ", " + members.add ")" + members.add " {\n" + members.add &" this->reference = " + members.add &"{constructorLibProc}(" + for param in constructorParams: + members.add param[0].getName() + members.add ", " + members.removeSuffix ", " + members.add ").reference;\n" + members.add "}\n\n" + + var dllParams: seq[(NimNode, NimNode)] + for param in constructorParams: + dllParams.add((param[0], param[1])) + dllProc(constructorLibProc, dllParams, objName) + + for (fieldName, fieldType) in fields: + let fieldNameSnaked = toSnakeCase(fieldName) + + if fieldType.kind != nnkBracketExpr: + let getProcName = &"$lib_{objNameSnaked}_get_{fieldNameSnaked}" + let setProcName = &"$lib_{objNameSnaked}_set_{fieldNameSnaked}" + + let getMemberName = &"get{fieldName.capitalizeAscii}" + let setMemberName = &"set{fieldName.capitalizeAscii}" + + dllProc(getProcName, [objName & " " & objNameSnaked], exportTypeCpp(fieldType)) + dllProc(setProcName, [objName & " " & objNameSnaked, exportTypeCpp(fieldType, "value")], exportTypeCpp(nil)) + + classes.add &" {exportTypeCpp(fieldType)} {getMemberName}();\n" + + members.add &"{exportTypeCpp(fieldType)} {objName}::{getMemberName}()" & "{\n" + members.add &" return {getProcName}(*this);\n" + members.add "}\n\n" + + classes.add &" void {setMemberName}({exportTypeCpp(fieldType)} value);\n" + + members.add &"void {objName}::{setMemberName}({exportTypeCpp(fieldType)} value)" & "{\n" + members.add &" {setProcName}(*this, value);\n" + members.add "}\n\n" + + # classes.add &" __declspec(property(get={getMemberName},put={setMemberName})) {exportTypeCpp(fieldType)} {fieldName};\n\n" + + else: + var helperName = fieldName + helperName[0] = toUpperAscii(helperName[0]) + let helperClassName = objName & helperName + + genSeqProcs( + objName, + &"$lib_{objNameSnaked}_{fieldNameSnaked}", + &".{toSnakeCase(objName)}", + fieldType[1] + ) + + # classes.add &" ~{objName}();\n\n" + + # members.add &"{objName}::~{objName}()" & "{\n" + # members.add &" // $lib_{toSnakeCase(objName)}_unref(*this);\n" + # members.add "}\n\n" + + classes.add &" free();\n\n" + + members.add &"{objName}::free()" & "{\n" + members.add &" $lib_{toSnakeCase(objName)}_unref(*this);\n" + members.add "}\n\n" + +proc exportRefObjectCppDone*() = + + classes.add "};\n\n" + +proc exportSeqCpp*(sym: NimNode) = + let + seqName = sym.getName() + seqNameSnaked = toSnakeCase(seqName) + + genRefObject(seqName) + + let newSeqProc = &"$lib_new_{toSnakeCase(seqName)}" + + dllProc(newSeqProc, seqName) + + genSeqProcs( + sym.getName(), + &"$lib_{seqNameSnaked}", + "", + sym[1] + ) + + classes.add &"struct {seqName} " & "{\n\n" + classes.add &" private:\n\n" + classes.add &" uint64_t reference;\n\n" + classes.add &" public:\n\n" + # classes.add &" ~{seqName}()" & "{\n" + # classes.add &" $lib_{seqNameSnaked}_unref(*this);\n" + # classes.add " }\n\n" + classes.add "};\n\n" + +const header = """ +#ifndef INCLUDE_$LIB_H +#define INCLUDE_$LIB_H + +#include + +""" + +const footer = """ +#endif +""" + +proc writeCpp*(dir, lib: string) = + writeFile(&"{dir}/{toSnakeCase(lib)}.hpp", (header & types & classes & "extern \"C\" {\n\n" & procs & "}\n\n" & members & footer) + .replace("$lib", toSnakeCase(lib)).replace("$LIB", lib.toUpperAscii()) + ) From 58610855640d053b8bf677636e4e226ff5376f9d Mon Sep 17 00:00:00 2001 From: treeform Date: Wed, 3 Aug 2022 18:40:30 -0700 Subject: [PATCH 2/3] Better exportProcCpp --- src/genny.nim | 9 +- src/genny/languages/cpp.nim | 208 ++++++++++++++---------------------- 2 files changed, 86 insertions(+), 131 deletions(-) diff --git a/src/genny.nim b/src/genny.nim index 00cb2a5..4d473e5 100644 --- a/src/genny.nim +++ b/src/genny.nim @@ -128,8 +128,6 @@ macro exportProcsTyped(body: typed) = for entry in body.asStmtList: procTyped(entry) - exportFunctionCpp(procTypedSym(entry)) - template exportProcs*(body: untyped) = ## Exports a list of procs. ## Procs can just be a name `doX` or fully qualified with `doX(int): int`. @@ -200,6 +198,8 @@ macro exportObjectTyped(body: typed) = exportProcC(procSym, sym, prefixes) exportProcCpp(procSym, sym, prefixes) + exportCloseObjectCpp() + template exportObject*(sym, body: untyped) = ## Exports an object, with these sections: ## * fields @@ -238,6 +238,8 @@ macro exportSeqTyped(body: typed) = for entry in body.asStmtList()[1 .. ^1]: procTyped(entry, sym) + exportCloseObjectCpp() + template exportSeq*(sym, body: untyped) = ## Exports a regular sequence. ## * procs section @@ -328,9 +330,8 @@ macro exportRefObjectTyped(body: typed) = exportProcNode(procSym, sym, prefixes) exportProcC(procSym, sym, prefixes) exportProcCpp(procSym, sym, prefixes) - exportMemberCpp(procSym, sym, prefixes) - exportRefObjectCppDone() + exportCloseObjectCpp() template exportRefObject*(sym, body: untyped) = ## Exports a ref object, with these sections: diff --git a/src/genny/languages/cpp.nim b/src/genny/languages/cpp.nim index e9921bb..b8f1955 100644 --- a/src/genny/languages/cpp.nim +++ b/src/genny/languages/cpp.nim @@ -95,8 +95,7 @@ proc exportEnumCpp*(sym: NimNode) = proc exportProcCpp*( sym: NimNode, owner: NimNode = nil, - prefixes: openarray[NimNode] = [], - standAlone = false + prefixes: openarray[NimNode] = [] ) = let procName = sym.repr @@ -118,139 +117,91 @@ proc exportProcCpp*( for entry in identDefs[0 .. ^3]: defaults.add((entry.repr, default)) - # let comments = - # if sym.getImpl()[6][0].kind == nnkCommentStmt: - # sym.getImpl()[6][0].repr - # elif sym.getImpl[6].kind == nnkAsgn and - # sym.getImpl[6][1].kind == nnkStmtListExpr and - # sym.getImpl[6][1][0].kind == nnkCommentStmt: - # sym.getImpl[6][1][0].repr - # else: - # "" - # if comments != "": - # let lines = comments.replace("## ", "").split("\n") - # procs.add "/**\n" - # for line in lines: - # procs.add &" * {line}\n" - # procs.add " */\n" - var dllParams: seq[(NimNode, NimNode)] for param in procParams: dllParams.add((param[0], param[1])) dllProc(&"$lib_{apiProcName}", dllParams, exportTypeCpp(procReturn)) + if owner == nil: -proc exportFunctionCpp*( - sym: NimNode, -) = - let - procName = sym.repr - procNameSnaked = toSnakeCase(procName) - procType = sym.getTypeInst() - procParams = procType[0][1 .. ^1] - procReturn = procType[0][0] - - var apiProcName = procNameSnaked - - if procReturn.kind != nnkEmpty: - members.add exportTypeCpp(procReturn) - members.add " " - members.add procName - members.add "(" - for param in procParams: - members.add exportTypeCpp(param[1], param[0].getName()) - members.add ", " - members.removeSuffix ", " - members.add ") {\n" - members.add " " - if procReturn.kind != nnkEmpty: - members.add "return " - members.add &"$lib_{apiProcName}(" - for param in procParams: - members.add param[0].getName() - members.add ", " - members.removeSuffix ", " - members.add ");\n" - members.add "};\n\n" - - -proc exportMemberCpp*( - sym: NimNode, - owner: NimNode = nil, - prefixes: openarray[NimNode] = [] -) = - let - procName = sym.repr - procNameSnaked = toSnakeCase(procName) - procType = sym.getTypeInst() - procParams = procType[0][1 .. ^1] - procReturn = procType[0][0] - - var apiProcName = "" - if owner != nil: - apiProcName.add &"{toSnakeCase(owner.getName())}_" - for prefix in prefixes: - apiProcName.add &"{toSnakeCase(prefix.getName())}_" - apiProcName.add &"{procNameSnaked}" + if procReturn.kind != nnkEmpty: + members.add exportTypeCpp(procReturn) + members.add " " + members.add procName + members.add "(" + for param in procParams: + members.add exportTypeCpp(param[1], param[0].getName()) + members.add ", " + members.removeSuffix ", " + members.add ") {\n" + members.add " " + if procReturn.kind != nnkEmpty: + members.add "return " + members.add &"$lib_{apiProcName}(" + for param in procParams: + members.add param[0].getName() + members.add ", " + members.removeSuffix ", " + members.add ");\n" + members.add "};\n\n" - let comments = - if sym.getImpl()[6][0].kind == nnkCommentStmt: - sym.getImpl()[6][0].repr - elif sym.getImpl[6].kind == nnkAsgn and - sym.getImpl[6][1].kind == nnkStmtListExpr and - sym.getImpl[6][1][0].kind == nnkCommentStmt: - sym.getImpl[6][1][0].repr - else: - "" - if comments != "": - let lines = comments.replace("## ", "").split("\n") - classes.add " /**\n" - for line in lines: - classes.add &" * {line}\n" - classes.add " */\n" - - classes.add &" {exportTypeCpp(procReturn)} {procName}(" - for param in procParams[1..^1]: - classes.add exportTypeCpp(param[1], param[0].getName()) - classes.add ", " - classes.removeSuffix ", " - classes.add ");\n\n" - - - - members.add &"{exportTypeCpp(procReturn)} {owner.getName()}::{procName}(" - for param in procParams[1..^1]: - members.add exportTypeCpp(param[1], param[0].getName()) - members.add ", " - members.removeSuffix ", " - members.add ") " - members.add "{\n" - if procReturn.kind == nnkEmpty: - members.add &" " else: - members.add &" return " - members.add &"$lib_{apiProcName}(" - members.add "*this, " - for param in procParams[1..^1]: - members.add param[0].getName() - members.add ", " - members.removeSuffix ", " - members.add ");\n" - members.add "};\n\n" - + let comments = + if sym.getImpl()[6][0].kind == nnkCommentStmt: + sym.getImpl()[6][0].repr + elif sym.getImpl[6].kind == nnkAsgn and + sym.getImpl[6][1].kind == nnkStmtListExpr and + sym.getImpl[6][1][0].kind == nnkCommentStmt: + sym.getImpl[6][1][0].repr + else: + "" + if comments != "": + let lines = comments.replace("## ", "").split("\n") + classes.add " /**\n" + for line in lines: + classes.add &" * {line}\n" + classes.add " */\n" + + classes.add &" {exportTypeCpp(procReturn)} {procName}(" + for param in procParams[1..^1]: + classes.add exportTypeCpp(param[1], param[0].getName()) + classes.add ", " + classes.removeSuffix ", " + classes.add ");\n\n" + + members.add &"{exportTypeCpp(procReturn)} {owner.getName()}::{procName}(" + for param in procParams[1..^1]: + members.add exportTypeCpp(param[1], param[0].getName()) + members.add ", " + members.removeSuffix ", " + members.add ") " + members.add "{\n" + if procReturn.kind == nnkEmpty: + members.add &" " + else: + members.add &" return " + members.add &"$lib_{apiProcName}(" + members.add "*this, " + for param in procParams[1..^1]: + members.add param[0].getName() + members.add ", " + members.removeSuffix ", " + members.add ");\n" + members.add "};\n\n" proc exportObjectCpp*(sym: NimNode, constructor: NimNode) = let objName = sym.repr - types.add &"struct {objName} " & "{\n" + types.add &"struct {objName};\n\n" + + classes.add &"struct {objName} " & "{\n" for identDefs in sym.getImpl()[2][2]: for property in identDefs[0 .. ^3]: - types.add &" {exportTypeCpp(identDefs[^2], toSnakeCase(property[1].repr))};\n" - types.add "};\n\n" + classes.add &" {exportTypeCpp(identDefs[^2], toSnakeCase(property[1].repr))};\n" if constructor != nil: exportProcCpp(constructor) - exportFunctionCpp(constructor) + #exportFunctionCpp(constructor) else: procs.add &"{objName} $lib_{toSnakeCase(objName)}(" for identDefs in sym.getImpl()[2][2]: @@ -277,9 +228,9 @@ proc exportObjectCpp*(sym: NimNode, constructor: NimNode) = members.add ");\n" members.add "};\n\n" - dllProc(&"$lib_{toSnakeCase(objName)}_eq", [&"{objName} a", &"{objName} b"], "char") + proc genRefObject(objName: string) = types.add &"struct {objName};\n\n" @@ -372,7 +323,7 @@ proc exportRefObjectCpp*( members.add &" return {getProcName}(*this);\n" members.add "}\n\n" - classes.add &" void {setMemberName}({exportTypeCpp(fieldType)} value);\n" + classes.add &" void {setMemberName}({exportTypeCpp(fieldType)} value);\n\n" members.add &"void {objName}::{setMemberName}({exportTypeCpp(fieldType)} value)" & "{\n" members.add &" {setProcName}(*this, value);\n" @@ -398,13 +349,13 @@ proc exportRefObjectCpp*( # members.add &" // $lib_{toSnakeCase(objName)}_unref(*this);\n" # members.add "}\n\n" - classes.add &" free();\n\n" + classes.add &" void free();\n\n" - members.add &"{objName}::free()" & "{\n" + members.add &"void {objName}::free()" & "{\n" members.add &" $lib_{toSnakeCase(objName)}_unref(*this);\n" members.add "}\n\n" -proc exportRefObjectCppDone*() = +proc exportCloseObjectCpp*() = classes.add "};\n\n" @@ -430,10 +381,13 @@ proc exportSeqCpp*(sym: NimNode) = classes.add &" private:\n\n" classes.add &" uint64_t reference;\n\n" classes.add &" public:\n\n" - # classes.add &" ~{seqName}()" & "{\n" - # classes.add &" $lib_{seqNameSnaked}_unref(*this);\n" - # classes.add " }\n\n" - classes.add "};\n\n" + + classes.add &" void free();\n\n" + + members.add &"void {seqName}::free()" & "{\n" + members.add &" $lib_{toSnakeCase(seqName)}_unref(*this);\n" + members.add "}\n\n" + const header = """ #ifndef INCLUDE_$LIB_H From 8ebef6d380dcf6a1cafa2d84f0dfdaac4214a2cf Mon Sep 17 00:00:00 2001 From: treeform Date: Wed, 3 Aug 2022 20:55:33 -0700 Subject: [PATCH 3/3] f --- src/genny/languages/cpp.nim | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/genny/languages/cpp.nim b/src/genny/languages/cpp.nim index b8f1955..b06fe78 100644 --- a/src/genny/languages/cpp.nim +++ b/src/genny/languages/cpp.nim @@ -123,7 +123,6 @@ proc exportProcCpp*( dllProc(&"$lib_{apiProcName}", dllParams, exportTypeCpp(procReturn)) if owner == nil: - if procReturn.kind != nnkEmpty: members.add exportTypeCpp(procReturn) members.add " " @@ -201,7 +200,6 @@ proc exportObjectCpp*(sym: NimNode, constructor: NimNode) = if constructor != nil: exportProcCpp(constructor) - #exportFunctionCpp(constructor) else: procs.add &"{objName} $lib_{toSnakeCase(objName)}(" for identDefs in sym.getImpl()[2][2]: @@ -230,15 +228,10 @@ proc exportObjectCpp*(sym: NimNode, constructor: NimNode) = dllProc(&"$lib_{toSnakeCase(objName)}_eq", [&"{objName} a", &"{objName} b"], "char") - proc genRefObject(objName: string) = types.add &"struct {objName};\n\n" - # types.add &"typedef uint64_t {objName};\n\n" - - # types.add &"struct {objName} {{ uint64_t ref; }};\n\n" - let unrefLibProc = &"$lib_{toSnakeCase(objName)}_unref" dllProc(unrefLibProc, [objName & " " & toSnakeCase(objName)], "void") @@ -329,6 +322,7 @@ proc exportRefObjectCpp*( members.add &" {setProcName}(*this, value);\n" members.add "}\n\n" + # TODO: property # classes.add &" __declspec(property(get={getMemberName},put={setMemberName})) {exportTypeCpp(fieldType)} {fieldName};\n\n" else: @@ -343,6 +337,7 @@ proc exportRefObjectCpp*( fieldType[1] ) + # TODO: ref/unref # classes.add &" ~{objName}();\n\n" # members.add &"{objName}::~{objName}()" & "{\n" @@ -402,6 +397,14 @@ const footer = """ """ proc writeCpp*(dir, lib: string) = - writeFile(&"{dir}/{toSnakeCase(lib)}.hpp", (header & types & classes & "extern \"C\" {\n\n" & procs & "}\n\n" & members & footer) - .replace("$lib", toSnakeCase(lib)).replace("$LIB", lib.toUpperAscii()) + writeFile(&"{dir}/{toSnakeCase(lib)}.hpp", ( + header & + types & + classes & + "extern \"C\" {\n\n" & + procs & + "}\n\n" & + members & + footer + ).replace("$lib", toSnakeCase(lib)).replace("$LIB", lib.toUpperAscii()) )