aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-01-24 22:44:16 -0600
committergenotrance <dev@genotrance.com>2019-01-27 22:05:54 -0600
commitd8c75a43f725ca3fc4111a55587ce5ca69d024e9 (patch)
tree8e770cfd35219b37517c4731056a1e34d9640fc6
parentf367234ca5da349a00982e6a7d70fdcd80404141 (diff)
downloadnimterop-d8c75a43f725ca3fc4111a55587ce5ca69d024e9.tar.gz
nimterop-d8c75a43f725ca3fc4111a55587ce5ca69d024e9.zip
Plugin support
-rw-r--r--.travis.yml2
-rw-r--r--appveyor.yml1
-rw-r--r--nimterop/cimport.nim15
-rw-r--r--nimterop/getters.nim36
-rw-r--r--nimterop/globals.nim6
-rw-r--r--nimterop/grammar.nim16
-rw-r--r--tests/tnimterop_c.nim7
-rw-r--r--toast.nim8
8 files changed, 72 insertions, 19 deletions
diff --git a/.travis.yml b/.travis.yml
index 8632daf..3118652 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,13 +5,11 @@ os:
language: c
env:
- - BRANCH=0.19.0
- BRANCH=0.19.2
- BRANCH=devel
cache:
directories:
- - "$HOME/.choosenim/toolchains/nim-0.19.0"
- "$HOME/.choosenim/toolchains/nim-0.19.2"
install:
diff --git a/appveyor.yml b/appveyor.yml
index 5768382..f8f45d7 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,7 +9,6 @@ matrix:
environment:
matrix:
- - NIM_VERSION: 0.19.0
- NIM_VERSION: 0.19.2
for:
diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim
index ce0ae18..8fcf66e 100644
--- a/nimterop/cimport.nim
+++ b/nimterop/cimport.nim
@@ -1,4 +1,4 @@
-import macros, os, strformat, strutils
+import hashes, macros, os, ospaths, strformat, strutils
const CIMPORT {.used.} = 1
@@ -102,6 +102,9 @@ proc getToast(fullpath: string, recurse: bool = false): string =
if gStateCT.symOverride.len != 0:
cmd.add &"--symOverride={gStateCT.symOverride.join(\",\")} "
+ if gStateCT.pluginFile.nBl and gStateCT.pluginFile.fileExists():
+ cmd.add &"--pluginFile={gStateCT.pluginFile.quoteShell} "
+
cmd.add &"{fullpath.quoteShell}"
echo cmd
(result, ret) = gorgeEx(cmd, cache=getCacheValue(fullpath))
@@ -170,6 +173,16 @@ macro cSkipSymbol*(skips: varargs[string]): untyped =
for skip in skips:
gStateCT.symOverride.add skip.strVal
+macro cPlugin*(body): untyped =
+ let
+ data = body.repr
+ path = getTempDir() / "nimterop" & ($data.hash() & ".nim")
+
+ if not fileExists(path):
+ writeFile(path, data)
+
+ gStateCT.pluginFile = path
+
proc cSearchPath*(path: string): string {.compileTime.}=
## Get full path to file or directory ``path`` in search path configured
## using `cAddSearchDir() <cimport.html#cAddSearchDir.m,>`_ and
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 24e250d..ed0652d 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -1,4 +1,4 @@
-import macros, os, sequtils, sets, strformat, strutils, tables
+import dynlib, macros, os, sequtils, sets, strformat, strutils, tables
import regex
@@ -88,7 +88,14 @@ proc getType*(str: string): string =
result = gTypeMap[result]
proc getIdentifier*(str: string): string =
- result = str.strip(chars={'_'}).replace(re"_+", "_")
+ doAssert str.len != 0, "Blank identifier error"
+
+ if gStateRT.onSymbol != nil:
+ result = gStateRT.onSymbol(str)
+ else:
+ result = str
+
+ doAssert result[0] != '_' and result[^1] != '_', &"Identifier '{result}' with leading/trailing underscore '_' not supported: use cPlugin() to handle"
if result in gReserved:
result = &"`{result}`"
@@ -306,4 +313,27 @@ proc getNimExpression*(expr: string): string =
proc getSplitComma*(joined: seq[string]): seq[string] =
for i in joined:
- result = result.concat(i.split(",")) \ No newline at end of file
+ result = result.concat(i.split(","))
+
+proc dll*(path: string): string =
+ let
+ (dir, name, ext) = 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("dynlib")
+
+proc loadPlugin*(fullpath: string) =
+ doAssert fileExists(fullpath), "Plugin file does not exist: " & fullpath
+ if not fileExists(fullpath.dll):
+ discard execAction("nim c --app:lib " & fullpath)
+ doAssert fileExists(fullpath.dll), "No plugin binary generated for " & fullpath
+
+ let lib = loadLib(fullpath.dll)
+ doAssert lib != nil, "Plugin load failed"
+
+ gStateRT.onSymbol = cast[proc(sym: string): string {.cdecl.}](lib.symAddr("onSymbol"))
+ doAssert gStateRT.onSymbol != nil, "onSymbol() load failed"
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index 42abf8f..e24e51d 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -51,15 +51,15 @@ type
nocache*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool
consts*, enums*, procs*, types*: HashSet[string]
-
- code*, constStr*, currentHeader*, debugStr*, enumStr*, mode*, procStr*, typeStr*: string
- sourceFile*: string # eg, C or C++ source or header file
+ constStr*, debugStr*, enumStr*, procStr*, typeStr*: string
+ code*, currentHeader*, mode*, pluginFile*, sourceFile*: string
ast*: Table[string, seq[ref Ast]]
data*: seq[tuple[name, val: string]]
when not declared(CIMPORT):
grammar*: seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode) {.nimcall.}]]
+ onSymbol*: proc(sym: string): string {.cdecl.}
var
gStateCT {.compiletime, used.}: State
gStateRT {.used.}: State
diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim
index f86db19..5a7ca66 100644
--- a/nimterop/grammar.nim
+++ b/nimterop/grammar.nim
@@ -344,11 +344,11 @@ proc initGrammar() =
))
proc pEnumCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) =
- var
- nname = name.getIdentifier()
-
- if nname.len == 0:
- nname = getUniqueIdentifier(gStateRT.enums, "Enum")
+ let nname =
+ if name.len == 0:
+ getUniqueIdentifier(gStateRT.enums, "Enum")
+ else:
+ name.getIdentifier()
if gStateRT.enums.addNewIdentifer(nname):
gStateRT.enumStr &= &"\ntype {nname}* = distinct int"
@@ -358,13 +358,13 @@ proc initGrammar() =
i = fstart
count = 0
while i < gStateRT.data.len-fend:
- let
- fname = gStateRT.data[i].val.getIdentifier()
-
if gStateRT.data[i].name == "enumerator":
i += 1
continue
+ let
+ fname = gStateRT.data[i].val.getIdentifier()
+
if i+1 < gStateRT.data.len-fend and
gStateRT.data[i+1].name in gEnumVals:
if gStateRT.consts.addNewIdentifer(fname):
diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim
index f0d5ed5..095fe20 100644
--- a/tests/tnimterop_c.nim
+++ b/tests/tnimterop_c.nim
@@ -8,6 +8,13 @@ cDefine("FORCE")
cIncludeDir "$projpath/include"
cAddSearchDir "$projpath/include"
cCompile cSearchPath("test.c")
+
+cPlugin:
+ import strutils
+
+ proc onSymbol*(sym: string): string {.exportc, dynlib.} =
+ return sym.strip(chars={'_'})
+
cImport cSearchPath "test.h"
check TEST_INT == 512
diff --git a/toast.nim b/toast.nim
index fe529ed..e555a62 100644
--- a/toast.nim
+++ b/toast.nim
@@ -113,6 +113,7 @@ proc main(
defines: seq[string] = @[],
includeDirs: seq[string] = @[],
symOverride: seq[string] = @[],
+ pluginFile: string = "",
source: seq[string],
) =
@@ -126,11 +127,15 @@ proc main(
debug: debug,
defines: defines,
includeDirs: includeDirs,
- symOverride: symOverride
+ symOverride: symOverride,
+ pluginFile: pluginFile
)
gStateRT.symOverride = gStateRT.symOverride.getSplitComma()
+ if pluginFile.nBl:
+ loadPlugin(pluginFile)
+
if pgrammar:
parseGrammar()
printGrammar()
@@ -146,6 +151,7 @@ when isMainModule:
"defines": "definitions to pass to preprocessor",
"includeDirs": "include directory to pass to preprocessor",
"symOverride": "skip generating specified symbols",
+ "pluginFile": "Nim file to build and load as a plugin",
"preprocess": "run preprocessor on header",
"pgrammar": "print grammar",
"recurse": "process #include files",