Besides the ordinary ES5-like function declarations, ucode 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 --