From 1d63481355f43c7be7a02e7409728c8fe0a9377a Mon Sep 17 00:00:00 2001 From: Novus Nota <68142933+novusnota@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:55:36 +0200 Subject: [PATCH] feat: re-wrote the FunC definition to match the 0.4.4 (#9) * Prism.js definition itself * Enhanced and expanded the test suite * Added extra niceties here and there --- .github/components.json | 3 +- langs/prism-func.js | 203 +++++--- langs/prism-tact.js | 344 +++++++------- package.json | 3 + tests/func/asm-functions.test | 248 ++++++++++ tests/func/comments.test | 33 -- tests/func/{default.test => complete.test} | 120 ++--- tests/func/constants.test | 57 +++ tests/func/functions.test | 166 +++++++ tests/func/globals.test | 85 ++++ tests/func/identifiers.test | 224 +++++++++ tests/func/literals-and-comments.test | 214 +++++++++ tests/func/pragmas.test | 208 +++++++++ tests/func/statements.test | 508 +++++++++++++++++++++ yarn.lock | 5 + 15 files changed, 2094 insertions(+), 327 deletions(-) create mode 100644 tests/func/asm-functions.test delete mode 100644 tests/func/comments.test rename tests/func/{default.test => complete.test} (77%) create mode 100644 tests/func/constants.test create mode 100644 tests/func/functions.test create mode 100644 tests/func/globals.test create mode 100644 tests/func/identifiers.test create mode 100644 tests/func/literals-and-comments.test create mode 100644 tests/func/pragmas.test create mode 100644 tests/func/statements.test diff --git a/.github/components.json b/.github/components.json index 354b067..c005693 100644 --- a/.github/components.json +++ b/.github/components.json @@ -510,7 +510,8 @@ "owner": "RunDevelopment" }, "func": { - "alias": ["FunC", "Func"], + "title": "FunC", + "alias": "fc", "owner": "sobolevn" }, "gml": { diff --git a/langs/prism-func.js b/langs/prism-func.js index 056e0cc..ad6b0ad 100644 --- a/langs/prism-func.js +++ b/langs/prism-func.js @@ -1,60 +1,143 @@ -/** - * @file Prism.js definition for FunC - * @link https://docs.ton.org/develop/func/overview - * @version 0.2.0 - * @author Nikita Sobolev (https://github.com/sobolevn) - * @license MIT - */ -(function (Prism) { - // 1. Does not start from " - // 2. Can start from ` and end with `, containing any character - // 3. Starts with underscore or { or } and have more than 1 character after it - // 4. Starts with letter, contains letters, numbers and underscores - var identifier = /(?!")(`([^`]+)`|((?=_)_|(?=\{)\{|(?=\})\}|(?![_`{}]))([^;,\[\]\(\)\s~.]+))/; - var string = /"[^\n"]+"[Hhcusa]?/; - var number = /\b([\d_]+|0x[\d_a-fA-F]+|0b[1_0]+)\b/; - - Prism.languages.func = { - 'include': { - pattern: /#include(.*);/, - inside: { - 'keyword': /#include/, - 'string': string, - 'punctuation': /;/ - }, - }, - 'pragma': { - pattern: /#pragma(.*);/, - inside: { - 'keyword': /#pragma|not-version|version/, - 'number': /(\d+)(.\d+)?(.\d+)?/, - 'operator': [/>=/, /<=/, /=/, />/, /|>=|<=|!=|==|~>>=|~>>|\/%|\^%=|\^%|~%|\^\/=|\^\/|~\/=|~\/|\+=|-=|\*=|\/=|%=|<<=|>>=|\^>>=|\^>>|&=|>>|<<|\^=|\|=|\^|=|~|\/|%|-|\*|\+|>|<|&|\||:|\?)/, - 'punctuation': /[\.;\(\),\[\]~\{\}]/, - }; -}(Prism)); \ No newline at end of file +/** + * @file Prism.js definition for FunC + * @link https://docs.ton.org/develop/func/overview + * @version 0.4.4 + * @author Novus Nota (https://github.com/novusnota) + * @author Nikita Sobolev (https://github.com/sobolevn) + * @license MIT + */ +(function(Prism) { + /** @type {Prism.GrammarValue} */ + var number = /-?\b(?:\d+|0x[\da-fA-F]+)\b(?![^\.~,;\[\]\(\)\s])/; + + /** @type {Prism.GrammarValue} */ + var string = [ + { // multi-line + pattern: /"""[\s\S]*?"""[Hhcusa]?/, + greedy: true, + inside: { + // string type + 'symbol': { + pattern: /("""[\s\S]*?""")[Hhcusa]/, + lookbehind: true, + greedy: true, + } + }, + }, + { // single-line + pattern: /"[^\n"]*"[Hhcusa]?/, + greedy: true, + inside: { + // string type + 'symbol': { + pattern: /("[^\n"]*")[Hhcusa]/, + lookbehind: true, + greedy: true, + } + }, + }, + ]; + + /** @type {Prism.GrammarValue} */ + var operator = /(?:!=|\?|:|%=|%|&=|&|\*=|\*|\+=|\+|->|-=|-|\/%|\/=|\/|<=>|<<=|<<|<=|<|==|=|>>=|>>|>=|>|\^>>=|\^>>|\^=|\^\/=|\^\/|\^%=|\^%|\^|\|=|\||~>>=|~>>|~\/=|~\/|~%|~)(?=\s)/; + + /** @type {RegExp[]} */ + var var_identifier = [ + // quoted + /`[^`\n]+`/, + // plain + /[^\.~,;\[\]\(\)\s]+/ + ]; + + /** Prism.js definition for FunC */ + Prism.languages.func = { + 'comment': [ + { // single-line + pattern: /;;.*/, + lookbehind: true, + greedy: true, + }, + { // multi-line, not nested (TODO: nesting) + // . isn't used, because it only applies to the single line + pattern: /\{-[\s\S]*?(?:-\}|$)/, + lookbehind: true, + greedy: true, + }, + { + // unused variable identifier + pattern: /\b_\b(?![^\.~,;\[\]\(\)\s])/ + }, + ], + + // Custom token for #pragma's + 'pragma': { + pattern: /#pragma(.*);/, + inside: { + 'keyword': /(?:#pragma|test-version-set|not-version|version|allow-post-modification|compute-asm-ltr)\b/, + 'number': /(?:\d+)(?:.\d+)?(?:.\d+)?/, + 'operator': /=|\^|<=|>=|<|>/, + 'string': string, + 'punctuation': /;/, + } + }, + + // Custom token for #include's + 'include': { + pattern: /#include(.*);/, + inside: { + 'keyword': /#include\b/, + 'string': string, + 'punctuation': /;/, + } + }, + + // builtin types + 'builtin': /\b(?:int|cell|slice|builder|cont|tuple|type)\b/, + + // builtin constants + 'boolean': /\b(?:false|true|nil|Nil)\b/, + + 'keyword': /\b(?:forall|extern|global|asm|impure|inline_ref|inline|auto_apply|method_id|operator|infixl|infixr|infix|const|return|var|repeat|do|while|until|try|catch|ifnot|if|then|elseifnot|elseif|else)\b/, + + 'number': number, + + 'string': string, + + 'operator': operator, + + 'punctuation': [/[\.,;\(\)\[\]]/, /[\{\}](?![^\.~,;\[\]\(\)\s])/], + + // Function and method names in declarations, definitions and calls + 'function': [ + { // quoted + pattern: new RegExp(var_identifier[0].source + /(?=\s*\()/.source), + greedy: true, + }, + { // bitwise not operator + pattern: /~_/, + greedy: true, + }, + { // remaining operators + pattern: new RegExp(/\^?_/.source + operator.source + /_/.source), + greedy: true, + }, + { // plain function or method name + pattern: new RegExp(/[\.~]?/.source + var_identifier[1].source + /(?=\s*\()/.source), + greedy: true, + }, + { // builtin functions and methods + pattern: /\b(?:divmod|moddiv|muldiv|muldivr|muldivc|muldivmod|null\?|throw|throw_if|throw_unless|throw_arg|throw_arg_if|throw_arg_unless|load_int|load_uint|preload_int|preload_uint|store_int|store_uint|load_bits|preload_bits|int_at|cell_at|slice_at|tuple_at|at|touch|touch2|run_method0|run_method1|run_method2|run_method3|~divmod|~moddiv|~store_int|~store_uint|~touch|~touch2|~dump|~stdump)\b/, + greedy: true, + }, + ], + + // Parametric polymorphism + 'class-name': /[A-Z][^\.~,;\[\]\(\)\s]*/, + + // All the rest of identifiers + 'variable': var_identifier.map(x => { return { pattern: x, greedy: true } }), + }; + + // Adding a fc alias + Prism.languages.fc = Prism.languages.func; +}(Prism)); diff --git a/langs/prism-tact.js b/langs/prism-tact.js index dd03f75..2c806c0 100644 --- a/langs/prism-tact.js +++ b/langs/prism-tact.js @@ -1,173 +1,171 @@ -/** - * @file Prism.js definition for Tact - * @link https://tact-lang.org - * @version 1.5.0 - * @author Novus Nota (https://github.com/novusnota) - * @license MIT - */ -(function(Prism) { - Prism.languages.tact = { - // reserved keywords - 'keyword': [ - { - pattern: /\b(?:abstract|asm|as|catch|const|contract(?!:)|do|else|extend|extends|foreach|fun|get|if|in|import|initOf|inline|let|message(?!:)|mutates|native|override|primitive|public|repeat|return|self|struct(?!:)|trait(?!:)|try|until|virtual|while|with)\b/, - }, - { // reserved function names - pattern: /\b(?:bounced|external|init|receive)\b(?=\()/ - }, - ], - - // built-in types - 'builtin': [ - { - pattern: /\b(?:Address|Bool|Builder|Cell|Int|Slice|String|StringBuilder)\b/, - }, - { // keyword after as, see: https://prismjs.com/extending.html#object-notation - pattern: /(\bas\s+)(?:coins|remaining|bytes32|bytes64|int257|u?int(?:2[0-5][0-6]|1[0-9][0-9]|[1-9][0-9]?))\b/, - lookbehind: true, - greedy: true, - }, - ], - - // TODO: somehow add this without breaking the maps - - // SCREAMING_SNAKE_CASE for null values and names of constants - 'constant': [ - { - pattern: /\bnull\b/, - }, - { - pattern: /\b[A-Z][A-Z0-9_]*\b/, - }, - ], - - // UpperCamelCase for names of contracts, traits, structs, messages - 'class-name': { - pattern: /\b[A-Z]\w*\b/, - }, - - // mappings to FunC - 'attribute': [ - { // functions - pattern: /@name/, - inside: { - 'function': /.+/, - }, - }, - { // contract interfaces - pattern: /@interface/, - inside: { - 'function': /.+/, - } - } - ], - - 'function': { - pattern: /\b\w+(?=\()/, - }, - - 'boolean': { - pattern: /\b(?:false|true)\b/, - }, - - 'number': [ - { // hexadecimal, case-insensitive /i - pattern: /\b0x[0-9a-f](?:_?[0-9a-f])*\b/i, - }, - { // octal, case-insensitive /i - pattern: /\b0o[0-7](?:_?[0-7])*\b/i, - }, - { // binary, case-insensitive /i - pattern: /\b0b[01](?:_?[01])*\b/i, - }, - { // decimal integers, starting with 0 - pattern: /\b0\d*\b/, - }, - { // other decimal integers - pattern: /\b[1-9](?:_?\d)*\b/, - }, - ], - - 'string': undefined, - - 'punctuation': { - pattern: /[{}[\]();,.:?]/, - }, - - 'comment': [ - { // single-line - pattern: /(^|[^\\:])\/\/.*/, - lookbehind: true, - greedy: true, - }, - { // multi-line - pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, - lookbehind: true, - greedy: true, - }, - { - // unused variable identifier - pattern: /\b_\b/ - } - ], - - 'operator': { - 'pattern': /![!=]?|->|[+\-*/%=]=?|[<>]=|<>?|~|\|[\|=]?|&[&=]?|\^=?/, - }, - - 'variable': { - 'pattern': /\b[a-zA-Z_]\w*\b/, - }, - - }; - - // strings, made this way to not collide with other entities - Prism.languages.insertBefore('tact', 'string', { - 'string-literal': { - pattern: /(?:(")(?:\\.|(?!\1)[^\\\r\n])*\1(?!\1))/, - greedy: true, - inside: { - 'regex': [ - { // \\ \" \n \r \t \v \b \f - pattern: /\\[\\"nrtvbf]/, - }, - { // hexEscape, \x00 through \xFF - pattern: /\\x[0-9a-fA-F]{2}/, - }, - { // unicodeEscape, \u0000 through \uFFFF - pattern: /\\u[0-9a-fA-F]{4}/, - }, - { // unicodeCodePoint, \u{0} through \u{FFFFFF} - pattern: /\\u\{[0-9a-fA-F]{1,6}\}/, - }, - ], - 'string': { - pattern: /[\s\S]+/, - }, - }, - }, - }); - - // map and bounced message generic type modifiers - Prism.languages.insertBefore('tact', 'keyword', { - 'generics': { - pattern: /(?:\b(?:bounced|map)\b<[^\\\r\n]*>)/, - greedy: true, - inside: { - 'builtin': [ - ...Prism.languages['tact']['builtin'], - { - pattern: /\b(?:bounced(?=<)|map(?=<))\b/ - }, - ], - 'class-name': Prism.languages['tact']['class-name'], - 'punctuation': { - pattern: /[<>(),.?]/, - }, - 'keyword': { - pattern: /\bas\b/, - }, - }, - }, - }); -}(Prism)); +/** + * @file Prism.js definition for Tact + * @link https://tact-lang.org + * @version 1.5.0 + * @author Novus Nota (https://github.com/novusnota) + * @license MIT + */ +(function(Prism) { + Prism.languages.tact = { + // reserved keywords + 'keyword': [ + { + pattern: /\b(?:abstract|asm|as|catch|const|contract(?!:)|do|else|extend|extends|foreach|fun|get|if|in|import|initOf|inline|let|message(?!:)|mutates|native|override|primitive|public|repeat|return|self|struct(?!:)|trait(?!:)|try|until|virtual|while|with)\b/, + }, + { // reserved function names + pattern: /\b(?:bounced|external|init|receive)\b(?=\()/ + }, + ], + + // built-in types + 'builtin': [ + { + pattern: /\b(?:Address|Bool|Builder|Cell|Int|Slice|String|StringBuilder)\b/, + }, + { // keyword after as, see: https://prismjs.com/extending.html#object-notation + pattern: /(\bas\s+)(?:coins|remaining|bytes32|bytes64|int257|u?int(?:2[0-5][0-6]|1[0-9][0-9]|[1-9][0-9]?))\b/, + lookbehind: true, + greedy: true, + }, + ], + + // SCREAMING_SNAKE_CASE for null values and names of constants + 'constant': [ + { + pattern: /\bnull\b/, + }, + { + pattern: /\b[A-Z][A-Z0-9_]*\b/, + }, + ], + + // UpperCamelCase for names of contracts, traits, structs, messages + 'class-name': { + pattern: /\b[A-Z]\w*\b/, + }, + + // mappings to FunC + 'attribute': [ + { // functions + pattern: /@name/, + inside: { + 'function': /.+/, + }, + }, + { // contract interfaces + pattern: /@interface/, + inside: { + 'function': /.+/, + } + } + ], + + 'function': { + pattern: /\b\w+(?=\()/, + }, + + 'boolean': { + pattern: /\b(?:false|true)\b/, + }, + + 'number': [ + { // hexadecimal, case-insensitive /i + pattern: /\b0x[0-9a-f](?:_?[0-9a-f])*\b/i, + }, + { // octal, case-insensitive /i + pattern: /\b0o[0-7](?:_?[0-7])*\b/i, + }, + { // binary, case-insensitive /i + pattern: /\b0b[01](?:_?[01])*\b/i, + }, + { // decimal integers, starting with 0 + pattern: /\b0\d*\b/, + }, + { // other decimal integers + pattern: /\b[1-9](?:_?\d)*\b/, + }, + ], + + 'string': undefined, + + 'punctuation': { + pattern: /[{}[\]();,.:?]/, + }, + + 'comment': [ + { // single-line + pattern: /(^|[^\\:])\/\/.*/, + lookbehind: true, + greedy: true, + }, + { // multi-line + pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, + lookbehind: true, + greedy: true, + }, + { + // unused variable identifier + pattern: /\b_\b/ + } + ], + + 'operator': { + 'pattern': /![!=]?|->|[+\-*/%=]=?|[<>]=|<>?|~|\|[\|=]?|&[&=]?|\^=?/, + }, + + 'variable': { + 'pattern': /\b[a-zA-Z_]\w*\b/, + }, + + }; + + // strings, made this way to not collide with other entities + Prism.languages.insertBefore('tact', 'string', { + 'string-literal': { + pattern: /(?:(")(?:\\.|(?!\1)[^\\\r\n])*\1(?!\1))/, + greedy: true, + inside: { + 'regex': [ + { // \\ \" \n \r \t \v \b \f + pattern: /\\[\\"nrtvbf]/, + }, + { // hexEscape, \x00 through \xFF + pattern: /\\x[0-9a-fA-F]{2}/, + }, + { // unicodeEscape, \u0000 through \uFFFF + pattern: /\\u[0-9a-fA-F]{4}/, + }, + { // unicodeCodePoint, \u{0} through \u{FFFFFF} + pattern: /\\u\{[0-9a-fA-F]{1,6}\}/, + }, + ], + 'string': { + pattern: /[\s\S]+/, + }, + }, + }, + }); + + // map and bounced message generic type modifiers + Prism.languages.insertBefore('tact', 'keyword', { + 'generics': { + pattern: /(?:\b(?:bounced|map)\b<[^\\\r\n]*>)/, + greedy: true, + inside: { + 'builtin': [ + ...Prism.languages['tact']['builtin'], + { + pattern: /\b(?:bounced(?=<)|map(?=<))\b/ + }, + ], + 'class-name': Prism.languages['tact']['class-name'], + 'punctuation': { + pattern: /[<>(),.?]/, + }, + 'keyword': { + pattern: /\bas\b/, + }, + }, + }, + }); +}(Prism)); diff --git a/package.json b/package.json index 43400c3..22e8602 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,10 @@ "test": "yarn test:tact && yarn test:func && yarn test:fift && yarn test:tlb", "test:tact": "cd .github/submodule-prism && npm run test:languages -- --language tact", "test:tact:accept": "cd .github/submodule-prism && npm run test:languages -- --language tact --accept", + "test:tact:update": "cd .github/submodule-prism && npm run test:languages -- --language tact --update", "test:func": "cd .github/submodule-prism && npm run test:languages -- --language func", "test:func:accept": "cd .github/submodule-prism && npm run test:languages -- --language func --accept", + "test:func:update": "cd .github/submodule-prism && npm run test:languages -- --language func --update", "test:fift": "cd .github/submodule-prism && npm run test:languages -- --language fift", "test:fift:accept": "cd .github/submodule-prism && npm run test:languages -- --language fift --accept", "test:tlb": "cd .github/submodule-prism && npm run test:languages -- --language tlb", @@ -29,6 +31,7 @@ "regex-coverage": "cd .github/submodule-prism && npm run regex-coverage" }, "devDependencies": { + "@types/prismjs": "^1.26.4", "symlink-dir": "^5.2.1" }, "packageManager": "yarn@1.22.22" diff --git a/tests/func/asm-functions.test b/tests/func/asm-functions.test new file mode 100644 index 0000000..97f4951 --- /dev/null +++ b/tests/func/asm-functions.test @@ -0,0 +1,248 @@ +;; Single assembly string +int inc_then_negate(int x) asm "INC NEGATE"; + +;; Multiple assembly strings +int inc_then_negate'(int x) asm "INC" "NEGATE"; + +;; Multi-line strings + +int inc_then_negate''(int x) asm """INC NEGATE"""; + +slice hello_world() asm """ + "Hello" + " " + "World" + $+ $+ $>s + PUSHSLICE +"""; + +;; Mix single-line and multi-line strings + +int inc_then_negate'''(int x) asm "INC" """ + NEGATE +"""; + +;; Arrangement of return values (and whitespaces check) + (builder, int) +store_uint_quiet (builder b, int x, int len) +asm (x b len) +"STUXQ"; + +;; Arrangement of arguments +(int, builder) store_uint_quiet'(int x, builder b, int len) + asm( -> 1 0) "STUXQ"; + +;; Arrangement of arguments mapped to return values +(int, builder) store_uint_quiet''(builder b, int x, int len) + asm(x b len -> 1 0) "STUXQ"; + +;; Parametric polymorphism with forall + +forall X, Y -> (X, Y) store_uint_quiet'''(builder b, int x, int len) asm(x b len -> 1 0) "STUXQ"; + +forall X -> X unsingle([X] t) asm "UNSINGLE"; + +---------------------------------------------------- + +[ + ["comment", ";; Single assembly string"], + + ["builtin", "int"], + ["function", "inc_then_negate"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"INC NEGATE\""]], + ["punctuation", ";"], + + ["comment", ";; Multiple assembly strings"], + + ["builtin", "int"], + ["function", "inc_then_negate'"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"INC\""]], + ["string", ["\"NEGATE\""]], + ["punctuation", ";"], + + ["comment", ";; Multi-line strings"], + + ["builtin", "int"], + ["function", "inc_then_negate''"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"\"\"INC NEGATE\"\"\""]], + ["punctuation", ";"], + + ["builtin", "slice"], + ["function", "hello_world"], + ["punctuation", "("], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"\"\"\r\n \"Hello\"\r\n \" \"\r\n \"World\"\r\n $+ $+ $>s\r\n PUSHSLICE\r\n\"\"\""]], + ["punctuation", ";"], + + ["comment", ";; Mix single-line and multi-line strings"], + + ["builtin", "int"], + ["function", "inc_then_negate'''"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"INC\""]], + ["string", ["\"\"\"\r\n NEGATE\r\n\"\"\""]], + ["punctuation", ";"], + + ["comment", ";; Arrangement of return values (and whitespaces check)"], + + ["punctuation", "("], + ["builtin", "builder"], + ["punctuation", ","], + ["builtin", "int"], + ["punctuation", ")"], + + ["function", "store_uint_quiet"], + ["punctuation", "("], + ["builtin", "builder"], + ["variable", "b"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "len"], + ["punctuation", ")"], + + ["keyword", "asm"], + ["punctuation", "("], + ["variable", "x"], + ["variable", "b"], + ["variable", "len"], + ["punctuation", ")"], + + ["string", ["\"STUXQ\""]], + ["punctuation", ";"], + + ["comment", ";; Arrangement of arguments"], + + ["punctuation", "("], + ["builtin", "int"], + ["punctuation", ","], + ["builtin", "builder"], + ["punctuation", ")"], + ["function", "store_uint_quiet'"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ","], + ["builtin", "builder"], + ["variable", "b"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "len"], + ["punctuation", ")"], + + ["keyword", "asm"], + ["punctuation", "("], + ["operator", "->"], + ["number", "1"], + ["number", "0"], + ["punctuation", ")"], + ["string", ["\"STUXQ\""]], + ["punctuation", ";"], + + ["comment", ";; Arrangement of arguments mapped to return values"], + + ["punctuation", "("], + ["builtin", "int"], + ["punctuation", ","], + ["builtin", "builder"], + ["punctuation", ")"], + ["function", "store_uint_quiet''"], + ["punctuation", "("], + ["builtin", "builder"], + ["variable", "b"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "len"], + ["punctuation", ")"], + + ["keyword", "asm"], + ["punctuation", "("], + ["variable", "x"], + ["variable", "b"], + ["variable", "len"], + ["operator", "->"], + ["number", "1"], + ["number", "0"], + ["punctuation", ")"], + ["string", ["\"STUXQ\""]], + ["punctuation", ";"], + + ["comment", ";; Parametric polymorphism with forall"], + + ["keyword", "forall"], + ["class-name", "X"], + ["punctuation", ","], + ["class-name", "Y"], + ["operator", "->"], + ["punctuation", "("], + ["class-name", "X"], + ["punctuation", ","], + ["class-name", "Y"], + ["punctuation", ")"], + ["function", "store_uint_quiet'''"], + ["punctuation", "("], + ["builtin", "builder"], + ["variable", "b"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "x"], + ["punctuation", ","], + ["builtin", "int"], + ["variable", "len"], + ["punctuation", ")"], + ["keyword", "asm"], + ["punctuation", "("], + ["variable", "x"], + ["variable", "b"], + ["variable", "len"], + ["operator", "->"], + ["number", "1"], + ["number", "0"], + ["punctuation", ")"], + ["string", ["\"STUXQ\""]], + ["punctuation", ";"], + + ["keyword", "forall"], + ["class-name", "X"], + ["operator", "->"], + ["class-name", "X"], + ["function", "unsingle"], + ["punctuation", "("], + ["punctuation", "["], + ["class-name", "X"], + ["punctuation", "]"], + ["variable", "t"], + ["punctuation", ")"], + ["keyword", "asm"], + ["string", ["\"UNSINGLE\""]], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Functions with asm strings diff --git a/tests/func/comments.test b/tests/func/comments.test deleted file mode 100644 index e7745b6..0000000 --- a/tests/func/comments.test +++ /dev/null @@ -1,33 +0,0 @@ -{- - Multiline test --} - -{- Single line test -} - -;; Single line - -;; - -;; Multiline -;; comment - -8 ;; inline -12 - ----------------------------------------------------- - -[ - ["comment", "{-\r\n\tMultiline test\r\n-}"], - - ["comment", "{- Single line test -}"], - - ["comment", ";; Single line"], - - ["comment", ";;"], - - ["comment", ";; Multiline"], - ["comment", ";; comment"], - - ["number", "8"], ["comment", ";; inline"], - ["number", "12"] -] diff --git a/tests/func/default.test b/tests/func/complete.test similarity index 77% rename from tests/func/default.test rename to tests/func/complete.test index 718c0f6..8088e93 100644 --- a/tests/func/default.test +++ b/tests/func/complete.test @@ -7,7 +7,7 @@ const int k_int = 1; () recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure { slice cs = in_msg_full.begin_parse(); - int flags = cs~load_uint(0x4_1_0); + int flags = cs~load_uint(0x4f); if ((flags & 1) == true) { ;; ignore all bounced messages return (); @@ -16,10 +16,8 @@ const int k_int = 1; slice sender_address = cs~load_msg_addr(); {- - {- - test - is test - -} - -} + Totally random number: 42 + -} ;; Send message var message = begin_cell() @@ -57,7 +55,7 @@ int counter() method_id { [ ["include", [ ["keyword", "#include"], - ["string", "\"../\""], + ["string", ["\"../\""]], ["punctuation", ";"] ]], ["pragma", [ @@ -81,13 +79,13 @@ int counter() method_id { ["keyword", "const"], ["builtin", "int"], ["variable", "k_int"], - ["variable", "="], + ["operator", "="], ["number", "1"], ["punctuation", ";"], ["punctuation", "("], ["punctuation", ")"], - ["variable", "recv_internal"], + ["function", "recv_internal"], ["punctuation", "("], ["builtin", "int"], ["variable", "my_balance"], @@ -106,22 +104,21 @@ int counter() method_id { ["builtin", "slice"], ["variable", "cs"], - ["variable", "="], + ["operator", "="], ["variable", "in_msg_full"], ["punctuation", "."], - ["variable", "begin_parse"], + ["function", "begin_parse"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], ["builtin", "int"], ["variable", "flags"], - ["variable", "="], + ["operator", "="], ["variable", "cs"], - ["operator", "~"], - ["variable", "load_uint"], + ["function", "~load_uint"], ["punctuation", "("], - ["number", "0x4_1_0"], + ["number", "0x4f"], ["punctuation", ")"], ["punctuation", ";"], @@ -129,10 +126,10 @@ int counter() method_id { ["punctuation", "("], ["punctuation", "("], ["variable", "flags"], - ["variable", "&"], + ["operator", "&"], ["number", "1"], ["punctuation", ")"], - ["variable", "=="], + ["operator", "=="], ["boolean", "true"], ["punctuation", ")"], ["punctuation", "{"], @@ -147,28 +144,26 @@ int counter() method_id { ["builtin", "slice"], ["variable", "sender_address"], - ["variable", "="], + ["operator", "="], ["variable", "cs"], - ["operator", "~"], - ["variable", "load_msg_addr"], + ["function", "~load_msg_addr"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], - ["comment", "{-\r\n {-\r\n test - is test\r\n -}"], - ["variable", "-}"], + ["comment", "{-\r\n Totally random number: 42\r\n\t-}"], ["comment", ";; Send message"], - ["builtin", "var"], + ["keyword", "var"], ["variable", "message"], - ["variable", "="], - ["variable", "begin_cell"], + ["operator", "="], + ["function", "begin_cell"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_uint"], + ["function", "store_uint"], ["punctuation", "("], ["number", "0x18"], ["punctuation", ","], @@ -176,50 +171,53 @@ int counter() method_id { ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_slice"], + ["function", "store_slice"], ["punctuation", "("], ["variable", "sender_address"], ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_coins"], + ["function", "store_coins"], ["punctuation", "("], ["number", "0"], ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_uint"], + ["function", "store_uint"], ["punctuation", "("], ["number", "0"], ["punctuation", ","], ["number", "1"], - ["variable", "+"], + ["operator", "+"], ["number", "4"], - ["variable", "+"], + ["operator", "+"], ["number", "4"], - ["variable", "+"], + ["operator", "+"], ["number", "64"], - ["variable", "+"], + ["operator", "+"], ["number", "32"], - ["variable", "+"], + ["operator", "+"], ["number", "1"], - ["variable", "+"], + ["operator", "+"], ["number", "1"], ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_slice"], + ["function", "store_slice"], ["punctuation", "("], - ["string", "\"Hello, world!\"s"], + ["string", [ + "\"Hello, world!\"", + ["symbol", "s"] + ]], ["punctuation", ")"], ["punctuation", "."], - ["variable", "end_cell"], + ["function", "end_cell"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], - ["variable", "send_raw_message"], + ["function", "send_raw_message"], ["punctuation", "("], ["variable", "message"], ["punctuation", ","], @@ -229,48 +227,47 @@ int counter() method_id { ["comment", ";; Update counter"], - ["builtin", "var"], + ["keyword", "var"], ["variable", "cs"], - ["variable", "="], - ["variable", "get_data"], + ["operator", "="], + ["function", "get_data"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "."], - ["variable", "begin_parse"], + ["function", "begin_parse"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], - ["builtin", "var"], + ["keyword", "var"], ["variable", "counter"], - ["variable", "="], + ["operator", "="], ["variable", "data"], - ["operator", "~"], - ["variable", "load_uint"], + ["function", "~load_uint"], ["punctuation", "("], ["number", "32"], ["punctuation", ")"], ["punctuation", ";"], - ["variable", "store_data"], + ["function", "store_data"], ["punctuation", "("], - ["variable", "begin_cell"], + ["function", "begin_cell"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "."], - ["variable", "store_uint"], + ["function", "store_uint"], ["punctuation", "("], ["variable", "counter"], - ["variable", "+"], + ["operator", "+"], ["number", "1"], ["punctuation", ","], ["number", "32"], ["punctuation", ")"], ["punctuation", "."], - ["variable", "end_cell"], + ["function", "end_cell"], ["punctuation", "("], ["punctuation", ")"], @@ -281,7 +278,7 @@ int counter() method_id { ["punctuation", "("], ["punctuation", ")"], - ["variable", "recv_external"], + ["function", "recv_external"], ["punctuation", "("], ["builtin", "slice"], ["variable", "in_msg"], @@ -289,7 +286,7 @@ int counter() method_id { ["keyword", "impure"], ["punctuation", "{"], - ["variable", "throw"], + ["function", "throw"], ["punctuation", "("], ["number", "0xffff"], ["punctuation", ")"], @@ -298,28 +295,27 @@ int counter() method_id { ["punctuation", "}"], ["builtin", "int"], - ["variable", "counter"], + ["function", "counter"], ["punctuation", "("], ["punctuation", ")"], ["keyword", "method_id"], ["punctuation", "{"], - ["builtin", "var"], + ["keyword", "var"], ["variable", "data"], - ["variable", "="], - ["variable", "get_data"], + ["operator", "="], + ["function", "get_data"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", "."], - ["variable", "begin_parse"], + ["function", "begin_parse"], ["punctuation", "("], ["punctuation", ")"], ["punctuation", ";"], ["keyword", "return"], ["variable", "data"], - ["operator", "~"], - ["variable", "load_uint"], + ["function", "~load_uint"], ["punctuation", "("], ["number", "32"], ["punctuation", ")"], @@ -327,3 +323,7 @@ int counter() method_id { ["punctuation", "}"] ] + +---------------------------------------------------- + +Complete test of the FunC language definition for Prism.js diff --git a/tests/func/constants.test b/tests/func/constants.test new file mode 100644 index 0000000..d6a4a0d --- /dev/null +++ b/tests/func/constants.test @@ -0,0 +1,57 @@ +;; Inferred type +const c1 = 42; + +;; Inferred type for multiple ones with using prior constants +const c2 = 27, c3 = c1; + +;; int, inferred int or slice from a string +const int c4 = 0, c5 = 0, slice c6 = "It's Zendaya"s; + +---------------------------------------------------- + +[ + ["comment", ";; Inferred type"], + + ["keyword", "const"], + ["variable", "c1"], + ["operator", "="], + ["number", "42"], + ["punctuation", ";"], + + ["comment", ";; Inferred type for multiple ones with using prior constants"], + + ["keyword", "const"], + ["variable", "c2"], + ["operator", "="], + ["number", "27"], + ["punctuation", ","], + ["variable", "c3"], + ["operator", "="], + ["variable", "c1"], + ["punctuation", ";"], + + ["comment", ";; int, inferred int or slice from a string"], + + ["keyword", "const"], + ["builtin", "int"], + ["variable", "c4"], + ["operator", "="], + ["number", "0"], + ["punctuation", ","], + ["variable", "c5"], + ["operator", "="], + ["number", "0"], + ["punctuation", ","], + ["builtin", "slice"], + ["variable", "c6"], + ["operator", "="], + ["string", [ + "\"It's Zendaya\"", + ["symbol", "s"] + ]], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Constants diff --git a/tests/func/functions.test b/tests/func/functions.test new file mode 100644 index 0000000..c41528b --- /dev/null +++ b/tests/func/functions.test @@ -0,0 +1,166 @@ +;; Void +() void(); + +;; Regular parameters +() params(int p1, cell p2, () p3, (slice) p4, [builder] p5); + +;; Parametric polymorphism with forall +forall X -> () poly(X p1); +forall X, Y -> (Y, X) poly'(X p1, Y p2); + +;; Attributes (called specifiers in TON Docs) +() attr() impure inline_ref inline method_id(0x2A); +() attr'() method_id(42); +() attr''() method_id; + +;; Empty body (note, that {} is an identifier, so there must be whitespace in-between) +() body() { } + +;; Everything +forall XXX -> XXX everything(XXX x) impure inline_ref inline method_id(0x2A) method_id { } + +---------------------------------------------------- + +[ + ["comment", ";; Void"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "void"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["comment", ";; Regular parameters"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "params"], + ["punctuation", "("], + ["builtin", "int"], + ["variable", "p1"], + ["punctuation", ","], + ["builtin", "cell"], + ["variable", "p2"], + ["punctuation", ","], + ["punctuation", "("], + ["punctuation", ")"], + ["variable", "p3"], + ["punctuation", ","], + ["punctuation", "("], + ["builtin", "slice"], + ["punctuation", ")"], + ["variable", "p4"], + ["punctuation", ","], + ["punctuation", "["], + ["builtin", "builder"], + ["punctuation", "]"], + ["variable", "p5"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["comment", ";; Parametric polymorphism with forall"], + + ["keyword", "forall"], + ["class-name", "X"], + ["operator", "->"], + ["punctuation", "("], + ["punctuation", ")"], + ["function", "poly"], + ["punctuation", "("], + ["class-name", "X"], + ["variable", "p1"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "forall"], + ["class-name", "X"], + ["punctuation", ","], + ["class-name", "Y"], + ["operator", "->"], + ["punctuation", "("], + ["class-name", "Y"], + ["punctuation", ","], + ["class-name", "X"], + ["punctuation", ")"], + ["function", "poly'"], + ["punctuation", "("], + ["class-name", "X"], + ["variable", "p1"], + ["punctuation", ","], + ["class-name", "Y"], + ["variable", "p2"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["comment", ";; Attributes (called specifiers in TON Docs)"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "attr"], + ["punctuation", "("], + ["punctuation", ")"], + ["keyword", "impure"], + ["keyword", "inline_ref"], + ["keyword", "inline"], + ["keyword", "method_id"], + ["punctuation", "("], + ["number", "0x2A"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "attr'"], + ["punctuation", "("], + ["punctuation", ")"], + ["keyword", "method_id"], + ["punctuation", "("], + ["number", "42"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "attr''"], + ["punctuation", "("], + ["punctuation", ")"], + ["keyword", "method_id"], + ["punctuation", ";"], + + ["comment", ";; Empty body (note, that {} is an identifier, so there must be whitespace in-between)"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "body"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["comment", ";; Everything"], + + ["keyword", "forall"], + ["class-name", "XXX"], + ["operator", "->"], + ["class-name", "XXX"], + ["function", "everything"], + ["punctuation", "("], + ["class-name", "XXX"], + ["variable", "x"], + ["punctuation", ")"], + ["keyword", "impure"], + ["keyword", "inline_ref"], + ["keyword", "inline"], + ["keyword", "method_id"], + ["punctuation", "("], + ["number", "0x2A"], + ["punctuation", ")"], + ["keyword", "method_id"], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Functions diff --git a/tests/func/globals.test b/tests/func/globals.test new file mode 100644 index 0000000..e288ee5 --- /dev/null +++ b/tests/func/globals.test @@ -0,0 +1,85 @@ +;; No type +global glob1; + +;; Primitive type +global int glob2; + +;; Mapped type +global int -> int glob3; + +;; Convoluted example +global ((int, (_, cont, cell, (), [int])) -> int) glob4; + +;; Multiple at once +global int glob5, (builder, tuple) glob6, glob7; + +---------------------------------------------------- + +[ + ["comment", ";; No type"], + ["keyword", "global"], ["variable", "glob1"], ["punctuation", ";"], + + ["comment", ";; Primitive type"], + + ["keyword", "global"], + ["builtin", "int"], + ["variable", "glob2"], + ["punctuation", ";"], + + ["comment", ";; Mapped type"], + + ["keyword", "global"], + ["builtin", "int"], + ["operator", "->"], + ["builtin", "int"], + ["variable", "glob3"], + ["punctuation", ";"], + + ["comment", ";; Convoluted example"], + + ["keyword", "global"], + ["punctuation", "("], + ["punctuation", "("], + ["builtin", "int"], + ["punctuation", ","], + ["punctuation", "("], + ["comment", "_"], + ["punctuation", ","], + ["builtin", "cont"], + ["punctuation", ","], + ["builtin", "cell"], + ["punctuation", ","], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ","], + ["punctuation", "["], + ["builtin", "int"], + ["punctuation", "]"], + ["punctuation", ")"], + ["punctuation", ")"], + ["operator", "->"], + ["builtin", "int"], + ["punctuation", ")"], + ["variable", "glob4"], + ["punctuation", ";"], + + ["comment", ";; Multiple at once"], + + ["keyword", "global"], + ["builtin", "int"], + ["variable", "glob5"], + ["punctuation", ","], + ["punctuation", "("], + ["builtin", "builder"], + ["punctuation", ","], + ["builtin", "tuple"], + ["punctuation", ")"], + ["variable", "glob6"], + ["punctuation", ","], + ["variable", "glob7"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Global variable declarations diff --git a/tests/func/identifiers.test b/tests/func/identifiers.test new file mode 100644 index 0000000..2adc972 --- /dev/null +++ b/tests/func/identifiers.test @@ -0,0 +1,224 @@ +;; Identifiers +global query'; +global query''; +;; global CHECK; +global _internal_val; +global message_found?; +global get_pubkeys&signatures; +global dict::udict_set_builder; +global _+_; +global __; +global fatal!; +global 123validname; +global 2+2=2*2; +global -alsovalidname; +global 0xefefefhahaha; +global {hehehe}; +global pa{--}in"`aaa`"; +global `I'm an identifier too`; +global `any symbols ; ~ () are allowed here...`; +;; global C4; +;; global C4g; +global 4C; +global _0x0; +global _0; +global 0x_; +global 0x0_; +global 0_; +global hash#256; +global 馃拃馃拃馃拃0xDEADBEEF馃拃馃拃馃拃; +global __tact_verify_address; +global __tact_pow2; +global randomize_lt; +global fixed248::asin; +global fixed248::nrand_fast; +global atan_f261_inlined; +global f谭虂蛯虁蛨台蜌i痰虗蛺虋泰蛿汰n谈處蛢蛬虝虩虧袒泰e谈虙炭虝蛼叹虧虣; +global 鉂わ笍鉂わ笍鉂わ笍thanks鉂わ笍鉂わ笍鉂わ笍; +global intslice; +global int2; + +;; Function identifiers, which can start with . or ~ +() ~impure_touch(); +() ~udict::delete_get_min(); +() .something(); + +---------------------------------------------------- + +[ + ["comment", ";; Identifiers"], + + ["keyword", "global"], + ["variable", "query'"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "query''"], + ["punctuation", ";"], + + ["comment", ";; global CHECK;"], + + ["keyword", "global"], + ["variable", "_internal_val"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "message_found?"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "get_pubkeys&signatures"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "dict::udict_set_builder"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "_+_"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "__"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "fatal!"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "123validname"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "2+2=2*2"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "-alsovalidname"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "0xefefefhahaha"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "{hehehe}"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "pa{--}in\"`aaa`\""], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "`I'm an identifier too`"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "`any symbols ; ~ () are allowed here...`"], + ["punctuation", ";"], + + ["comment", ";; global C4;"], + + ["comment", ";; global C4g;"], + + ["keyword", "global"], + ["variable", "4C"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "_0x0"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "_0"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "0x_"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "0x0_"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "0_"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "hash#256"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "馃拃馃拃馃拃0xDEADBEEF馃拃馃拃馃拃"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "__tact_verify_address"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "__tact_pow2"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "randomize_lt"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "fixed248::asin"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "fixed248::nrand_fast"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "atan_f261_inlined"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "f谭虂蛯虁蛨台蜌i痰虗蛺虋泰蛿汰n谈處蛢蛬虝虩虧袒泰e谈虙炭虝蛼叹虧虣"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "鉂わ笍鉂わ笍鉂わ笍thanks鉂わ笍鉂わ笍鉂わ笍"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "intslice"], + ["punctuation", ";"], + + ["keyword", "global"], + ["variable", "int2"], + ["punctuation", ";"], + + ["comment", ";; Function identifiers, which can start with . or ~"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "~impure_touch"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "~udict::delete_get_min"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "."], + ["function", "something"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Identifiers. Yes, they're this crazy... diff --git a/tests/func/literals-and-comments.test b/tests/func/literals-and-comments.test new file mode 100644 index 0000000..e5d85f6 --- /dev/null +++ b/tests/func/literals-and-comments.test @@ -0,0 +1,214 @@ +;; Integer literals +() integers() { + 42; + 0x2A; + 0x2a; + + -42; + -0x2A; + -0x2a; +} + +;; String literals +() strings() { + "slice"; + "2A"s; + "EQAFmjUoZUqKFEBGYFEMbv-m61sFStgAfUR8J6hJDwUU09iT"a; + "int hex"u; + "int 32 bits of sha256"h; + "int 256 bits of sha256"H; + "int crc32"c; + + """ + multi + line + """; + + """2A"""s; + """EQAFmjUoZUqKFEBGYFEMbv-m61sFStgAfUR8J6hJDwUU09iT"""a; + """ + ... + """u; + """ + ... + """h; + """ + ... + """H; + """ + ... + """c; +} + +;; Single-line comment +{- + Multi-line comment + ;; Also a part of the multi-line comment, not a single-line one +-} + +;; Comment madness +forall ;; ... +X, Y ;; ... +-> ;; ... +() {- + ... +-} ;; ... +comments! +() ;; ... +{ {- ... -} return (); {- ... -} } + +---------------------------------------------------- + +[ + ["comment", ";; Integer literals"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "integers"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["number", "42"], + ["punctuation", ";"], + + ["number", "0x2A"], + ["punctuation", ";"], + + ["number", "0x2a"], + ["punctuation", ";"], + + ["number", "-42"], ["punctuation", ";"], + ["number", "-0x2A"], ["punctuation", ";"], + ["number", "-0x2a"], ["punctuation", ";"], + ["punctuation", "}"], + + ["comment", ";; String literals"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "strings"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["string", ["\"slice\""]], + ["punctuation", ";"], + + ["string", [ + "\"2A\"", + ["symbol", "s"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"EQAFmjUoZUqKFEBGYFEMbv-m61sFStgAfUR8J6hJDwUU09iT\"", + ["symbol", "a"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"int hex\"", + ["symbol", "u"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"int 32 bits of sha256\"", + ["symbol", "h"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"int 256 bits of sha256\"", + ["symbol", "H"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"int crc32\"", + ["symbol", "c"] + ]], + ["punctuation", ";"], + + ["string", ["\"\"\"\r\n multi\r\n line\r\n \"\"\""]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"2A\"\"\"", + ["symbol", "s"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"EQAFmjUoZUqKFEBGYFEMbv-m61sFStgAfUR8J6hJDwUU09iT\"\"\"", + ["symbol", "a"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"\r\n ...\r\n \"\"\"", + ["symbol", "u"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"\r\n ...\r\n \"\"\"", + ["symbol", "h"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"\r\n ...\r\n \"\"\"", + ["symbol", "H"] + ]], + ["punctuation", ";"], + + ["string", [ + "\"\"\"\r\n ...\r\n \"\"\"", + ["symbol", "c"] + ]], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["comment", ";; Single-line comment"], + ["comment", "{- \r\n Multi-line comment\r\n ;; Also a part of the multi-line comment, not a single-line one\r\n-}"], + + ["comment", ";; Comment madness"], + + ["keyword", "forall"], + ["comment", ";; ..."], + + ["class-name", "X"], + ["punctuation", ","], + ["class-name", "Y"], + ["comment", ";; ..."], + + ["operator", "->"], + ["comment", ";; ..."], + + ["punctuation", "("], + ["punctuation", ")"], + ["comment", "{-\r\n ...\r\n-}"], + ["comment", ";; ..."], + + ["function", "comments!"], + + ["punctuation", "("], + ["punctuation", ")"], + ["comment", ";; ..."], + + ["punctuation", "{"], + ["comment", "{- ... -}"], + ["keyword", "return"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["comment", "{- ... -}"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Literals and comments diff --git a/tests/func/pragmas.test b/tests/func/pragmas.test new file mode 100644 index 0000000..c6e05f1 --- /dev/null +++ b/tests/func/pragmas.test @@ -0,0 +1,208 @@ +;; Literals +#pragma allow-post-modification; +#pragma compute-asm-ltr; + +;; Version ranges +#pragma version 0; +#pragma version 0.0; +#pragma version 0.0.0; +#pragma version =0; +#pragma version =0.0; +#pragma version =0.0.0; +#pragma version ^0; +#pragma version <0; +#pragma version >0; +#pragma version <=0; +#pragma version >=0; +#pragma not-version 0; +#pragma not-version 0.0; +#pragma not-version 0.0.0; +#pragma not-version =0; +#pragma not-version =0.0; +#pragma not-version =0.0.0; +#pragma not-version ^0; +#pragma not-version <0; +#pragma not-version >0; +#pragma not-version <=0; +#pragma not-version >=0; + +;; Used in internal tests of FunC in ton-blockchain/ton monorepo +#pragma test-version-set "0.4.4"; + +---------------------------------------------------- + +[ + ["comment", ";; Literals"], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "allow-post-modification"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "compute-asm-ltr"], + ["punctuation", ";"] + ]], + + ["comment", ";; Version ranges"], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["number", "0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["number", "0.0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "="], + ["number", "0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "="], + ["number", "0.0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "^"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "<"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", ">"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", "<="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "version"], + ["operator", ">="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["number", "0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["number", "0.0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "="], + ["number", "0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "="], + ["number", "0.0.0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "^"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "<"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", ">"], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", "<="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "not-version"], + ["operator", ">="], + ["number", "0"], + ["punctuation", ";"] + ]], + + ["comment", ";; Used in internal tests of FunC in ton-blockchain/ton monorepo"], + ["pragma", [ + ["keyword", "#pragma"], + ["keyword", "test-version-set"], + ["string", ["\"0.4.4\""]], + ["punctuation", ";"] + ]] +] + +---------------------------------------------------- + +Pragmas diff --git a/tests/func/statements.test b/tests/func/statements.test new file mode 100644 index 0000000..8558c44 --- /dev/null +++ b/tests/func/statements.test @@ -0,0 +1,508 @@ +;; return +() return_stmt() { return (); } +int return_stmt'() { return 42; } + +;; Block +() block_stmt() { + { + { return (); } + } +} + +;; Empty +() empty_stmt() { ; + ; ; ; ; +} + +;; Condition +() cond_stmt() { + if 1 { } + ifnot 0 { } + + if 1 { ; ; } + ifnot 0 { ; ; } + + if 0 { ; ; } else { ; ; } + ifnot 1 { ; ; } else { ; ; } + + if 0 { } elseif 1 { } + if 0 { } elseifnot 0 { } + ifnot 1 { } elseif 1 { } + ifnot 1 { } elseifnot 0 { } + + if 0 { ; ; } elseif 1 { ; ; } + if 0 { ; ; } elseifnot 0 { ; ; } + ifnot 1 { ; ; } elseif 1 { ; ; } + ifnot 1 { ; ; } elseifnot 0 { ; ; } + + if 0 { ; ; } elseif 0 { ; ; } else { ; ; } + ifnot 1 { ; ; } elseifnot 1 { ; ; } else { ; ; } +} + +;; repeat +() repeat_stmt() { + repeat (1) { } + + repeat 1 { + ; ; ; + } +} + +;; do...until +() until_stmt() { + do { } until 0; + + do { + ; ; ; + { repeat 1 { } } + } until 0; +} + +;; while +() while_stmt() { + while 0 { } + + while 0 { + ; ; ; + { repeat 1 { } } + } +} + +;; try...catch +() try_catch_stmt() { + try { + ; ; ; + { } + } catch (_, _) { + ; ; ; + { } + } + + try { } catch (_) { } + try { } catch (exception, exit_code) { } +} + +;; Expression (most of the related tests are in another file) +() expression_stmt() { + 42; +} + +---------------------------------------------------- + +[ + ["comment", ";; return"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "return_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "return"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["builtin", "int"], + ["function", "return_stmt'"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + ["keyword", "return"], + ["number", "42"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["comment", ";; Block"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "block_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["punctuation", "{"], + + ["punctuation", "{"], + ["keyword", "return"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["punctuation", "}"], + + ["punctuation", "}"], + + ["comment", ";; Empty"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "empty_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", ";"], + + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["comment", ";; Condition"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "cond_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "if"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "else"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "else"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "elseif"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "elseifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "elseif"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "elseifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseif"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseif"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseifnot"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "if"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseif"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "else"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "ifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "elseifnot"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + ["keyword", "else"], + ["punctuation", "{"], + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["punctuation", "}"], + + ["comment", ";; repeat"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "repeat_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "repeat"], + ["punctuation", "("], + ["number", "1"], + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "repeat"], ["number", "1"], ["punctuation", "{"], + ["punctuation", ";"], ["punctuation", ";"], ["punctuation", ";"], + ["punctuation", "}"], + ["punctuation", "}"], + + ["comment", ";; do...until"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "until_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "do"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "until"], + ["number", "0"], + ["punctuation", ";"], + + ["keyword", "do"], + ["punctuation", "{"], + + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + + ["punctuation", "{"], + ["keyword", "repeat"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", "}"], + + ["punctuation", "}"], + ["keyword", "until"], + ["number", "0"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["comment", ";; while"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "while_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "while"], + ["number", "0"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "while"], + ["number", "0"], + ["punctuation", "{"], + + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + + ["punctuation", "{"], + ["keyword", "repeat"], + ["number", "1"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", "}"], + + ["punctuation", "}"], + + ["punctuation", "}"], + + ["comment", ";; try...catch"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "try_catch_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "try"], + ["punctuation", "{"], + + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + + ["punctuation", "{"], + ["punctuation", "}"], + + ["punctuation", "}"], + ["keyword", "catch"], + ["punctuation", "("], + ["comment", "_"], + ["punctuation", ","], + ["comment", "_"], + ["punctuation", ")"], + ["punctuation", "{"], + + ["punctuation", ";"], + ["punctuation", ";"], + ["punctuation", ";"], + + ["punctuation", "{"], + ["punctuation", "}"], + + ["punctuation", "}"], + + ["keyword", "try"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "catch"], + ["punctuation", "("], + ["comment", "_"], + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "try"], + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "catch"], + ["punctuation", "("], + ["variable", "exception"], + ["punctuation", ","], + ["variable", "exit_code"], + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["punctuation", "}"], + + ["comment", ";; Expression (most of the related tests are in another file)"], + + ["punctuation", "("], + ["punctuation", ")"], + ["function", "expression_stmt"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["number", "42"], + ["punctuation", ";"], + + ["punctuation", "}"] +] + +---------------------------------------------------- + +Statements diff --git a/yarn.lock b/yarn.lock index 1e10ab2..23a644c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@types/prismjs@^1.26.4": + version "1.26.4" + resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.4.tgz#1a9e1074619ce1d7322669e5b46fbe823925103a" + integrity sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg== + "@zkochan/rimraf@^2.1.2": version "2.1.3" resolved "https://registry.yarnpkg.com/@zkochan/rimraf/-/rimraf-2.1.3.tgz#1074cb72d6e4997275285b04296a343b6ac7046b"