aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-12-20 00:10:31 -0600
committerGanesh Viswanathan <dev@genotrance.com>2019-12-20 00:10:31 -0600
commit54dfd61b1bda02f3ce0124e47192018c1e8b349f (patch)
treeb4832e3d15ad5381b569ce43a7de3680b1ba1580
parenta2809b02d1c0696c0b7f5d767e79a947201a7c05 (diff)
downloadnimterop-54dfd61b1bda02f3ce0124e47192018c1e8b349f.tar.gz
nimterop-54dfd61b1bda02f3ce0124e47192018c1e8b349f.zip
Fix #161 - enable stubbing in toast
-rw-r--r--README.md1
-rw-r--r--nimterop/toast.nim69
2 files changed, 57 insertions, 13 deletions
diff --git a/README.md b/README.md
index 67689b3..ca16293 100644
--- a/README.md
+++ b/README.md
@@ -112,6 +112,7 @@ Options(opt-arg sep :|=|spc):
-E=, --prefix= strings {} Strip prefix from identifiers
-p, --preprocess bool false run preprocessor on header
-r, --recurse bool false process #include files
+ -s, --stub bool false stub out undefined type references as objects
-F=, --suffix= strings {} Strip suffix from identifiers
-O=, --symOverride= strings {} skip generating specified symbols
```
diff --git a/nimterop/toast.nim b/nimterop/toast.nim
index 34409fc..871230d 100644
--- a/nimterop/toast.nim
+++ b/nimterop/toast.nim
@@ -54,7 +54,7 @@ proc printLisp(gState: State, root: TSNode) =
break
proc process(gState: State, path: string, astTable: AstTable) =
- doAssert existsFile(path), "Invalid path " & path
+ doAssert existsFile(path), &"Invalid path {path}"
var
parser = tsParserNew()
@@ -81,7 +81,7 @@ proc process(gState: State, path: string, astTable: AstTable) =
elif gState.mode == "cpp":
doAssert parser.tsParserSetLanguage(treeSitterCpp()), "Failed to load C++ parser"
else:
- doAssert false, "Invalid parser " & gState.mode
+ doAssert false, &"Invalid parser {gState.mode}"
var
tree = parser.tsParserParseString(nil, gState.code.cstring, gState.code.len.uint32)
@@ -115,6 +115,7 @@ proc main(
prefix: seq[string] = @[],
preprocess = false,
recurse = false,
+ stub = false,
suffix: seq[string] = @[],
symOverride: seq[string] = @[],
source: seq[string]
@@ -153,20 +154,26 @@ proc main(
outputFile = output
outputHandle: File
stdoutBackup = stdout
+ check = check or stub
+
+ # Fix output file extention
+ if outputFile.len != 0:
+ if outputFile.splitFile().ext != ".nim":
+ outputFile = outputFile & ".nim"
# Check needs a file
if check and outputFile.len == 0:
outputFile = getTempDir() / "toast_" & ($getTime().toUnix()).addFileExt("nim")
when defined(windows):
# https://github.com/nim-lang/Nim/issues/12939
- echo "Cannot print wrapper with check on Windows, review " & outputFile & "\n"
+ echo &"Cannot print wrapper with check on Windows, review {outputFile}\n"
# Redirect output to file
if outputFile.len != 0:
when defined(windows):
- doAssert stdout.reopen(outputFile, fmWrite), "Failed to write to " & outputFile
+ doAssert stdout.reopen(outputFile, fmWrite), &"Failed to write to {outputFile}"
else:
- doAssert outputHandle.open(outputFile, fmWrite), "Failed to write to " & outputFile
+ doAssert outputHandle.open(outputFile, fmWrite), &"Failed to write to {outputFile}"
stdout = outputHandle
# Process grammar into AST
@@ -187,18 +194,52 @@ proc main(
# Restore stdout
stdout = stdoutBackup
- # Print wrapper if temporarily redirected to file
- if check and output.len == 0:
- stdout.write outputFile.readFile()
-
# Check Nim output
if gState.pnim and check:
+ # Run nim check on generated wrapper
var
(check, err) = execCmdEx(&"{getCurrentCompilerExe()} check {outputFile}")
- if err == 0:
- echo "# Checked wrapper successfully"
- else:
- doAssert err == 0, "# Nim check failed:\n\n" & check
+ if err != 0:
+ # Failed check so try stubbing
+ if stub:
+ # Close output file to prepend stubs
+ when not defined(windows):
+ outputHandle.close()
+ else:
+ stdout.close()
+
+ # Find undeclared identifiers in error
+ var
+ data = ""
+ stubData = ""
+ for line in check.splitLines:
+ if "undeclared identifier" in line:
+ try:
+ # Add stub of object type
+ stubData &= " " & line.split("'")[1] & " = object\n"
+ except:
+ discard
+
+ # Include in wrapper file
+ data = outputFile.readFile()
+ if "type\n" in data:
+ # In existing type block
+ data = data.replace("type\n", "type\n" & stubData)
+ else:
+ # At the top if none already
+ data = "type\n" & stubData & data
+ outputFile.writeFile(data)
+
+ # Rerun nim check on stubbed wrapper
+ (check, err) = execCmdEx(&"{getCurrentCompilerExe()} check {outputFile}")
+ doAssert err == 0, "# Nim check with stub failed:\n\n" & check
+ else:
+ doAssert err == 0, "# Nim check failed:\n\n" & check
+
+ when not defined(windows):
+ # Print wrapper if temporarily redirected to file
+ if check and output.len == 0:
+ stdout.write outputFile.readFile()
when isMainModule:
# Setup cligen command line help and short flags
@@ -221,6 +262,7 @@ when isMainModule:
"recurse": "process #include files",
"source" : "C/C++ source/header",
"prefix": "Strip prefix from identifiers",
+ "stub": "stub out undefined type references as objects",
"suffix": "Strip suffix from identifiers",
"symOverride": "skip generating specified symbols"
}, short = {
@@ -237,6 +279,7 @@ when isMainModule:
"prefix": 'E',
"preprocess": 'p',
"recurse": 'r',
+ "stub": 's',
"suffix": 'F',
"symOverride": 'O'
})