ast2 newTypeIdent cleanup, pragma tests, docs.nim docs

This commit is contained in:
Ganesh Viswanathan 2020-03-25 15:17:20 -05:00
commit 8b9c39f42e
6 changed files with 154 additions and 41 deletions

View file

@ -37,6 +37,7 @@ task test, "Test":
buildToastTask()
execTest "tests/tast2.nim"
#execCmd "nim c -f -d:HEADER -r tests/tast2.nim"
execTest "tests/tnimterop_c.nim"
execCmd "nim cpp -f -r tests/tnimterop_cpp.nim"

View file

@ -4,4 +4,4 @@ Module that should import everything so that `nim doc --project nimtero/all` run
# TODO: make sure it does import everything.
import "."/[cimport, build, types, plugin]
import "."/[docs, cimport, build, types, plugin]

View file

@ -248,12 +248,13 @@ proc newPragmaExpr(nimState: NimState, node: TSNode, ident: PNode, pragmas: seq[
result.add ident
result.add nimState.newPragma(node, pragmas)
proc newTypeIdent(nimState: NimState, node: TSNode, fname = "", pragmas: seq[string] = @[]): PNode =
# Create nkTypeDef PNode with first ident
proc newTypeIdent(nimState: NimState, node: TSNode, kind = nskType, fname = "", pragmas: seq[string] = @[]): PNode =
# Create nkTypeDef PNode with first ident if `nskType` else just create an nkPostfix node for `nskProc`
#
# If `fname`, use it instead of node.getAtom() for name
# If `pragmas`, add as nkPragmaExpr but only if `nskType` since procs add pragmas elsewhere
let
(tname, origname, info) = nimState.getNameInfo(node.getAtom(), nskType)
(tname, origname, info) = nimState.getNameInfo(node.getAtom(), kind)
name =
if fname.nBl:
@ -262,32 +263,49 @@ proc newTypeIdent(nimState: NimState, node: TSNode, fname = "", pragmas: seq[str
tname
ident = nimState.getIdent(name, info)
prident =
if pragmas.nBl and not ident.isNil:
nimState.newPragmaExpr(node, ident, pragmas)
else:
ident
if name.Bl:
# Name skipped or overridden since blank
result = nimState.getOverrideOrSkip(node, origname, nskType)
result = nimState.getOverrideOrSkip(node, origname, kind)
elif nimState.addNewIdentifer(name):
# type name* =
#
# nkTypeDef(
# nkPostfix(
# nkIdent("*"),
# nkIdent(name)
# ),
# nkEmpty()
# )
result = newNode(nkTypeDef)
result.add prident
result.add newNode(nkEmpty)
if kind == nskType:
# type name* =
#
# nkTypeDef(
# nkPostfix(
# nkIdent("*"),
# nkIdent(name)
# ),
# nkEmpty()
# )
let
pragmas =
if nimState.includeHeader and tname == origname:
# Need to add impShort
pragmas & nimState.impShort
else:
pragmas
prident =
if pragmas.nBl and not ident.isNil:
nimState.newPragmaExpr(node, ident, pragmas)
else:
ident
result = newNode(nkTypeDef)
result.add prident
result.add newNode(nkEmpty)
elif kind == nskProc:
# name*
#
# nkPostfix(
# nkIdent("*"),
# nkIdent(name)
# )
result = ident
nimState.identifierNodes[name] = result
else:
necho &"# type '{origname}' is duplicate, skipped"
necho &"# $1 '{origname}' is duplicate, skipped" % getKeyword(kind)
proc newPtrTree(nimState: NimState, count: int, typ: PNode): PNode =
# Create nkPtrTy tree depending on count
@ -520,9 +538,11 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
else:
@["bycopy"]
typeDefExisting = not typeDef.isNil
typeDef =
if typeDef.isNil:
nimState.newTypeIdent(node, fname, pragmas)
nimState.newTypeIdent(node, fname = fname, pragmas = pragmas)
else:
typeDef
@ -558,10 +578,14 @@ proc addTypeObject(nimState: NimState, node: TSNode, typeDef: PNode = nil, fname
typeDef.add obj
# If typeDef was passed in, need to add pragmas if any
if pragmas.nBl and typeDef[0].kind != nkPragmaExpr:
let
npexpr = nimState.newPragmaExpr(node, typedef[0], pragmas)
typedef[0] = npexpr
if pragmas.nBl and typeDefExisting:
if typeDef[0].kind != nkPragmaExpr:
# includeHeader already added impShort
let
npexpr = nimState.newPragmaExpr(node, typedef[0], pragmas)
typedef[0] = npexpr
else:
nimState.addPragma(node, typeDef[0][1], pragmas)
# nkTypeSection.add
nimState.typeSection.add typeDef
@ -1112,13 +1136,12 @@ proc addProc(nimState: NimState, node: TSNode) =
for i in start+1 ..< node.len:
let
# node[i] = identifier = name
tident = nimState.newTypeIdent(node[i])
ident = nimState.newTypeIdent(node[i], kind = nskProc)
if not tident.isNil:
if not ident.isNil:
let
# Only need the ident tree, not nkTypeDef parent
ident = tident[0]
name = tident.getIdentName()
name = ident.getIdentName()
# node[i] could have nested pointers
tcount = node[i].getPtrCount()
@ -1258,7 +1281,7 @@ proc setupPragmas(nimState: NimState, root: TSNode, fullpath: string) =
nimState.constSection.add nimState.newConstDef(
root, fname = nimState.currentHeader, fval = '"' & fullpath & '"')
nimState.addPragma(root, impPragma, "header", newStrNode(nkStrLit, nimState.currentHeader))
nimState.addPragma(root, impPragma, "header", nimState.getIdent(nimState.currentHeader))
nimState.addPragma(root, impCPragma, "pragma", nimState.getIdent(nimState.impShort & "C"))
nimState.addPragma(root, impCPragma, nimState.impShort)
@ -1312,9 +1335,9 @@ proc printNim*(gState: State, fullpath: string, root: TSNode) =
var
tree = newNode(nkStmtList)
tree.add nimState.pragmaSection
tree.add nimState.enumSection
tree.add nimState.constSection
tree.add nimState.pragmaSection
tree.add nimState.typeSection
tree.add nimState.procSection

View file

@ -1,6 +1,10 @@
import macros, strformat
from os import parentDir, getCurrentCompilerExe, DirSep
when defined(nimdoc):
from os import getCurrentDir, paramCount, paramStr
proc getNimRootDir(): string =
#[
hack, but works

View file

@ -11,7 +11,7 @@ typedef struct A3 {};
typedef struct A4 A4, *A4p;
typedef const int A5;
typedef int *A6;
typedef A0 **A7;
typedef struct A0 **A7;
typedef void *A8;
// Forward declaration
@ -104,6 +104,8 @@ typedef enum VSPresetFormat {
// DUPLICATES
#ifndef HEADER
#define A 1
#define B 1.0
#define C 0x10
@ -117,7 +119,7 @@ typedef struct A3 {};
typedef struct A4 A4, *A4p;
typedef const int A5;
typedef int *A6;
typedef A0 **A7;
typedef struct A0 **A7;
typedef void *A8;
// Forward declaration
@ -131,7 +133,7 @@ typedef char *(*A11)[3];
typedef struct A1 *A111[12];
typedef int **(*A12)(int, int b, int *c, int *, int *count[4], int (*func)(int, int));
typedef int A13(int, int);
typedef int A13(int, int, void (*func)(void));
struct A14 { volatile char a1; };
struct A15 { char *a1; const int *a2[1]; };
@ -200,4 +202,6 @@ typedef enum VSPresetFormat {
// Anonymous
//typedef struct { char a1; };
//struct A2 test_proc1(struct A0 a);
//struct A2 test_proc1(struct A0 a);
#endif

View file

@ -1,4 +1,4 @@
import tables
import macros, sets, tables
import nimterop/[cimport]
@ -12,7 +12,36 @@ cOverride:
type
A1* = A0
cImport("include/tast2.h", flags="-d -f:ast2 -ENK_")
when defined(HEADER):
cDefine("HEADER")
const
flags = " -H"
imp = @["importc", "header:headertast2"]
else:
const
flags = ""
imp = @[]
cImport("include/tast2.h", flags="-d -f:ast2 -ENK_" & flags)
proc getPragmas(n: NimNode): HashSet[string] =
for i in 0 ..< n.len:
if n[i].kind == nnkPragma:
for j in 0 ..< n[i].len:
if n[i][j].kind == nnkIdent:
result.incl $n[i][j]
elif n[i][j].kind == nnkExprColonExpr:
result.incl $n[i][j][0] & ":" & $n[i][j][1]
else:
result.incl n[i].getPragmas()
macro checkPragmas(t: typed, pragmas: static[seq[string]]): untyped =
let
ast = t.getImpl()
prag = ast.getPragmas()
exprag = pragmas.toHashSet()
doAssert symmetricDifference(prag, exprag).len == 0,
"\nWrong number of pragmas in " & $t & "\n" & $prag & " vs " & $exprag
proc testFields(t: typedesc, fields: Table[string, string] = initTable[string, string]()) =
var
@ -31,62 +60,114 @@ assert C == 0x10
assert D == "hello"
assert E == 'c'
const
pragmas = @["bycopy"] & imp
assert A0 is object
testFields(A0, {"f1": "cint"}.toTable())
checkPragmas(A0, pragmas)
assert A1 is A0
testFields(A1, {"f1": "cint"}.toTable())
assert A2 is object
testFields(A2)
checkPragmas(A2, pragmas)
assert A3 is object
testFields(A3)
checkPragmas(A3, pragmas)
assert A4 is object
testFields(A4)
checkPragmas(A4, pragmas)
assert A4p is ptr A4
checkPragmas(A4p, imp)
assert A5 is cint
checkPragmas(A5, imp)
assert A6 is ptr cint
checkPragmas(A6, imp)
assert A7 is ptr ptr A0
checkPragmas(A7, imp)
assert A8 is pointer
checkPragmas(A8, imp)
assert A9p is array[3, cstring]
checkPragmas(A9p, imp)
#assert A9 is array[4, cchar]
#checkPragmas(A9, imp)
assert A10 is array[3, array[6, cstring]]
checkPragmas(A10, imp)
assert A11 is ptr array[3, cstring]
checkPragmas(A11, imp)
assert A111 is array[12, ptr A1]
checkPragmas(A111, imp)
assert A12 is proc(a1: cint, b: cint, c: ptr cint, a4: ptr cint, count: array[4, ptr cint], `func`: proc(a1: cint, a2: cint): cint): ptr ptr cint
checkPragmas(A12, imp)
assert A13 is proc(a1: cint, a2: cint, `func`: proc()): cint
checkPragmas(A13, imp)
assert A14 is object
testFields(A14, {"a1": "cchar"}.toTable())
checkPragmas(A14, pragmas)
assert A15 is object
testFields(A15, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
checkPragmas(A15, pragmas)
assert A16 is object
testFields(A16, {"f1": "cchar"}.toTable())
checkPragmas(A16, pragmas)
assert A17 is object
testFields(A17, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
checkPragmas(A17, pragmas)
assert A18 is A17
checkPragmas(A18, imp)
assert A18p is ptr A17
checkPragmas(A18p, imp)
assert A19 is object
testFields(A19, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
checkPragmas(A19, pragmas)
assert A19p is ptr A19
checkPragmas(A19p, imp)
assert A20 is object
testFields(A20, {"a1": "cchar"}.toTable())
checkPragmas(A20, pragmas)
assert A21 is A20
checkPragmas(A21, imp)
assert A21p is ptr A20
checkPragmas(A21p, imp)
assert A22 is object
testFields(A22, {"f1": "ptr ptr cint", "f2": "array[0..254, ptr cint]"}.toTable())
checkPragmas(A22, pragmas)
assert U1 is object
assert sizeof(U1) == sizeof(cfloat)
checkPragmas(U1, pragmas & @["union"])
assert U2 is object
assert sizeof(U2) == 256 * sizeof(cint)
checkPragmas(U2, pragmas & @["union"])
assert PANEL_WINDOW == 1
assert PANEL_GROUP == 2