getOverride and Final
This commit is contained in:
parent
3c71729839
commit
2696e900c0
7 changed files with 142 additions and 46 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import os, sets, strformat, strutils, tables, times
|
||||
import macros, os, sets, strformat, strutils, tables, times
|
||||
|
||||
import regex
|
||||
|
||||
|
|
@ -187,6 +187,7 @@ proc printNim*(gState: State, fullpath: string, root: TSNode, astTable: AstTable
|
|||
if nimState.enumStr.nBl:
|
||||
echo &"{nimState.enumStr}\n"
|
||||
|
||||
nimState.constStr = nimState.getOverrideFinal(nskConst) & nimState.constStr
|
||||
if nimState.constStr.nBl:
|
||||
echo &"const{nimState.constStr}\n"
|
||||
|
||||
|
|
@ -195,9 +196,11 @@ proc printNim*(gState: State, fullpath: string, root: TSNode, astTable: AstTable
|
|||
{{.pragma: {nimState.impShort}C, {nimState.impShort}, cdecl{nimState.getDynlib()}.}}
|
||||
"""
|
||||
|
||||
nimState.typeStr = nimState.getOverrideFinal(nskType) & nimState.typeStr
|
||||
if nimState.typeStr.nBl:
|
||||
echo &"type{nimState.typeStr}\n"
|
||||
|
||||
nimState.procStr = nimState.getOverrideFinal(nskProc) & nimState.procStr
|
||||
if nimState.procStr.nBl:
|
||||
echo &"{nimState.procStr}\n"
|
||||
|
||||
|
|
|
|||
|
|
@ -201,22 +201,64 @@ macro cOverride*(body): untyped =
|
|||
## `cOverride() <cimport.html#cOverride.m>`_ only affects calls to
|
||||
## `cImport() <cimport.html#cImport.m%2C%2Cstring%2Cstring%2Cstring>`_ that follow it.
|
||||
|
||||
proc recFindIdent(node: NimNode): seq[string] =
|
||||
if node.kind != nnkIdent:
|
||||
for child in node:
|
||||
result.add recFindIdent(child)
|
||||
if result.len != 0 and node.kind notin [nnkTypeSection, nnkConstSection]:
|
||||
break
|
||||
elif $node != "*":
|
||||
result.add $node
|
||||
iterator findOverrides(node: NimNode): tuple[name, override: string, kind: NimNodeKind] =
|
||||
for child in node:
|
||||
case child.kind
|
||||
of nnkTypeSection, nnkConstSection:
|
||||
# Types, const
|
||||
for inst in child:
|
||||
let name =
|
||||
if inst[0].kind == nnkPragmaExpr:
|
||||
$inst[0][0]
|
||||
else:
|
||||
$inst[0]
|
||||
|
||||
for sym in body:
|
||||
gStateCT.symOverride.add recFindIdent(sym)
|
||||
yield (name.strip(chars={'*'}), inst.repr, child.kind)
|
||||
of nnkProcDef:
|
||||
let
|
||||
name = $child[0]
|
||||
|
||||
result = body
|
||||
yield (name.strip(chars={'*'}), child.repr, child.kind)
|
||||
else:
|
||||
discard
|
||||
|
||||
if gStateCT.debug:
|
||||
echo "# Overriding " & gStateCT.symOverride.join(" ")
|
||||
if gStateCT.overrides.len == 0:
|
||||
gStateCT.overrides = """
|
||||
import sets, tables
|
||||
|
||||
proc onSymbolOverride*(sym: var Symbol) {.exportc, dynlib.} =
|
||||
"""
|
||||
|
||||
# If cPlugin called before cOverride
|
||||
if gStateCT.pluginSourcePath.len != 0:
|
||||
gStateCT.pluginSourcePath = ""
|
||||
|
||||
var
|
||||
names: seq[string]
|
||||
for name, override, kind in body.findOverrides():
|
||||
let
|
||||
typ =
|
||||
case kind
|
||||
of nnkTypeSection: "nskType"
|
||||
of nnkConstSection: "nskConst"
|
||||
of nnkProcDef: "nskProc"
|
||||
else: ""
|
||||
|
||||
gStateCT.overrides &= &"""
|
||||
if sym.name == "{name}" and sym.kind == {typ} and "{name}" in cOverrides["{typ}"]:
|
||||
sym.override = """ & "\"\"\"" & override & "\"\"\"\n"
|
||||
|
||||
gStateCT.overrides &= &" cOverrides[\"{typ}\"].excl \"{name}\"\n"
|
||||
|
||||
gStateCT.overrides = gStateCT.overrides.replace("proc onSymbolOverride",
|
||||
&"cOverrides[\"{typ}\"].incl \"{name}\"\nproc onSymbolOverride")
|
||||
|
||||
names.add name
|
||||
|
||||
gStateCT.symOverride.add name
|
||||
|
||||
if gStateCT.debug and names.len != 0:
|
||||
echo "# Overriding " & names.join(" ")
|
||||
|
||||
proc cSkipSymbol*(skips: seq[string]) {.compileTime.} =
|
||||
## Similar to `cOverride() <cimport.html#cOverride.m>`_, this macro allows
|
||||
|
|
@ -228,6 +270,22 @@ proc cSkipSymbol*(skips: seq[string]) {.compileTime.} =
|
|||
static: cSkipSymbol @["proc1", "Type2"]
|
||||
gStateCT.symOverride.add skips
|
||||
|
||||
proc cPluginHelper(body: string) =
|
||||
gStateCT.pluginSource = body
|
||||
|
||||
let
|
||||
data = "import macros, nimterop/plugin\n\n" & body & gStateCT.overrides
|
||||
hash = data.hash().abs()
|
||||
path = getProjectCacheDir("cPlugins", forceClean = false) / "nimterop_" & $hash & ".nim"
|
||||
|
||||
if not fileExists(path) or gStateCT.nocache or compileOption("forceBuild"):
|
||||
mkDir(path.parentDir())
|
||||
writeFile(path, data)
|
||||
|
||||
doAssert fileExists(path), "Unable to write plugin file: " & path
|
||||
|
||||
gStateCT.pluginSourcePath = path
|
||||
|
||||
macro cPlugin*(body): untyped =
|
||||
## When `cOverride() <cimport.html#cOverride.m>`_ and
|
||||
## `cSkipSymbol() <cimport.html#cSkipSymbol%2Cseq[T][string]>`_
|
||||
|
|
@ -276,18 +334,7 @@ macro cPlugin*(body): untyped =
|
|||
if sym.kind == nskProc and sym.name.contains("SDL_"):
|
||||
sym.name = sym.name.replace("SDL_", "")
|
||||
|
||||
let
|
||||
data = "import macros, nimterop/plugin\n\n" & body.repr
|
||||
hash = data.hash().abs()
|
||||
path = getProjectCacheDir("cPlugins", forceClean = false) / "nimterop_" & $hash & ".nim"
|
||||
|
||||
if not fileExists(path) or gStateCT.nocache or compileOption("forceBuild"):
|
||||
mkDir(path.parentDir())
|
||||
writeFile(path, data)
|
||||
|
||||
doAssert fileExists(path), "Unable to write plugin file: " & path
|
||||
|
||||
gStateCT.pluginSourcePath = path
|
||||
cPluginHelper(body.repr)
|
||||
|
||||
proc cSearchPath*(path: string): string {.compileTime.}=
|
||||
## Get full path to file or directory `path` in search path configured
|
||||
|
|
@ -529,6 +576,9 @@ macro cImport*(filename: static string, recurse: static bool = false, dynlib: st
|
|||
let
|
||||
fullpath = findPath(filename)
|
||||
|
||||
if gStateCT.overrides.len != 0 and gStateCT.pluginSourcePath.len == 0:
|
||||
cPluginHelper(gStateCT.pluginSource)
|
||||
|
||||
echo "# Importing " & fullpath.sanitizePath
|
||||
|
||||
let
|
||||
|
|
|
|||
|
|
@ -127,17 +127,28 @@ proc getIdentifier*(nimState: NimState, name: string, kind: NimSymKind, parent="
|
|||
else:
|
||||
result = ""
|
||||
|
||||
proc getOverride*(nimState: NimState, name: string, kind: NimSymKind, parent=""): string =
|
||||
proc getOverride*(nimState: NimState, name: string, kind: NimSymKind): string =
|
||||
doAssert name.len != 0, "Blank identifier error"
|
||||
|
||||
if nimState.gState.onSymbol != nil:
|
||||
if nimState.gState.onSymbolOverride != nil:
|
||||
var
|
||||
nname = nimState.getIdentifier(name, kind, parent)
|
||||
sym = Symbol(name: nname, parent: parent, kind: kind)
|
||||
nimState.gState.onSymbol(sym)
|
||||
nname = nimState.getIdentifier(name, kind, "Parent")
|
||||
sym = Symbol(name: nname, kind: kind)
|
||||
nimState.gState.onSymbolOverride(sym)
|
||||
|
||||
result = sym.override
|
||||
|
||||
proc getOverrideFinal*(nimState: NimState, kind: NimSymKind): string =
|
||||
let
|
||||
typ = $kind
|
||||
|
||||
if nimState.gState.onSymbolOverrideFinal != nil:
|
||||
for i in nimState.gState.onSymbolOverrideFinal(typ):
|
||||
result &= "\n" & nimState.getOverride(i, kind)
|
||||
|
||||
if kind != nskProc:
|
||||
result = result.replace(re"(?m)^(.*?)$", " $1")
|
||||
|
||||
proc getUniqueIdentifier*(nimState: NimState, prefix = ""): string =
|
||||
var
|
||||
name = prefix & "_" & nimState.sourceFile.extractFilename().multiReplace([(".", ""), ("-", "")])
|
||||
|
|
@ -155,7 +166,9 @@ proc addNewIdentifer*(nimState: NimState, name: string): bool =
|
|||
nimName = name[0] & name[1 .. ^1].replace("_", "").toLowerAscii
|
||||
|
||||
if nimState.identifiers.hasKey(nimName):
|
||||
doAssert name == nimState.identifiers[nimName], &"Identifier '{name}' is a stylistic duplicate of identifier '{nimState.identifiers[nimName]}', use 'cPlugin:onSymbol()' to rename"
|
||||
doAssert name == nimState.identifiers[nimName],
|
||||
&"Identifier '{name}' is a stylistic duplicate of identifier " &
|
||||
&"'{nimState.identifiers[nimName]}', use 'cPlugin:onSymbol()' to rename"
|
||||
result = false
|
||||
else:
|
||||
nimState.identifiers[nimName] = name
|
||||
|
|
@ -463,7 +476,10 @@ proc loadPlugin*(gState: State, sourcePath: string) =
|
|||
doAssert lib != nil, "Plugin $1 compiled to $2 failed to load" % [sourcePath, pdll]
|
||||
|
||||
gState.onSymbol = cast[OnSymbol](lib.symAddr("onSymbol"))
|
||||
doAssert gState.onSymbol != nil, "onSymbol() load failed from " & pdll
|
||||
|
||||
gState.onSymbolOverride = cast[OnSymbol](lib.symAddr("onSymbolOverride"))
|
||||
|
||||
gState.onSymbolOverrideFinal = cast[OnSymbolOverrideFinal](lib.symAddr("onSymbolOverrideFinal"))
|
||||
|
||||
proc expandSymlinkAbs*(path: string): string =
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -57,9 +57,10 @@ type
|
|||
|
||||
nocache*, nocomments*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool
|
||||
|
||||
code*, dynlib*, mode*, nim*, pluginSourcePath*: string
|
||||
code*, dynlib*, mode*, nim*, overrides*, pluginSource*, pluginSourcePath*: string
|
||||
|
||||
onSymbol*: OnSymbol
|
||||
onSymbol*, onSymbolOverride*: OnSymbol
|
||||
onSymbolOverrideFinal*: OnSymbolOverrideFinal
|
||||
|
||||
NimState {.used.} = ref object
|
||||
identifiers*: TableRef[string, string]
|
||||
|
|
|
|||
|
|
@ -20,14 +20,22 @@ proc initGrammar(): Grammar =
|
|||
nimState.debugStr &= "\n# define X Y"
|
||||
|
||||
let
|
||||
name = nimState.getIdentifier(nimState.data[0].val, nskConst)
|
||||
val = nimState.data[1].val.getLit()
|
||||
|
||||
if val.nBl:
|
||||
let
|
||||
name = nimState.getIdentifier(nimState.data[0].val, nskConst)
|
||||
if name.nBl:
|
||||
if val.nBl:
|
||||
if nimState.addNewIdentifer(name):
|
||||
nimState.constStr &= &"{nimState.getComments()}\n {name}* = {val}"
|
||||
else:
|
||||
let
|
||||
override = nimState.getOverride(name, nskConst)
|
||||
|
||||
if name.nBl and nimState.addNewIdentifer(name):
|
||||
nimState.constStr &= &"{nimState.getComments()}\n {name}* = {val}"
|
||||
if override.len != 0:
|
||||
if nimState.addNewIdentifer(name):
|
||||
nimState.constStr &= &"{nimState.getComments()}\n {override}"
|
||||
else:
|
||||
nimState.constStr &= &"{nimState.getComments()}\n # Const '{name}' skipped"
|
||||
))
|
||||
|
||||
let
|
||||
|
|
@ -653,17 +661,22 @@ proc initGrammar(): Grammar =
|
|||
|
||||
if override.len != 0:
|
||||
nimState.procStr &= &"{nimState.getComments(true)}\n{override}"
|
||||
break
|
||||
else:
|
||||
nimState.procStr &= &"{nimState.getComments(true)}\n# Unable to wrap declaration '{i.val}'"
|
||||
nimState.procStr &= &"{nimState.getComments(true)}\n# Declaration '{i.val}' skipped"
|
||||
|
||||
else:
|
||||
if i.name == "type_identifier":
|
||||
let
|
||||
override = nimState.getOverride(i.val, nskType)
|
||||
|
||||
if override.len != 0:
|
||||
nimState.typeStr &= &"{nimState.getComments()}\n{override}"
|
||||
let
|
||||
override = override.replace(re"(?m)^(.*?)$", " $1")
|
||||
nimState.typeStr &= &"{nimState.getComments()}\n{override} #" & $nimState.data
|
||||
else:
|
||||
nimState.typeStr &= &"{nimState.getComments()}\n # Unable to wrap type '{i.val}'"
|
||||
nimState.typeStr &= &"{nimState.getComments()}\n # Type '{i.val}' skipped"
|
||||
|
||||
))
|
||||
|
||||
proc initRegex(ast: ref Ast) =
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import macros
|
||||
import macros, sets, tables
|
||||
|
||||
type
|
||||
Symbol* = object
|
||||
|
|
@ -8,3 +8,15 @@ type
|
|||
override*: string
|
||||
|
||||
OnSymbol* = proc(sym: var Symbol) {.cdecl.}
|
||||
OnSymbolOverrideFinal* = proc(typ: string): HashSet[string] {.cdecl.}
|
||||
|
||||
var
|
||||
cOverrides*: Table[string, HashSet[string]]
|
||||
|
||||
cOverrides = initTable[string, HashSet[string]]()
|
||||
cOverrides["nskType"] = initSet[string]()
|
||||
cOverrides["nskConst"] = initSet[string]()
|
||||
cOverrides["nskProc"] = initSet[string]()
|
||||
|
||||
proc onSymbolOverrideFinal*(typ: string): HashSet[string] {.exportc, dynlib.} =
|
||||
result = cOverrides[typ]
|
||||
|
|
|
|||
|
|
@ -48,8 +48,9 @@ cOverride:
|
|||
z_crc_t = culong
|
||||
alloc_func* {.importc.} = proc(opaque: voidpf, items, size: uint) {.cdecl.}
|
||||
Bytef {.importc.} = object
|
||||
|
||||
when defined(posix):
|
||||
|
||||
when defined(posix):
|
||||
cOverride:
|
||||
type
|
||||
pthread_mutex_s = object
|
||||
pthread_cond_s = object
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue