ast2 nested struct support

This commit is contained in:
Ganesh Viswanathan 2020-04-14 19:40:46 -05:00
commit 92fe90f834
4 changed files with 82 additions and 27 deletions

View file

@ -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")

View file

@ -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:

View file

@ -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:

View file

@ -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)