use luallaby::LuaError; mod macros; test!( function, " function pyt(a, b) return (a^2 + b^2) ^ 0.5 end print(pyt(3, 4)) ", " 5.0 " ); test!( function_scope_1, " a = 5 function f() print(a) end local a = 6 f() ", " 5 " ); test!( function_scope_2, " a = 5 function f() print(a) end a = 6 f() ", " 6 " ); test!( function_scope_3, " function f() print(a) end local a = 6 f() ", " nil " ); test!( function_scope_4, " function f() print(a) end a = 6 f() ", " 6 " ); test!( function_scope_5, " do a = 5 function f() print(a) end end f() print(a) ", " 5 5 " ); test!( function_scope_6, " do local a = 5 function f() print(a) end end f() print(a) ", " 5 nil " ); test!( function_scope_7, " do a = 5 function f() local b = 7 print(a) return function() print(b) end end end f()() print(a) ", " 5 7 5 " ); test!( function_scope_8, " local outer = function () local x = \"hello\" local middle = function () local inner = function () print(x) end print(\"inner\") return inner end print(\"outer\") return middle end outer()()() ", " outer inner hello " ); test!( function_scope_9, " d = 8 print(a, b, c, d) function f(c) local a a = 2 b = 4 print(a, b, c, d) end f(6) print(a, b, c, d) ", " nil\tnil\tnil\t8 2\t4\t6\t8 nil\t4\tnil\t8 " ); test!( function_recursive, " function f(n) print(n) -- writing if statement with only expressions local g = n == 0 or f(n - 1) end f(4) ", " 4 3 2 1 0 " ); test!( function_return_semicolon, " function f() return 1, 2, 3; end print(f()) ", " 1\t2\t3 " ); test!( function_multi_return, " function f() return 1, 2, 3 end print(f()) print((f())) ", " 1\t2\t3 1 " ); test!( function_multi_return_assign, " function f() return 1, 2, 3 end a = f() print(a) a, b, c, d = f() print(a, b, c, d) ", " 1 1\t2\t3\tnil " ); test!( function_multi_return_assign_local, " function f() return 1, 2, 3 end do local a = f() print(a) local a, b, c, d = f() print(a, b, c, d) end ", " 1 1\t2\t3\tnil " ); test!( function_early_return, " function f() print(0) do return end print(1) end f() ", " 0 " ); test!( function_varargs, " function f(...) print(...) print((...)) print(1, ...) print(..., 1) end f(1, 2, 3) ", " 1\t2\t3 1 1\t1\t2\t3 1\t1 " ); test!( function_argument_filling, " function f(a, b) print(a) print(b) end function g(a, b, ...) print(a) print(b) print(...) end function r() return 1,2,3 end f(3) print() f(3, 4) print() f(3, 4, 5) print() f(r(), 10) print() f(r()) print() g(3) print() g(3, 4) print() g(3, 4, 5, 8) print() g(5, r()) print() ", " 3 nil 3 4 3 4 1 10 1 2 3 nil 3 4 3 4 5\t8 5 1 2\t3 " ); test!( function_local, " function f() print(0) end do local function f() print(1) end f() end f() ", " 1 0 " ); test!( function_local_recursive, " local function f(n) if n == 5 then return end print(n) f(n + 1) end f(1) ", " 1 2 3 4 " ); test_err!( function_local_variable, "local f = function () f() end f()", LuaError::CallInvalid(..) ); test_err!( function_local_fail, "do local function f() end end f()", LuaError::CallInvalid(..) ); test_regex!( function_call_without_parentheses, " print{1, 2, 3} print\"abc\" function f() return print end f{1, 2, 3}\"def\" ", " table: 0x([a-fA-F0-9])+ abc def " ); test!( function_assign_table, " a = {} function a.b(x) print(x) end a.b(4) a = {} a.b = {} function a.b.c(x) print(x, x, x) end a.b.c(7) ", " 4 7\t7\t7 " ); test_regex!( function_call_method, " a = {} a.v = function (t, n) print(t, n) return t end a:v(2) a:v(7):v(8) ", " table: 0x([a-fA-F0-9])+\t2 table: 0x([a-fA-F0-9])+\t7 table: 0x([a-fA-F0-9])+\t8 " ); test!( function_assign_table_method, " a = {} function a:b(x) print(x) end a:b(1) a.b(1) a = {} a.b = {} function a.b:c(x) print(x, x, x) end a.b:c(7) a.b.c(7) ", " 1 nil 7\t7\t7 nil\tnil\tnil " ); test_err!( function_assign_table_method_fail, "a = {}; function a:b:c() end", LuaError::UnexpectedToken(..) ); test!( function_tail_call, " function f(x) return x * x end function g(x) return f(x) end print(g(4)) ", " 16 " ); test!( function_tail_call_protected, " function f(x) return x * x end function g(x) return pcall(f, x) end print(g(4)) ", " true\t16 " ); test!( function_tail_call_builtin, " function f(x) return math.abs(x) end print(f(-4)) ", " 4 " );