diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2019-01-27 11:37:33 -0600 |
|---|---|---|
| committer | genotrance <dev@genotrance.com> | 2019-01-27 22:05:54 -0600 |
| commit | f7a77b7ab9c7cae36014e1991245e0d4c1da7099 (patch) | |
| tree | 1a0f1d8f2669d7b6f83e5b375b758c88593fa4d2 | |
| parent | a8b08e1867c6ad130a86d7848b45a5698fdd7699 (diff) | |
| download | nimterop-f7a77b7ab9c7cae36014e1991245e0d4c1da7099.tar.gz nimterop-f7a77b7ab9c7cae36014e1991245e0d4c1da7099.zip | |
Improve onSymbol API
| -rw-r--r-- | nimterop/cimport.nim | 25 | ||||
| -rw-r--r-- | nimterop/getters.nim | 10 | ||||
| -rw-r--r-- | nimterop/globals.nim | 14 | ||||
| -rw-r--r-- | nimterop/grammar.nim | 32 | ||||
| -rw-r--r-- | tests/tmath.nim | 4 | ||||
| -rw-r--r-- | tests/tnimterop_c.nim | 4 |
6 files changed, 58 insertions, 31 deletions
diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim index bd330b4..0a4a138 100644 --- a/nimterop/cimport.nim +++ b/nimterop/cimport.nim @@ -174,18 +174,33 @@ macro cSkipSymbol*(skips: varargs[string]): untyped = macro cPlugin*(body): untyped = ## When `cOverride() <cimport.html#cOverride.m,>`_ and `cSkipSymbol() <cimport.html#cSkipSymbol.m%2Cvarargs[string]>`_ - ## are not adequate, the `cPlugin() <cimport.html#cPlugin.m,>`_ macro can be used to customize the generated Nim output. - ## The following callbacks are available at this time. + ## are not adequate, the `cPlugin() <cimport.html#cPlugin.m,>`_ macro can be used + ## to customize the generated Nim output. The following callbacks are available at + ## this time. ## + ## .. code-block:: nim + ## + ## proc onSymbol(sym: var Symbol): Result {.exportc, dynlib.} + ## + ## `onSymbol()` can be used to handle symbol name modifications required due to invalid + ## characters like `_` or to rename duplicate types. It can also be used to remove prefixes + ## and suffixes. The symbol name and type is provided to the callback and the name can be + ## modified. Symbol types can be any of the following: + ## - `nskConst` for constants + ## - `nskType` for type identifiers, including primitive + ## - `nskParam` for param names + ## - `nskField` for struct field names + ## - `nskEnumField` for enum (field) names, though they are in the global namespace as `nskConst` + ## - `nskProc` - for proc names runnableExamples: cPlugin: import strutils - proc onSymbol*(sym: string): string {.exportc, dynlib.} = - return sym.strip(chars={'_'}) + proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} = + sym.name = sym.name.strip(chars={'_'}) let - data = body.repr + data = "import nimterop/cimport\n\n" & body.repr hash = data.hash() phash = if hash<0: -hash else: hash path = getTempDir() / "nimterop_" & $phash & ".nim" diff --git a/nimterop/getters.nim b/nimterop/getters.nim index 30a0001..e2cfbe9 100644 --- a/nimterop/getters.nim +++ b/nimterop/getters.nim @@ -90,11 +90,17 @@ proc getType*(str: string): string = template checkUnderscores(str, errmsg: string): untyped = doAssert str[0] != '_' and str[^1] != '_', errmsg -proc getIdentifier*(str: string): string = +proc getIdentifier*(str: string, kind: NimSymKind): string = doAssert str.len != 0, "Blank identifier error" if gStateRT.onSymbol != nil: - result = gStateRT.onSymbol(str) + var + sym = Symbol(name: str, kind: kind) + res = gStateRT.onSymbol(sym) + + doAssert res.error == 0, res.message + + result = sym.name checkUnderscores(result, &"Identifier '{str}' still contains leading/trailing underscores '_' after 'cPlugin:onSymbol()': result '{result}'") else: result = str diff --git a/nimterop/globals.nim b/nimterop/globals.nim index 22b2794..dac31e5 100644 --- a/nimterop/globals.nim +++ b/nimterop/globals.nim @@ -45,9 +45,13 @@ type tonim*: proc (ast: ref Ast, node: TSNode) regex*: Regex - Symbol = object - name: string - kind: NimSymKind + Symbol* = object + name*: string + kind*: NimSymKind + + Result* = object + error*: int + message*: string State = object compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string] @@ -63,7 +67,7 @@ type when not declared(CIMPORT): grammar*: seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode) {.nimcall.}]] - onSymbol*: proc(sym: string): string {.cdecl.} + onSymbol*: proc(sym: var Symbol): Result {.cdecl.} var gStateCT {.compiletime, used.}: State gStateRT {.used.}: State @@ -79,4 +83,4 @@ type CompileMode = enum const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant when not declared(CIMPORT): - export gAtoms, gExpressions, gEnumVals, Kind, Ast, Symbol, State, gStateRT, nBl, CompileMode, modeDefault
\ No newline at end of file + export gAtoms, gExpressions, gEnumVals, Kind, Ast, State, gStateRT, nBl, CompileMode, modeDefault
\ No newline at end of file diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim index 5a7ca66..259a9d4 100644 --- a/nimterop/grammar.nim +++ b/nimterop/grammar.nim @@ -1,4 +1,4 @@ -import sets, strformat, strutils, tables +import macros, sets, strformat, strutils, tables import regex @@ -14,7 +14,7 @@ proc initGrammar() = """, proc (ast: ref Ast, node: TSNode) = let - name = gStateRT.data[0].val.getIdentifier() + name = gStateRT.data[0].val.getIdentifier(nskConst) val = gStateRT.data[1].val.getLit() if val.nBl and gStateRT.consts.addNewIdentifer(name): @@ -67,7 +67,7 @@ proc initGrammar() = """ template funcParamCommon(pname, ptyp, pptr, pout, count, i: untyped): untyped = - ptyp = gStateRT.data[i].val.getIdentifier() + ptyp = gStateRT.data[i].val.getIdentifier(nskType) if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "pointer_declarator": pptr = "ptr " i += 1 @@ -75,7 +75,7 @@ proc initGrammar() = pptr = "" if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "identifier": - pname = gStateRT.data[i+1].val.getIdentifier() + pname = gStateRT.data[i+1].val.getIdentifier(nskParam) i += 2 else: pname = "a" & $count @@ -104,7 +104,7 @@ proc initGrammar() = proc (ast: ref Ast, node: TSNode) = var i = 0 - typ = gStateRT.data[i].val.getIdentifier() + typ = gStateRT.data[i].val.getIdentifier(nskType) name = "" tptr = "" aptr = "" @@ -120,7 +120,7 @@ proc initGrammar() = i += 1 if i < gStateRT.data.len: - name = gStateRT.data[i].val.getIdentifier() + name = gStateRT.data[i].val.getIdentifier(nskType) i += 1 if gStateRT.types.addNewIdentifer(name): @@ -144,8 +144,10 @@ proc initGrammar() = gStateRT.typeStr &= &" {name}* = proc({pout}) {{.nimcall.}}\n" else: if i < gStateRT.data.len and gStateRT.data[i].name in ["identifier", "number_literal"]: - let - flen = gStateRT.data[i].val.getIdentifier() + var + flen = gStateRT.data[i].val + if gStateRT.data[i].name == "identifier": + flen = flen.getIdentifier(nskConst) gStateRT.typeStr &= &" {name}* = {aptr}array[{flen}, {getPtrType(tptr&typ)}]\n" else: if name == typ: @@ -157,7 +159,7 @@ proc initGrammar() = proc pDupTypeCommon(nname: string, fend: int, isEnum=false) = var dname = gStateRT.data[^1].val - ndname = gStateRT.data[^1].val.getIdentifier() + ndname = gStateRT.data[^1].val.getIdentifier(nskType) dptr = if fend == 2: "ptr " @@ -175,7 +177,7 @@ proc initGrammar() = proc pStructCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) = var - nname = name.getIdentifier() + nname = name.getIdentifier(nskType) prefix = "" union = "" @@ -231,7 +233,7 @@ proc initGrammar() = aptr = "ptr " i += 1 - fname = gStateRT.data[i].val.getIdentifier() + fname = gStateRT.data[i].val.getIdentifier(nskField) if i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name in gEnumVals: let flen = gStateRT.data[i+1].val.getNimExpression() @@ -348,7 +350,7 @@ proc initGrammar() = if name.len == 0: getUniqueIdentifier(gStateRT.enums, "Enum") else: - name.getIdentifier() + name.getIdentifier(nskType) if gStateRT.enums.addNewIdentifer(nname): gStateRT.enumStr &= &"\ntype {nname}* = distinct int" @@ -363,7 +365,7 @@ proc initGrammar() = continue let - fname = gStateRT.data[i].val.getIdentifier() + fname = gStateRT.data[i].val.getIdentifier(nskEnumField) if i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name in gEnumVals: @@ -447,7 +449,7 @@ proc initGrammar() = """, proc (ast: ref Ast, node: TSNode) = var - ftyp = gStateRT.data[0].val.getIdentifier() + ftyp = gStateRT.data[0].val.getIdentifier(nskType) fptr = "" i = 1 @@ -464,7 +466,7 @@ proc initGrammar() = var fname = gStateRT.data[i].val - fnname = fname.getIdentifier() + fnname = fname.getIdentifier(nskProc) pout, pname, ptyp, pptr = "" count = 1 diff --git a/tests/tmath.nim b/tests/tmath.nim index 5e98968..a561251 100644 --- a/tests/tmath.nim +++ b/tests/tmath.nim @@ -14,8 +14,8 @@ cAddStdDir() cPlugin: import strutils - proc onSymbol*(sym: string): string {.exportc, dynlib.} = - return sym.strip(chars={'_'}) + proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} = + sym.name = sym.name.strip(chars={'_'}) cImport cSearchPath("math.h") diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim index 095fe20..c9b4667 100644 --- a/tests/tnimterop_c.nim +++ b/tests/tnimterop_c.nim @@ -12,8 +12,8 @@ cCompile cSearchPath("test.c") cPlugin: import strutils - proc onSymbol*(sym: string): string {.exportc, dynlib.} = - return sym.strip(chars={'_'}) + proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} = + sym.name = sym.name.strip(chars={'_'}) cImport cSearchPath "test.h" |
