Updated with feedback

This commit is contained in:
Ganesh Viswanathan 2019-01-25 16:41:54 -06:00 • committed by genotrance
commit 6c1f458a84
3 changed files with 53 additions and 46 deletions

View file

@ -1,4 +1,4 @@
import hashes, macros, os, ospaths, strformat, strutils
import hashes, macros, os, strformat, strutils
const CIMPORT {.used.} = 1
@ -88,24 +88,24 @@ proc getToast(fullpath: string, recurse: bool = false): string =
ret = 0
cmd = when defined(Windows): "cmd /c " else: ""
cmd &= "toast --pnim --preprocess "
cmd &= "toast --pnim --preprocess"
if recurse:
cmd.add "--recurse "
cmd.add " --recurse"
for i in gStateCT.defines:
cmd.add &"--defines+={i.quoteShell} "
cmd.add &" --defines+={i.quoteShell}"
for i in gStateCT.includeDirs:
cmd.add &"--includeDirs+={i.quoteShell} "
cmd.add &" --includeDirs+={i.quoteShell}"
if gStateCT.symOverride.len != 0:
cmd.add &"--symOverride={gStateCT.symOverride.join(\",\")} "
cmd.add &" --symOverride={gStateCT.symOverride.join(\",\")}"
if gStateCT.pluginFile.nBl and gStateCT.pluginFile.fileExists():
cmd.add &"--pluginFile={gStateCT.pluginFile.quoteShell} "
if gStateCT.pluginFile.nBl:
cmd.add &" --pluginFile={gStateCT.pluginFile.quoteShell}"
cmd.add &"{fullpath.quoteShell}"
cmd.add &" {fullpath.quoteShell}"
echo cmd
(result, ret) = gorgeEx(cmd, cache=getCacheValue(fullpath))
doAssert ret == 0, getToastError(result)
@ -130,7 +130,7 @@ macro cOverride*(body): untyped =
##
## int svGetCallerInfo(const char** fileName, int *lineNumber);
##
## This could get mapped to:
## This might mapped to:
##
## .. code-block:: nim
##
@ -166,9 +166,8 @@ macro cSkipSymbol*(skips: varargs[string]): untyped =
## Similar to `cOverride() <cimport.html#cOverride.m,>`_, this macro allows
## filtering out symbols not of interest from the generated output.
##
## .. code-block:: nim
##
## cSkipSymbol "proc1", "Type2"
runnableExamples:
cSkipSymbol "proc1", "Type2"
for skip in skips:
gStateCT.symOverride.add skip.strVal
@ -178,21 +177,24 @@ macro cPlugin*(body): untyped =
## 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
##
## cPlugin:
## import strutils
##
## proc onSymbol*(sym: string): string {.exportc, dynlib.} =
## return sym.strip(chars={'_'})
runnableExamples:
cPlugin:
import strutils
proc onSymbol*(sym: string): string {.exportc, dynlib.} =
return sym.strip(chars={'_'})
let
data = body.repr
path = getTempDir() / "nimterop" & ($data.hash() & ".nim")
hash = data.hash()
phash = if hash<0: -hash else: hash
path = getTempDir() / "nimterop_" & $phash & ".nim"
if not fileExists(path):
if not fileExists(path) or gStateCT.nocache:
writeFile(path, data)
doAssert fileExists(path), "Unable to write plugin file: " & path
gStateCT.pluginFile = path
proc cSearchPath*(path: string): string {.compileTime.}=
@ -209,8 +211,8 @@ proc cSearchPath*(path: string): string {.compileTime.}=
if result.len == 0:
var found = false
for inc in gStateCT.searchDirs:
result = (inc & "/" & path).replace("\\", "/")
if fileExists(result) or dirExists(result):
result = findPath(inc & "/" & path, fail = false)
if result.len != 0:
found = true
break
doAssert found, "File or directory not found: " & path &
@ -297,10 +299,9 @@ macro cAddStdDir*(mode = "c"): untyped =
##
## This allows something like this:
##
## .. code-block:: nim
##
## cAddStdDir()
## cImport cSearchPath("math.h")
runnableExamples:
cAddStdDir()
echo cSearchPath("math.h")
result = newNimNode(nnkStmtList)

View file

@ -1,4 +1,4 @@
import dynlib, macros, os, sequtils, sets, strformat, strutils, tables
import dynlib, macros, os, sequtils, sets, strformat, strutils, tables, times
import regex
@ -87,15 +87,18 @@ proc getType*(str: string): string =
if gTypeMap.hasKey(result):
result = gTypeMap[result]
template checkUnderscores(str, errmsg: string): untyped =
doAssert str[0] != '_' and str[^1] != '_', errmsg
proc getIdentifier*(str: string): string =
doAssert str.len != 0, "Blank identifier error"
if gStateRT.onSymbol != nil:
result = gStateRT.onSymbol(str)
checkUnderscores(result, &"Identifier '{str}' still contains leading/trailing underscores '_' after 'cPlugin:onSymbol()': result '{result}'")
else:
result = str
doAssert result[0] != '_' and result[^1] != '_', &"Identifier '{result}' with leading/trailing underscore '_' not supported: use cPlugin() to handle"
checkUnderscores(result, &"Identifier '{result}' contains unsupported leading/trailing underscores '_': use 'cPlugin:onSymbol()' to handle")
if result in gReserved:
result = &"`{result}`"
@ -317,23 +320,22 @@ proc getSplitComma*(joined: seq[string]): seq[string] =
proc dll*(path: string): string =
let
(dir, name, ext) = path.splitFile()
(dir, name, _) = path.splitFile()
when defined(Windows):
result = dir/name.addFileExt("dll")
when defined(Linux):
result = dir/"lib" & name.addFileExt("so")
when defined(OSX):
result = dir/"lib" & name.addFileExt("dylib")
result = dir / (DynlibFormat % name)
proc loadPlugin*(fullpath: string) =
doAssert fileExists(fullpath), "Plugin file does not exist: " & fullpath
if not fileExists(fullpath.dll):
let
pdll = fullpath.dll
if not fileExists(pdll) or
fullpath.getLastModificationTime() > pdll.getLastModificationTime():
discard execAction("nim c --app:lib " & fullpath)
doAssert fileExists(fullpath.dll), "No plugin binary generated for " & fullpath
doAssert fileExists(pdll), "No plugin binary generated for " & fullpath
let lib = loadLib(fullpath.dll)
doAssert lib != nil, "Plugin load failed"
let lib = loadLib(pdll)
doAssert lib != nil, "Plugin $1 compiled to $2 failed to load" % [fullpath, pdll]
gStateRT.onSymbol = cast[proc(sym: string): string {.cdecl.}](lib.symAddr("onSymbol"))
doAssert gStateRT.onSymbol != nil, "onSymbol() load failed"
gStateRT.onSymbol = cast[typeof(gStateRT.onSymbol)](lib.symAddr("onSymbol"))
doAssert gStateRT.onSymbol != nil, "onSymbol() load failed from " & pdll

View file

@ -1,4 +1,4 @@
import sequtils, sets, tables
import macros, sequtils, sets, tables
import regex
@ -45,6 +45,10 @@ type
tonim*: proc (ast: ref Ast, node: TSNode)
regex*: Regex
Symbol = object
name: string
kind: NimSymKind
State = object
compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string]
@ -75,4 +79,4 @@ type CompileMode = enum
const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant
when not declared(CIMPORT):
export gAtoms, gExpressions, gEnumVals, Kind, Ast, State, gStateRT, nBl, CompileMode, modeDefault
export gAtoms, gExpressions, gEnumVals, Kind, Ast, Symbol, State, gStateRT, nBl, CompileMode, modeDefault