aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2020-05-20 15:16:26 -0500
committerGanesh Viswanathan <dev@genotrance.com>2020-05-20 15:16:26 -0500
commite32fd4d1d2542a6ffaeb8221a3da7ef136669651 (patch)
tree20e22a8e606adca551d0c0a9c667c078cd902cb9
parent7d3f52f1dc0829bc8540a413925147b96b5298fe (diff)
downloadnimterop-e32fd4d1d2542a6ffaeb8221a3da7ef136669651.tar.gz
nimterop-e32fd4d1d2542a6ffaeb8221a3da7ef136669651.zip
ast2 handle tree-sitter errors, multi-reorder
-rw-r--r--nimterop/ast2.nim102
-rw-r--r--nimterop/getters.nim8
-rw-r--r--nimterop/globals.nim3
3 files changed, 65 insertions, 48 deletions
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim
index 3d52e02..e2cdf8f 100644
--- a/nimterop/ast2.nim
+++ b/nimterop/ast2.nim
@@ -27,7 +27,7 @@ proc getOverrideOrSkip(gState: State, node: TSNode, origname: string, kind: NimS
if not pnode.isNil:
result = pnode[0][0]
else:
- gecho &"\n# $1'{origname}' skipped" % skind
+ gecho &"# {skind}'{origname}' skipped"
gState.skippedSyms.incl origname
proc addOverrideFinal(gState: State, kind: NimSymKind) =
@@ -391,7 +391,7 @@ proc newXIdent(gState: State, node: TSNode, kind = nskType, fname = "", pragmas:
gState.identifierNodes[name] = result
else:
- gecho &"# $1 '{origname}' is duplicate, skipped" % getKeyword(kind)
+ gecho &"# {getKeyword(kind)} '{origname}' is duplicate, skipped"
proc newArrayTree(gState: State, node: TSNode, typ, size: PNode = nil): PNode =
# Create nkBracketExpr tree depending on input
@@ -682,7 +682,7 @@ proc newProcTy(gState: State, name: string, node: TSNode, rtyp: PNode): PNode =
if node.getVarargs():
gState.addPragma(node, result[^1], "varargs")
-proc processNode(gState: State, node: TSNode): bool
+proc processNode(gState: State, node: TSNode): Status
proc newRecListTree(gState: State, name: string, node: TSNode): PNode =
# Create nkRecList tree for specified object
if not node.isNil:
@@ -720,9 +720,9 @@ proc newRecListTree(gState: State, name: string, node: TSNode): PNode =
$gState.enumSection[^1][0][1]
)
else:
- (true, "")
+ (success, "")
- if not processed:
+ if processed != success:
return nil
# Add nkIdentDefs for each field
@@ -1699,35 +1699,52 @@ proc addDef(gState: State, node: TSNode) =
if not gState.noHeader:
gState.addProc(node[start+1], node[start], commentNodes)
else:
- gecho &"\n# proc '$1' skipped - static inline procs cannot work with '--noHeader | -H'" %
+ gecho "# proc '$1' skipped - static inline procs cannot work with '--noHeader | -H'" %
gState.getNodeVal(node[start+1].getAtom())
-proc processNode(gState: State, node: TSNode): bool =
- result = true
-
- case node.getName()
- of "preproc_def":
- gState.addConst(node)
- of "type_definition":
- if node.len > 0 and node[0].getName() == "enum_specifier":
- gState.addEnum(node)
- elif node.len > 0 and node[0].getName() == "union_specifier":
- gState.addType(node, union = true)
+proc processNode(gState: State, node: TSNode): Status =
+ const
+ known = ["preproc_def", "type_definition",
+ "struct_specifier", "union_specifier", "enum_specifier",
+ "declaration", "function_definition"].toHashSet()
+
+ result = success
+ let
+ name = node.getName()
+ if name in known:
+ # Recognized top-level nodes
+ let
+ err = node.anyChildInTree("ERROR")
+ if not err.isNil:
+ # Bail on errors
+ gState.printDebug(node)
+ gecho &"# tree-sitter parse error: '{gState.getNodeVal(node).splitLines()[0]}', skipped"
+ result = Status.error
else:
- gState.addType(node)
- of "struct_specifier":
- gState.addType(node)
- of "union_specifier":
- gState.addType(node, union = true)
- of "enum_specifier":
- gState.addEnum(node)
- of "declaration":
- gState.addDecl(node)
- of "function_definition":
- gState.addDef(node)
+ # Process nodes
+ case name
+ of "preproc_def":
+ gState.addConst(node)
+ of "type_definition":
+ if node.len > 0 and node[0].getName() == "enum_specifier":
+ gState.addEnum(node)
+ elif node.len > 0 and node[0].getName() == "union_specifier":
+ gState.addType(node, union = true)
+ else:
+ gState.addType(node)
+ of "struct_specifier":
+ gState.addType(node)
+ of "union_specifier":
+ gState.addType(node, union = true)
+ of "enum_specifier":
+ gState.addEnum(node)
+ of "declaration":
+ gState.addDecl(node)
+ of "function_definition":
+ gState.addDef(node)
else:
- # Unknown
- result = false
+ # Unknown, will check child nodes
+ result = unknown
proc searchTree(gState: State, root: TSNode) =
# Search AST generated by tree-sitter for recognized elements
@@ -1735,7 +1752,7 @@ proc searchTree(gState: State, root: TSNode) =
node = root
nextnode: TSNode
depth = 0
- processed = false
+ processed = success
while true:
if not node.isNil and depth > -1:
@@ -1743,7 +1760,7 @@ proc searchTree(gState: State, root: TSNode) =
else:
break
- if not processed and node.len != 0:
+ if processed == unknown and node.len != 0:
nextnode = node[0]
depth += 1
else:
@@ -1773,27 +1790,28 @@ proc searchTree(gState: State, root: TSNode) =
proc setupPragmas(gState: State, root: TSNode, fullpath: string) =
# Create shortcut pragmas to reduce clutter
var
- hdrPragma: PNode
- dynPragma: PNode
+ count = 0
if not gState.noHeader:
# {.pragma: impnameHdr, header: "xxx".}
- hdrPragma = gState.newPragma(root, "pragma", gState.getIdent(gState.impShort & "Hdr"))
+ let
+ hdrPragma = gState.newPragma(root, "pragma", gState.getIdent(gState.impShort & "Hdr"))
gState.addPragma(root, hdrPragma, "header", newStrNode(nkStrLit, fullpath))
+ gState.pragmaSection.add hdrPragma
+ count += 1
if gState.dynlib.nBl:
# {.pragma: impnameDyn, dynlib: libname.}
- dynPragma = gState.newPragma(root, "pragma", gState.getIdent(gState.impShort & "Dyn"))
+ let
+ dynPragma = gState.newPragma(root, "pragma", gState.getIdent(gState.impShort & "Dyn"))
gState.addPragma(root, dynPragma, "dynlib", gState.getIdent(gState.dynlib))
-
- # Add pragma shortcuts to output
- if not hdrPragma.isNil:
- gState.pragmaSection.add hdrPragma
- if not dynPragma.isNil:
gState.pragmaSection.add dynPragma
+ count += 1
# Add `{.experimental: "codeReordering".} for #206
- gState.pragmaSection.add gState.newPragma(root, "experimental", newStrNode(nkStrLit, "codeReordering"))
+ if gState.pragmaSection.len == count:
+ # Only if not already done
+ gState.pragmaSection.add gState.newPragma(root, "experimental", newStrNode(nkStrLit, "codeReordering"))
proc initNim*(gState: State) =
# Initialize for parseNim() one time
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 716c577..0906d56 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -251,7 +251,6 @@ proc getPreprocessor*(gState: State, fullpath: string) =
cmts = if gState.noComments: "" else: "-CC"
cmd = &"""{getCompiler()} -E {cmts} -dD {getGccModeArg(gState.mode)} -w """
- ddata: seq[string]
rdata: seq[string]
start = false
sfile = fullpath.sanitizePath(noQuote = true)
@@ -302,11 +301,8 @@ proc getPreprocessor*(gState: State, fullpath: string) =
if start:
if "#undef" in line:
continue
- elif line.startsWith("#define"):
- ddata.add line
- else:
- rdata.add line
- gState.code = ddata.join("\n") & "\n" & rdata.join("\n")
+ rdata.add line
+ gState.code = rdata.join("\n")
converter toString*(kind: Kind): string =
return case kind:
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index ac25a40..8062ac8 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -131,6 +131,9 @@ when defined(TOAST):
AstTable* {.used.} = TableRef[string, seq[ref Ast]]
+ Status* = enum
+ success, unknown, error
+
# Redirect output to file when required
template gecho*(args: string) =
if gState.outputHandle.isNil: