aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2020-05-18 11:22:54 -0500
committerGanesh Viswanathan <dev@genotrance.com>2020-05-18 23:47:31 -0500
commit11f84d4d8075d96aed623d09972a79f2702486a8 (patch)
tree8bc5a1d949c7d5d268a3d29776c3a7fc9025bde2
parent985741cc8de35ea36933ddb845f93316288c30b8 (diff)
downloadnimterop-11f84d4d8075d96aed623d09972a79f2702486a8.tar.gz
nimterop-11f84d4d8075d96aed623d09972a79f2702486a8.zip
var support, interleaved #defines, fix ast1 default, misc performance
-rw-r--r--nimterop/ast2.nim505
-rw-r--r--nimterop/exprparser.nim3
-rw-r--r--nimterop/getters.nim35
-rw-r--r--nimterop/globals.nim2
-rw-r--r--nimterop/toast.nim8
-rw-r--r--nimterop/tshelp.nim2
-rw-r--r--tests/rsa.nim3
7 files changed, 316 insertions, 242 deletions
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim
index dff355e..3d52e02 100644
--- a/nimterop/ast2.nim
+++ b/nimterop/ast2.nim
@@ -1,7 +1,5 @@
import macros, os, sequtils, sets, strformat, strutils, tables, times
-import options as opts
-
import compiler/[ast, idents, lineinfos, modulegraphs, msgs, options, renderer]
import "."/treesitter/api
@@ -136,6 +134,8 @@ proc newConstDef(gState: State, node: TSNode, fname = "", fval = ""): PNode =
result.add valident[0]
else:
result.add valident
+ # In case symbol was skipped earlier
+ gState.skippedSyms.excl origname
else:
gecho &"# const '{origname}' is duplicate, skipped"
else:
@@ -251,7 +251,7 @@ proc newXIdent(gState: State, node: TSNode, kind = nskType, fname = "", pragmas:
(tname, torigname, info) =
if not atom.isNil:
- gState.getNameInfo(node.getAtom(), kind)
+ gState.getNameInfo(atom, kind)
else:
("", "", gState.getLineInfo(node))
@@ -342,46 +342,42 @@ proc newXIdent(gState: State, node: TSNode, kind = nskType, fname = "", pragmas:
result.add prident
result.add newNode(nkEmpty)
elif kind == nskVar:
- # var name* {.importc: "abc".}
+ # Used by `addVar()` for regular vars and proc vars
#
- # nkIdentDefs(
- # nkPragmaExpr(
- # nkPostfix(
- # nkIdent("*"),
- # nkIdent(name)
- # ),
- # nkPragma(
- # nkExprColonExpr(
- # nkIdent("importc"),
- # nkStrLit("abc")
- # )
+ # name* {.importc: "abc".}
+ #
+ # nkPragmaExpr(
+ # nkPostfix(
+ # nkIdent("*"),
+ # nkIdent(name)
+ # ),
+ # nkPragma(
+ # nkExprColonExpr(
+ # nkIdent("importc"),
+ # nkStrLit("abc")
# )
# )
# )
- let
- prident = block:
- var
- prident: PNode
- # Add {.importc.} pragma
- if name != origname:
- # Name changed
- prident = gState.newPragmaExpr(node, ident, "importc", newStrNode(nkStrLit, &"{origname}"))
- else:
- prident = gState.newPragmaExpr(node, ident, "importc")
-
- if gState.dynlib.nBl:
- # Add {.dynlib.}
- gState.addPragma(node, prident[1], gState.impShort & "Dyn")
- elif not gState.noHeader:
- # Add {.header.}
- gState.addPragma(node, prident[1], gState.impShort & "Hdr")
-
- if pragmas.nBl:
- gState.addPragma(node, prident[1], pragmas)
- prident
-
- result = newNode(nkIdentDefs)
- result.add prident
+ result = block:
+ var
+ prident: PNode
+ # Add {.importc.} pragma
+ if name != origname:
+ # Name changed
+ prident = gState.newPragmaExpr(node, ident, "importc", newStrNode(nkStrLit, &"{origname}"))
+ else:
+ prident = gState.newPragmaExpr(node, ident, "importc")
+
+ if gState.dynlib.nBl:
+ # Add {.dynlib.}
+ gState.addPragma(node, prident[1], gState.impShort & "Dyn")
+ elif not gState.noHeader:
+ # Add {.header.}
+ gState.addPragma(node, prident[1], gState.impShort & "Hdr")
+
+ if pragmas.nBl:
+ gState.addPragma(node, prident[1], pragmas)
+ prident
elif kind == nskProc:
# name*
#
@@ -426,12 +422,39 @@ proc newArrayTree(gState: State, node: TSNode, typ, size: PNode = nil): PNode =
proc getTypeArray(gState: State, node: TSNode, tident: PNode, name: string): PNode
proc getTypeProc(gState: State, name: string, node, rnode: TSNode): PNode
-iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInteger, ftname = "", exported = false): PNode =
- # Create nkIdentDefs tree for specified proc parameter or object field
+proc getTypeAndStart(gState: State, name: string, node: TSNode, ftname = ""):
+ tuple[tname: string, tinfo: TLineInfo, tident: PNode, start: int] =
+ # Shortcut to get start node and type info from first node
#
- # For proc, param should not be `exported`
+ # `name` is the parent type or proc
#
- # If `ftname` is set, use it as the type name
+ # If `ftname` is set, use it as the type name instead
+ result.start = getStartAtom(node)
+
+ let
+ # node[start] - param type
+ (tname0, _, tinfo) = gState.getNameInfo(node[result.start].getAtom(), nskType, parent = name)
+
+ # Override type name
+ result.tname =
+ if ftname.nBl:
+ ftname
+ else:
+ tname0
+
+ result.tinfo = tinfo
+ result.tident = gState.getIdent(result.tname, tinfo, exported = false)
+
+proc newIdentDef(gState: State, name: string, node: TSNode, tname: string, tinfo: TLineInfo, tident: PNode,
+ start, offset, poffset: SomeInteger, exported = false): PNode =
+ # Create nkIdentDefs tree for specified proc parameter, object field or var/proc var
+ #
+ # `name` is the parent type or proc - if blank, this is a var so add pragmas
+ # `tname`, `tinfo` and `tident` are the type info for the node
+ # `start` is the `node` child where type is located
+ # `offset` is the nth `node` child where specified param/field/var is located - from `addVar()`
+ # `poffset` is the param number and used for unnamed params in procs - from `newIdentDefs()` iterator
+ # `isvar` when true adds pragmas
#
# pname: [ptr ..] typ
#
@@ -441,7 +464,7 @@ iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInt
# nkEmpty()
# )
#
- # For object, field should be exported
+ # For objects and vars/proc vars, field should be exported
#
# pname*: [ptr ..] typ
#
@@ -453,6 +476,125 @@ iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInt
# typ,
# nkEmpty()
# )
+ result = newNode(nkIdentDefs)
+
+ let
+ fdecl = node[offset].firstChildInTree("function_declarator")
+ afdecl = node[offset].firstChildInTree("abstract_function_declarator")
+ adecl = node[offset].firstChildInTree("array_declarator")
+ abst = node[offset].getName() == "abstract_pointer_declarator"
+ if fdecl.isNil and afdecl.isNil and adecl.isNil:
+ if abst:
+ # Only for proc with no named param with pointer type
+ # Create a param name based on poffset
+ #
+ # int func(char *, int **);
+ let
+ pname = "a" & $(poffset+1)
+ pident = gState.getIdent(pname, tinfo, exported)
+ acount = node[offset].getXCount("abstract_pointer_declarator")
+ result.add pident
+ result.add gState.newPtrTree(acount, tident)
+ result.add newNode(nkEmpty)
+ else:
+ # Named param, simple type
+ if name.nBl:
+ # Types and procs - `newIdentDefs()` iterator
+ let
+ (pname, _, pinfo) = gState.getNameInfo(node[offset].getAtom(), nskField, parent = name)
+ pident = gState.getIdent(pname, pinfo, exported)
+
+ # Bitfield support - typedef struct { int field: 1; };
+ prident =
+ if node.len > offset and node[offset + 1].getName() == "bitfield_clause":
+ gState.newPragmaExpr(node, pident, "bitsize",
+ newIntNode(nkIntLit, parseInt(gState.getNodeVal(node[offset + 1].getAtom()))))
+ else:
+ pident
+
+ result.add prident
+ else:
+ # Vars - `addVar()`
+ let
+ pident = gState.newXIdent(node[offset], nskVar)
+ if pident.isNil:
+ return nil
+
+ result.add pident
+
+ let
+ count = node[offset].getPtrCount()
+ if count > 0:
+ result.add gState.newPtrTree(count, tident)
+ else:
+ result.add tident
+ result.add newNode(nkEmpty)
+ elif not fdecl.isNil:
+ # Named param, function pointer
+ var
+ name = name
+ pident: PNode
+ if name.nBl:
+ # Types and procs - `newIdentDefs()` iterator
+ let
+ (pname, _, pinfo) = gState.getNameInfo(node[offset].getAtom(), nskField, parent = name)
+ pident = gState.getIdent(pname, pinfo, exported)
+ else:
+ # Vars - `addVar()`
+ pident = gState.newXIdent(node[offset], nskVar)
+ if pident.isNil:
+ return nil
+ # The var is the parent
+ name = pident.getIdentName()
+
+ result.add pident
+ result.add gState.getTypeProc(name, node[offset], node[start])
+ result.add newNode(nkEmpty)
+ elif not afdecl.isNil:
+ # Only for proc with no named param with function pointer type
+ # Create a param name based on poffset
+ #
+ # int func(int (*)(int *));
+ let
+ pname = "a" & $(poffset+1)
+ pident = gState.getIdent(pname, tinfo, exported)
+ procTy = gState.getTypeProc(name, node[offset], node[start])
+ result.add pident
+ result.add procTy
+ result.add newNode(nkEmpty)
+ elif not adecl.isNil:
+ # Named param, array type
+ var
+ name = name
+ pident: PNode
+ if name.nBl:
+ # Types and procs - `newIdentDefs()` iterator
+ let
+ (pname, _, pinfo) = gState.getNameInfo(node[offset].getAtom(), nskField, parent = name)
+ pident = gState.getIdent(pname, pinfo, exported)
+ else:
+ # Vars - `addVar()`
+ pident = gState.newXIdent(node[offset], nskVar)
+ if pident.isNil:
+ return nil
+ # The var is the parent
+ name = pident.getIdentName()
+
+ result.add pident
+ result.add gState.getTypeArray(node[offset], tident, name)
+ result.add newNode(nkEmpty)
+ else:
+ result = nil
+
+iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInteger, ftname = "", exported = false): PNode =
+ # Create nkIdentDefs tree for specified proc parameter or object field
+ #
+ # `name` is the parent type or proc
+ # `offset` is the param number and used for unnamed params in procs
+ #
+ # For proc, param should not be `exported`
+ #
+ # If `ftname` is set, use it as the type name
#
# Iterator since structs can have multiple comma separated fields for the
# same type so can yield multiple results.
@@ -460,23 +602,12 @@ iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInt
# struct ABC { int w, h; };
#
# This is not applicable for procs.
- var
- start = getStartAtom(node)
-
let
- # node[start] - param type
- (tname0, _, tinfo) = gState.getNameInfo(node[start].getAtom(), nskType, parent = name)
-
- # Override type name
- tname =
- if ftname.nBl:
- ftname
- else:
- tname0
-
- tident = gState.getIdent(tname, tinfo, exported = false)
+ (tname, tinfo, tident, start0) = gState.getTypeAndStart(name, node, ftname)
# Skip qualifiers after type
+ var
+ start = start0
while start < node.len - 1 and node[start+1].getName() == "type_qualifier":
start += 1
@@ -503,82 +634,7 @@ iterator newIdentDefs(gState: State, name: string, node: TSNode, offset: SomeInt
for i in start+1 ..< node.len:
if node[i].getName() == "bitfield_clause":
continue
-
- var
- result = newNode(nkIdentDefs)
-
- let
- fdecl = node[i].firstChildInTree("function_declarator")
- afdecl = node[i].firstChildInTree("abstract_function_declarator")
- adecl = node[i].firstChildInTree("array_declarator")
- abst = node[i].getName() == "abstract_pointer_declarator"
- if fdecl.isNil and afdecl.isNil and adecl.isNil:
- if abst:
- # Only for proc with no named param with pointer type
- # Create a param name based on offset
- #
- # int func(char *, int **);
- let
- pname = "a" & $(offset+1)
- pident = gState.getIdent(pname, tinfo, exported)
- acount = node[i].getXCount("abstract_pointer_declarator")
- result.add pident
- result.add gState.newPtrTree(acount, tident)
- result.add newNode(nkEmpty)
- else:
- # Named param, simple type
- let
- (pname, _, pinfo) = gState.getNameInfo(node[i].getAtom(), nskField, parent = name)
- pident = gState.getIdent(pname, pinfo, exported)
-
- # Bitfield support - typedef struct { int field: 1; };
- prident =
- if node.len > i and node[i + 1].getName() == "bitfield_clause":
- gState.newPragmaExpr(node, pident, "bitsize",
- newIntNode(nkIntLit, parseInt(gState.getNodeVal(node[i + 1].getAtom()))))
- else:
- pident
-
- count = node[i].getPtrCount()
-
- result.add prident
- if count > 0:
- result.add gState.newPtrTree(count, tident)
- else:
- result.add tident
- result.add newNode(nkEmpty)
- elif not fdecl.isNil:
- # Named param, function pointer
- let
- (pname, _, pinfo) = gState.getNameInfo(node[i].getAtom(), nskField, parent = name)
- pident = gState.getIdent(pname, pinfo, exported)
- result.add pident
- result.add gState.getTypeProc(name, node[i], node[start])
- result.add newNode(nkEmpty)
- elif not afdecl.isNil:
- # Only for proc with no named param with function pointer type
- # Create a param name based on offset
- #
- # int func(int (*)(int *));
- let
- pname = "a" & $(offset+1)
- pident = gState.getIdent(pname, tinfo, exported)
- procTy = gState.getTypeProc(name, node[i], node[start])
- result.add pident
- result.add procTy
- result.add newNode(nkEmpty)
- elif not adecl.isNil:
- # Named param, array type
- let
- (pname, _, pinfo) = gState.getNameInfo(node[i].getAtom(), nskField, parent = name)
- pident = gState.getIdent(pname, pinfo, exported)
- result.add pident
- result.add gState.getTypeArray(node[i], tident, name)
- result.add newNode(nkEmpty)
- else:
- result = nil
-
- yield result
+ yield gState.newIdentDef(name, node, tname, tinfo, tident, start, i, offset, exported)
proc newFormalParams(gState: State, name: string, node: TSNode, rtyp: PNode): PNode =
# Create nkFormalParams tree for specified params and return type
@@ -967,11 +1023,8 @@ proc addTypeArray(gState: State, node: TSNode) =
# Add a type of array type
decho("addTypeArray()")
let
- start = getStartAtom(node)
+ (_, _, tident, start) = gState.getTypeAndStart("addTypeArray", node)
- # node[start] = identifier = type name
- (tname, _, info) = gState.getNameInfo(node[start].getAtom(), nskType, parent = "addTypeArray")
- tident = gState.getIdent(tname, info, exported = false)
commentNodes = gState.getCommentNodes(node)
# Could have multiple types, comma separated
@@ -1015,6 +1068,7 @@ proc addTypeArray(gState: State, node: TSNode) =
proc getTypeProc(gState: State, name: string, node, rnode: TSNode): PNode =
# Create proc type tree
#
+ # `name` is the parent type or proc
# `rnode` is the return type
let
# rnode = identifier = return type name
@@ -1368,7 +1422,7 @@ proc addEnum(gState: State, node: TSNode) =
fnames: HashSet[string]
# Hold all of field information so that we can add all of them
# after the const identifiers has been updated
- fieldDeclarations: seq[tuple[fname: string, fval: string, cexpr: Option[TSNode], comment: seq[TSNode]]]
+ fieldDeclarations: seq[tuple[fname, forigname, fval, cexpr: string, comment: seq[TSNode]]]
for i in 0 .. enumlist.len - 1:
let
en = enumlist[i]
@@ -1378,7 +1432,8 @@ proc addEnum(gState: State, node: TSNode) =
let
atom = en.getAtom()
commentNodes = gState.getCommentNodes(en)
- fname = gState.getIdentifier(gState.getNodeVal(atom), nskEnumField)
+ forigname = gState.getNodeVal(atom)
+ fname = gState.getIdentifier(forigname, nskEnumField)
if fname.nBl and gState.addNewIdentifer(fname):
var
@@ -1391,9 +1446,9 @@ proc addEnum(gState: State, node: TSNode) =
fval = &"({prev} + 1).{name}"
if en.len > 1 and en[1].getName() in gEnumVals:
- fieldDeclarations.add((fname, "", some(en[1]), commentNodes))
+ fieldDeclarations.add((fname, forigname, "", gState.getNodeVal(en[1]), commentNodes))
else:
- fieldDeclarations.add((fname, fval, none(TSNode), commentNodes))
+ fieldDeclarations.add((fname, forigname, fval, "", commentNodes))
fnames.incl fname
prev = fname
@@ -1403,78 +1458,25 @@ proc addEnum(gState: State, node: TSNode) =
gState.constIdentifiers.incl fnames
# parseCExpression requires all const identifiers to be present for the enum
- for (fname, fval, cexprNode, commentNodes) in fieldDeclarations:
- var fval = fval
- if cexprNode.isSome:
- fval = "(" & $gState.parseCExpression(gState.getNodeVal(cexprNode.get()), name) & ")." & name
- # Cannot use newConstDef() since parseString(fval) adds backticks to and/or
- let constNode = gState.parseString(&"const {fname}* = {fval}")[0][0]
+ for (fname, forigname, fval, cexpr, commentNodes) in fieldDeclarations:
+ let
+ fval =
+ if fval.Bl:
+ "(" & $gState.parseCExpression(cexpr, name) & ")." & name
+ else: fval
+
+ # Cannot use newConstDef() since parseString(fval) adds backticks to and/or
+ constNode = gState.parseString(&"const {fname}* = {fval}")[0][0]
+
constNode.comment = gState.getCommentsStr(commentNodes)
gState.constSection.add constNode
+ # In case symbol was skipped earlier
+ gState.skippedSyms.excl forigname
# Add other names
if node.getName() == "type_definition" and node.len > 1:
gState.addTypeTyped(node, ftname = name, offset = offset)
-proc addProcVar(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
- # Add a proc variable
- decho("addProcVar()")
- let
- # node = identifier = name
- identDefs = gState.newXIdent(node, kind = nskVar, istype = true)
-
- if not identDefs.isNil:
- let
- name = identDefs.getIdentName()
- # origname = gState.getNodeVal(node.getAtom())
-
- procTy = gState.getTypeProc(name, node, rnode)
-
- identDefs.add procTy
- identDefs.add newNode(nkEmpty)
-
- # var X* {.importc: "_X": proc(a1: Y, a2: Z): P {.cdecl.}
- #
- # nkIdentDefs(
- # nkPragmaExpr(
- # nkPostfix(
- # nkIdent("*"),
- # nkIdent("X")
- # ),
- # nkPragma(
- # nkExprColonExpr(
- # nkIdent("importc"),
- # nkStrLit("_X")
- # )
- # )
- # ),
- # nkProcTy(
- # nkFormalParams(
- # nkIdent("P"),
- # nkIdentDefs(
- # nkIdent("a1"),
- # nkIdent("Y"),
- # nkEmpty()
- # ),
- # nkIdentDefs(
- # nkIdent("a2"),
- # nkIdent("Z"),
- # nkEmpty()
- # )
- # ),
- # nkPragma(
- # nkIdent("cdecl")
- # )
- # ),
- # nkEmpty()
- # )
-
- identDefs.comment = gState.getCommentsStr(commentNodes)
- # nkVarSection.add
- gState.varSection.add identDefs
-
- gState.printDebug(identDefs)
-
proc addProc(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
# Add a proc
#
@@ -1585,6 +1587,65 @@ proc addProc(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
gState.printDebug(procDef)
+proc addVar(gState: State, node: TSNode, offset: SomeInteger, commentNodes: seq[TSNode]) =
+ # Add a regular variable
+ #
+ # `node` is the `nth` child of (declaration)
+ # `tnode` is the type node, the first child of (declaration)
+ decho("addVar()")
+ let
+ (tname, tinfo, tident, start) = gState.getTypeAndStart("", node)
+
+ identDefs = gState.newIdentDef("", node, tname, tinfo, tident, start, offset, 0, exported = true)
+
+ if not identDefs.isNil:
+ # proc var
+ #
+ # P (*_X)(Y a1, Z a2);
+ #
+ # var X* {.importc: "_X": proc(a1: Y, a2: Z): P {.cdecl.}
+ #
+ # nkIdentDefs(
+ # nkPragmaExpr(
+ # nkPostfix(
+ # nkIdent("*"),
+ # nkIdent("X")
+ # ),
+ # nkPragma(
+ # nkExprColonExpr(
+ # nkIdent("importc"),
+ # nkStrLit("_X")
+ # )
+ # )
+ # ),
+ # nkProcTy(
+ # nkFormalParams(
+ # nkIdent("P"),
+ # nkIdentDefs(
+ # nkIdent("a1"),
+ # nkIdent("Y"),
+ # nkEmpty()
+ # ),
+ # nkIdentDefs(
+ # nkIdent("a2"),
+ # nkIdent("Z"),
+ # nkEmpty()
+ # )
+ # ),
+ # nkPragma(
+ # nkIdent("cdecl")
+ # )
+ # ),
+ # nkEmpty()
+ # )
+
+ identDefs.comment = gState.getCommentsStr(commentNodes)
+
+ # nkVarSection.add
+ gState.varSection.add identDefs
+
+ gState.printDebug(identDefs)
+
proc addDecl(gState: State, node: TSNode) =
# Add a declaration
decho("addDecl()")
@@ -1598,31 +1659,29 @@ proc addDecl(gState: State, node: TSNode) =
commentNodes: seq[TSNode]
for i in start+1 ..< node.len:
+ if node[i].getName() == "comment":
+ continue
+
+ if firstDecl:
+ # If it's the first declaration, use the whole node
+ # to get the comment above/below
+ commentNodes = gState.getCommentNodes(node)
+ firstDecl = false
+ else:
+ commentNodes = gState.getCommentNodes(node[i])
+
if not node[i].firstChildInTree("function_declarator").isNil:
# Proc declaration - var or actual proc
if node[i].getAtom().getPxName(1) == "pointer_declarator":
# proc var
- if firstDecl:
- # If it's the first declaration, use the whole node
- # to get the comment above/below
- commentNodes = gState.getCommentNodes(node)
- firstDecl = false
- else:
- commentNodes = gState.getCommentNodes(node[i])
- gState.addProcVar(node[i], node[start], commentNodes)
+ #gState.addProcVar(node[i], node[start], commentNodes)
+ gState.addVar(node, i, commentNodes)
else:
# proc
- if firstDecl:
- # If it's the first declaration, use the whole node
- # to get the comment above/below
- commentNodes = gState.getCommentNodes(node)
- firstDecl = false
- else:
- commentNodes = gState.getCommentNodes(node[i])
gState.addProc(node[i], node[start], commentNodes)
else:
# Regular var
- discard
+ gState.addVar(node, i, commentNodes)
proc addDef(gState: State, node: TSNode) =
# Wrap static inline definition if {.header.} mode is specified
diff --git a/nimterop/exprparser.nim b/nimterop/exprparser.nim
index b2b8c2c..0fea184 100644
--- a/nimterop/exprparser.nim
+++ b/nimterop/exprparser.nim
@@ -600,7 +600,8 @@ proc processTSNode(gState: State, node: TSNode, typeofNode: var PNode): PNode =
else:
raise newException(ExprParseError, &"Unsupported node type \"{nodeName}\" for node \"{node.val}\"")
- decho "NODE RESULT: ", result
+ if result.kind != nkNone:
+ decho "NODE RESULT: ", result
proc parseCExpression*(gState: State, codeRoot: TSNode): PNode =
## Parse a c expression from a root ts node
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index e600b18..825b1c4 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -116,7 +116,7 @@ proc getType*(str: string): string =
if str == "void":
return "object"
- result = str.strip(chars={'_'}).replace(re"\s+", " ")
+ result = str.strip(chars={'_'}).splitWhitespace().join(" ")
if gTypeMap.hasKey(result):
result = gTypeMap[result]
@@ -246,17 +246,23 @@ proc getKeyword*(kind: NimSymKind): string =
proc getCurrentHeader*(fullpath: string): string =
("header" & fullpath.splitFile().name.multiReplace([(".", ""), ("-", "")]))
-proc getPreprocessor*(gState: State, fullpath: string): string =
+proc getPreprocessor*(gState: State, fullpath: string) =
var
cmts = if gState.noComments: "" else: "-CC"
cmd = &"""{getCompiler()} -E {cmts} -dD {getGccModeArg(gState.mode)} -w """
- rdata: seq[string] = @[]
+ ddata: seq[string]
+ rdata: seq[string]
start = false
sfile = fullpath.sanitizePath(noQuote = true)
+ sfileName = sfile.extractFilename()
+ pDir = sfile.expandFilename().parentDir()
+ includeDirs: seq[string]
+
for inc in gState.includeDirs:
cmd &= &"-I{inc.sanitizePath} "
+ includeDirs.add inc.absolutePath().sanitizePath(noQuote = true)
for def in gState.defines:
cmd &= &"-D{def} "
@@ -267,7 +273,10 @@ proc getPreprocessor*(gState: State, fullpath: string): string =
else:
cmd &= "-D__attribute__(x)= "
- cmd &= "-D__restrict= -D__extension__= "
+ cmd &= "-D__restrict= -D__extension__= -D__inline__=inline -D__inline=inline "
+
+ # https://github.com/tree-sitter/tree-sitter-c/issues/43
+ cmd &= "-D_Noreturn= "
cmd &= &"{fullpath.sanitizePath}"
@@ -278,26 +287,26 @@ proc getPreprocessor*(gState: State, fullpath: string): string =
start = false
let
saniLine = line.sanitizePath(noQuote = true)
- if sfile in saniLine:
- start = true
- elif not ("\\" in line) and not ("/" in line) and extractFilename(sfile) in line:
+ if sfile in saniLine or
+ (DirSep notin saniLine and sfileName in saniLine):
start = true
elif gState.recurse:
- let
- pDir = sfile.expandFilename().parentDir().sanitizePath(noQuote = true)
if pDir.Bl or pDir in saniLine:
start = true
else:
- for inc in gState.includeDirs:
- if inc.absolutePath().sanitizePath(noQuote = true) in saniLine:
+ for inc in includeDirs:
+ if inc in saniLine:
start = true
break
else:
if start:
if "#undef" in line:
continue
- rdata.add line
- return rdata.join("\n")
+ elif line.startsWith("#define"):
+ ddata.add line
+ else:
+ rdata.add line
+ gState.code = ddata.join("\n") & "\n" & rdata.join("\n")
converter toString*(kind: Kind): string =
return case kind:
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index 05284a9..79b1637 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -139,7 +139,7 @@ template Bl*(s: typed): untyped {.used.} =
# Redirect output to file when required
template gecho*(args: string) =
if gState.outputHandle.isNil:
- stdout.writeLine(args)
+ echo args
else:
gState.outputHandle.writeLine(args)
diff --git a/nimterop/toast.nim b/nimterop/toast.nim
index f54aa67..02d6494 100644
--- a/nimterop/toast.nim
+++ b/nimterop/toast.nim
@@ -13,7 +13,7 @@ proc process(gState: State, path: string, astTable: AstTable) =
gState.mode = getCompilerMode(path)
if gState.preprocess:
- gState.code = gState.getPreprocessor(path)
+ gState.getPreprocessor(path)
else:
gState.code = readFile(path)
@@ -35,7 +35,7 @@ proc main(
debug = false,
defines: seq[string] = @[],
dynlib: string = "",
- feature: seq[Feature] = @[Feature.ast1],
+ feature: seq[Feature] = @[],
includeDirs: seq[string] = @[],
mode = "",
nim: string = "nim",
@@ -83,6 +83,10 @@ proc main(
# Set gDebug in build.nim
build.gDebug = debug
+ # Default `ast` mode
+ if gState.feature.Bl:
+ gState.feature.add Feature.ast1
+
# Split some arguments with ,
gState.symOverride = gState.symOverride.getSplitComma()
gState.prefix = gState.prefix.getSplitComma()
diff --git a/nimterop/tshelp.nim b/nimterop/tshelp.nim
index 9565a1f..6760aa9 100644
--- a/nimterop/tshelp.nim
+++ b/nimterop/tshelp.nim
@@ -50,7 +50,7 @@ proc getName*(node: TSNode): string {.inline.} =
proc getNodeVal*(code: var string, node: TSNode): string =
if not node.isNil:
- return code[node.tsNodeStartByte() .. node.tsNodeEndByte()-1].strip()
+ return code[node.tsNodeStartByte() .. node.tsNodeEndByte()-1]
proc getNodeVal*(gState: State, node: TSNode): string =
gState.code.getNodeVal(node)
diff --git a/tests/rsa.nim b/tests/rsa.nim
index e7bde89..a4aa64b 100644
--- a/tests/rsa.nim
+++ b/tests/rsa.nim
@@ -35,10 +35,11 @@ cPlugin:
cOverride:
proc OPENSSL_die*(assertion: cstring; file: cstring; line: cint) {.importc.}
+# Skip comments for https://github.com/tree-sitter/tree-sitter-c/issues/44
cImport(@[
basePath / "rsa.h",
basePath / "err.h",
-], recurse = true, flags = "-f:ast2 -s " & FLAGS)
+], recurse = true, flags = "-f:ast2 -s -c " & FLAGS)
{.passL: cryptoLPath.}