aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2020-01-09 13:58:34 -0600
committerGanesh Viswanathan <dev@genotrance.com>2020-01-16 09:23:54 -0600
commitee58be398ad47fe62a722d29bba9fc5344a513ad (patch)
treea3ecea209c9db5003eff9d1f4d6aacc0c56f58b1
parent166eae7a5a7bdc697c2a8103e89302f5415b5bad (diff)
downloadnimterop-ee58be398ad47fe62a722d29bba9fc5344a513ad.tar.gz
nimterop-ee58be398ad47fe62a722d29bba9fc5344a513ad.zip
Fix type bugs, enable basic tests
-rw-r--r--nimterop.nimble23
-rw-r--r--nimterop/ast2.nim128
-rw-r--r--nimterop/getters.nim9
-rw-r--r--nimterop/globals.nim10
-rw-r--r--tests/include/test3.h42
-rw-r--r--tests/tnimterop2.nim71
6 files changed, 223 insertions, 60 deletions
diff --git a/nimterop.nimble b/nimterop.nimble
index 3b6b7c1..39a2346 100644
--- a/nimterop.nimble
+++ b/nimterop.nimble
@@ -36,19 +36,22 @@ task docs, "Generate docs":
task test, "Test":
buildToastTask()
- execTest "tests/tnimterop_c.nim"
- execCmd "nim cpp -f -r tests/tnimterop_cpp.nim"
- execCmd "./nimterop/toast -pnk -E=_ tests/include/toast.h"
- execTest "tests/tpcre.nim"
+ execTest "tests/tnimterop2.nim"
+
+ # Commented out until newalgo is ready
+ # execTest "tests/tnimterop_c.nim"
+ # execCmd "nim cpp -f -r tests/tnimterop_cpp.nim"
+ # execCmd "./nimterop/toast -pnk -E=_ tests/include/toast.h"
+ # execTest "tests/tpcre.nim"
# Platform specific tests
- when defined(Windows):
- execTest "tests/tmath.nim"
- if defined(OSX) or defined(Windows) or not existsEnv("TRAVIS"):
- execTest "tests/tsoloud.nim"
+ # when defined(Windows):
+ # execTest "tests/tmath.nim"
+ # if defined(OSX) or defined(Windows) or not existsEnv("TRAVIS"):
+ # execTest "tests/tsoloud.nim"
# getHeader tests
- withDir("tests"):
- execCmd("nim e getheader.nims")
+ # withDir("tests"):
+ # execCmd("nim e getheader.nims")
docsTask()
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim
index caa2a13..6c62b05 100644
--- a/nimterop/ast2.nim
+++ b/nimterop/ast2.nim
@@ -13,6 +13,7 @@ proc addConst(nimState: NimState, node: TSNode) =
# (identifier)
# (preproc_arg)
# )
+ decho("addConst()")
nimState.printDebug(node)
if node[0].getName() == "identifier" and
@@ -51,6 +52,8 @@ proc addConst(nimState: NimState, node: TSNode) =
proc newTypeIdent(nimState: NimState, node: TSNode, override = ""): PNode =
# Create nkTypeDef PNode with first ident
+ #
+ # If `override`, use it instead of node.getAtom() for name
let
(name, info) = nimState.getNameInfo(node.getAtom(), nskType)
# TODO - check blank and override
@@ -60,30 +63,46 @@ proc newTypeIdent(nimState: NimState, node: TSNode, override = ""): PNode =
else:
nimState.getIdent(name, info)
+ # type name* =
+ #
+ # nkTypeDef(
+ # nkPostfix(
+ # nkIdent("*"),
+ # nkIdent(name)
+ # ),
+ # nkEmpty()
+ # )
result = newNode(nkTypeDef)
result.add ident
result.add newNode(nkEmpty)
-proc newPtrTree(count: int, typ: PNode): PNode =
+proc newPtrTree(nimState: NimState, count: int, typ: PNode): PNode =
# Create nkPtrTy tree depending on count
#
# Reduce by 1 if Nim type available for ptr X - e.g. ptr cchar = cstring
- #
- # nkPtrTy(
- # nkPtrTy(
- # typ
- # )
- # )
var
count = count
+ chng = false
if typ.kind == nkIdent:
let
tname = typ.ident.s
ptname = getPtrType(tname)
if tname != ptname:
- typ.ident.s = ptname
+ # If Nim type available, use that ident
+ result = nimState.getIdent(ptname, typ.info, exported = false)
+ chng = true
+ # One ptr reduced
count -= 1
if count > 0:
+ # Nested nkPtrTy(typ) depending on count
+ #
+ # [ptr ...] typ
+ #
+ # nkPtrTy(
+ # nkPtrTy(
+ # typ
+ # )
+ # )
result = newNode(nkPtrTy)
var
parent = result
@@ -93,11 +112,17 @@ proc newPtrTree(count: int, typ: PNode): PNode =
parent.add child
parent = child
parent.add typ
- else:
+ elif not chng:
+ # Either no ptr, or none left after Nim type adjustment
result = typ
proc newArrayTree(nimState: NimState, node: TSNode, typ, size: PNode): PNode =
# Create nkBracketExpr tree depending on input
+ let
+ (_, info) = nimState.getNameInfo(node, nskType)
+ ident = nimState.getIdent("array", info, exported = false)
+
+ # array[size, typ]
#
# nkBracketExpr(
# nkIdent("array"),
@@ -105,11 +130,6 @@ proc newArrayTree(nimState: NimState, node: TSNode, typ, size: PNode): PNode =
# typ
# )
result = newNode(nkBracketExpr)
-
- let
- (_, info) = nimState.getNameInfo(node, nskType)
- ident = nimState.getIdent("array", info, exported = false)
-
result.add ident
result.add size
result.add typ
@@ -122,6 +142,8 @@ proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64
#
# For proc, param should not be exported
#
+ # pname: [ptr ..] typ
+ #
# nkIdentDefs(
# nkIdent(pname),
# typ,
@@ -130,6 +152,8 @@ proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64
#
# For object, field should be exported
#
+ # pname*: [ptr ..] typ
+ #
# nkIdentDefs(
# nkPostfix(
# nkIdent("*"),
@@ -171,7 +195,7 @@ proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64
pident = nimState.getIdent(pname, tinfo, exported)
acount = node[1].getXCount("abstract_pointer_declarator")
result.add pident
- result.add newPtrTree(acount, tident)
+ result.add nimState.newPtrTree(acount, tident)
result.add newNode(nkEmpty)
else:
# Named param, simple type
@@ -182,7 +206,7 @@ proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64
count = node[1].getPtrCount()
result.add pident
if count > 0:
- result.add newPtrTree(count, tident)
+ result.add nimState.newPtrTree(count, tident)
else:
result.add tident
result.add newNode(nkEmpty)
@@ -207,18 +231,6 @@ proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64
proc newProcTree(nimState: NimState, name: string, node: TSNode, rtyp: PNode): PNode =
# Create nkProcTy tree for specified proc type
- #
- # nkProcTy(
- # nkFormalParams(
- # rtyp,
- # nkIdentDefs( # multiple depending on params
- # ..
- # )
- # ),
- # nkEmpty()
- # )
- result = newNode(nkProcTy)
-
let
fparam = newNode(nkFormalParams)
@@ -233,18 +245,32 @@ proc newProcTree(nimState: NimState, name: string, node: TSNode, rtyp: PNode): P
if not param.isNil:
fparam.add param
+ # proc(pname: ptyp ..): rtyp
+ #
+ # nkProcTy(
+ # nkFormalParams(
+ # rtyp,
+ # nkIdentDefs( # multiple depending on params
+ # ..
+ # )
+ # ),
+ # nkEmpty()
+ # )
+ result = newNode(nkProcTy)
result.add fparam
result.add newNode(nkEmpty)
proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
# Create nkRecList tree for specified object
- #
- # nkRecList(
- # nkIdentDefs( # multiple depending on fields
- # ..
- # )
- # )
if not node.isNil:
+ # fname*: ftyp
+ # ..
+ #
+ # nkRecList(
+ # nkIdentDefs( # multiple depending on fields
+ # ..
+ # )
+ # )
result = newNode(nkRecList)
for i in 0 ..< node.len:
@@ -259,6 +285,7 @@ proc addTypeObject(nimState: NimState, node: TSNode, override = "", duplicate =
#
# If `override` is set, use it as the name
# If `duplicate` is set, don't add the same name
+ decho("addTypeObject()")
let
# TODO - check blank and override
typeDef = nimState.newTypeIdent(node, override)
@@ -304,6 +331,7 @@ proc addTypeTyped(nimState: NimState, node: TSNode, toverride = "", duplicate =
#
# If `toverride` is set, use it as the type name
# If `duplicate` is set, don't add the same name
+ decho("addTypeTyped()")
for i in 1 ..< node.len:
# Add a type of a specific type
let
@@ -326,7 +354,7 @@ proc addTypeTyped(nimState: NimState, node: TSNode, toverride = "", duplicate =
if $typeDef[0][1] != tname:
if count > 0:
# If pointers
- typeDef.add newPtrTree(count, ident)
+ typeDef.add nimState.newPtrTree(count, ident)
else:
typeDef.add ident
@@ -348,7 +376,7 @@ proc addTypeTyped(nimState: NimState, node: TSNode, toverride = "", duplicate =
nimState.printDebug(typeDef)
else:
- nimState.addTypeObject(node, duplicate)
+ nimState.addTypeObject(node, duplicate = duplicate)
proc getTypeArray(nimState: NimState, node: TSNode): PNode =
# Create array type tree
@@ -388,7 +416,7 @@ proc getTypeArray(nimState: NimState, node: TSNode): PNode =
if tcount > 0:
# If pointers
- result = newPtrTree(tcount, result)
+ result = nimState.newPtrTree(tcount, result)
for i in 0 ..< acount:
let
@@ -398,10 +426,11 @@ proc getTypeArray(nimState: NimState, node: TSNode): PNode =
cnode = cnode[0]
if ncount > 0:
- result = newPtrTree(ncount, result)
+ result = nimState.newPtrTree(ncount, result)
proc addTypeArray(nimState: NimState, node: TSNode) =
# Add a type of array type
+ decho("addTypeArray()")
let
# node[1] = identifer = name
# TODO - check blank and override
@@ -466,15 +495,16 @@ proc getTypeProc(nimState: NimState, name: string, node: TSNode): PNode =
var
retType = nimState.getIdent(rname, rinfo, exported = false)
if tcount > 0:
- retType = newPtrTree(tcount, retType)
+ retType = nimState.newPtrTree(tcount, retType)
# Proc with return type and params
result = nimState.newProcTree(name, plist, retType)
if ncount > 1:
- result = newPtrTree(ncount-1, result)
+ result = nimState.newPtrTree(ncount-1, result)
proc addTypeProc(nimState: NimState, node: TSNode) =
# Add a type of proc type
+ decho("addTypeProc()")
let
# node[1] = identifier = name
# TODO - check blank and override
@@ -519,6 +549,7 @@ proc addTypeProc(nimState: NimState, node: TSNode) =
nimState.printDebug(typeDef)
proc addType(nimState: NimState, node: TSNode) =
+ decho("addType()")
nimState.printDebug(node)
if node.getName() == "struct_specifier":
@@ -550,12 +581,14 @@ proc addType(nimState: NimState, node: TSNode) =
# )
# (field_declaration ...)
# )
+ decho("addType(): case 1")
nimState.addTypeObject(node)
elif node.getName() == "type_definition":
if node.len >= 2:
let
fdlist = node[0].anyChildInTree("field_declaration_list")
- if nimState.getNodeVal(node[1]) == "":
+ if (fdlist.isNil or (not fdlist.isNil and fdlist.len == 0)) and
+ nimState.getNodeVal(node[1]) == "":
# typedef struct X;
#
# (type_definition
@@ -574,6 +607,7 @@ proc addType(nimState: NimState, node: TSNode) =
# )
# (type_definition = "")
# )
+ decho("addType(): case 2")
nimState.addTypeObject(node[0])
else:
let
@@ -596,6 +630,7 @@ proc addType(nimState: NimState, node: TSNode) =
# (type_identifier)
# )
# )
+ decho("addType(): case 3")
nimState.addTypeTyped(node)
elif not fdecl.isNil:
# typedef X (*Y)(a1, a2, a3);
@@ -625,6 +660,7 @@ proc addType(nimState: NimState, node: TSNode) =
# )
# )
# )
+ decho("addType(): case 4")
nimState.addTypeProc(node)
elif not adecl.isNil:
# typedef struct X Y[a][..];
@@ -646,6 +682,7 @@ proc addType(nimState: NimState, node: TSNode) =
# )
# )
# )
+ decho("addType(): case 5")
nimState.addTypeArray(node)
else:
if node.firstChildInTree("field_declaration_list").isNil:
@@ -673,6 +710,7 @@ proc addType(nimState: NimState, node: TSNode) =
# )
# First add struct as object
+ decho("addType(): case 6")
nimState.addTypeObject(node[0])
if node.len > 1 and nimState.getNodeVal(node[1]) != "":
@@ -684,6 +722,7 @@ proc addType(nimState: NimState, node: TSNode) =
# typedef struct { .. } Y, *Z;
# Get any name that isn't a pointer
+ decho("addType(): case 7")
let
name = block:
var
@@ -692,22 +731,21 @@ proc addType(nimState: NimState, node: TSNode) =
if node[i].getName() == "type_identifier":
name = nimState.getNodeVal(node[i].getAtom())
- if name.len == 0:
- name = nimState.getUniqueIdentifier("STRUCT")
-
name
# Now add struct as object with specified name
nimState.addTypeObject(node[0], override = name)
- if node.len > 1 and nimState.getNodeVal(node[1]) != "":
+ if name.len != 0:
# Add any additional names except duplicate
nimState.addTypeTyped(node, toverride = name, duplicate = name)
proc addEnum(nimState: NimState, node: TSNode) =
+ decho("addEnum()")
nimState.printDebug(node)
proc addProc(nimState: NimState, node: TSNode) =
+ decho("addProc()")
nimState.printDebug(node)
proc processNode(nimState: NimState, node: TSNode): bool =
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 081364a..13093f7 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -313,7 +313,10 @@ proc anyChildInTree*(node: TSNode, ntype: string): TSNode =
ccnode = cnode[i].anyChildInTree(ntype)
if not ccnode.isNil():
return ccnode
- cnode = cnode.tsNodeNextNamedSibling()
+ if cnode != node:
+ cnode = cnode.tsNodeNextNamedSibling()
+ else:
+ break
proc mostNestedChildInTree*(node: TSNode): TSNode =
# Search for the most nested child of node's type in tree
@@ -444,6 +447,10 @@ proc printTree*(nimState: NimState, pnode: PNode, offset = "") =
if offset.len == 0:
echo ""
+template decho*(str: untyped): untyped =
+ if nimState.gState.debug:
+ echo str.getCommented()
+
proc printDebug*(nimState: NimState, node: TSNode) =
if nimState.gState.debug:
echo ("Input => " & nimState.getNodeVal(node)).getCommented()
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index 1921b1b..be24436 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -1,10 +1,11 @@
import sequtils, sets, tables
-import compiler/[ast, idents, options]
+import regex
import "."/plugin
when not declared(CIMPORT):
+ import compiler/[ast, idents, options]
import "."/treesitter/api
const
@@ -52,9 +53,10 @@ type
commentStr*, debugStr*, skipStr*: string
# Nim compiler objects
- constSection*, enumSection*, procSection*, typeSection*: PNode
- identCache*: IdentCache
- config*: ConfigRef
+ when not declared(CIMPORT):
+ constSection*, enumSection*, procSection*, typeSection*: PNode
+ identCache*: IdentCache
+ config*: ConfigRef
gState*: State
diff --git a/tests/include/test3.h b/tests/include/test3.h
new file mode 100644
index 0000000..d1cf8aa
--- /dev/null
+++ b/tests/include/test3.h
@@ -0,0 +1,42 @@
+
+#define A 1
+#define B 1.0
+#define C 0x10
+#define D "hello"
+#define E 'c'
+
+struct A0;
+struct A1 {};
+typedef struct A2;
+typedef struct A3 {};
+typedef struct A4 A4, *A4p;
+typedef int A5;
+typedef int *A6;
+typedef A0 **A7;
+typedef void *A8;
+
+typedef char *A9[3];
+typedef char *A10[3][6];
+typedef char *(*A11)[3];
+
+typedef int **(*A12)(int, int b, int *c, int *, int *count[4], int (*func)(int, int));
+typedef int A13(int, int);
+
+struct A14 { char a1; };
+struct A15 { char *a1; int *a2[1]; };
+
+typedef struct A16 { char f1; };
+typedef struct A17 { char *a1; int *a2[1]; } A18, *A18p;
+typedef struct { char *a1; int *a2[1]; } A19, *A19p;
+
+typedef struct A20 { char a1; } A20, A21, *A21p;
+
+//Expression
+//typedef struct A21 { int **f1; int abc[123+132]; } A21;
+
+//Unions
+//union UNION1 {int f1; };
+//typedef union UNION2 { int **f1; int abc[123+132]; } UNION2;
+
+// Anonymous
+//typedef struct { char a1; };
diff --git a/tests/tnimterop2.nim b/tests/tnimterop2.nim
new file mode 100644
index 0000000..1e9c21d
--- /dev/null
+++ b/tests/tnimterop2.nim
@@ -0,0 +1,71 @@
+import tables
+
+import nimterop/[cimport]
+
+static:
+ cDebug()
+
+cImport("include/test3.h", flags="-d")
+
+proc testFields(t: typedesc, fields: Table[string, string] = initTable[string, string]()) =
+ var
+ obj: t
+ count = 0
+ for name, value in obj.fieldPairs():
+ count += 1
+ assert name in fields, $t & "." & name & " invalid"
+ assert $fields[name] == $typeof(value),
+ "typeof(" & $t & ":" & name & ") != " & fields[name] & ", is " & $typeof(value)
+ assert count == fields.len, "Failed for " & $t
+
+assert A == 1
+assert B == 1.0
+assert C == 0x10
+assert D == "hello"
+assert E == 'c'
+
+assert A0 is object
+testFields(A0)
+assert A1 is object
+testFields(A1)
+assert A2 is object
+testFields(A2)
+assert A3 is object
+testFields(A3)
+assert A4 is object
+testFields(A4)
+assert A4p is ptr A4
+assert A5 is cint
+assert A6 is ptr cint
+assert A7 is ptr ptr A0
+assert A8 is pointer
+
+assert A9 is array[3, cstring]
+assert A10 is array[3, array[6, cstring]]
+assert A11 is ptr array[3, cstring]
+
+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
+assert A13 is proc(a1: cint, a2: cint): cint
+
+assert A14 is object
+testFields(A14, {"a1": "cchar"}.toTable())
+
+assert A15 is object
+testFields(A15, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
+
+assert A16 is object
+testFields(A16, {"f1": "cchar"}.toTable())
+
+assert A17 is object
+testFields(A17, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
+assert A18 is A17
+assert A18p is ptr A17
+
+assert A19 is object
+testFields(A19, {"a1": "cstring", "a2": "array[0..0, ptr cint]"}.toTable())
+assert A19p is ptr A19
+
+assert A20 is object
+testFields(A20, {"a1": "cchar"}.toTable())
+assert A21 is A20
+assert A21p is ptr A20