aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2018-12-27 22:42:55 -0600
committerGanesh Viswanathan <dev@genotrance.com>2018-12-27 22:42:55 -0600
commit21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a (patch)
tree0d3fb8f8f5f45943309e2bcf7327b1cbd57b2f04
parentc7a3c7b7d606b00fa1c676e244c39002b8fc1609 (diff)
downloadnimterop-21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a.tar.gz
nimterop-21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a.zip
Struct field function pointers, cstring, show toast error in cimport
-rw-r--r--nimterop/ast.nim33
-rw-r--r--nimterop/cimport.nim10
-rw-r--r--nimterop/getters.nim14
-rw-r--r--nimterop/grammar.nim66
-rw-r--r--tests/include/test.c6
-rw-r--r--tests/include/test.h9
-rw-r--r--tests/tnimterop_c.nim11
7 files changed, 121 insertions, 28 deletions
diff --git a/nimterop/ast.nim b/nimterop/ast.nim
index 4c8e253..ea50b1d 100644
--- a/nimterop/ast.nim
+++ b/nimterop/ast.nim
@@ -32,23 +32,28 @@ proc saveNodeData(node: TSNode): bool =
if name in ["math_expression", "primitive_type", "sized_type_specifier"]:
val = val.getType()
- let
- nparent = node.tsNodeParent()
- if not nparent.tsNodeIsNull() and node.tsNodePrevNamedSibling().tsNodeIsNull():
- let
- npname = nparent.tsNodeType()
- npparent = nparent.tsNodeParent()
- if npname == "pointer_declarator" or
- ($npname in ["function_declarator", "array_declarator"] and
- not npparent.tsNodeIsNull() and npparent.tsNodeType() == "pointer_declarator"):
-
- if gStateRT.data[^1].val != "object":
- gStateRT.data[^1].val = "ptr " & gStateRT.data[^1].val.getIdentifier()
- else:
- gStateRT.data[^1].val = "pointer"
+ if node.tsNodePrevNamedSibling().tsNodeIsNull() and
+ ((node.isPName("pointer_declarator") and not node.isPPName("function_declarator")) or
+ (node.getPName() in ["function_declarator", "array_declarator"] and node.isPPName("pointer_declarator"))):
+ if gStateRT.data[^1].val != "object":
+ gStateRT.data[^1].val = "ptr " & gStateRT.data[^1].val.getIdentifier()
+ if gStateRT.data[^1].val == "ptr char":
+ gStateRT.data[^1].val = "cstring"
+ else:
+ gStateRT.data[^1].val = "pointer"
gStateRT.data.add((name, val))
+ if node.isPName("pointer_declarator") and node.isPPName("function_declarator"):
+ gStateRT.data.add(("function_declarator", ""))
+
+ elif name in ["abstract_pointer_declarator"]:
+ gStateRT.data[^1].val = "ptr " & gStateRT.data[^1].val.getIdentifier()
+ if gStateRT.data[^1].val == "ptr char":
+ gStateRT.data[^1].val = "cstring"
+ elif name == "field_declaration":
+ gStateRT.data.add(("field_declaration", ""))
+
return true
proc searchAstForNode(ast: ref Ast, node: TSNode): bool =
diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim
index dd51166..2d29e6c 100644
--- a/nimterop/cimport.nim
+++ b/nimterop/cimport.nim
@@ -164,7 +164,15 @@ macro cImport*(filename: static string): untyped =
echo "Importing " & fullpath
- result.add parseStmt(getToast(fullpath))
+ let
+ output = getToast(fullpath)
+
+ try:
+ result.add parseStmt(output)
+ except:
+ echo output
+ echo "Failed to import generated nim"
+ result.add parseStmt(output)
if gStateCT.debug:
echo result.repr
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 7ce16bd..df1c3d7 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -191,3 +191,17 @@ proc getAstChildByName*(ast: ref Ast, name: string): ref Ast =
for i in 0 .. ast.children.len-1:
if name in ast.children[i].name.split("|"):
return ast.children[i]
+
+proc getPName*(node: TSNode): string =
+ if not node.tsNodeIsNull():
+ let
+ nparent = node.tsNodeParent()
+ if not nparent.tsNodeIsNull():
+ return $nparent.tsNodeType()
+
+proc isPName*(node: TSNode, name: string): bool =
+ return node.getPName() == name
+
+proc isPPName*(node: TSNode, name: string): bool =
+ if node.getPName().len != 0:
+ return node.tsNodeParent().isPName(name)
diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim
index bb789bc..b278872 100644
--- a/nimterop/grammar.nim
+++ b/nimterop/grammar.nim
@@ -25,6 +25,7 @@ proc initGrammar() =
))
let typeGrammar = """
+ (type_qualifier?)
(primitive_type|type_identifier?)
(sized_type_specifier?
(primitive_type?)
@@ -88,6 +89,10 @@ proc initGrammar() =
var
i = fstart
while i < gStateRT.data.len-fend:
+ if gStateRT.data[i].name == "field_declaration":
+ i += 1
+ continue
+
let
ftyp = gStateRT.data[i].val.getIdentifier()
fname = gStateRT.data[i+1].val.getIdentifier()
@@ -96,17 +101,64 @@ proc initGrammar() =
flen = gStateRT.data[i+2].val.getIdentifier()
gStateRT.typeStr &= &" {fname}*: array[{flen}, {ftyp}]\n"
i += 3
+ elif i+2 < gStateRT.data.len-fend and gStateRT.data[i+2].name == "function_declarator":
+ var
+ pout, pname, ptyp = ""
+ count = 1
+
+ i += 3
+ while i < gStateRT.data.len-fend:
+ if gStateRT.data[i].name == "field_declaration":
+ break
+
+ ptyp = gStateRT.data[i].val.getIdentifier()
+ if gStateRT.data[i+1].name == "identifier":
+ pname = gStateRT.data[i+1].val.getIdentifier()
+ i += 2
+ else:
+ pname = "a" & $count
+ count += 1
+ i += 1
+ if ptyp != "object":
+ pout &= &"{pname}: {ptyp},"
+
+ if pout.len != 0 and pout[^1] == ',':
+ pout = pout[0 .. ^2]
+ if ftyp != "object":
+ gStateRT.typeStr &= &" {fname}*: proc({pout}): {ftyp} {{.nimcall.}}\n"
+ else:
+ gStateRT.typeStr &= &" {fname}*: proc({pout}) {{.nimcall.}}\n"
+ i += 1
else:
gStateRT.typeStr &= &" {fname}*: {ftyp}\n"
i += 2
let
- fieldGrammar = """
+ paramListGrammar = &"""
+ (parameter_list
+ (parameter_declaration*
+ {typeGrammar}
+ (identifier?)
+ (pointer_declarator?
+ (identifier)
+ )
+ (abstract_pointer_declarator?)
+ )
+ )
+ """
+
+ fieldGrammar = &"""
(field_identifier?)
(array_declarator?
(field_identifier)
(identifier|number_literal)
)
+ (function_declarator?
+ (pointer_declarator
+ (field_identifier)
+ )
+ {paramListGrammar}
+ )
"""
fieldListGrammar = &"""
@@ -231,16 +283,7 @@ proc initGrammar() =
let funcGrammar = &"""
(function_declarator?
(identifier)
- (parameter_list
- (parameter_declaration*
- (type_qualifier?)
- {typeGrammar}
- (identifier?)
- (pointer_declarator?
- (identifier)
- )
- )
- )
+ {paramListGrammar}
)
"""
@@ -248,7 +291,6 @@ proc initGrammar() =
gStateRT.grammar.add((&"""
(declaration
(storage_class_specifier?)
- (type_qualifier?)
{typeGrammar}
{funcGrammar}
(pointer_declarator?
diff --git a/tests/include/test.c b/tests/include/test.c
index d63c974..3a59ffc 100644
--- a/tests/include/test.c
+++ b/tests/include/test.c
@@ -48,4 +48,10 @@ unsigned char test_call_param6(UNION2 param1) {
int test_call_param7(union UNION1 param1) {
return param1.field1;
+}
+
+float test_call_param8(int *param1) {
+ *param1 = 5 * *param1;
+
+ return 1.0 * *param1;
} \ No newline at end of file
diff --git a/tests/include/test.h b/tests/include/test.h
index e040d7f..29181c5 100644
--- a/tests/include/test.h
+++ b/tests/include/test.h
@@ -52,6 +52,12 @@ typedef struct {
ENUM4 *field5[TEST_INT];
} STRUCT4;
+typedef struct STRUCT5 {
+ int (*tci)();
+ struct STRUCT1 (*tcp)(int);
+ float (*tcp8)(int *i);
+} STRUCT5;
+
union UNION1 {
int field1;
float field2;
@@ -69,4 +75,5 @@ STRUCT2 test_call_param3(int param1, struct STRUCT1 param2);
ENUM2 test_call_param4(enum ENUM param1);
union UNION1 test_call_param5(float param1);
unsigned char test_call_param6(UNION2 param1);
-int test_call_param7(union UNION1 param1); \ No newline at end of file
+int test_call_param7(union UNION1 param1);
+float test_call_param8(int *param1); \ No newline at end of file
diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim
index deef7d2..69f8105 100644
--- a/tests/tnimterop_c.nim
+++ b/tests/tnimterop_c.nim
@@ -21,6 +21,7 @@ var
s2: STRUCT2
s3: STRUCT3
s4: STRUCT4
+ s5: STRUCT5
e: ENUM
e2: ENUM2 = enum5
@@ -33,6 +34,8 @@ var
u: UNION1
u2: UNION2
+ i: int
+
pt = 3
ct = 4
@@ -41,12 +44,18 @@ s2.field1 = 6
s3.field1 = 7
s4.field2[2] = 5
s4.field3[3] = enum1
+s5.tci = test_call_int
+s5.tcp = test_call_param
+s5.tcp8 = test_call_param8
+check s5.tci() == 5
e = enum1
e2 = enum4
u2.field2 = 'c'
+i = 5
+
check test_call_int() == 5
check test_call_param(5).field1 == 5
check test_call_param2(5, s2).field1 == 11
@@ -56,6 +65,8 @@ check test_call_param5(5.0).field2 == 5.0
check test_call_param6(u2) == 'c'
u.field1 = 4
check test_call_param7(u) == 4
+check test_call_param8(addr i) == 25.0
+check i == 25
check e3 == enum7
check e4 == enum11