Improve onSymbol API
This commit is contained in:
parent
a8b08e1867
commit
f7a77b7ab9
6 changed files with 58 additions and 31 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
export gAtoms, gExpressions, gEnumVals, Kind, Ast, State, gStateRT, nBl, CompileMode, modeDefault
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue