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 =
|
macro cPlugin*(body): untyped =
|
||||||
## When `cOverride() <cimport.html#cOverride.m,>`_ and `cSkipSymbol() <cimport.html#cSkipSymbol.m%2Cvarargs[string]>`_
|
## 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.
|
## are not adequate, the `cPlugin() <cimport.html#cPlugin.m,>`_ macro can be used
|
||||||
## The following callbacks are available at this time.
|
## 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:
|
runnableExamples:
|
||||||
cPlugin:
|
cPlugin:
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc onSymbol*(sym: string): string {.exportc, dynlib.} =
|
proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} =
|
||||||
return sym.strip(chars={'_'})
|
sym.name = sym.name.strip(chars={'_'})
|
||||||
|
|
||||||
let
|
let
|
||||||
data = body.repr
|
data = "import nimterop/cimport\n\n" & body.repr
|
||||||
hash = data.hash()
|
hash = data.hash()
|
||||||
phash = if hash<0: -hash else: hash
|
phash = if hash<0: -hash else: hash
|
||||||
path = getTempDir() / "nimterop_" & $phash & ".nim"
|
path = getTempDir() / "nimterop_" & $phash & ".nim"
|
||||||
|
|
|
||||||
|
|
@ -90,11 +90,17 @@ proc getType*(str: string): string =
|
||||||
template checkUnderscores(str, errmsg: string): untyped =
|
template checkUnderscores(str, errmsg: string): untyped =
|
||||||
doAssert str[0] != '_' and str[^1] != '_', errmsg
|
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"
|
doAssert str.len != 0, "Blank identifier error"
|
||||||
|
|
||||||
if gStateRT.onSymbol != nil:
|
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}'")
|
checkUnderscores(result, &"Identifier '{str}' still contains leading/trailing underscores '_' after 'cPlugin:onSymbol()': result '{result}'")
|
||||||
else:
|
else:
|
||||||
result = str
|
result = str
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,13 @@ type
|
||||||
tonim*: proc (ast: ref Ast, node: TSNode)
|
tonim*: proc (ast: ref Ast, node: TSNode)
|
||||||
regex*: Regex
|
regex*: Regex
|
||||||
|
|
||||||
Symbol = object
|
Symbol* = object
|
||||||
name: string
|
name*: string
|
||||||
kind: NimSymKind
|
kind*: NimSymKind
|
||||||
|
|
||||||
|
Result* = object
|
||||||
|
error*: int
|
||||||
|
message*: string
|
||||||
|
|
||||||
State = object
|
State = object
|
||||||
compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string]
|
compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string]
|
||||||
|
|
@ -63,7 +67,7 @@ type
|
||||||
when not declared(CIMPORT):
|
when not declared(CIMPORT):
|
||||||
grammar*: seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode) {.nimcall.}]]
|
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
|
var
|
||||||
gStateCT {.compiletime, used.}: State
|
gStateCT {.compiletime, used.}: State
|
||||||
gStateRT {.used.}: State
|
gStateRT {.used.}: State
|
||||||
|
|
@ -79,4 +83,4 @@ type CompileMode = enum
|
||||||
const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant
|
const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant
|
||||||
|
|
||||||
when not declared(CIMPORT):
|
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
|
import regex
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ proc initGrammar() =
|
||||||
""",
|
""",
|
||||||
proc (ast: ref Ast, node: TSNode) =
|
proc (ast: ref Ast, node: TSNode) =
|
||||||
let
|
let
|
||||||
name = gStateRT.data[0].val.getIdentifier()
|
name = gStateRT.data[0].val.getIdentifier(nskConst)
|
||||||
val = gStateRT.data[1].val.getLit()
|
val = gStateRT.data[1].val.getLit()
|
||||||
|
|
||||||
if val.nBl and gStateRT.consts.addNewIdentifer(name):
|
if val.nBl and gStateRT.consts.addNewIdentifer(name):
|
||||||
|
|
@ -67,7 +67,7 @@ proc initGrammar() =
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template funcParamCommon(pname, ptyp, pptr, pout, count, i: untyped): untyped =
|
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":
|
if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "pointer_declarator":
|
||||||
pptr = "ptr "
|
pptr = "ptr "
|
||||||
i += 1
|
i += 1
|
||||||
|
|
@ -75,7 +75,7 @@ proc initGrammar() =
|
||||||
pptr = ""
|
pptr = ""
|
||||||
|
|
||||||
if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "identifier":
|
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
|
i += 2
|
||||||
else:
|
else:
|
||||||
pname = "a" & $count
|
pname = "a" & $count
|
||||||
|
|
@ -104,7 +104,7 @@ proc initGrammar() =
|
||||||
proc (ast: ref Ast, node: TSNode) =
|
proc (ast: ref Ast, node: TSNode) =
|
||||||
var
|
var
|
||||||
i = 0
|
i = 0
|
||||||
typ = gStateRT.data[i].val.getIdentifier()
|
typ = gStateRT.data[i].val.getIdentifier(nskType)
|
||||||
name = ""
|
name = ""
|
||||||
tptr = ""
|
tptr = ""
|
||||||
aptr = ""
|
aptr = ""
|
||||||
|
|
@ -120,7 +120,7 @@ proc initGrammar() =
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
if i < gStateRT.data.len:
|
if i < gStateRT.data.len:
|
||||||
name = gStateRT.data[i].val.getIdentifier()
|
name = gStateRT.data[i].val.getIdentifier(nskType)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
if gStateRT.types.addNewIdentifer(name):
|
if gStateRT.types.addNewIdentifer(name):
|
||||||
|
|
@ -144,8 +144,10 @@ proc initGrammar() =
|
||||||
gStateRT.typeStr &= &" {name}* = proc({pout}) {{.nimcall.}}\n"
|
gStateRT.typeStr &= &" {name}* = proc({pout}) {{.nimcall.}}\n"
|
||||||
else:
|
else:
|
||||||
if i < gStateRT.data.len and gStateRT.data[i].name in ["identifier", "number_literal"]:
|
if i < gStateRT.data.len and gStateRT.data[i].name in ["identifier", "number_literal"]:
|
||||||
let
|
var
|
||||||
flen = gStateRT.data[i].val.getIdentifier()
|
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"
|
gStateRT.typeStr &= &" {name}* = {aptr}array[{flen}, {getPtrType(tptr&typ)}]\n"
|
||||||
else:
|
else:
|
||||||
if name == typ:
|
if name == typ:
|
||||||
|
|
@ -157,7 +159,7 @@ proc initGrammar() =
|
||||||
proc pDupTypeCommon(nname: string, fend: int, isEnum=false) =
|
proc pDupTypeCommon(nname: string, fend: int, isEnum=false) =
|
||||||
var
|
var
|
||||||
dname = gStateRT.data[^1].val
|
dname = gStateRT.data[^1].val
|
||||||
ndname = gStateRT.data[^1].val.getIdentifier()
|
ndname = gStateRT.data[^1].val.getIdentifier(nskType)
|
||||||
dptr =
|
dptr =
|
||||||
if fend == 2:
|
if fend == 2:
|
||||||
"ptr "
|
"ptr "
|
||||||
|
|
@ -175,7 +177,7 @@ proc initGrammar() =
|
||||||
|
|
||||||
proc pStructCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) =
|
proc pStructCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) =
|
||||||
var
|
var
|
||||||
nname = name.getIdentifier()
|
nname = name.getIdentifier(nskType)
|
||||||
prefix = ""
|
prefix = ""
|
||||||
union = ""
|
union = ""
|
||||||
|
|
||||||
|
|
@ -231,7 +233,7 @@ proc initGrammar() =
|
||||||
aptr = "ptr "
|
aptr = "ptr "
|
||||||
i += 1
|
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:
|
if i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name in gEnumVals:
|
||||||
let
|
let
|
||||||
flen = gStateRT.data[i+1].val.getNimExpression()
|
flen = gStateRT.data[i+1].val.getNimExpression()
|
||||||
|
|
@ -348,7 +350,7 @@ proc initGrammar() =
|
||||||
if name.len == 0:
|
if name.len == 0:
|
||||||
getUniqueIdentifier(gStateRT.enums, "Enum")
|
getUniqueIdentifier(gStateRT.enums, "Enum")
|
||||||
else:
|
else:
|
||||||
name.getIdentifier()
|
name.getIdentifier(nskType)
|
||||||
|
|
||||||
if gStateRT.enums.addNewIdentifer(nname):
|
if gStateRT.enums.addNewIdentifer(nname):
|
||||||
gStateRT.enumStr &= &"\ntype {nname}* = distinct int"
|
gStateRT.enumStr &= &"\ntype {nname}* = distinct int"
|
||||||
|
|
@ -363,7 +365,7 @@ proc initGrammar() =
|
||||||
continue
|
continue
|
||||||
|
|
||||||
let
|
let
|
||||||
fname = gStateRT.data[i].val.getIdentifier()
|
fname = gStateRT.data[i].val.getIdentifier(nskEnumField)
|
||||||
|
|
||||||
if i+1 < gStateRT.data.len-fend and
|
if i+1 < gStateRT.data.len-fend and
|
||||||
gStateRT.data[i+1].name in gEnumVals:
|
gStateRT.data[i+1].name in gEnumVals:
|
||||||
|
|
@ -447,7 +449,7 @@ proc initGrammar() =
|
||||||
""",
|
""",
|
||||||
proc (ast: ref Ast, node: TSNode) =
|
proc (ast: ref Ast, node: TSNode) =
|
||||||
var
|
var
|
||||||
ftyp = gStateRT.data[0].val.getIdentifier()
|
ftyp = gStateRT.data[0].val.getIdentifier(nskType)
|
||||||
fptr = ""
|
fptr = ""
|
||||||
i = 1
|
i = 1
|
||||||
|
|
||||||
|
|
@ -464,7 +466,7 @@ proc initGrammar() =
|
||||||
|
|
||||||
var
|
var
|
||||||
fname = gStateRT.data[i].val
|
fname = gStateRT.data[i].val
|
||||||
fnname = fname.getIdentifier()
|
fnname = fname.getIdentifier(nskProc)
|
||||||
pout, pname, ptyp, pptr = ""
|
pout, pname, ptyp, pptr = ""
|
||||||
count = 1
|
count = 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ cAddStdDir()
|
||||||
cPlugin:
|
cPlugin:
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc onSymbol*(sym: string): string {.exportc, dynlib.} =
|
proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} =
|
||||||
return sym.strip(chars={'_'})
|
sym.name = sym.name.strip(chars={'_'})
|
||||||
|
|
||||||
cImport cSearchPath("math.h")
|
cImport cSearchPath("math.h")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ cCompile cSearchPath("test.c")
|
||||||
cPlugin:
|
cPlugin:
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
proc onSymbol*(sym: string): string {.exportc, dynlib.} =
|
proc onSymbol*(sym: var Symbol): Result {.exportc, dynlib.} =
|
||||||
return sym.strip(chars={'_'})
|
sym.name = sym.name.strip(chars={'_'})
|
||||||
|
|
||||||
cImport cSearchPath "test.h"
|
cImport cSearchPath "test.h"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue