aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2020-03-25 15:17:20 -0500
committerGanesh Viswanathan <dev@genotrance.com>2020-03-25 15:17:20 -0500
commit8b9c39f42eec79607392c81538e08da1b814809a (patch)
treea6971f90c00d67bc0e28476727380f0033ba3fa1
parente98564528ee8a9fc934bb2de31114b66673b3eaa (diff)
downloadnimterop-8b9c39f42eec79607392c81538e08da1b814809a.tar.gz
nimterop-8b9c39f42eec79607392c81538e08da1b814809a.zip
ast2 newTypeIdent cleanup, pragma tests, docs.nim docs
-rw-r--r--nimterop.nimble1
-rw-r--r--nimterop/all.nim2
-rw-r--r--nimterop/ast2.nim91
-rw-r--r--nimterop/docs.nim4
-rw-r--r--tests/include/tast2.h12
-rw-r--r--tests/tast2.nim85
6 files changed, 154 insertions, 41 deletions
diff --git a/nimterop.nimble b/nimterop.nimble
index c33e78b..86ee029 100644
--- a/nimterop.nimble
+++ b/nimterop.nimble
@@ -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"
diff --git a/nimterop/all.nim b/nimterop/all.nim
index dc22967..fef1bdd 100644
--- a/nimterop/all.nim
+++ b/nimterop/all.nim
@@ -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]
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim
index 62fdcf2..93b26a1 100644
--- a/nimterop/ast2.nim
+++ b/nimterop/ast2.nim
@@ -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
diff --git a/nimterop/docs.nim b/nimterop/docs.nim
index a194086..97fab96 100644
--- a/nimterop/docs.nim
+++ b/nimterop/docs.nim
@@ -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
diff --git a/tests/include/tast2.h b/tests/include/tast2.h
index 84505db..8e84b01 100644
--- a/tests/include/tast2.h
+++ b/tests/include/tast2.h
@@ -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); \ No newline at end of file
+//struct A2 test_proc1(struct A0 a);
+
+#endif \ No newline at end of file
diff --git a/tests/tast2.nim b/tests/tast2.nim
index 56b1868..76e4561 100644
--- a/tests/tast2.nim
+++ b/tests/tast2.nim
@@ -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