1 The `function foo;` syntax allows forward-declaring a function name 2 before providing its definition. This enables mutual recursion between 3 functions at the same scope level. 4 5 6 1. A forward-declared function can be defined and called normally. 7 8 -- Expect stdout -- 9 hello 10 -- End -- 11 12 -- Testcase -- 13 {% 14 function greet; 15 16 function greet() { 17 return "hello"; 18 } 19 20 print(greet(), "\n"); 21 %} 22 -- End -- 23 24 25 2. Forward declarations enable mutual recursion. 26 27 -- Expect stdout -- 28 [ 29 true, 30 true, 31 true, 32 true 33 ] 34 -- End -- 35 36 -- Testcase -- 37 {% 38 function is_even; 39 function is_odd; 40 41 function is_even(n) { 42 if (n == 0) return true; 43 return is_odd(n - 1); 44 } 45 46 function is_odd(n) { 47 if (n == 0) return false; 48 return is_even(n - 1); 49 } 50 51 printf("%.J\n", [ 52 is_even(0), 53 is_odd(1), 54 is_even(10), 55 is_odd(11) 56 ]); 57 %} 58 -- End -- 59 60 61 3. Assignment to a forward-declared function is forbidden (constant binding). 62 63 -- Expect stderr -- 64 Syntax error: Invalid assignment to constant 'foo' 65 In line 4, byte 31: 66 67 ` foo = function() { return 2; };` 68 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ 69 70 71 -- End -- 72 73 -- Testcase -- 74 {% 75 function foo; 76 77 foo = function() { return 2; }; 78 %} 79 -- End -- 80 81 82 4. A `let` declaration after a forward declaration is forbidden. 83 84 -- Expect stderr -- 85 Syntax error: Variable 'foo' redeclared 86 In line 4, byte 6: 87 88 ` let foo = 1;` 89 ^-- Near here 90 91 92 -- End -- 93 94 -- Testcase -- 95 {% 96 function foo; 97 98 let foo = 1; 99 %} 100 -- End -- 101 102 103 5. A `const` declaration after a forward declaration is forbidden. 104 105 -- Expect stderr -- 106 Syntax error: Variable 'foo' redeclared 107 In line 4, byte 8: 108 109 ` const foo = 1;` 110 ^-- Near here 111 112 113 -- End -- 114 115 -- Testcase -- 116 {% 117 function foo; 118 119 const foo = 1; 120 %} 121 -- End -- 122 123 124 6. Defining a function twice after forward declaration is forbidden. 125 126 -- Expect stderr -- 127 Syntax error: Redeclaration of constant 'foo' 128 In line 5, byte 2: 129 130 ` function foo() { return 2; }` 131 ^-- Near here 132 133 134 -- End -- 135 136 -- Testcase -- 137 {% 138 function foo; 139 140 function foo() { return 1; } 141 function foo() { return 2; } 142 %} 143 -- End -- 144 145 146 7. Duplicate forward declarations are forbidden. 147 148 -- Expect stderr -- 149 Syntax error: Function 'foo' redeclared 150 In line 3, byte 11: 151 152 ` function foo;` 153 Near here ---^ 154 155 156 -- End -- 157 158 -- Testcase -- 159 {% 160 function foo; 161 function foo; 162 %} 163 -- End -- 164 165 166 8. Forward declaration after a definition is forbidden. 167 168 -- Expect stderr -- 169 Syntax error: Variable 'foo' redeclared 170 In line 3, byte 11: 171 172 ` function foo;` 173 Near here ---^ 174 175 176 -- End -- 177 178 -- Testcase -- 179 {% 180 function foo() { return 1; } 181 function foo; 182 %} 183 -- End -- 184 185 186 9. Calling an unfilled forward declaration raises a runtime error. 187 188 -- Expect stderr -- 189 Type error: `foo` is not a function, got null instead 190 In line 4, byte 6: 191 192 ` foo();` 193 ~~~~^~ 194 195 196 -- End -- 197 198 -- Testcase -- 199 {% 200 function foo; 201 202 foo(); 203 %} 204 -- End -- 205 206 207 10. A nested function can capture a forward-declared name as upvalue. 208 209 -- Expect stdout -- 210 hello from foo 211 -- End -- 212 213 -- Testcase -- 214 {% 215 function foo; 216 217 function call_foo() { 218 return foo(); 219 } 220 221 function foo() { 222 return "hello from foo"; 223 } 224 225 print(call_foo(), "\n"); 226 %} 227 -- End -- 228 229 230 11. Forward declarations work with export. 231 232 -- File test-forward-decl.uc -- 233 export function foo; 234 235 function foo() { 236 return "exported"; 237 } 238 -- End -- 239 240 -- Args -- 241 -R 242 -- End -- 243 244 -- Expect stdout -- 245 exported 246 -- End -- 247 248 -- Testcase -- 249 import { foo } from "./files/test-forward-decl.uc"; 250 251 print(foo(), "\n"); 252 -- End -- 253 254 255 12. Increment/decrement of a forward-declared function is forbidden. 256 257 -- Expect stderr -- 258 Syntax error: Invalid increment/decrement of constant 'foo' 259 In line 4, byte 5: 260 261 ` foo++;` 262 ^-- Near here 263 264 265 -- End -- 266 267 -- Testcase -- 268 {% 269 function foo; 270 271 foo++; 272 %} 273 -- End -- 274 275 276 13. In strict mode, the name of a regular function declaration is a 277 constant binding, so assigning to it is forbidden. 278 279 -- Expect stderr -- 280 Syntax error: Invalid assignment to constant 'foo' 281 In line 6, byte 8: 282 283 ` foo = 1;` 284 ~~~~~~^ 285 286 287 -- End -- 288 289 -- Testcase -- 290 {% 291 "use strict"; 292 293 function foo() { return 1; } 294 295 foo = 1; 296 %} 297 -- End -- 298 299 300 14. In strict mode, compound assignments to a regular function 301 name are forbidden as well. 302 303 -- Expect stderr -- 304 Syntax error: Invalid assignment to constant 'foo' 305 In line 6, byte 9: 306 307 ` foo += 1;` 308 ~~~~~~~^ 309 310 311 -- End -- 312 313 -- Testcase -- 314 {% 315 "use strict"; 316 317 function foo() { return 1; } 318 319 foo += 1; 320 %} 321 -- End -- 322 323 324 15. In strict mode, increment/decrement of a regular function name 325 is forbidden. 326 327 -- Expect stderr -- 328 Syntax error: Invalid increment/decrement of constant 'foo' 329 In line 6, byte 5: 330 331 ` foo++;` 332 ^-- Near here 333 334 335 -- End -- 336 337 -- Testcase -- 338 {% 339 "use strict"; 340 341 function foo() { return 1; } 342 343 foo++; 344 %} 345 -- End -- 346 347 348 16. In strict mode, a regular function may not be declared twice in the 349 same scope. 350 351 -- Expect stderr -- 352 Syntax error: Variable 'foo' redeclared 353 In line 6, byte 11: 354 355 ` function foo() { return 2; }` 356 Near here ---^ 357 358 359 -- End -- 360 361 -- Testcase -- 362 {% 363 "use strict"; 364 365 function foo() { return 1; } 366 367 function foo() { return 2; } 368 %} 369 -- End -- 370 371 372 17. In non-strict mode, the name of a regular function declaration is a 373 mutable binding, so assigning to it rebinds the name. 374 375 -- Expect exitcode -- 376 0 377 -- End -- 378 379 -- Testcase -- 380 {% 381 function foo() { return 1; } 382 383 foo = 1; 384 %} 385 -- End --
This page was automatically generated by LXR 0.3.1. • OpenWrt