Plugin support
This commit is contained in:
parent
f367234ca5
commit
d8c75a43f7
8 changed files with 72 additions and 19 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ matrix:
|
|||
|
||||
environment:
|
||||
matrix:
|
||||
- NIM_VERSION: 0.19.0
|
||||
- NIM_VERSION: 0.19.2
|
||||
|
||||
for:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(","))
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue