aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2020-04-14 19:40:46 -0500
committerGanesh Viswanathan <dev@genotrance.com>2020-04-14 19:40:46 -0500
commit92fe90f834b1afc1098d4ed63760ca811ab48484 (patch)
tree850f3d83d9f49df27f41600399b39e2076904a57
parent08306b98020d5dcfd513b515f7955d44cfef1d6b (diff)
downloadnimterop-92fe90f834b1afc1098d4ed63760ca811ab48484.tar.gz
nimterop-92fe90f834b1afc1098d4ed63760ca811ab48484.zip
ast2 nested struct support
-rw-r--r--nimterop.nimble2
-rw-r--r--nimterop/ast2.nim77
-rw-r--r--nimterop/getters.nim28
-rw-r--r--nimterop/lisp.nim2
4 files changed, 82 insertions, 27 deletions
diff --git a/nimterop.nimble b/nimterop.nimble
index 9600faa..37c395d 100644
--- a/nimterop.nimble
+++ b/nimterop.nimble
@@ -29,7 +29,7 @@ task bt, "build toast":
execCmd("nim c --hints:off -d:danger nimterop/toast.nim")
task btd, "build toast":
- execCmd("nim c -g --hints:off nimterop/toast.nim")
+ execCmd("nim c -g nimterop/toast.nim")
task docs, "Generate docs":
buildDocs(@["nimterop/all.nim"], "build/htmldocs")
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim
index 708b473..8dba84a 100644
--- a/nimterop/ast2.nim
+++ b/nimterop/ast2.nim
@@ -495,10 +495,12 @@ proc newArrayTree(nimState: NimState, node: TSNode, typ, size: PNode = nil): PNo
proc getTypeArray(nimState: NimState, node, tnode: TSNode, name: string): PNode
proc getTypeProc(nimState: NimState, name: string, node, rnode: TSNode): PNode
-iterator newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: SomeInteger, exported = false): PNode =
+iterator newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: SomeInteger, ftname = "", exported = false): PNode =
# Create nkIdentDefs tree for specified proc parameter or object field
#
- # For proc, param should not be exported
+ # For proc, param should not be `exported`
+ #
+ # If `ftname` is set, use it as the type name
#
# pname: [ptr ..] typ
#
@@ -531,7 +533,15 @@ iterator newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: So
start = getStartAtom(node)
# node[start] - param type
- (tname, _, tinfo) = nimState.getNameInfo(node[start].getAtom(), nskType, parent = name)
+ (tname0, _, tinfo) = nimState.getNameInfo(node[start].getAtom(), nskType, parent = name)
+
+ # Override type name
+ tname =
+ if ftname.nBl:
+ ftname
+ else:
+ tname0
+
tident = nimState.getIdent(tname, tinfo, exported = false)
if start == node.len - 1:
@@ -676,6 +686,7 @@ proc newProcTy(nimState: NimState, name: string, node: TSNode, rtyp: PNode): PNo
result.add nimState.newFormalParams(name, node, rtyp)
result.add nimState.newPragma(node, nimState.gState.convention)
+proc processNode(nimState: NimState, node: TSNode): bool
proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
# Create nkRecList tree for specified object
if not node.isNil:
@@ -691,8 +702,34 @@ proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
for i in 0 ..< node.len:
if node[i].getName() == "field_declaration":
+ # Check for nested structs / unions / enums
+ let
+ fdecl = node[i].anyChildInTree("field_declaration_list")
+ edecl = node[i].anyChildInTree("enumerator_list")
+
+ # `tname` is name of nested struct / union / enum just
+ # added, passed on as type name for field in `newIdentDefs()`
+ (processed, tname) =
+ if not fdecl.isNil:
+ # Nested struct / union
+ (
+ nimState.processNode(fdecl.tsNodeParent()),
+ nimState.typeSection[^1].getIdentName()
+ )
+ elif not edecl.isNil:
+ # Nested enum
+ (
+ nimState.processNode(edecl.tsNodeParent()),
+ $nimState.enumSection[^1][0][1]
+ )
+ else:
+ (true, "")
+
+ if not processed:
+ return nil
+
# Add nkIdentDefs for each field
- for field in nimState.newIdentDefs(name, node[i], i, exported = true):
+ for field in nimState.newIdentDefs(name, node[i], i, ftname = tname, exported = true):
if not field.isNil:
result.add field
@@ -722,6 +759,16 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
pragmas
+ fname =
+ if not node.firstChildInTree("field_declaration_list").isNil and
+ node.tsNodeParent().getName() == "field_declaration":
+ # If nested struct / union without a name
+ nimState.getUniqueIdentifier(
+ if union: "Union" else: "Type"
+ )
+ else:
+ fname
+
typeDefExisting = not typeDef.isNil
typeDef =
@@ -784,7 +831,11 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
if not fdlist.isNil and fdlist.len > 0:
# Add fields to object if present
- obj.add nimState.newRecListTree(name, fdlist)
+ let
+ fields = nimState.newRecListTree(name, fdlist)
+ if fields.isNil:
+ return
+ obj.add fields
else:
obj.add newNode(nkEmpty)
@@ -828,7 +879,11 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
def[2].kind == nkObjectTy and def[2].len == 3 and
def[2][2].kind == nkEmpty:
# Add fields to existing object
- def[2][2] = nimState.newRecListTree(name, fdlist)
+ let
+ fields = nimState.newRecListTree(name, fdlist)
+ if fields.isNil:
+ return
+ def[2][2] = fields
# Change incompleteStruct to bycopy pragma
if def[0].kind == nkPragmaExpr and def[0].len == 2 and
@@ -1180,7 +1235,7 @@ proc addType(nimState: NimState, node: TSNode, union = false) =
let
fdecl = node[1].anyChildInTree("function_declarator")
adecl = node[1].anyChildInTree("array_declarator")
- if fdlist.isNil():
+ if fdlist.isNil:
if adecl.isNil and fdecl.isNil:
# typedef X Y;
# typedef X *Y;
@@ -1605,18 +1660,18 @@ proc searchTree(nimState: NimState, root: TSNode) =
processed = false
while true:
- if not node.isNil() and depth > -1:
+ if not node.isNil and depth > -1:
processed = nimState.processNode(node)
else:
break
- if not processed and node.len() != 0:
+ if not processed and node.len != 0:
nextnode = node[0]
depth += 1
else:
nextnode = node.tsNodeNextNamedSibling()
- if nextnode.isNil():
+ if nextnode.isNil:
while true:
node = node.tsNodeParent()
depth -= 1
@@ -1624,7 +1679,7 @@ proc searchTree(nimState: NimState, root: TSNode) =
break
if node == root:
break
- if not node.tsNodeNextNamedSibling().isNil():
+ if not node.tsNodeNextNamedSibling().isNil:
node = node.tsNodeNextNamedSibling()
break
else:
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 76b528d..aeefbd8 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -214,7 +214,7 @@ proc len*(node: TSNode): int =
result = node.tsNodeNamedChildCount().int
proc `[]`*(node: TSNode, i: SomeInteger): TSNode =
- if i < node.len():
+ if i < node.len:
result = node.tsNodeNamedChild(i.uint32)
proc getName*(node: TSNode): string {.inline.} =
@@ -233,10 +233,10 @@ proc getAtom*(node: TSNode): TSNode =
# Get child node which is topmost atom
if node.getName() in gAtoms:
return node
- elif node.len() != 0:
+ elif node.len != 0:
if node[0].getName() == "type_qualifier":
# Skip const, volatile
- if node.len() > 1:
+ if node.len > 1:
return node[1].getAtom()
else:
return
@@ -262,10 +262,10 @@ proc getXCount*(node: TSNode, ntype: string, reverse = false): int =
if reverse:
cnode = cnode.tsNodeParent()
else:
- if cnode.len() != 0:
+ if cnode.len != 0:
if cnode[0].getName() == "type_qualifier":
# Skip const, volatile
- if cnode.len() > 1:
+ if cnode.len > 1:
cnode = cnode[1]
else:
break
@@ -285,7 +285,7 @@ proc getDeclarator*(node: TSNode): TSNode =
# Return if child is a function or array declarator
if node.getName() in ["function_declarator", "array_declarator"]:
return node
- elif node.len() != 0:
+ elif node.len != 0:
return node[0].getDeclarator()
proc firstChildInTree*(node: TSNode, ntype: string): TSNode =
@@ -307,7 +307,7 @@ proc anyChildInTree*(node: TSNode, ntype: string): TSNode =
for i in 0 ..< cnode.len:
let
ccnode = cnode[i].anyChildInTree(ntype)
- if not ccnode.isNil():
+ if not ccnode.isNil:
return ccnode
if cnode != node:
cnode = cnode.tsNodeNextNamedSibling()
@@ -326,7 +326,7 @@ proc mostNestedChildInTree*(node: TSNode): TSNode =
proc inChildren*(node: TSNode, ntype: string): bool =
# Search for node type in immediate children
result = false
- for i in 0 ..< node.len():
+ for i in 0 ..< node.len:
if (node[i]).getName() == ntype:
result = true
break
@@ -342,7 +342,7 @@ proc getLineCol*(gState: State, node: TSNode): tuple[line, col: int] =
result.col += 1
proc getTSNodeNamedChildCountSansComments*(node: TSNode): int =
- for i in 0 ..< node.len():
+ for i in 0 ..< node.len:
if node.getName() != "comment":
result += 1
@@ -352,11 +352,11 @@ proc getPxName*(node: TSNode, offset: int): string =
np = node
count = 0
- while not np.isNil() and count < offset:
+ while not np.isNil and count < offset:
np = np.tsNodeParent()
count += 1
- if count == offset and not np.isNil():
+ if count == offset and not np.isNil:
return np.getName()
proc printLisp*(gState: State, root: TSNode): string =
@@ -366,7 +366,7 @@ proc printLisp*(gState: State, root: TSNode): string =
depth = 0
while true:
- if not node.isNil() and depth > -1:
+ if not node.isNil and depth > -1:
result &= spaces(depth)
let
(line, col) = gState.getLineCol(node)
@@ -386,7 +386,7 @@ proc printLisp*(gState: State, root: TSNode): string =
result &= ")\n"
nextnode = node.tsNodeNextNamedSibling()
- if nextnode.isNil():
+ if nextnode.isNil:
while true:
node = node.tsNodeParent()
depth -= 1
@@ -395,7 +395,7 @@ proc printLisp*(gState: State, root: TSNode): string =
result &= spaces(depth) & ")\n"
if node == root:
break
- if not node.tsNodeNextNamedSibling().isNil():
+ if not node.tsNodeNextNamedSibling().isNil:
node = node.tsNodeNextNamedSibling()
break
else:
diff --git a/nimterop/lisp.nim b/nimterop/lisp.nim
index fb488d8..8287cf5 100644
--- a/nimterop/lisp.nim
+++ b/nimterop/lisp.nim
@@ -35,7 +35,7 @@ proc readFromTokens(): ref Ast =
idx += 2
while gTokens[idx] != ")":
var res = readFromTokens()
- if not res.isNil():
+ if not res.isNil:
result.children.add(res)
elif gTokens[idx] == ")":
doAssert false, "Poor AST " & $(idx: idx)