var support, interleaved #defines, fix ast1 default, misc performance
This commit is contained in:
parent
985741cc8d
commit
11f84d4d80
7 changed files with 314 additions and 240 deletions
|
|
@ -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")
|
||||
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 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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue