diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2018-12-27 22:42:55 -0600 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2018-12-27 22:42:55 -0600 |
| commit | 21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a (patch) | |
| tree | 0d3fb8f8f5f45943309e2bcf7327b1cbd57b2f04 | |
| parent | c7a3c7b7d606b00fa1c676e244c39002b8fc1609 (diff) | |
| download | nimterop-21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a.tar.gz nimterop-21bd2d4112e5bf40d3fe52435cc15ccd5d4ad71a.zip | |
Struct field function pointers, cstring, show toast error in cimport
| -rw-r--r-- | nimterop/ast.nim | 33 | ||||
| -rw-r--r-- | nimterop/cimport.nim | 10 | ||||
| -rw-r--r-- | nimterop/getters.nim | 14 | ||||
| -rw-r--r-- | nimterop/grammar.nim | 66 | ||||
| -rw-r--r-- | tests/include/test.c | 6 | ||||
| -rw-r--r-- | tests/include/test.h | 9 | ||||
| -rw-r--r-- | tests/tnimterop_c.nim | 11 |
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 |
