aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-03-23 13:33:52 -0500
committerGanesh Viswanathan <dev@genotrance.com>2019-03-23 13:33:52 -0500
commit454403b9fe96788534ade09631d3546edc418add (patch)
treeace5ca6a855967036caea8997ab280aa8a4b7ffc
parent28e2d7bb872c94ca0f25ba0e018b5d6132dc8fbc (diff)
downloadnimterop-454403b9fe96788534ade09631d3546edc418add.tar.gz
nimterop-454403b9fe96788534ade09631d3546edc418add.zip
Double pointer support
-rw-r--r--nimterop/ast.nim9
-rw-r--r--nimterop/getters.nim6
-rw-r--r--nimterop/globals.nim4
-rw-r--r--nimterop/grammar.nim89
-rw-r--r--tests/include/test.c4
-rw-r--r--tests/include/test.h15
-rw-r--r--tests/tnimterop_c.nim16
7 files changed, 111 insertions, 32 deletions
diff --git a/nimterop/ast.nim b/nimterop/ast.nim
index aede004..dc0ac3c 100644
--- a/nimterop/ast.nim
+++ b/nimterop/ast.nim
@@ -23,6 +23,7 @@ proc saveNodeData(node: TSNode, nimState: NimState): bool =
pname = node.getPxName(1)
ppname = node.getPxName(2)
pppname = node.getPxName(3)
+ ppppname = node.getPxName(4)
if node.tsNodePrevNamedSibling().tsNodeIsNull():
if pname == "pointer_declarator":
@@ -30,9 +31,15 @@ proc saveNodeData(node: TSNode, nimState: NimState): bool =
nimState.data.add(("pointer_declarator", ""))
elif ppname == "array_declarator":
nimState.data.add(("array_pointer_declarator", ""))
+
+ # Double pointer
+ if ppname == "pointer_declarator":
+ nimState.data.add(("pointer_declarator", ""))
elif pname in ["function_declarator", "array_declarator"]:
if ppname == "pointer_declarator":
nimState.data.add(("pointer_declarator", ""))
+ if pppname == "pointer_declarator":
+ nimState.data.add(("pointer_declarator", ""))
nimState.data.add((name, val))
@@ -41,6 +48,8 @@ proc saveNodeData(node: TSNode, nimState: NimState): bool =
ppname == "function_declarator":
if pppname == "pointer_declarator":
nimState.data.insert(("pointer_declarator", ""), nimState.data.len-1)
+ if ppppname == "pointer_declarator":
+ nimState.data.insert(("pointer_declarator", ""), nimState.data.len-1)
nimState.data.add(("function_declarator", ""))
elif name in gExpressions:
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 2fe7447..052e532 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -24,7 +24,7 @@ using
var
when while
xor
-yield""".split(Whitespace).toSet()
+yield""".split(Whitespace).toHashSet()
const gTypeMap = {
# char
@@ -151,8 +151,12 @@ proc getPtrType*(str: string): string =
result = case str:
of "ptr cchar":
"cstring"
+ of "ptr ptr cchar":
+ "ptr cstring"
of "ptr object":
"pointer"
+ of "ptr ptr object":
+ "ptr pointer"
else:
str
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index bdb29dc..2f1a451 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -16,14 +16,14 @@ const
"primitive_type",
"sized_type_specifier",
"type_identifier"
- ].toSet()
+ ].toHashSet()
gExpressions {.used.} = @[
"parenthesized_expression",
"bitwise_expression",
"shift_expression",
"math_expression"
- ].toSet()
+ ].toHashSet()
gEnumVals {.used.} = @[
"identifier",
diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim
index 3895aa1..8cd3275 100644
--- a/nimterop/grammar.nim
+++ b/nimterop/grammar.nim
@@ -50,6 +50,9 @@ proc initGrammar(): Grammar =
{typeGrammar}
(identifier|type_identifier?)
(pointer_declarator?
+ (pointer_declarator!
+ (identifier|type_identifier)
+ )
(identifier|type_identifier)
)
(abstract_pointer_declarator?)
@@ -61,6 +64,9 @@ proc initGrammar(): Grammar =
(function_declarator*
(identifier|type_identifier!)
(pointer_declarator
+ (pointer_declarator!
+ (type_identifier)
+ )
(type_identifier)
)
{paramListGrammar}
@@ -70,6 +76,9 @@ proc initGrammar(): Grammar =
arrGrammar = &"""
(array_declarator!
(pointer_declarator!
+ (pointer_declarator!
+ (type_identifier)
+ )
(type_identifier)
)
(type_identifier)
@@ -80,11 +89,10 @@ proc initGrammar(): Grammar =
template funcParamCommon(fname, pname, ptyp, pptr, pout, count, i: untyped): untyped =
ptyp = nimState.data[i].val.getIdentifier(nskType, fname)
- if i+1 < nimState.data.len and nimState.data[i+1].name == "pointer_declarator":
- pptr = "ptr "
+ pptr = ""
+ while i+1 < nimState.data.len and nimState.data[i+1].name == "pointer_declarator":
+ pptr &= "ptr "
i += 1
- else:
- pptr = ""
if i+1 < nimState.data.len and nimState.data[i+1].name == "identifier":
pname = nimState.data[i+1].val.getIdentifier(nskParam, fname)
@@ -94,8 +102,8 @@ proc initGrammar(): Grammar =
count += 1
i += 1
- if pptr == "ptr " or ptyp != "object":
- pout &= &"{pname}: {getPtrType(pptr&ptyp)},"
+ if pptr.len != 0 or ptyp != "object":
+ pout &= &"{pname}: {getPtrType(pptr&ptyp)}, "
# typedef int X
# typedef X Y
@@ -107,6 +115,11 @@ proc initGrammar(): Grammar =
(type_identifier!)
{arrGrammar}
(pointer_declarator!
+ (pointer_declarator!
+ (type_identifier!)
+ {arrGrammar}
+ {funcGrammar}
+ )
(type_identifier!)
{arrGrammar}
{funcGrammar}
@@ -123,13 +136,13 @@ proc initGrammar(): Grammar =
aptr = ""
i += 1
- if i < nimState.data.len:
+ while i < nimState.data.len and "pointer" in nimState.data[i].name:
case nimState.data[i].name:
of "pointer_declarator":
- tptr = "ptr "
+ tptr &= "ptr "
i += 1
of "array_pointer_declarator":
- aptr = "ptr "
+ aptr &= "ptr "
i += 1
if i < nimState.data.len:
@@ -149,10 +162,10 @@ proc initGrammar(): Grammar =
funcParamCommon(fname, pname, ptyp, pptr, pout, count, i)
- if pout.len != 0 and pout[^1] == ',':
- pout = pout[0 .. ^2]
+ if pout.len != 0 and pout[^2 .. ^1] == ", ":
+ pout = pout[0 .. ^3]
- if tptr == "ptr " or typ != "object":
+ if tptr.len != 0 or typ != "object":
nimState.typeStr &= &"\n {name}* = proc({pout}): {getPtrType(tptr&typ)} {{.nimcall.}}"
else:
nimState.typeStr &= &"\n {name}* = proc({pout}) {{.nimcall.}}"
@@ -242,13 +255,14 @@ proc initGrammar(): Grammar =
ftyp = nimState.data[i].val.getType()
i += 1
- case nimState.data[i].name:
- of "pointer_declarator":
- fptr = "ptr "
- i += 1
- of "array_pointer_declarator":
- aptr = "ptr "
- i += 1
+ while i < nimState.data.len-fend and "pointer" in nimState.data[i].name:
+ case nimState.data[i].name:
+ of "pointer_declarator":
+ fptr &= "ptr "
+ i += 1
+ of "array_pointer_declarator":
+ aptr &= "ptr "
+ i += 1
fname = nimState.data[i].val.getIdentifier(nskField, nname)
@@ -273,9 +287,9 @@ proc initGrammar(): Grammar =
funcParamCommon(fname, pname, ptyp, pptr, pout, count, i)
- if pout.len != 0 and pout[^1] == ',':
- pout = pout[0 .. ^2]
- if fptr == "ptr " or ftyp != "object":
+ if pout.len != 0 and pout[^2 .. ^1] == ", ":
+ pout = pout[0 .. ^3]
+ if fptr.len != 0 or ftyp != "object":
nimState.typeStr &= &"\n {fname}*: proc({pout}): {getPtrType(fptr&ftyp)} {{.nimcall.}}"
else:
nimState.typeStr &= &"\n {fname}*: proc({pout}) {{.nimcall.}}"
@@ -297,12 +311,18 @@ proc initGrammar(): Grammar =
(array_declarator!
(field_identifier!)
(pointer_declarator
+ (pointer_declarator!
+ (field_identifier)
+ )
(field_identifier)
)
(^$1+)
)
(function_declarator+
(pointer_declarator
+ (pointer_declarator!
+ (field_identifier)
+ )
(field_identifier)
)
{paramListGrammar}
@@ -314,6 +334,9 @@ proc initGrammar(): Grammar =
(field_declaration+
{typeGrammar}
(pointer_declarator!
+ (pointer_declarator!
+ {fieldGrammar}
+ )
{fieldGrammar}
)
{fieldGrammar}
@@ -341,6 +364,9 @@ proc initGrammar(): Grammar =
)
(type_identifier!)
(pointer_declarator
+ (pointer_declarator!
+ (type_identifier)
+ )
(type_identifier)
)
)
@@ -433,6 +459,9 @@ proc initGrammar(): Grammar =
{result[^1].grammar}
(type_identifier!)
(pointer_declarator
+ (pointer_declarator!
+ (type_identifier)
+ )
(type_identifier)
)
)
@@ -459,6 +488,9 @@ proc initGrammar(): Grammar =
(storage_class_specifier?)
{typeGrammar}
(pointer_declarator!
+ (pointer_declarator!
+ {funcGrammar}
+ )
{funcGrammar}
)
{funcGrammar}
@@ -474,11 +506,10 @@ proc initGrammar(): Grammar =
i += 1
continue
- if nimState.data[i].name == "pointer_declarator":
- fptr = "ptr "
+ fptr = ""
+ while i < nimState.data.len and nimState.data[i].name == "pointer_declarator":
+ fptr &= "ptr "
i += 1
- else:
- fptr = ""
var
fname = nimState.data[i].val
@@ -493,12 +524,12 @@ proc initGrammar(): Grammar =
funcParamCommon(fnname, pname, ptyp, pptr, pout, count, i)
- if pout.len != 0 and pout[^1] == ',':
- pout = pout[0 .. ^2]
+ if pout.len != 0 and pout[^2 .. ^1] == ", ":
+ pout = pout[0 .. ^3]
if fnname.nBl and nimState.identifiers.addNewIdentifer(fnname):
let ftyp = nimState.data[0].val.getIdentifier(nskType, fnname)
- if fptr == "ptr " or ftyp != "object":
+ if fptr.len != 0 or ftyp != "object":
nimState.procStr &= &"\nproc {fnname}*({pout}): {getPtrType(fptr&ftyp)} {{.{genImportC(fname, fnname)}, header: {nimState.currentHeader}.}}"
else:
nimState.procStr &= &"\nproc {fnname}*({pout}) {{.{genImportC(fname, fnname)}, header: {nimState.currentHeader}.}}"
diff --git a/tests/include/test.c b/tests/include/test.c
index 0312b4f..8990df9 100644
--- a/tests/include/test.c
+++ b/tests/include/test.c
@@ -60,6 +60,10 @@ void *test_call9() {
return NULL;
}
+void **test_call10(int **param1) {
+ return NULL;
+}
+
void multiline1(void) {}
void *multiline2(void) {
diff --git a/tests/include/test.h b/tests/include/test.h
index e85acfd..9dba8ba 100644
--- a/tests/include/test.h
+++ b/tests/include/test.h
@@ -108,6 +108,7 @@ unsigned char test_call_param6(UNION2 param1);
int test_call_param7(union UNION1 param1);
float test_call_param8(int *param1);
void *test_call9();
+void **test_call10(int **param1);
// Issue #58
void
@@ -131,6 +132,20 @@ UNION3 test_call_etype_ptr3();
typedef struct _Kernel { char name; } *Kernel;
+// Double pointers
+typedef void **DVOIDPTR;
+typedef int **DINTPTR;
+
+struct dstruct {
+ int **field1;
+};
+
+typedef struct dstruct2 {
+ char **field1;
+ float **field2;
+ void **(*tcv)(int **param1);
+} DSTRUCT2;
+
#ifdef __cplusplus
}
#endif \ No newline at end of file
diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim
index 86ac0fd..3fc33b9 100644
--- a/tests/tnimterop_c.nim
+++ b/tests/tnimterop_c.nim
@@ -145,3 +145,19 @@ when false:
doAssert foobar1(3) == OSDEF * 3
when false: # Error: undeclared identifier: 'foobar2'
doAssert foobar2(3) == 3 + 1
+
+# Double pointer
+var
+ dv: DVOIDPTR
+ di: DINTPTR
+ ds: dstruct
+ cstr = "Hello".cstring
+ ds2: DSTRUCT2
+
+dv = addr vptr
+di = addr iptr
+
+ds.field1 = di
+ds2.field1 = addr cstr
+ds2.tcv = test_call10
+check ds2.tcv(di) == nil \ No newline at end of file