From 4d68f4cb482400ee8bbc596a763b0c7161ba6ae2 Mon Sep 17 00:00:00 2001 From: Novus Nota <68142933+novusnota@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:58:14 +0200 Subject: [PATCH] fix(grammar): mostly accurate `funcId` representation (#628) --- CHANGELOG.md | 1 + cspell.json | 3 + .../__snapshots__/grammar.spec.ts.snap | 512 +++++++++++++++++- src/grammar/grammar.ohm | 13 +- .../test-failed/funcid-native-fun-comma.tact | 2 + .../test-failed/funcid-native-fun-dot.tact | 2 + .../funcid-native-fun-multiline-comments.tact | 2 + .../funcid-native-fun-number-decimal.tact | 2 + .../funcid-native-fun-number-hexadecimal.tact | 2 + .../test-failed/funcid-native-fun-number.tact | 2 + .../funcid-native-fun-only-underscore.tact | 2 + .../test-failed/funcid-native-fun-parens.tact | 2 + .../funcid-native-fun-semicolons.tact | 2 + .../test-failed/funcid-native-fun-space.tact | 2 + .../test-failed/funcid-native-fun-string.tact | 2 + .../funcid-native-fun-unclosed-parens.tact | 2 + ...t-void-decl-trailing-comma-no-params.tact} | 0 ...un-non-void-trailing-comma-no-params.tact} | 0 src/grammar/test/items-native-fun-decls.tact | 2 +- src/grammar/test/items-native-fun-funcid.tact | 53 ++ 20 files changed, 601 insertions(+), 7 deletions(-) create mode 100644 src/grammar/test-failed/funcid-native-fun-comma.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-dot.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-multiline-comments.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-number-decimal.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-number-hexadecimal.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-number.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-only-underscore.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-parens.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-semicolons.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-space.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-string.tact create mode 100644 src/grammar/test-failed/funcid-native-fun-unclosed-parens.tact rename src/grammar/test-failed/{item-native-fun-not-void-decl-trailing-comma-no-params.tact.tact => item-native-fun-not-void-decl-trailing-comma-no-params.tact} (100%) rename src/grammar/test-failed/{trait-fun-non-void-trailing-comma-no-params.tact.tact => trait-fun-non-void-trailing-comma-no-params.tact} (100%) create mode 100644 src/grammar/test/items-native-fun-funcid.tact diff --git a/CHANGELOG.md b/CHANGELOG.md index 538566929..b060b6e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Constant evaluation for structures with default and optional fields: PR [#621](https://github.com/tact-lang/tact/pull/621) - Report error for self-referencing and mutually-recursive types: PR [#624](https://github.com/tact-lang/tact/pull/624) - Error reporting for bounced receivers with missing parameter types: PR [#626](https://github.com/tact-lang/tact/pull/626) +- Allowed range of FunC function identifiers in `grammar.ohm`: PR [#628](https://github.com/tact-lang/tact/pull/628) ## [1.4.0] - 2024-06-21 diff --git a/cspell.json b/cspell.json index eaa270749..d3dfcb929 100644 --- a/cspell.json +++ b/cspell.json @@ -25,6 +25,7 @@ "forall", "funs", "funcfiftlib", + "funcid", "idict", "initof", "infixl", @@ -92,6 +93,8 @@ "grammar/sample.json", "src/generator/writers/writeStdlib.ts", "src/grammar/grammar.ohm-bundle.d.ts", + "src/grammar/test/items-native-fun-funcid.tact", + "src/grammar/test-failed/funcid-*.tact", "src/imports/stdlib.ts", "/src/test/compilation-failed/const-eval-failed.spec.ts", "src/test/e2e-emulated/address.spec.ts", diff --git a/src/grammar/__snapshots__/grammar.spec.ts.snap b/src/grammar/__snapshots__/grammar.spec.ts.snap index ad58ab621..2677286fe 100644 --- a/src/grammar/__snapshots__/grammar.spec.ts.snap +++ b/src/grammar/__snapshots__/grammar.spec.ts.snap @@ -71,6 +71,126 @@ Line 2, col 24: " `; +exports[`grammar should fail funcid-native-fun-comma 1`] = ` +":1:19: Parse error: expected ")" + +Line 1, col 19: +> 1 | @name(send_message,then_terminate) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-dot 1`] = ` +":1:10: Parse error: expected ")" + +Line 1, col 10: +> 1 | @name(msg.sender) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-multiline-comments 1`] = ` +":1:7: Parse error: expected not ("\\"" or "{-") + +Line 1, col 7: +> 1 | @name({-aaa-}) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-number 1`] = ` +":1:10: Parse error: expected not (a whiteSpace or "(" or ")" or "," or "." or ";" or "~") + +Line 1, col 10: +> 1 | @name(123) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-number-decimal 1`] = ` +":1:8: Parse error: expected not (a whiteSpace or "(" or ")" or "," or "." or ";" or "~") + +Line 1, col 8: +> 1 | @name(0) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-number-hexadecimal 1`] = ` +":1:10: Parse error: expected not (a whiteSpace or "(" or ")" or "," or "." or ";" or "~") + +Line 1, col 10: +> 1 | @name(0x0) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-only-underscore 1`] = ` +":1:8: Parse error: expected not (a whiteSpace or "(" or ")" or "," or "." or ";" or "~") + +Line 1, col 8: +> 1 | @name(_) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-parens 1`] = ` +":1:11: Parse error: expected ")" + +Line 1, col 11: +> 1 | @name(take(first)Entry) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-semicolons 1`] = ` +":1:9: Parse error: expected ")" + +Line 1, col 9: +> 1 | @name(pa;;in"\`aaa\`") + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-space 1`] = ` +":1:11: Parse error: expected ")" + +Line 1, col 11: +> 1 | @name(foo foo) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-string 1`] = ` +":1:7: Parse error: expected not ("\\"" or "{-") + +Line 1, col 7: +> 1 | @name("not_a_string) + ^ + 2 | native idTest(); +" +`; + +exports[`grammar should fail funcid-native-fun-unclosed-parens 1`] = ` +":1:9: Parse error: expected not (a whiteSpace or "(" or ")" or "," or "." or ";" or "~") + +Line 1, col 9: +> 1 | @name(aa(bb) + ^ + 2 | native idTest(); +" +`; + exports[`grammar should fail ident-cannot-be-if-reserved-word 1`] = ` ":2:9: Parse error: expected not a reservedWord @@ -186,7 +306,7 @@ Line 1, col 20: " `; -exports[`grammar should fail item-native-fun-not-void-decl-trailing-comma-no-params.tact 1`] = ` +exports[`grammar should fail item-native-fun-not-void-decl-trailing-comma-no-params 1`] = ` ":2:31: Empty parameter list should not have a dangling comma. Line 2, col 31: 1 | @name(native_name_2) @@ -324,7 +444,7 @@ Line 1, col 17: " `; -exports[`grammar should fail trait-fun-non-void-trailing-comma-no-params.tact 1`] = ` +exports[`grammar should fail trait-fun-non-void-trailing-comma-no-params 1`] = ` ":2:39: Empty parameter list should not have a dangling comma. Line 2, col 39: 1 | trait Test { @@ -3699,6 +3819,394 @@ native testFunc(): Bool;, } `; +exports[`grammar should parse items-native-fun-funcid 1`] = ` +{ + "id": 55, + "imports": [], + "items": [ + { + "attributes": [], + "id": 3, + "kind": "native_function_decl", + "loc": @name(query') +native idTest1();, + "name": { + "id": 1, + "kind": "id", + "loc": idTest1, + "text": "idTest1", + }, + "nativeName": { + "id": 2, + "kind": "func_id", + "loc": query', + "text": "query'", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 6, + "kind": "native_function_decl", + "loc": @name(query'') +native idTest2();, + "name": { + "id": 4, + "kind": "id", + "loc": idTest2, + "text": "idTest2", + }, + "nativeName": { + "id": 5, + "kind": "func_id", + "loc": query'', + "text": "query''", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 9, + "kind": "native_function_decl", + "loc": @name(CHECK) +native idTest3();, + "name": { + "id": 7, + "kind": "id", + "loc": idTest3, + "text": "idTest3", + }, + "nativeName": { + "id": 8, + "kind": "func_id", + "loc": CHECK, + "text": "CHECK", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 12, + "kind": "native_function_decl", + "loc": @name(_internal_val) +native idTest4();, + "name": { + "id": 10, + "kind": "id", + "loc": idTest4, + "text": "idTest4", + }, + "nativeName": { + "id": 11, + "kind": "func_id", + "loc": _internal_val, + "text": "_internal_val", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 15, + "kind": "native_function_decl", + "loc": @name(message_found?) +native idTest5();, + "name": { + "id": 13, + "kind": "id", + "loc": idTest5, + "text": "idTest5", + }, + "nativeName": { + "id": 14, + "kind": "func_id", + "loc": message_found?, + "text": "message_found?", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 18, + "kind": "native_function_decl", + "loc": @name(get_pubkeys&signatures) +native idTest6();, + "name": { + "id": 16, + "kind": "id", + "loc": idTest6, + "text": "idTest6", + }, + "nativeName": { + "id": 17, + "kind": "func_id", + "loc": get_pubkeys&signatures, + "text": "get_pubkeys&signatures", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 21, + "kind": "native_function_decl", + "loc": @name(dict::udict_set_builder) +native idTest7();, + "name": { + "id": 19, + "kind": "id", + "loc": idTest7, + "text": "idTest7", + }, + "nativeName": { + "id": 20, + "kind": "func_id", + "loc": dict::udict_set_builder, + "text": "dict::udict_set_builder", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 24, + "kind": "native_function_decl", + "loc": @name(_+_) +native idTest8();, + "name": { + "id": 22, + "kind": "id", + "loc": idTest8, + "text": "idTest8", + }, + "nativeName": { + "id": 23, + "kind": "func_id", + "loc": _+_, + "text": "_+_", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 27, + "kind": "native_function_decl", + "loc": @name(__) +native idTest9();, + "name": { + "id": 25, + "kind": "id", + "loc": idTest9, + "text": "idTest9", + }, + "nativeName": { + "id": 26, + "kind": "func_id", + "loc": __, + "text": "__", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 30, + "kind": "native_function_decl", + "loc": @name(fatal!) +native idTest10();, + "name": { + "id": 28, + "kind": "id", + "loc": idTest10, + "text": "idTest10", + }, + "nativeName": { + "id": 29, + "kind": "func_id", + "loc": fatal!, + "text": "fatal!", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 33, + "kind": "native_function_decl", + "loc": @name(123validname) +native idTest11();, + "name": { + "id": 31, + "kind": "id", + "loc": idTest11, + "text": "idTest11", + }, + "nativeName": { + "id": 32, + "kind": "func_id", + "loc": 123validname, + "text": "123validname", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 36, + "kind": "native_function_decl", + "loc": @name(2+2=2*2) +native idTest12();, + "name": { + "id": 34, + "kind": "id", + "loc": idTest12, + "text": "idTest12", + }, + "nativeName": { + "id": 35, + "kind": "func_id", + "loc": 2+2=2*2, + "text": "2+2=2*2", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 39, + "kind": "native_function_decl", + "loc": @name(-alsovalidname) +native idTest13();, + "name": { + "id": 37, + "kind": "id", + "loc": idTest13, + "text": "idTest13", + }, + "nativeName": { + "id": 38, + "kind": "func_id", + "loc": -alsovalidname, + "text": "-alsovalidname", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 42, + "kind": "native_function_decl", + "loc": @name(0xefefefhahaha) +native idTest14();, + "name": { + "id": 40, + "kind": "id", + "loc": idTest14, + "text": "idTest14", + }, + "nativeName": { + "id": 41, + "kind": "func_id", + "loc": 0xefefefhahaha, + "text": "0xefefefhahaha", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 45, + "kind": "native_function_decl", + "loc": @name({hehehe}) +native idTest15();, + "name": { + "id": 43, + "kind": "id", + "loc": idTest15, + "text": "idTest15", + }, + "nativeName": { + "id": 44, + "kind": "func_id", + "loc": {hehehe}, + "text": "{hehehe}", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 48, + "kind": "native_function_decl", + "loc": @name(pa{--}in"\`aaa\`") +native idTest16();, + "name": { + "id": 46, + "kind": "id", + "loc": idTest16, + "text": "idTest16", + }, + "nativeName": { + "id": 47, + "kind": "func_id", + "loc": pa{--}in"\`aaa\`", + "text": "pa{--}in"\`aaa\`"", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 51, + "kind": "native_function_decl", + "loc": @name(\`I'm a function too\`) +native idTest17();, + "name": { + "id": 49, + "kind": "id", + "loc": idTest17, + "text": "idTest17", + }, + "nativeName": { + "id": 50, + "kind": "func_id", + "loc": \`I'm a function too\`, + "text": "\`I'm a function too\`", + }, + "params": [], + "return": null, + }, + { + "attributes": [], + "id": 54, + "kind": "native_function_decl", + "loc": @name(\`any symbols ; ~ () are allowed here...\`) +native idTest18();, + "name": { + "id": 52, + "kind": "id", + "loc": idTest18, + "text": "idTest18", + }, + "nativeName": { + "id": 53, + "kind": "func_id", + "loc": \`any symbols ; ~ () are allowed here...\`, + "text": "\`any symbols ; ~ () are allowed here...\`", + }, + "params": [], + "return": null, + }, + ], + "kind": "module", +} +`; + exports[`grammar should parse items-struct-msg-fun-const 1`] = ` { "id": 60, diff --git a/src/grammar/grammar.ohm b/src/grammar/grammar.ohm index efe02496d..a253dadc7 100644 --- a/src/grammar/grammar.ohm +++ b/src/grammar/grammar.ohm @@ -253,7 +253,7 @@ Tact { letterAscii = letterAsciiLC | letterAsciiUC - letterComment = letterAsciiLC | letterAsciiUC | digit | "_" + letterDigitUnderscore = letterAsciiLC | letterAsciiUC | digit | "_" // Tact identifiers idStart = letterAscii | "_" @@ -262,10 +262,13 @@ Tact { id = ~reservedWord #idStart #(idPart*) - // FunC identifiers - funcLetter = letterAscii | "_" | "'" | "?" | "!" | "::" | "&" + // FunC identifiers, where `funcId` stands for FunC function identifier + // The plain identifier cannot be a single underscore nor just a number + funcPlainId = "_"? "-"? "0x"? hexDigit* ~hexDigit (~(whiteSpace | "(" | ")" | "," | "." | ";" | "~") any)+ - funcId = funcLetter #(funcLetter | digit)* + funcQuotedId = "`" (~("`" | "\n") any)+ "`" + + funcId = ~("\"" | "{-") ("." | "~")? (funcQuotedId | funcPlainId) // Boolean literals boolLiteral = ("true" | "false") ~idPart @@ -360,6 +363,8 @@ Tact { reservedWord = keyword // Comments + whiteSpace = "\t" | " " | lineTerminator + space += comment | lineTerminator comment = multiLineComment | singleLineComment diff --git a/src/grammar/test-failed/funcid-native-fun-comma.tact b/src/grammar/test-failed/funcid-native-fun-comma.tact new file mode 100644 index 000000000..796d23bed --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-comma.tact @@ -0,0 +1,2 @@ +@name(send_message,then_terminate) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-dot.tact b/src/grammar/test-failed/funcid-native-fun-dot.tact new file mode 100644 index 000000000..f0f9ab3ba --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-dot.tact @@ -0,0 +1,2 @@ +@name(msg.sender) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-multiline-comments.tact b/src/grammar/test-failed/funcid-native-fun-multiline-comments.tact new file mode 100644 index 000000000..b10f8d781 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-multiline-comments.tact @@ -0,0 +1,2 @@ +@name({-aaa-}) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-number-decimal.tact b/src/grammar/test-failed/funcid-native-fun-number-decimal.tact new file mode 100644 index 000000000..982cc7c29 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-number-decimal.tact @@ -0,0 +1,2 @@ +@name(0) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-number-hexadecimal.tact b/src/grammar/test-failed/funcid-native-fun-number-hexadecimal.tact new file mode 100644 index 000000000..2cf61f82c --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-number-hexadecimal.tact @@ -0,0 +1,2 @@ +@name(0x0) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-number.tact b/src/grammar/test-failed/funcid-native-fun-number.tact new file mode 100644 index 000000000..eb52799e2 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-number.tact @@ -0,0 +1,2 @@ +@name(123) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-only-underscore.tact b/src/grammar/test-failed/funcid-native-fun-only-underscore.tact new file mode 100644 index 000000000..5df424e55 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-only-underscore.tact @@ -0,0 +1,2 @@ +@name(_) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-parens.tact b/src/grammar/test-failed/funcid-native-fun-parens.tact new file mode 100644 index 000000000..fca4a6cd6 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-parens.tact @@ -0,0 +1,2 @@ +@name(take(first)Entry) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-semicolons.tact b/src/grammar/test-failed/funcid-native-fun-semicolons.tact new file mode 100644 index 000000000..7f0ab4e66 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-semicolons.tact @@ -0,0 +1,2 @@ +@name(pa;;in"`aaa`") +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-space.tact b/src/grammar/test-failed/funcid-native-fun-space.tact new file mode 100644 index 000000000..00e4e73ed --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-space.tact @@ -0,0 +1,2 @@ +@name(foo foo) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-string.tact b/src/grammar/test-failed/funcid-native-fun-string.tact new file mode 100644 index 000000000..85f572f80 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-string.tact @@ -0,0 +1,2 @@ +@name("not_a_string) +native idTest(); diff --git a/src/grammar/test-failed/funcid-native-fun-unclosed-parens.tact b/src/grammar/test-failed/funcid-native-fun-unclosed-parens.tact new file mode 100644 index 000000000..58b89c314 --- /dev/null +++ b/src/grammar/test-failed/funcid-native-fun-unclosed-parens.tact @@ -0,0 +1,2 @@ +@name(aa(bb) +native idTest(); diff --git a/src/grammar/test-failed/item-native-fun-not-void-decl-trailing-comma-no-params.tact.tact b/src/grammar/test-failed/item-native-fun-not-void-decl-trailing-comma-no-params.tact similarity index 100% rename from src/grammar/test-failed/item-native-fun-not-void-decl-trailing-comma-no-params.tact.tact rename to src/grammar/test-failed/item-native-fun-not-void-decl-trailing-comma-no-params.tact diff --git a/src/grammar/test-failed/trait-fun-non-void-trailing-comma-no-params.tact.tact b/src/grammar/test-failed/trait-fun-non-void-trailing-comma-no-params.tact similarity index 100% rename from src/grammar/test-failed/trait-fun-non-void-trailing-comma-no-params.tact.tact rename to src/grammar/test-failed/trait-fun-non-void-trailing-comma-no-params.tact diff --git a/src/grammar/test/items-native-fun-decls.tact b/src/grammar/test/items-native-fun-decls.tact index 1180e1796..3d839193a 100644 --- a/src/grammar/test/items-native-fun-decls.tact +++ b/src/grammar/test/items-native-fun-decls.tact @@ -5,4 +5,4 @@ native testFunc(); native testFunc(): Int; @name(native_name_3) -native testFunc(): Bool; \ No newline at end of file +native testFunc(): Bool; diff --git a/src/grammar/test/items-native-fun-funcid.tact b/src/grammar/test/items-native-fun-funcid.tact new file mode 100644 index 000000000..d4fa3b818 --- /dev/null +++ b/src/grammar/test/items-native-fun-funcid.tact @@ -0,0 +1,53 @@ +@name(query') +native idTest1(); + +@name(query'') +native idTest2(); + +@name(CHECK) +native idTest3(); + +@name(_internal_val) +native idTest4(); + +@name(message_found?) +native idTest5(); + +@name(get_pubkeys&signatures) +native idTest6(); + +@name(dict::udict_set_builder) +native idTest7(); + +@name(_+_) +native idTest8(); + +@name(__) +native idTest9(); + +@name(fatal!) +native idTest10(); + +@name(123validname) +native idTest11(); + +@name(2+2=2*2) +native idTest12(); + +@name(-alsovalidname) +native idTest13(); + +@name(0xefefefhahaha) +native idTest14(); + +@name({hehehe}) +native idTest15(); + +@name(pa{--}in"`aaa`") +native idTest16(); + +@name(`I'm a function too`) +native idTest17(); + +@name(`any symbols ; ~ () are allowed here...`) +native idTest18();