ast2 nested struct support
This commit is contained in:
parent
08306b9802
commit
92fe90f834
4 changed files with 82 additions and 27 deletions
|
|
@ -29,7 +29,7 @@ task bt, "build toast":
|
||||||
execCmd("nim c --hints:off -d:danger nimterop/toast.nim")
|
execCmd("nim c --hints:off -d:danger nimterop/toast.nim")
|
||||||
|
|
||||||
task btd, "build toast":
|
task btd, "build toast":
|
||||||
execCmd("nim c -g --hints:off nimterop/toast.nim")
|
execCmd("nim c -g nimterop/toast.nim")
|
||||||
|
|
||||||
task docs, "Generate docs":
|
task docs, "Generate docs":
|
||||||
buildDocs(@["nimterop/all.nim"], "build/htmldocs")
|
buildDocs(@["nimterop/all.nim"], "build/htmldocs")
|
||||||
|
|
|
||||||
|
|
@ -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 getTypeArray(nimState: NimState, node, tnode: TSNode, name: string): PNode
|
||||||
proc getTypeProc(nimState: NimState, name: string, node, rnode: TSNode): 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
|
# 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
|
# pname: [ptr ..] typ
|
||||||
#
|
#
|
||||||
|
|
@ -531,7 +533,15 @@ iterator newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: So
|
||||||
start = getStartAtom(node)
|
start = getStartAtom(node)
|
||||||
|
|
||||||
# node[start] - param type
|
# 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)
|
tident = nimState.getIdent(tname, tinfo, exported = false)
|
||||||
|
|
||||||
if start == node.len - 1:
|
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.newFormalParams(name, node, rtyp)
|
||||||
result.add nimState.newPragma(node, nimState.gState.convention)
|
result.add nimState.newPragma(node, nimState.gState.convention)
|
||||||
|
|
||||||
|
proc processNode(nimState: NimState, node: TSNode): bool
|
||||||
proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
|
proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
|
||||||
# Create nkRecList tree for specified object
|
# Create nkRecList tree for specified object
|
||||||
if not node.isNil:
|
if not node.isNil:
|
||||||
|
|
@ -691,8 +702,34 @@ proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
|
||||||
|
|
||||||
for i in 0 ..< node.len:
|
for i in 0 ..< node.len:
|
||||||
if node[i].getName() == "field_declaration":
|
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
|
# 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:
|
if not field.isNil:
|
||||||
result.add field
|
result.add field
|
||||||
|
|
||||||
|
|
@ -722,6 +759,16 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
|
||||||
|
|
||||||
pragmas
|
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
|
typeDefExisting = not typeDef.isNil
|
||||||
|
|
||||||
typeDef =
|
typeDef =
|
||||||
|
|
@ -784,7 +831,11 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
|
||||||
|
|
||||||
if not fdlist.isNil and fdlist.len > 0:
|
if not fdlist.isNil and fdlist.len > 0:
|
||||||
# Add fields to object if present
|
# 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:
|
else:
|
||||||
obj.add newNode(nkEmpty)
|
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].kind == nkObjectTy and def[2].len == 3 and
|
||||||
def[2][2].kind == nkEmpty:
|
def[2][2].kind == nkEmpty:
|
||||||
# Add fields to existing object
|
# 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
|
# Change incompleteStruct to bycopy pragma
|
||||||
if def[0].kind == nkPragmaExpr and def[0].len == 2 and
|
if def[0].kind == nkPragmaExpr and def[0].len == 2 and
|
||||||
|
|
@ -1180,7 +1235,7 @@ proc addType(nimState: NimState, node: TSNode, union = false) =
|
||||||
let
|
let
|
||||||
fdecl = node[1].anyChildInTree("function_declarator")
|
fdecl = node[1].anyChildInTree("function_declarator")
|
||||||
adecl = node[1].anyChildInTree("array_declarator")
|
adecl = node[1].anyChildInTree("array_declarator")
|
||||||
if fdlist.isNil():
|
if fdlist.isNil:
|
||||||
if adecl.isNil and fdecl.isNil:
|
if adecl.isNil and fdecl.isNil:
|
||||||
# typedef X Y;
|
# typedef X Y;
|
||||||
# typedef X *Y;
|
# typedef X *Y;
|
||||||
|
|
@ -1605,18 +1660,18 @@ proc searchTree(nimState: NimState, root: TSNode) =
|
||||||
processed = false
|
processed = false
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
if not node.isNil() and depth > -1:
|
if not node.isNil and depth > -1:
|
||||||
processed = nimState.processNode(node)
|
processed = nimState.processNode(node)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not processed and node.len() != 0:
|
if not processed and node.len != 0:
|
||||||
nextnode = node[0]
|
nextnode = node[0]
|
||||||
depth += 1
|
depth += 1
|
||||||
else:
|
else:
|
||||||
nextnode = node.tsNodeNextNamedSibling()
|
nextnode = node.tsNodeNextNamedSibling()
|
||||||
|
|
||||||
if nextnode.isNil():
|
if nextnode.isNil:
|
||||||
while true:
|
while true:
|
||||||
node = node.tsNodeParent()
|
node = node.tsNodeParent()
|
||||||
depth -= 1
|
depth -= 1
|
||||||
|
|
@ -1624,7 +1679,7 @@ proc searchTree(nimState: NimState, root: TSNode) =
|
||||||
break
|
break
|
||||||
if node == root:
|
if node == root:
|
||||||
break
|
break
|
||||||
if not node.tsNodeNextNamedSibling().isNil():
|
if not node.tsNodeNextNamedSibling().isNil:
|
||||||
node = node.tsNodeNextNamedSibling()
|
node = node.tsNodeNextNamedSibling()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ proc len*(node: TSNode): int =
|
||||||
result = node.tsNodeNamedChildCount().int
|
result = node.tsNodeNamedChildCount().int
|
||||||
|
|
||||||
proc `[]`*(node: TSNode, i: SomeInteger): TSNode =
|
proc `[]`*(node: TSNode, i: SomeInteger): TSNode =
|
||||||
if i < node.len():
|
if i < node.len:
|
||||||
result = node.tsNodeNamedChild(i.uint32)
|
result = node.tsNodeNamedChild(i.uint32)
|
||||||
|
|
||||||
proc getName*(node: TSNode): string {.inline.} =
|
proc getName*(node: TSNode): string {.inline.} =
|
||||||
|
|
@ -233,10 +233,10 @@ proc getAtom*(node: TSNode): TSNode =
|
||||||
# Get child node which is topmost atom
|
# Get child node which is topmost atom
|
||||||
if node.getName() in gAtoms:
|
if node.getName() in gAtoms:
|
||||||
return node
|
return node
|
||||||
elif node.len() != 0:
|
elif node.len != 0:
|
||||||
if node[0].getName() == "type_qualifier":
|
if node[0].getName() == "type_qualifier":
|
||||||
# Skip const, volatile
|
# Skip const, volatile
|
||||||
if node.len() > 1:
|
if node.len > 1:
|
||||||
return node[1].getAtom()
|
return node[1].getAtom()
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
@ -262,10 +262,10 @@ proc getXCount*(node: TSNode, ntype: string, reverse = false): int =
|
||||||
if reverse:
|
if reverse:
|
||||||
cnode = cnode.tsNodeParent()
|
cnode = cnode.tsNodeParent()
|
||||||
else:
|
else:
|
||||||
if cnode.len() != 0:
|
if cnode.len != 0:
|
||||||
if cnode[0].getName() == "type_qualifier":
|
if cnode[0].getName() == "type_qualifier":
|
||||||
# Skip const, volatile
|
# Skip const, volatile
|
||||||
if cnode.len() > 1:
|
if cnode.len > 1:
|
||||||
cnode = cnode[1]
|
cnode = cnode[1]
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
@ -285,7 +285,7 @@ proc getDeclarator*(node: TSNode): TSNode =
|
||||||
# Return if child is a function or array declarator
|
# Return if child is a function or array declarator
|
||||||
if node.getName() in ["function_declarator", "array_declarator"]:
|
if node.getName() in ["function_declarator", "array_declarator"]:
|
||||||
return node
|
return node
|
||||||
elif node.len() != 0:
|
elif node.len != 0:
|
||||||
return node[0].getDeclarator()
|
return node[0].getDeclarator()
|
||||||
|
|
||||||
proc firstChildInTree*(node: TSNode, ntype: string): TSNode =
|
proc firstChildInTree*(node: TSNode, ntype: string): TSNode =
|
||||||
|
|
@ -307,7 +307,7 @@ proc anyChildInTree*(node: TSNode, ntype: string): TSNode =
|
||||||
for i in 0 ..< cnode.len:
|
for i in 0 ..< cnode.len:
|
||||||
let
|
let
|
||||||
ccnode = cnode[i].anyChildInTree(ntype)
|
ccnode = cnode[i].anyChildInTree(ntype)
|
||||||
if not ccnode.isNil():
|
if not ccnode.isNil:
|
||||||
return ccnode
|
return ccnode
|
||||||
if cnode != node:
|
if cnode != node:
|
||||||
cnode = cnode.tsNodeNextNamedSibling()
|
cnode = cnode.tsNodeNextNamedSibling()
|
||||||
|
|
@ -326,7 +326,7 @@ proc mostNestedChildInTree*(node: TSNode): TSNode =
|
||||||
proc inChildren*(node: TSNode, ntype: string): bool =
|
proc inChildren*(node: TSNode, ntype: string): bool =
|
||||||
# Search for node type in immediate children
|
# Search for node type in immediate children
|
||||||
result = false
|
result = false
|
||||||
for i in 0 ..< node.len():
|
for i in 0 ..< node.len:
|
||||||
if (node[i]).getName() == ntype:
|
if (node[i]).getName() == ntype:
|
||||||
result = true
|
result = true
|
||||||
break
|
break
|
||||||
|
|
@ -342,7 +342,7 @@ proc getLineCol*(gState: State, node: TSNode): tuple[line, col: int] =
|
||||||
result.col += 1
|
result.col += 1
|
||||||
|
|
||||||
proc getTSNodeNamedChildCountSansComments*(node: TSNode): int =
|
proc getTSNodeNamedChildCountSansComments*(node: TSNode): int =
|
||||||
for i in 0 ..< node.len():
|
for i in 0 ..< node.len:
|
||||||
if node.getName() != "comment":
|
if node.getName() != "comment":
|
||||||
result += 1
|
result += 1
|
||||||
|
|
||||||
|
|
@ -352,11 +352,11 @@ proc getPxName*(node: TSNode, offset: int): string =
|
||||||
np = node
|
np = node
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
while not np.isNil() and count < offset:
|
while not np.isNil and count < offset:
|
||||||
np = np.tsNodeParent()
|
np = np.tsNodeParent()
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
if count == offset and not np.isNil():
|
if count == offset and not np.isNil:
|
||||||
return np.getName()
|
return np.getName()
|
||||||
|
|
||||||
proc printLisp*(gState: State, root: TSNode): string =
|
proc printLisp*(gState: State, root: TSNode): string =
|
||||||
|
|
@ -366,7 +366,7 @@ proc printLisp*(gState: State, root: TSNode): string =
|
||||||
depth = 0
|
depth = 0
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
if not node.isNil() and depth > -1:
|
if not node.isNil and depth > -1:
|
||||||
result &= spaces(depth)
|
result &= spaces(depth)
|
||||||
let
|
let
|
||||||
(line, col) = gState.getLineCol(node)
|
(line, col) = gState.getLineCol(node)
|
||||||
|
|
@ -386,7 +386,7 @@ proc printLisp*(gState: State, root: TSNode): string =
|
||||||
result &= ")\n"
|
result &= ")\n"
|
||||||
nextnode = node.tsNodeNextNamedSibling()
|
nextnode = node.tsNodeNextNamedSibling()
|
||||||
|
|
||||||
if nextnode.isNil():
|
if nextnode.isNil:
|
||||||
while true:
|
while true:
|
||||||
node = node.tsNodeParent()
|
node = node.tsNodeParent()
|
||||||
depth -= 1
|
depth -= 1
|
||||||
|
|
@ -395,7 +395,7 @@ proc printLisp*(gState: State, root: TSNode): string =
|
||||||
result &= spaces(depth) & ")\n"
|
result &= spaces(depth) & ")\n"
|
||||||
if node == root:
|
if node == root:
|
||||||
break
|
break
|
||||||
if not node.tsNodeNextNamedSibling().isNil():
|
if not node.tsNodeNextNamedSibling().isNil:
|
||||||
node = node.tsNodeNextNamedSibling()
|
node = node.tsNodeNextNamedSibling()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ proc readFromTokens(): ref Ast =
|
||||||
idx += 2
|
idx += 2
|
||||||
while gTokens[idx] != ")":
|
while gTokens[idx] != ")":
|
||||||
var res = readFromTokens()
|
var res = readFromTokens()
|
||||||
if not res.isNil():
|
if not res.isNil:
|
||||||
result.children.add(res)
|
result.children.add(res)
|
||||||
elif gTokens[idx] == ")":
|
elif gTokens[idx] == ")":
|
||||||
doAssert false, "Poor AST " & $(idx: idx)
|
doAssert false, "Poor AST " & $(idx: idx)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue