Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions src/genny/internal.nim
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ proc exportProcInternal*(
internal.removeSuffix ", "
internal.add ")"
if procReturn.kind != nnkEmpty:
internal.add &": {exportTypeNim(procReturn)}"
internal.add &": {exportReturnTypeNim(procReturn)}"
internal.add &" {exportProcPragmas} =\n"
if procRaises:
internal.add " try:\n "
Expand All @@ -68,7 +68,7 @@ proc exportProcInternal*(
if procReturnsSeq:
internal.add &"{procReturn.getSeqName()}(s: {callExpr})"
elif procReturn.kind != nnkEmpty:
internal.add convertExportExprNim(callExpr, procReturn)
internal.add convertExportReturnExprNim(callExpr, procReturn)
else:
internal.add callExpr
if procRaises:
Expand Down Expand Up @@ -155,10 +155,10 @@ proc exportRefObjectInternal*(
if fieldType.kind != nnkBracketExpr:
internal.add "proc "
internal.add &"$lib_{objNameSnaked}_get_{fieldNameSnaked}*"
internal.add &"({objNameSnaked}: {objName}): {exportTypeNim(fieldType)}"
internal.add &"({objNameSnaked}: {objName}): {exportReturnTypeNim(fieldType)}"
internal.add &" {exportProcPragmas} =\n"
internal.add " "
internal.add convertExportExprNim(&"{objNameSnaked}.{fieldName}", fieldType)
internal.add convertExportReturnExprNim(&"{objNameSnaked}.{fieldName}", fieldType)
internal.add "\n"
internal.add "\n"

Expand Down Expand Up @@ -186,10 +186,10 @@ proc exportRefObjectInternal*(
internal.add ")\n"
internal.add "\n"

internal.add &"proc {prefix}_get*({objNameSnaked}: {objName}, i: int): {exportTypeNim(fieldType[1])}"
internal.add &"proc {prefix}_get*({objNameSnaked}: {objName}, i: int): {exportReturnTypeNim(fieldType[1])}"
internal.add &" {exportProcPragmas} =\n"
internal.add " "
internal.add convertExportExprNim(&"{objNameSnaked}.{fieldName}[i]", fieldType[1])
internal.add convertExportReturnExprNim(&"{objNameSnaked}.{fieldName}[i]", fieldType[1])
internal.add "\n"
internal.add "\n"

Expand Down Expand Up @@ -240,11 +240,11 @@ proc generateSeqs(sym: NimNode) =
internal.add ")\n"
internal.add "\n"

internal.add &"proc $lib_{seqNameSnaked}_get*(s: {seqName}, i: int): {exportTypeNim(sym[1])}"
internal.add &"proc $lib_{seqNameSnaked}_get*(s: {seqName}, i: int): {exportReturnTypeNim(sym[1])}"
internal.add &" {exportProcPragmas}"
internal.add " =\n"
internal.add " "
internal.add convertExportExprNim("s.s[i]", sym[1])
internal.add convertExportReturnExprNim("s.s[i]", sym[1])
internal.add "\n"
internal.add "\n"

Expand Down Expand Up @@ -283,11 +283,32 @@ when not defined(gcArc) and not defined(gcOrc):

when (NimMajor, NimMinor, NimPatch) == (1, 6, 2):
{.error: "Nim 1.6.2 not supported with Genny due to FFI issues.".}

type GennyBuffer* = ref object
data: string

proc newGennyBuffer*(data: string): GennyBuffer =
result = GennyBuffer(data: data)
GC_ref(result)

proc $lib_genny_buffer_data*(buffer: GennyBuffer): cstring {.raises: [], cdecl, exportc, dynlib.} =
if buffer == nil:
return nil
buffer.data.cstring

proc $lib_genny_buffer_len*(buffer: GennyBuffer): int {.raises: [], cdecl, exportc, dynlib.} =
if buffer == nil:
return 0
buffer.data.len

proc $lib_genny_buffer_unref*(buffer: GennyBuffer) {.raises: [], cdecl, exportc, dynlib.} =
if buffer != nil:
GC_unref(buffer)
"""

proc writeInternal*(dir, lib: string) =
createDir(dir)
writeFile(
&"{dir}/internal.nim",
header & internal.replace("$Lib", lib).replace("$lib", toSnakeCase(lib))
(header & internal).replace("$Lib", lib).replace("$lib", toSnakeCase(lib))
)
23 changes: 19 additions & 4 deletions src/genny/languages/c.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ proc exportTypeC(sym: NimNode): string =
else:
typ.repr

proc exportReturnTypeC(sym: NimNode): string =
let typ = sym.stripSink
if typ.repr == "string":
"GennyBuffer"
else:
exportTypeC(typ)

proc exportTypeC(sym: NimNode, name: string): string =
let typ = sym.stripSink
if typ.kind == nnkBracketExpr:
Expand Down Expand Up @@ -142,7 +149,7 @@ proc exportProcC*(
var dllParams: seq[(NimNode, NimNode)]
for param in procParams:
dllParams.add((param[0], param[1]))
dllProc(&"$lib_{apiProcName}", dllParams, exportTypeC(procReturn))
dllProc(&"$lib_{apiProcName}", dllParams, exportReturnTypeC(procReturn))

proc exportObjectC*(sym: NimNode, constructor: NimNode) =
let objName = sym.repr
Expand Down Expand Up @@ -175,7 +182,7 @@ proc genRefObject(objName: string) =
proc genSeqProcs(objName, procPrefix, selfSuffix: string, entryType: NimNode) =
let objArg = objName & " " & toSnakeCase(objName)
dllProc(&"{procPrefix}_len", [objArg], "intptr_t")
dllProc(&"{procPrefix}_get", [objArg, "intptr_t index"], exportTypeC(entryType))
dllProc(&"{procPrefix}_get", [objArg, "intptr_t index"], exportReturnTypeC(entryType))
dllProc(&"{procPrefix}_set", [objArg, "intptr_t index", exportTypeC(entryType, "value")], "void")
dllProc(&"{procPrefix}_delete", [objArg, "intptr_t index"], "void")
dllProc(&"{procPrefix}_add", [objArg, exportTypeC(entryType, "value")], "void")
Expand Down Expand Up @@ -213,7 +220,7 @@ proc exportRefObjectC*(

let setProcName = &"$lib_{objNameSnaked}_set_{fieldNameSnaked}"

dllProc(getProcName, [objName & " " & objNameSnaked], exportTypeC(fieldType))
dllProc(getProcName, [objName & " " & objNameSnaked], exportReturnTypeC(fieldType))
dllProc(setProcName, [objName & " " & objNameSnaked, exportTypeC(fieldType, "value")], exportTypeC(nil))
else:
var helperName = fieldName
Expand Down Expand Up @@ -251,6 +258,14 @@ const header = """

#include <stdint.h>

typedef struct GennyBufferHandle* GennyBuffer;

"""

const bufferProcs = """
const char* $lib_genny_buffer_data(GennyBuffer buffer);
intptr_t $lib_genny_buffer_len(GennyBuffer buffer);
void $lib_genny_buffer_unref(GennyBuffer buffer);
"""

const externCStart = """
Expand All @@ -273,6 +288,6 @@ const footer = """

proc writeC*(dir, lib: string) =
createDir(dir)
writeFile(&"{dir}/{toSnakeCase(lib)}.h", (header & types & externCStart & procs & externCEnd & footer)
writeFile(&"{dir}/{toSnakeCase(lib)}.h", (header & types & externCStart & bufferProcs & procs & externCEnd & footer)
.replace("$lib", toSnakeCase(lib)).replace("$LIB", lib.toUpperAscii())
)
104 changes: 89 additions & 15 deletions src/genny/languages/cpp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ proc isSeqLike(sym: NimNode): bool =
proc isRuneType(sym: NimNode): bool =
sym.stripSink.repr == "Rune"

proc isStringType(sym: NimNode): bool =
sym.stripSink.repr == "string"

proc exportTypeCpp(sym: NimNode, abi = false): string =
let typ = sym.stripSink
if typ.kind == nnkBracketExpr:
Expand Down Expand Up @@ -70,6 +73,18 @@ proc exportTypeCpp(sym: NimNode, abi = false): string =
proc exportTypeCppAbi(sym: NimNode): string =
exportTypeCpp(sym, abi = true)

proc exportReturnTypeCpp(sym: NimNode): string =
if sym.isStringType:
"std::string"
else:
exportTypeCpp(sym)

proc exportReturnTypeCppAbi(sym: NimNode): string =
if sym.isStringType:
"GennyBuffer"
else:
exportTypeCppAbi(sym)

proc exportTypeCpp(sym: NimNode, name: string, abi = false): string =
let typ = sym.stripSink
if typ.kind == nnkBracketExpr:
Expand All @@ -95,7 +110,9 @@ proc cppArgValue(argType: NimNode, argName: string): string =
argName

proc cppReturnValue(returnType: NimNode, call: string): string =
if returnType.isRuneType:
if returnType.isStringType:
&"gennyBufferToString({call})"
elif returnType.isRuneType:
&"static_cast<char32_t>({call})"
else:
call
Expand Down Expand Up @@ -156,11 +173,11 @@ proc exportProcCpp*(
var dllParams: seq[(NimNode, NimNode)]
for param in procParams:
dllParams.add((param[0], param[1]))
dllProc(&"$lib_{apiProcName}", dllParams, exportTypeCppAbi(procReturn))
dllProc(&"$lib_{apiProcName}", dllParams, exportReturnTypeCppAbi(procReturn))

if owner == nil:
if procReturn.kind != nnkEmpty:
members.add exportTypeCpp(procReturn)
members.add exportReturnTypeCpp(procReturn)
members.add " "
members.add procName
members.add "("
Expand Down Expand Up @@ -199,14 +216,14 @@ proc exportProcCpp*(
classes.add &" * {line}\n"
classes.add " */\n"

classes.add &" {exportTypeCpp(procReturn)} {procName}("
classes.add &" {exportReturnTypeCpp(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}("
members.add &"{exportReturnTypeCpp(procReturn)} {owner.getName()}::{procName}("
for param in procParams[1..^1]:
members.add exportTypeCpp(param[1], param[0].getName())
members.add ", "
Expand Down Expand Up @@ -278,7 +295,7 @@ proc genRefObject(objName: string) =
proc genSeqProcs(objName, procPrefix, selfSuffix: string, entryType: NimNode) =
let objArg = objName & " " & toSnakeCase(objName)
dllProc(&"{procPrefix}_len", [objArg], "std::intptr_t")
dllProc(&"{procPrefix}_get", [objArg, "std::intptr_t index"], exportTypeCppAbi(entryType))
dllProc(&"{procPrefix}_get", [objArg, "std::intptr_t index"], exportReturnTypeCppAbi(entryType))
dllProc(&"{procPrefix}_set", [objArg, "std::intptr_t index", exportTypeCppAbi(entryType, "value")], "void")
dllProc(&"{procPrefix}_delete", [objArg, "std::intptr_t index"], "void")
dllProc(&"{procPrefix}_add", [objArg, exportTypeCppAbi(entryType, "value")], "void")
Expand All @@ -287,12 +304,13 @@ proc genSeqProcs(objName, procPrefix, selfSuffix: string, entryType: NimNode) =
proc genSeqClassMethods(seqName, procPrefix: string, entryType: NimNode) =
let
entryTypeCpp = exportTypeCpp(entryType)
entryReturnTypeCpp = exportReturnTypeCpp(entryType)
entryValue = cppArgValue(entryType, "value")
getCall = &"{procPrefix}_get(*this, index)"

classes.add &" std::intptr_t size();\n"
classes.add &" {entryTypeCpp} get(std::intptr_t index);\n"
classes.add &" {entryTypeCpp} operator[](std::intptr_t index);\n"
classes.add &" {entryReturnTypeCpp} get(std::intptr_t index);\n"
classes.add &" {entryReturnTypeCpp} operator[](std::intptr_t index);\n"
classes.add &" void set(std::intptr_t index, {entryTypeCpp} value);\n"
classes.add &" void removeAt(std::intptr_t index);\n"
classes.add &" void add({entryTypeCpp} value);\n"
Expand All @@ -302,11 +320,11 @@ proc genSeqClassMethods(seqName, procPrefix: string, entryType: NimNode) =
members.add &" return {procPrefix}_len(*this);\n"
members.add "}\n\n"

members.add &"{entryTypeCpp} {seqName}::get(std::intptr_t index)" & "{\n"
members.add &"{entryReturnTypeCpp} {seqName}::get(std::intptr_t index)" & "{\n"
members.add &" return {cppReturnValue(entryType, getCall)};\n"
members.add "}\n\n"

members.add &"{entryTypeCpp} {seqName}::operator[](std::intptr_t index)" & "{\n"
members.add &"{entryReturnTypeCpp} {seqName}::operator[](std::intptr_t index)" & "{\n"
members.add &" return get(index);\n"
members.add "}\n\n"

Expand All @@ -332,11 +350,12 @@ proc genSeqFieldMethods(objName, procPrefix, fieldName: string, entryType: NimNo

let
entryTypeCpp = exportTypeCpp(entryType)
entryReturnTypeCpp = exportReturnTypeCpp(entryType)
entryValue = cppArgValue(entryType, "value")
getCall = &"{procPrefix}_get(*this, index)"

classes.add &" std::intptr_t {fieldName}Size();\n"
classes.add &" {entryTypeCpp} get{fieldCap}(std::intptr_t index);\n"
classes.add &" {entryReturnTypeCpp} get{fieldCap}(std::intptr_t index);\n"
classes.add &" void set{fieldCap}(std::intptr_t index, {entryTypeCpp} value);\n"
classes.add &" void remove{fieldCap}(std::intptr_t index);\n"
classes.add &" void add{fieldCap}({entryTypeCpp} value);\n"
Expand All @@ -346,7 +365,7 @@ proc genSeqFieldMethods(objName, procPrefix, fieldName: string, entryType: NimNo
members.add &" return {procPrefix}_len(*this);\n"
members.add "}\n\n"

members.add &"{entryTypeCpp} {objName}::get{fieldCap}(std::intptr_t index)" & "{\n"
members.add &"{entryReturnTypeCpp} {objName}::get{fieldCap}(std::intptr_t index)" & "{\n"
members.add &" return {cppReturnValue(entryType, getCall)};\n"
members.add "}\n\n"

Expand Down Expand Up @@ -428,12 +447,12 @@ proc exportRefObjectCpp*(
let getMemberName = &"get{fieldName.capitalizeAscii}"
let setMemberName = &"set{fieldName.capitalizeAscii}"

dllProc(getProcName, [objName & " " & objNameSnaked], exportTypeCppAbi(fieldType))
dllProc(getProcName, [objName & " " & objNameSnaked], exportReturnTypeCppAbi(fieldType))
dllProc(setProcName, [objName & " " & objNameSnaked, exportTypeCppAbi(fieldType, "value")], exportTypeCppAbi(nil))

classes.add &" {exportTypeCpp(fieldType)} {getMemberName}();\n"
classes.add &" {exportReturnTypeCpp(fieldType)} {getMemberName}();\n"

members.add &"{exportTypeCpp(fieldType)} {objName}::{getMemberName}()" & "{\n"
members.add &"{exportReturnTypeCpp(fieldType)} {objName}::{getMemberName}()" & "{\n"
let getCall = &"{getProcName}(*this)"
members.add &" return {cppReturnValue(fieldType, getCall)};\n"
members.add "}\n\n"
Expand Down Expand Up @@ -529,7 +548,59 @@ const header = """
#ifndef INCLUDE_$LIB_H
#define INCLUDE_$LIB_H

#include <cstddef>
#include <cstdint>
#include <string>

"""

const bufferClass = """
struct GennyBuffer {

private:

std::uintptr_t reference;

public:

const char* data();
std::intptr_t len();
void free();

};

"""

const bufferProcs = """
const char* $lib_genny_buffer_data(GennyBuffer buffer);
std::intptr_t $lib_genny_buffer_len(GennyBuffer buffer);
void $lib_genny_buffer_unref(GennyBuffer buffer);

"""

const bufferMembers = """
static inline std::string gennyBufferToString(GennyBuffer buffer) {
const char* data = $lib_genny_buffer_data(buffer);
std::intptr_t len = $lib_genny_buffer_len(buffer);
std::string result;
if (data != nullptr && len > 0) {
result.assign(data, static_cast<std::size_t>(len));
}
$lib_genny_buffer_unref(buffer);
return result;
}

const char* GennyBuffer::data() {
return $lib_genny_buffer_data(*this);
}

std::intptr_t GennyBuffer::len() {
return $lib_genny_buffer_len(*this);
}

void GennyBuffer::free() {
$lib_genny_buffer_unref(*this);
}

"""

Expand All @@ -542,10 +613,13 @@ proc writeCpp*(dir, lib: string) =
writeFile(&"{dir}/{toSnakeCase(lib)}.hpp", (
header &
types &
bufferClass &
classes &
"extern \"C\" {\n\n" &
bufferProcs &
procs &
"}\n\n" &
bufferMembers &
members &
footer
).replace("$lib", toSnakeCase(lib)).replace("$LIB", lib.toUpperAscii())
Expand Down
Loading
Loading