1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
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 --
|