diff options
Diffstat (limited to 'tests/00_syntax')
22 files changed, 0 insertions, 1464 deletions
diff --git a/tests/00_syntax/00_single_line_comments b/tests/00_syntax/00_single_line_comments deleted file mode 100644 index 24a32a2..0000000 --- a/tests/00_syntax/00_single_line_comments +++ /dev/null @@ -1,15 +0,0 @@ -Single line comments. - --- Expect stdout -- -This is a test. - a test. -A test . - --- End -- - --- Testcase -- -This is {# a comment within #} a test. -{# Comment before #} a test. -A test {# and a comment after #}. -{# This is a comment with embedded "{#" tag. #} --- End -- diff --git a/tests/00_syntax/01_unterminated_comment b/tests/00_syntax/01_unterminated_comment deleted file mode 100644 index 1d3669c..0000000 --- a/tests/00_syntax/01_unterminated_comment +++ /dev/null @@ -1,15 +0,0 @@ -Unterminated comment - --- Expect stderr -- -Syntax error: Unterminated template block -In line 1, byte 9: - - `This is {# an unclosed comment` - ^-- Near here - - --- End -- - --- Testcase -- -This is {# an unclosed comment --- End -- diff --git a/tests/00_syntax/02_multi_line_comments b/tests/00_syntax/02_multi_line_comments deleted file mode 100644 index 99fc37e..0000000 --- a/tests/00_syntax/02_multi_line_comments +++ /dev/null @@ -1,12 +0,0 @@ -Multiline comments. - --- Expect stdout -- -This is an example text for testing comment blocks. --- End -- - --- Testcase -- -This is an example text {# containing -a comment spanning multiple lines and - different indentation - #} for testing comment blocks. --- End -- diff --git a/tests/00_syntax/03_expression_blocks b/tests/00_syntax/03_expression_blocks deleted file mode 100644 index 3568016..0000000 --- a/tests/00_syntax/03_expression_blocks +++ /dev/null @@ -1,11 +0,0 @@ -Testing expression blocks. - --- Expect stdout -- -The result of 3 * 7 is 21. -To escape the start tag, output it as string expression: {{ --- End -- - --- Testcase -- -The result of 3 * 7 is {{ 3 * 7 }}. -To escape the start tag, output it as string expression: {{ "{{" }} --- End -- diff --git a/tests/00_syntax/04_statement_blocks b/tests/00_syntax/04_statement_blocks deleted file mode 100644 index 920ed71..0000000 --- a/tests/00_syntax/04_statement_blocks +++ /dev/null @@ -1,20 +0,0 @@ -Testing statement blocks. - --- Expect stdout -- -The result of 3 * 7 is 21. -A statement block may contain multiple statements: Hello World -To escape the start tag, output it as string expression: {% -Alternatively print it: {% --- End -- - --- Testcase -- -The result of 3 * 7 is {%+ print(3 * 7) %}. -A statement block may contain multiple statements: {%+ - print("Hello "); - print("World"); -%} - -To escape the start tag, output it as string expression: {{ "{%" }} -Alternatively print it: {%+ print("{%") %} - --- End -- diff --git a/tests/00_syntax/05_block_nesting b/tests/00_syntax/05_block_nesting deleted file mode 100644 index fcfd7da..0000000 --- a/tests/00_syntax/05_block_nesting +++ /dev/null @@ -1,24 +0,0 @@ -Nesting blocks into non-comment blocks should fail. - --- Expect stderr -- -Syntax error: Template blocks may not be nested -In line 2, byte 61: - - `We may not nest statement blocks into expression blocks: {{ {% print(1 + 2) %} }}.` - Near here --------------------------------------------------^ - - -Syntax error: Template blocks may not be nested -In line 3, byte 61: - - `We may not nest expression blocks into statement blocks: {% {{ 1 + 2 }} %}.` - Near here --------------------------------------------------^ - - --- End -- - --- Testcase -- -We can nest other block types into comments: {# {% {{ 1 + 2 }} %} #} -We may not nest statement blocks into expression blocks: {{ {% print(1 + 2) %} }}. -We may not nest expression blocks into statement blocks: {% {{ 1 + 2 }} %}. --- End -- diff --git a/tests/00_syntax/06_open_statement_block b/tests/00_syntax/06_open_statement_block deleted file mode 100644 index 9c2d142..0000000 --- a/tests/00_syntax/06_open_statement_block +++ /dev/null @@ -1,13 +0,0 @@ -The last statement block of a template may remain open, this is useful for templates -that contain only code. - --- Expect stdout -- -This template consists entirely of script code! --- End -- - --- Testcase -- -{% - print("This template "); - print("consists entirely "); - print("of script code!\n"); --- End -- diff --git a/tests/00_syntax/07_embedded_single_line_comments b/tests/00_syntax/07_embedded_single_line_comments deleted file mode 100644 index 43f188c..0000000 --- a/tests/00_syntax/07_embedded_single_line_comments +++ /dev/null @@ -1,21 +0,0 @@ -Statement and expression blocks may contain C++-style comments. -A C++-style comment is started by two subsequent slashes and spans -until the next newline. - --- Expect stdout -- -The result of 5 + 9 is 14. -Statement blocks may use C++ comments too: Test Another test. --- End -- - --- Testcase -- -The result of 5 + 9 is {{ // The block end tag is ignored: }} -// And the expression block continues here! -5 + 9 }}. -Statement blocks may use C++ comments too: {%+ - print("Test"); // A comment. - - // Another comment. - print(" Another test."); -%} - --- End -- diff --git a/tests/00_syntax/08_embedded_multi_line_comments b/tests/00_syntax/08_embedded_multi_line_comments deleted file mode 100644 index 75aba5f..0000000 --- a/tests/00_syntax/08_embedded_multi_line_comments +++ /dev/null @@ -1,24 +0,0 @@ -Statement and expression blocks may contain C-style comments. -A C-style comment is started by a slash followed by an asterisk -and ended by an asterisk followed by a slash. - -Such comments may appear everywhere within statement or expression -blocks, even in the middle of statements or expressions. - --- Expect stdout -- -The result of 12 - 4 is 8. -Statement blocks may use C comments too: Test Another test. The final test. --- End -- - --- Testcase -- -The result of 12 - 4 is {{ /* A comment before */ 12 - /* or even within */ 4 /* or after an expression */ }}. -Statement blocks may use C comments too: {%+ - print("Test"); /* A comment. */ - - /* Another comment. */ - print(" Another test."); - - print(/* A comment within */ " The final test."); -%} - --- End -- diff --git a/tests/00_syntax/09_string_literals b/tests/00_syntax/09_string_literals deleted file mode 100644 index 0967850..0000000 --- a/tests/00_syntax/09_string_literals +++ /dev/null @@ -1,50 +0,0 @@ -String literals may be enclosed in single or double quotes. -Embedded escape sequences are started with a backslash, followed -by either a hexadecimal, an octal or a single character escape sequence. - --- Expect stdout -- -Single quoted string -Double quoted string -Unicode escape sequence: ☀💩 -Escaped double quote (") character -Escaped single quote (') character -Hexadecimal escape: XYZ xyz -Octal escape: ABC xyz -{ "Single char escape": "\u0007\b\u001b\f\r\t\u000b\\\n" } --- End -- - --- Testcase -- -{{ 'Single quoted string' }} -{{ "Double quoted string" }} -{{ "Unicode escape sequence: \u2600\uD83D\uDCA9" }} -{{ "Escaped double quote (\") character" }} -{{ 'Escaped single quote (\') character' }} -{{ "Hexadecimal escape: \x58\x59\x5A \x78\x79\x7a" }} -{{ "Octal escape: \101\102\103 \170\171\172" }} -{{ { "Single char escape": "\a\b\e\f\r\t\v\\\n" } }} --- End -- - - -Testing various parsing corner cases. - --- Expect stdout -- -[ "\t", "\n", "y", "\u0001", "\n", "\u0001\u0002", "\u0001\u0002", "\u0001\u0002", "\u0001a", "\na" ] --- End -- - --- Testcase -- -{% - print([ - "\ ", // properly handle escaped tab - "\ -", // properly handle escaped newline - "\y", // substitute unrecognized escape with escaped char - "\1", // handle short octal sequence at end of string - "\12", // handle short octal sequence at end of string - "\1\2", // handle subsequent short octal sequences - "\001\2", // handle short sequence after long one - "\1\002", // handle long sequence after short one - "\1a", // handle short octal sequence terminated by non-octal char - "\12a" // handle short octal sequence terminated by non-octal char - ], "\n"); -%} --- End -- diff --git a/tests/00_syntax/10_numeric_literals b/tests/00_syntax/10_numeric_literals deleted file mode 100644 index 3e367d0..0000000 --- a/tests/00_syntax/10_numeric_literals +++ /dev/null @@ -1,26 +0,0 @@ -C-style numeric integer and float literals are understood, as well -as the special keywords "Infinity" and "NaN" to denote the IEEE 754 -floating point values. - -Numeric values are either stored as signed 64 bit integers or signed -doubles internally. - --- Expect stdout -- -Integers literals: 123, 127, 2748, 57082 -Float literals: 10, 10.3, 1.23456e-65, 16.0625 -Special values: Infinity, Infinity, NaN, NaN -Minimum values: -9223372036854775808, -1.79769e+308 -Maximum values: 9223372036854775807, 1.79769e+308 -Minimum truncation: -9223372036854775808, -Infinity -Maximum truncation: 9223372036854775807, Infinity --- End -- - --- Testcase -- -Integers literals: {{ 123 }}, {{ 0177 }}, {{ 0xabc }}, {{ 0xDEFA }} -Float literals: {{ 10. }}, {{ 10.3 }}, {{ 123.456e-67 }}, {{ 0x10.1 }} -Special values: {{ Infinity }}, {{ 1 / 0 }}, {{ NaN }}, {{ "x" / 1 }} -Minimum values: {{ -9223372036854775808 }}, {{ -1.7976931348623158e+308 }} -Maximum values: {{ 9223372036854775807 }}, {{ 1.7976931348623158e+308 }} -Minimum truncation: {{ -10000000000000000000 }}, {{ -1.0e309 }} -Maximum truncation: {{ 10000000000000000000 }}, {{ 1.0e309 }} --- End -- diff --git a/tests/00_syntax/11_misc_literals b/tests/00_syntax/11_misc_literals deleted file mode 100644 index 372741c..0000000 --- a/tests/00_syntax/11_misc_literals +++ /dev/null @@ -1,17 +0,0 @@ -The utpl script language features a number of keywords which represent -certain special values. - --- Expect stdout -- -The "this" keyword refers to the current function context: object -The "null" keyword represents the null value: null -The "true" keyword represents a true boolean value: true -The "false" keyword represents a false boolean value: false --- End -- - --- Testcase -- -{% let t = { f: function() { return this; } } %} -The "this" keyword refers to the current function context: {{ type(t.f()) }} -The "null" keyword represents the null value: {{ "" + null }} -The "true" keyword represents a true boolean value: {{ true }} -The "false" keyword represents a false boolean value: {{ false }} --- End -- diff --git a/tests/00_syntax/12_block_whitespace_control b/tests/00_syntax/12_block_whitespace_control deleted file mode 100644 index 911171c..0000000 --- a/tests/00_syntax/12_block_whitespace_control +++ /dev/null @@ -1,47 +0,0 @@ -By default, whitespace before a block start tag or after a block end tag -is retained. By suffixing the start tag or prefixing the end tag with a -dash, the leading or trailing whitespace is trimmed respectively. - --- Expect stdout -- -Whitespace control applies to all block types: -Comment before: | |, after: | |, both: || -Statement before: |test |, after: | test|, both: |test| -Expression before: |test |, after: | test|, both: |test| - -By default whitespace around a block is retained. -Leading whitespace can be trimmed like this. -The same applies to trailing whitespace. -It is also possible to trim bothleading and trailingwhitespace. - -Stripping works across multiple lines as well:test - -Likewise, stripping over multiple lines of trailing whitespace works as -expected too.This is after the block. --- End -- - --- Testcase -- -Whitespace control applies to all block types: -Comment before: | {#- test #} |, after: | {#- test #} |, both: | {#- test -#} | -Statement before: | {%- print("test") %} |, after: | {%+ print("test") -%} |, both: | {%- print("test") -%} | -Expression before: | {{- "test" }} |, after: | {{ "test" -}} |, both: | {{- "test" -}} | - -By default whitespace {{ "around a block" }} is retained. -Leading whitespace can be trimmed {#- note the leading dash #} like this. -The same applies to {# note the trailing dash -#} trailing whitespace. -It is also possible to trim both {{- "leading and trailing" -}} whitespace. - -Stripping works across multiple lines as well: - -{%- - /* The word "test" will be printed after "well:" above */ - print("test") -%} - - -Likewise, stripping over multiple lines of trailing whitespace works as -expected too. - -{#- Any whitespace after "expected too." and before "This is after the block" will be trimmed. -#} - -This is after the block. --- End -- diff --git a/tests/00_syntax/13_object_literals b/tests/00_syntax/13_object_literals deleted file mode 100644 index 18fbbed..0000000 --- a/tests/00_syntax/13_object_literals +++ /dev/null @@ -1,174 +0,0 @@ -The utpl script language supports declaring objects (dictionaries) using -either JSON or JavaScript notation. - --- Expect stdout -- -{ } -{ "name": "Bob", "age": 31, "email": { "work": "bob@example.com", "private": "bob@example.org" } } -{ "banana": "yellow", "tomato": "red", "broccoli": "green" } -{ "foo": "bar", "complex key": "qrx" } -{ "foo": { "bar": true } } --- End -- - --- Testcase -- -{% - // An empty object can be declared using a pair of curly brackets - empty_obj = { }; - - // It is also possible to use JSON notation to declare an object - json_obj = { - "name": "Bob", - "age": 31, - "email": { - "work": "bob@example.com", - "private": "bob@example.org" - } - }; - - // Declaring an object in JavaScript notation is supported as well - another_obj = { - banana: "yellow", - tomato: "red", - broccoli: "green" - }; - - // Mixing styles is allowed too - third_obj = { - foo: "bar", - "complex key": "qrx" - }; - - // Important caveat: when nesting objects, ensure that curly brackets - // are separated by space or newline to avoid interpretation as - // expression block tag! - nested_obj = { foo: { bar: true } }; // <-- mind the space in "} }" - - // Printing (or stringifying) objects will return their JSON representation - print(empty_obj, "\n"); - print(json_obj, "\n"); - print(another_obj, "\n"); - print(third_obj, "\n"); - print(nested_obj, "\n"); -%} --- End -- - - -Additionally, utpl implements ES6-like spread operators to allow shallow copying -of object properties into other objects. - --- Expect stdout -- -{ "foo": true, "bar": false } -{ "foo": true, "bar": false, "baz": 123, "qrx": 456 } -{ "foo": false, "bar": true, "baz": 123, "qrx": 456 } -{ "foo": true, "bar": false } -{ "foo": true, "bar": false, "level2": { "baz": 123, "qrx": 456 } } -{ "foo": true, "bar": false, "0": 7, "1": 8, "2": 9 } --- End -- - --- Testcase -- -{% - o1 = { foo: true, bar: false }; - o2 = { baz: 123, qrx: 456 }; - arr = [7, 8, 9]; - - print(join("\n", [ - // copying one object into another - { ...o1 }, - - // combining two objects - { ...o1, ...o2 }, - - // copying object and override properties - { ...o1, ...o2, foo: false, bar: true }, - - // default properties overwritten by spread operator - { foo: 123, bar: 456, ...o1 }, - - // nested spread operators - { ...o1, level2: { ...o2 } }, - - // merging array into objects - { ...o1, ...arr } - ]), "\n"); -%} --- End -- - - -ES2015 short hand property notation is supported as well. - --- Expect stdout -- -{ "a": 123, "b": true, "c": "test" } --- End -- - --- Testcase -- -{% - a = 123; - b = true; - c = "test"; - - o = { a, b, c }; - - print(o, "\n"); -%} --- End -- - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ':' -In line 2, byte 14: - - ` o = { "foo" };` - Near here ------^ - - --- End -- - --- Testcase -- -{% - o = { "foo" }; -%} --- End -- - - -ES2015 computed property names are supported. - --- Expect stdout -- -{ "test": true, "hello": false, "ABC": 123 } --- End -- - --- Testcase -- -{% - s = "test"; - o = { - [s]: true, - ["he" + "llo"]: false, - [uc("abc")]: 123 - }; - - print(o, "\n"); -%} --- End -- - --- Expect stderr -- -Syntax error: Expecting expression -In line 2, byte 10: - - ` o1 = { []: true };` - Near here --^ - - -Syntax error: Unexpected token -Expecting ']' -In line 3, byte 14: - - ` o2 = { [true, false]: 123 };` - Near here ------^ - - --- End -- - --- Testcase -- -{% - o1 = { []: true }; - o2 = { [true, false]: 123 }; -%} --- End -- diff --git a/tests/00_syntax/14_array_literals b/tests/00_syntax/14_array_literals deleted file mode 100644 index 941ee4a..0000000 --- a/tests/00_syntax/14_array_literals +++ /dev/null @@ -1,82 +0,0 @@ -The utpl script language supports declaring arrays using JSON notation. - --- Expect stdout -- -[ ] -[ "first", "second", 123, [ "a", "nested", "array" ], { "a": "nested object" } ] --- End -- - --- Testcase -- -{% - // An empty array can be declared using a pair of square brackets - empty_array = [ ]; - - // JSON notation is used to declare an array with contents - json_array = [ - "first", - "second", - 123, - [ "a", "nested", "array" ], - { a: "nested object" } - ]; - - // Printing (or stringifying) arrays will return their JSON representation - print(empty_array, "\n"); - print(json_array, "\n"); --- End -- - - -Additionally, utpl implements ES6-like spread operators to allow shallow copying -of array values into other arrays. - --- Expect stdout -- -[ 1, 2, 3 ] -[ 1, 2, 3, 4, 5, 6 ] -[ 1, 2, 3, 4, 5, 6, false, true ] -[ 1, 2, 3, false, true, 4, 5, 6 ] -[ 1, 2, 3, [ 4, 5, 6 ] ] --- End -- - --- Testcase -- -{% - a1 = [ 1, 2, 3 ]; - a2 = [ 4, 5, 6 ]; - - print(join("\n", [ - // copying one array into another - [ ...a1 ], - - // combining two arrays - [ ...a1, ...a2 ], - - // copying array and append values - [ ...a1, ...a2, false, true ], - - // copy array and interleave values - [ ...a1, false, true, ...a2 ], - - // nested spread operators - [ ...a1, [ ...a2 ] ] - ]), "\n"); -%} --- End -- - -Contrary to merging arrays into objects, objects cannot be merged into arrays. - --- Expect stderr -- -Type error: ({ "foo": true, "bar": false }) is not iterable -In line 5, byte 21: - - ` print([ ...arr, ...obj ], "\n");` - Near here -------------^ - - --- End -- - --- Testcase -- -{% - arr = [ 1, 2, 3 ]; - obj = { foo: true, bar: false }; - - print([ ...arr, ...obj ], "\n"); -%} --- End -- diff --git a/tests/00_syntax/15_function_declarations b/tests/00_syntax/15_function_declarations deleted file mode 100644 index 4257dd6..0000000 --- a/tests/00_syntax/15_function_declarations +++ /dev/null @@ -1,164 +0,0 @@ -Function declarations follow the ECMAScript 5 syntax. Functions can be -declared anonymously, which is useful for "throw-away" functions such -as sort or filter callbacks or for building objects or arrays of function -values. - -If functions are declared with a name, the resulting function value is -automatically assigned under the given name to the current scope. - -When function values are stringifed, the resulting string will describe -the declaration of the function. - -Nesting function declarations is possible as well. - - --- Expect stdout -- -function() { ... } -function test_fn(a, b) { ... } -function test2_fn(a, b) { ... } - -A function declaration using the alternative syntax: -The function was called with arguments 123 and 456. - --- End -- - --- Testcase -- -{% - // declare an anonymous function and - // assign resulting value - anon_fn = function() { - return "test"; - }; - - // declare a named function - function test_fn(a, b) { - return a + b; - } - - // nesting functions is legal - function test2_fn(a, b) { - function test3_fn(a, b) { - return a * b; - } - - return a + test3_fn(a, b); - } - - print(anon_fn, "\n"); - print(test_fn, "\n"); - print(test2_fn, "\n"); -%} - -A function declaration using the alternative syntax: -{% function test3_fn(a, b): %} -The function was called with arguments {{ a }} and {{ b }}. -{% endfunction %} -{{ test3_fn(123, 456) }} --- End -- - - -Additionally, utpl implements ES6-like "rest" argument syntax to declare -variadic functions. - --- Expect stdout -- -function non_variadic(a, b, c, d, e) { ... } -[ 1, 2, 3, 4, 5 ] -function variadic_1(a, b, ...args) { ... } -[ 1, 2, [ 3, 4, 5 ] ] -function variadic_2(...args) { ... } -[ [ 1, 2, 3, 4, 5 ] ] --- End -- - --- Testcase -- -{% - // ordinary, non-variadic function - function non_variadic(a, b, c, d, e) { - return [ a, b, c, d, e ]; - } - - // fixed amount of arguments with variable remainder - function variadic_1(a, b, ...args) { - return [ a, b, args ]; - } - - // only variable arguments - function variadic_2(...args) { - return [ args ]; - } - - print(join("\n", [ - non_variadic, - non_variadic(1, 2, 3, 4, 5), - variadic_1, - variadic_1(1, 2, 3, 4, 5), - variadic_2, - variadic_2(1, 2, 3, 4, 5) - ]), "\n"); -%} --- End -- - - -Complementary to the "rest" argument syntax, the spread operator may be -used in function call arguments to pass arrays of values as argument list. - --- Expect stdout -- -[ 1, 2, 3, 4, 5, 6 ] -[ 4, 5, 6, 1, 2, 3 ] -[ 1, 2, 3, 1, 2, 3 ] -[ 1, 2, 3 ] --- End -- - --- Testcase -- -{% - arr = [ 1, 2, 3 ]; - - function test(...args) { - return args; - } - - print(join("\n", [ - test(...arr, 4, 5, 6), - test(4, 5, 6, ...arr), - test(...arr, ...arr), - test(...arr) - ]), "\n"); -%} --- End -- - - -Rest arguments may be only used once in a declaration and they must always -be the last item in the argument list. - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ')' -In line 2, byte 26: - - ` function illegal(...args, ...args2) {}` - Near here ------------------^ - - --- End -- - --- Testcase -- -{% - function illegal(...args, ...args2) {} -%} --- End -- - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ')' -In line 2, byte 26: - - ` function illegal(...args, a, b) {}` - Near here ------------------^ - - --- End -- - --- Testcase -- -{% - function illegal(...args, a, b) {} -%} --- End -- diff --git a/tests/00_syntax/16_for_loop b/tests/00_syntax/16_for_loop deleted file mode 100644 index 67edc21..0000000 --- a/tests/00_syntax/16_for_loop +++ /dev/null @@ -1,299 +0,0 @@ -Two for-loop variants are supported: a C-style counting for loop -consisting of an initialization expression, a test condition -and a step expression and a for-in-loop variant which allows -enumerating properties of objects or items of arrays. - -Additionally, utpl supports an alternative syntax suitable for -template block tags. - - --- Expect stdout -- -A simple counting for-loop: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 - -If the loop body consists of only one statement, the curly braces -may be omitted: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 - -Any of the init-, test- and increment expressions may be omitted. - -Loop without initialization statement: -Iteration null -Iteration 1 -Iteration 2 - -Loop without test statement: -Iteration 0 -Iteration 1 -Iteration 2 - -Loop without init-, test- or increment statement: -Iteration 1 -Iteration 2 -Iteration 3 - -For-in loop enumerating object properties: -Key: foo -Key: bar - -For-in loop enumerating array items: -Item: one -Item: two -Item: three - -A counting for-loop using the alternative syntax: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 - -A for-in loop using the alternative syntax: -Item 123 -Item 456 -Item 789 - -For-in and counting for loops may declare variables: -Iteration 0 -Iteration 1 -Iteration 2 - -Item 123 -Item 456 -Item 789 --- End -- - --- Testcase -- -A simple counting for-loop: -{% - for (i = 0; i < 10; i++) { - print("Iteration "); - print(i); - print("\n"); - } -%} - -If the loop body consists of only one statement, the curly braces -may be omitted: -{% - for (i = 0; i < 10; i++) - print("Iteration ", i, "\n"); -%} - -Any of the init-, test- and increment expressions may be omitted. - -Loop without initialization statement: -{% - for (; j < 3; j++) - print("Iteration " + j + "\n"); -%} - -Loop without test statement: -{% - for (j = 0;; j++) { - if (j == 3) - break; - - print("Iteration ", j, "\n"); - } -%} - -Loop without init-, test- or increment statement: -{% - for (;;) { - if (k++ == 3) - break; - - print("Iteration ", k, "\n"); - } -%} - -For-in loop enumerating object properties: -{% - obj = { foo: true, bar: false }; - for (key in obj) - print("Key: ", key, "\n"); -%} - -For-in loop enumerating array items: -{% - arr = [ "one", "two", "three" ]; - for (item in arr) - print("Item: ", item, "\n"); -%} - -A counting for-loop using the alternative syntax: -{% for (x = 0; x < 10; x++): -%} -Iteration {{ x }} -{% endfor %} - -A for-in loop using the alternative syntax: -{% for (n in [123, 456, 789]): -%} -Item {{ n }} -{% endfor %} - -For-in and counting for loops may declare variables: -{% for (let i = 0; i < 3; i++): %} -Iteration {{ i }} -{% endfor %} - -{% for (let n in [123, 456, 789]): %} -Item {{ n }} -{% endfor %} --- End -- - - -By specifying two loop variables in for-in loop expressions, keys -and values can be iterated simultaneously. - --- Expect stdout -- -true -false -123 -456 -[ 0, true ] -[ 1, false ] -[ 2, 123 ] -[ 3, 456 ] -foo -bar -baz -qrx -[ "foo", true ] -[ "bar", false ] -[ "baz", 123 ] -[ "qrx", 456 ] --- End -- - --- Testcase -- -{% - let arr = [ true, false, 123, 456 ]; - let obj = { foo: true, bar: false, baz: 123, qrx: 456 }; - - // iterating arrays with one loop variable yields the array values - for (let x in arr) - print(x, "\n"); - - // iterating arrays with two loop variables yields the array indexes - // and their corresponding values - for (let x, y in arr) - print([x, y], "\n"); - - // iterating objects with one loop variable yields the object keys - for (let x in obj) - print(x, "\n"); - - // iterating objects with two loop variables yields the object keys - // and their corresponding values - for (let x, y in obj) - print([x, y], "\n"); -%} --- End -- - - -Ensure that for-in loop expressions with more than two variables are -rejected. - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 24: - - ` for (let x, y, z in {})` - Near here ----------------^ - - --- End -- - --- Testcase -- -{% - for (let x, y, z in {}) - ; -%} --- End -- - - -Ensure that assignments in for-in loop expressions are rejected. - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 25: - - ` for (let x = 1, y in {})` - Near here -----------------^ - - --- End -- - --- Testcase -- -{% - for (let x = 1, y in {}) - ; -%} --- End -- - - -Ensure that too short for-in loop expressions are rejected (1/2). - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 12: - - ` for (let x)` - Near here ----^ - - --- End -- - --- Testcase -- -{% - for (let x) - ; -%} --- End -- - - -Ensure that too short for-in loop expressions are rejected (2/2). - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 15: - - ` for (let x, y)` - Near here -------^ - - --- End -- - --- Testcase -- -{% - for (let x, y) - ; -%} --- End -- diff --git a/tests/00_syntax/17_while_loop b/tests/00_syntax/17_while_loop deleted file mode 100644 index 1e68d6b..0000000 --- a/tests/00_syntax/17_while_loop +++ /dev/null @@ -1,71 +0,0 @@ -Utpl implements C-style while loops which run as long as the condition -is fulfilled. - -Like with for-loops, an alternative syntax form suitable for template -blocks is supported. - - --- Expect stdout -- -A simple counting while-loop: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 - -If the loop body consists of only one statement, the curly braces -may be omitted: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 - -A counting while-loop using the alternative syntax: -Iteration 0 -Iteration 1 -Iteration 2 -Iteration 3 -Iteration 4 -Iteration 5 -Iteration 6 -Iteration 7 -Iteration 8 -Iteration 9 --- End -- - --- Testcase -- -A simple counting while-loop: -{% - i = 0; - while (i < 10) { - print("Iteration "); - print(i); - print("\n"); - i++; - } -%} - -If the loop body consists of only one statement, the curly braces -may be omitted: -{% - i = 0; - while (i < 10) - print("Iteration ", i++, "\n"); -%} - -A counting while-loop using the alternative syntax: -{% while (x < 10): -%} -Iteration {{ "" + x++ }} -{% endwhile %} --- End -- diff --git a/tests/00_syntax/18_if_condition b/tests/00_syntax/18_if_condition deleted file mode 100644 index 9e02767..0000000 --- a/tests/00_syntax/18_if_condition +++ /dev/null @@ -1,121 +0,0 @@ -Utpl implements C-style if/else conditions and ?: ternary statements. - -Like with for- and while-loops, an alternative syntax form suitable -for template blocks is supported. - - --- Expect stdout -- -This should print "one": -one - -This should print "two": -two - -Multiple conditions can be used by chaining if/else statements: -three - -If the conditional block consists of only one statement, the curly -braces may be omitted: -two - -An if-condition using the alternative syntax: -Variable x has another value. - - -An if-condition using the special "elif" keyword in alternative syntax mode: -Variable x was set to five. - - -Ternary expressions function similar to if/else statements but -only allow for a single expression in the true and false branches: -Variable x is one --- End -- - --- Testcase -- -This should print "one": -{% - x = 0; - - if (x == 0) { - print("one"); - } - else { - print("two"); - } -%} - - -This should print "two": -{% - x = 1; - - if (x == 0) { - print("one"); - } - else { - print("two"); - } -%} - - -Multiple conditions can be used by chaining if/else statements: -{% - x = 2; - - if (x == 0) { - print("one"); - } - else if (x == 1) { - print("two"); - } - else if (x == 2) { - print("three"); - } - else { - print("four"); - } -%} - - -If the conditional block consists of only one statement, the curly -braces may be omitted: -{% - x = 5; - - if (x == 0) - print("one"); - else - print("two"); -%} - - -An if-condition using the alternative syntax: -{% if (x == 1): -%} -Variable x was set to one. -{% else -%} -Variable x has another value. -{% endif %} - - -An if-condition using the special "elif" keyword in alternative syntax mode: -{% if (x == 0): -%} -Variable x was set to zero. -{% elif (x == 1): -%} -Variable x was set to one. -{% elif (x == 5): -%} -Variable x was set to five. -{% else -%} -Variable x has another value. -{% endif %} - - -Ternary expressions function similar to if/else statements but -only allow for a single expression in the true and false branches: -{% - x = 1; - s = (x == 1) ? "Variable x is one" : "Variable x has another value"; - - print(s); -%} - --- End -- diff --git a/tests/00_syntax/19_arrow_functions b/tests/00_syntax/19_arrow_functions deleted file mode 100644 index 102c527..0000000 --- a/tests/00_syntax/19_arrow_functions +++ /dev/null @@ -1,124 +0,0 @@ -Besides the ordinary ES5-like function declarations, utpl supports ES6 inspired -arrow function syntax as well. Such arrow functions are useful for callbacks to functions such as replace(), map() or filter(). - --- Expect stdout -- -() => { ... } -test -(a, b) => { ... } -3 -(...args) => { ... } -15 -(a) => { ... } -10 -(a) => { ... } -36 --- End -- - --- Testcase -- -{% - - // assign arrow function to variable - test1_fn = () => { - return "test"; - }; - - // assign arrow function with parameters - test2_fn = (a, b) => { - return a + b; - }; - - // nesting functions is legal - test3_fn = (...args) => { - nested_fn = (a, b) => { - return a * b; - }; - - return args[0] + nested_fn(args[0], args[1]); - }; - - // parentheses may be omitted if arrow function takes only one argument - test4_fn = a => { - a * 2; - }; - - // curly braces may be omitted if function body is a single expression - test5_fn = a => a * a; - - print(join("\n", [ - test1_fn, - test1_fn(), - test2_fn, - test2_fn(1, 2), - test3_fn, - test3_fn(3, 4), - test4_fn, - test4_fn(5), - test5_fn, - test5_fn(6) - ]), "\n"); -%} --- End -- - - -While the main advantage of arrow functions is the compact syntax, another -important difference to normal functions is the "this" context behaviour - -arrow functions do not have an own "this" context and simply inherit it from -the outer calling scope. - --- Expect stdout -- -this is set to obj: true -arrow function uses outher this: true -normal function has own this: true -arrow function as method has no this: true --- End -- - --- Testcase -- -{% - obj = { - method: function() { - let that = this; - let arr = () => { - print("arrow function uses outher this: ", that == this, "\n"); - }; - let fn = function() { - print("normal function has own this: ", that != this, "\n"); - }; - - print("this is set to obj: ", this == obj, "\n"); - - arr(); - fn(); - }, - - arrowfn: () => { - print("arrow function as method has no this: ", this == null, "\n"); - } - }; - - obj.method(); - obj.arrowfn(); -%} --- End -- - - -Due to the difficulty of recognizing arrow function expressions with an LR(1) -grammar the parser has to use a generic expression rule on the lhs argument list -and verify that it does not contain non-label nodes while building the ast. The -subsequent testcase asserts that case. - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 10: - - ` (a + 1) => { print("test\n") }` - Near here --^ - - --- End -- - --- Testcase -- -{% - (a + 1) => { print("test\n") } -%} --- End -- diff --git a/tests/00_syntax/20_list_expressions b/tests/00_syntax/20_list_expressions deleted file mode 100644 index d5ba459..0000000 --- a/tests/00_syntax/20_list_expressions +++ /dev/null @@ -1,45 +0,0 @@ -Similar to ES5, utpl's language grammar allows comma separated list expressions -in various contexts. Unless such lists happen to be part of a function call -or array construction expression, only the last result of such an expression -list should be used while still evaluating all sub-expressions, triggering -side effects such as function calls or variable assignments. - --- Expect stdout -- -4 -[ 1, 3 ] -{ "a": true, "b": 1 } -function call -[ "test", "assigment" ] -true -true -true -[ 2, 3 ] --- End -- - --- Testcase -- -{% - // only the last value is considered - print(1 + (2, 3), "\n"); - - // in array constructors, parenthesized lists are reduced to the last value - print([ (0, 1), (2, 3) ], "\n"); - - // in object constructors, parenthesized lists are reduced to the last value - print({ a: (false, true), b: (0, 1) }, "\n"); - - // all list expressions are evaluated and may have side effects, even if - // results are discareded - x = (print("function call\n"), y = "assigment", "test"); - print([x, y], "\n"); - - // property access operates on the last value of a parenthesized list expression - print(({foo: false}, {foo: true}).foo, "\n"); - print(({foo: false}, {foo: true})["foo"], "\n"); - - // computed property access uses the last list expression value - print(({foo: true})["bar", "baz", "foo"], "\n"); - - // same list semantics apply to function call parameters - ((...args) => print(args, "\n"))((1, 2), 3); -%} --- End -- diff --git a/tests/00_syntax/21_regex_literals b/tests/00_syntax/21_regex_literals deleted file mode 100644 index 3af53bb..0000000 --- a/tests/00_syntax/21_regex_literals +++ /dev/null @@ -1,89 +0,0 @@ -Regex literals are enclosed in forward slashes and may contain zero -or more trailing flag characters. Interpretation of escape sequences -within regular expression literals is subject of the underlying -regular expression engine. - --- Expect stdout -- -[ "/Hello world/", "/test/gis", "/test/g", "/test1 \\\/ test2/", "/\\x31\n\\.\u0007\b\\c\\u2600\\\\/" ] --- End -- - --- Testcase -- -{% - print([ - /Hello world/, // A very simple expression - /test/gsi, // Regular expression flags - /test/gg, // Repeated flags - /test1 \/ test2/, // Escaped forward slash - /\x31\n\.\a\b\c\u2600\\/ // Ensure that escape sequences are passed as-is - ], "\n"); -%} --- End -- - - -Testing regular expression type. - --- Expect stdout -- -object --- End -- - --- Testcase -- -{{ type(/foo/) }} --- End -- - - -Testing invalid flag characters. - --- Expect stderr -- -Syntax error: Unexpected token -Expecting ';' -In line 2, byte 8: - - ` /test/x` - ^-- Near here - - --- End -- - --- Testcase -- -{% - /test/x -%} --- End -- - - -Testing unclosed regular expression. - --- Expect stderr -- -Syntax error: Unterminated string -In line 2, byte 2: - - ` /foo \/` - ^-- Near here - - --- End -- - --- Testcase -- -{% - /foo \/ -%} --- End -- - - -Testing regex compilation errors. - --- Expect stderr -- -Syntax error: Unmatched \{ -In line 2, byte 3: - - ` /foo {/` - ^-- Near here - - --- End -- - --- Testcase -- -{% - /foo {/ -%} --- End -- |