From dd64edd58fe25ec74ae5958128cf3f74b0692f3b Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 28 Jan 2026 18:43:14 +0800 Subject: Fixed compiler issues and added 800+ test cases. --- spec/outputs/test/advanced_macro_spec.lua | 92 ++++++ spec/outputs/test/close_attribute_spec.lua | 226 +++++++++++++++ spec/outputs/test/const_attribute_spec.lua | 131 +++++++++ spec/outputs/test/do_statement_spec.lua | 238 ++++++++++++++++ spec/outputs/test/functions_advanced_spec.lua | 259 +++++++++++++++++ spec/outputs/test/implicit_object_spec.lua | 243 ++++++++++++++++ spec/outputs/test/in_expression_spec.lua | 180 ++++++------ spec/outputs/test/multiline_args_spec.lua | 219 +++++++++++++++ spec/outputs/test/named_varargs_spec.lua | 16 +- spec/outputs/test/operator_advanced_spec.lua | 210 ++++++++++++++ spec/outputs/test/param_destructure_spec.lua | 369 +++++++++++++++++++++++++ spec/outputs/test/reverse_index_spec.lua | 4 - spec/outputs/test/slicing_spec.lua | 324 ++++++++++++++++++++++ spec/outputs/test/stub_spec.lua | 148 ++++++++++ spec/outputs/test/table_append_spec.lua | 15 +- spec/outputs/test/table_comprehension_spec.lua | 297 ++++++++++++++++++++ spec/outputs/test/tables_advanced_spec.lua | 260 +++++++++++++++++ spec/outputs/test/varargs_assignment_spec.lua | 6 +- spec/outputs/test/whitespace_spec.lua | 159 +++++++++++ spec/outputs/test/with_statement_spec.lua | 279 +++++++++++++++++++ spec/outputs/test/yaml_string_spec.lua | 42 ++- spec/outputs/unicode/string.lua | 14 +- spec/outputs/unicode/syntax.lua | 2 +- 23 files changed, 3584 insertions(+), 149 deletions(-) create mode 100644 spec/outputs/test/advanced_macro_spec.lua create mode 100644 spec/outputs/test/close_attribute_spec.lua create mode 100644 spec/outputs/test/const_attribute_spec.lua create mode 100644 spec/outputs/test/do_statement_spec.lua create mode 100644 spec/outputs/test/functions_advanced_spec.lua create mode 100644 spec/outputs/test/implicit_object_spec.lua create mode 100644 spec/outputs/test/multiline_args_spec.lua create mode 100644 spec/outputs/test/operator_advanced_spec.lua create mode 100644 spec/outputs/test/param_destructure_spec.lua create mode 100644 spec/outputs/test/slicing_spec.lua create mode 100644 spec/outputs/test/stub_spec.lua create mode 100644 spec/outputs/test/table_comprehension_spec.lua create mode 100644 spec/outputs/test/tables_advanced_spec.lua create mode 100644 spec/outputs/test/whitespace_spec.lua create mode 100644 spec/outputs/test/with_statement_spec.lua (limited to 'spec/outputs') diff --git a/spec/outputs/test/advanced_macro_spec.lua b/spec/outputs/test/advanced_macro_spec.lua new file mode 100644 index 0000000..0a46978 --- /dev/null +++ b/spec/outputs/test/advanced_macro_spec.lua @@ -0,0 +1,92 @@ +return describe("advanced macro", function() + it("should evaluate macro at compile time", function() + local area = 6.2831853071796 * 5 + return assert.is_true(area > 0) + end) + it("should support macro with arguments", function() + local result = (5 + 10) + return assert.same(result, 15) + end) + it("should handle string returning macro", function() + local result = 'hello world' + return assert.same(result, "hello world") + end) + it("should work with conditional compilation", function() + debugMode = true + assert.is_true(debugMode) + return assert.is_true(debugMode) + end) + it("should support macro generating conditional code", function() + debugMode = true + local x = 10 + return assert.same(x, 10) + end) + it("should work with lua code insertion", function() + local macro_test_var = 42 + do +local macro_test_var = 99 + end + return assert.same(macro_test_var, 42) + end) + it("should support multi-line raw lua", function() + local multiline_var = "test" +multiline_var = "test work" + local multiline_var1 = "test1" + assert.same(multiline_var, "test work") + return assert.same(multiline_var1, "test1") + end) + it("should export macro from module", function() + local result = (5 * 2) + return assert.same(result, 10) + end) + it("should work with builtin FILE macro", function() + local result = "./spec/inputs/test/advanced_macro_spec.yue" + return assert.is_true(type(result) == "string") + end) + it("should work with builtin LINE macro", function() + local result = 82 + return assert.is_true(type(result) == "number") + end) + it("should support argument validation", function() + local result = 123 + return assert.same(result, 123) + end) + it("should handle string argument validation", function() + local result = "hello" + return assert.same(result, "hello") + end) + it("should work with is_ast check", function() + local result = (10 + 20) + return assert.same(result, 30) + end) + it("should support macro generating macro", function() + local result = "Red" + return assert.same(result, "Red") + end) + it("should handle complex macro logic", function() + local my_print + my_print = function(...) + return ... + end + local a, b, c = my_print("hello", "world", 123) + assert.same(a, "hello") + assert.same(b, "world") + return assert.same(c, 123) + end) + it("should work with table manipulation", function() + local result = { + "1", + "2", + "3" + } + return assert.same(result, { + "1", + "2", + "3" + }) + end) + return it("should support string concatenation in macro", function() + local result = ("hello" .. "world") + return assert.same(result, "helloworld") + end) +end) diff --git a/spec/outputs/test/close_attribute_spec.lua b/spec/outputs/test/close_attribute_spec.lua new file mode 100644 index 0000000..cc64da8 --- /dev/null +++ b/spec/outputs/test/close_attribute_spec.lua @@ -0,0 +1,226 @@ +return describe("close attribute", function() + it("should declare close variable", function() + local closed = false + do + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + end + return assert.is_true(closed) + end) + it("should work with metatable syntax", function() + local called = false + do + local _ = setmetatable({ }, { + __close = function() + called = true + end + }) + end + return assert.is_true(called) + end) + it("should handle multiple close scopes", function() + local order = { } + do + local first = setmetatable({ }, { + __close = function() + return table.insert(order, "first") + end + }) + local second = setmetatable({ }, { + __close = function() + return table.insert(order, "second") + end + }) + end + return assert.same(order, { + "second", + "first" + }) + end) + it("should work with resources", function() + local resource_opened = false + local resource_closed = false + do + resource_opened = true + local _ = setmetatable({ }, { + __close = function() + resource_closed = true + end + }) + end + assert.is_true(resource_opened) + return assert.is_true(resource_closed) + end) + it("should support close in function", function() + local closed = false + local fn + fn = function() + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + return "result" + end + local result = fn() + assert.same(result, "result") + return assert.is_true(closed) + end) + it("should work with fat arrow", function() + local closed = false + local obj = setmetatable({ + value = 10, + }, { + __close = function(self) + closed = true + end + }) + do + local _ = obj + end + return assert.is_true(closed) + end) + it("should handle nested close scopes", function() + local outer_closed = false + local inner_closed = false + do + local outer = setmetatable({ }, { + __close = function() + outer_closed = true + end + }) + do + local inner = setmetatable({ }, { + __close = function() + inner_closed = true + end + }) + end + end + assert.is_true(inner_closed) + return assert.is_true(outer_closed) + end) + it("should work with conditional close", function() + local closed = false + local should_close = true + if should_close then + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + end + return assert.is_true(closed) + end) + it("should support close in loop", function() + local closed_count = 0 + for i = 1, 3 do + do + local _ = setmetatable({ }, { + __close = function() + closed_count = closed_count + 1 + end + }) + end + end + return assert.same(closed_count, 3) + end) + it("should work with table destructuring", function() + local closed = false + do + local tb = setmetatable({ }, { + __close = function() + closed = true + end + }) + end + return assert.is_true(closed) + end) + it("should handle close with return value", function() + local closed = false + local fn + fn = function() + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + return 42 + end + local result = fn() + assert.same(result, 42) + return assert.is_true(closed) + end) + it("should work with error handling", function() + local closed = false + local error_thrown = false + do + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + error_thrown = true + end + assert.is_true(closed) + return assert.is_true(error_thrown) + end) + it("should support close in varargs function", function() + local closed = false + local fn + fn = function(...) + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + return { + ... + } + end + local result = fn(1, 2, 3) + assert.same(result, { + 1, + 2, + 3 + }) + return assert.is_true(closed) + end) + it("should work with multiple variables", function() + local first_closed = false + local second_closed = false + do + local first = setmetatable({ }, { + __close = function() + first_closed = true + end + }) + local second = setmetatable({ }, { + __close = function() + second_closed = true + end + }) + end + assert.is_true(first_closed) + return assert.is_true(second_closed) + end) + return it("should handle close in try block", function() + local closed = false + local success = false + success = xpcall(function() + local _ = setmetatable({ }, { + __close = function() + closed = true + end + }) + return true + end, function(err) + return false + end) + assert.is_true(success) + return assert.is_true(closed) + end) +end) diff --git a/spec/outputs/test/const_attribute_spec.lua b/spec/outputs/test/const_attribute_spec.lua new file mode 100644 index 0000000..2e2f7a3 --- /dev/null +++ b/spec/outputs/test/const_attribute_spec.lua @@ -0,0 +1,131 @@ +return describe("const attribute", function() + it("should declare const variable", function() + local a = 123 + return assert.same(a, 123) + end) + it("should prevent reassignment", function() + local b = 456 + return assert.same(b, 456) + end) + it("should work with strings", function() + local name = "test" + return assert.same(name, "test") + end) + it("should support const with destructuring", function() + local tb = { + a = 1, + b = 2, + 3, + 4 + } + local a, b, c, d + a, b, c, d = tb.a, tb.b, tb[1], tb[2] + assert.same(a, 1) + assert.same(b, 2) + assert.same(c, 3) + return assert.same(d, 4) + end) + it("should handle nested const", function() + local nested = { + inner = { + value = 10 + } + } + return assert.same(nested.inner.value, 10) + end) + it("should work with arrays", function() + local items + items = { + 1, + 2, + 3 + } + return assert.same(items[1], 1) + end) + it("should support const in function scope", function() + local fn + fn = function() + local local_const = "local" + return local_const + end + local result = fn() + return assert.same(result, "local") + end) + it("should work with multiple const declarations", function() + local x = 1 + local y = 2 + local z = 3 + return assert.same(x + y + z, 6) + end) + it("should handle const functions", function() + local add + add = function(a, b) + return a + b + end + return assert.same(add(5, 10), 15) + end) + it("should work with const tables", function() + local config = { + host = "localhost", + port = 8080 + } + assert.same(config.host, "localhost") + return assert.same(config.port, 8080) + end) + it("should support global const", function() + GLOBAL_CONST = 999 + return assert.same(GLOBAL_CONST, 999) + end) + it("should work with boolean const", function() + local flag = true + local another = false + assert.is_true(flag) + return assert.is_false(another) + end) + it("should handle nil const", function() + local nil_value = nil + return assert.same(nil_value, nil) + end) + it("should work with expressions", function() + local calculated = 10 + 20 + return assert.same(calculated, 30) + end) + it("should work in table comprehension", function() + local multiplier = 2 + local items = { + 1, + 2, + 3 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #items do + local item = items[_index_0] + _accum_0[_len_0] = item * multiplier + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 2, + 4, + 6 + }) + end) + return it("should work with complex expressions", function() + local complex = { + data = { + 1, + 2, + 3 + }, + nested = { + key = "value" + } + } + assert.same(complex.data[1], 1) + return assert.same(complex.nested.key, "value") + end) +end) diff --git a/spec/outputs/test/do_statement_spec.lua b/spec/outputs/test/do_statement_spec.lua new file mode 100644 index 0000000..fb93fa0 --- /dev/null +++ b/spec/outputs/test/do_statement_spec.lua @@ -0,0 +1,238 @@ +return describe("do statement", function() + it("should create new scope", function() + local x = 10 + do + local x = 20 + assert.same(x, 20) + end + return assert.same(x, 10) + end) + it("should return value from do block", function() + local result + do + local x = 5 + result = x * 2 + end + return assert.same(result, 10) + end) + it("should work with multiple statements", function() + local result + do + local a = 1 + local b = 2 + local c = 3 + result = a + b + c + end + return assert.same(result, 6) + end) + it("should handle nested do blocks", function() + local result + do + local x = 10 + local y + do + local z = 5 + y = z * 2 + end + result = x + y + end + return assert.same(result, 20) + end) + it("should support conditional in do block", function() + local result + do + local value = 5 + if value > 3 then + result = value * 2 + else + result = value + end + end + return assert.same(result, 10) + end) + it("should work with loops in do block", function() + local result + do + local sum = 0 + for i = 1, 5 do + sum = sum + i + end + result = sum + end + return assert.same(result, 15) + end) + it("should handle table operations", function() + local result + do + local tb = { + 1, + 2, + 3 + } + table.insert(tb, 4) + result = #tb + end + return assert.same(result, 4) + end) + it("should work with function definition", function() + local result + do + local fn + fn = function(x) + return x * 2 + end + result = fn(5) + end + return assert.same(result, 10) + end) + it("should support variable shadowing", function() + local x = "outer" + local result + do + local x = "inner" + result = x + end + assert.same(result, "inner") + return assert.same(x, "outer") + end) + it("should work with method calls", function() + local obj = { + value = 10, + double = function(self) + return self.value * 2 + end + } + local result + do + local _accum_0 + repeat + _accum_0 = obj:double() + break + until true + result = _accum_0 + end + return assert.same(result, 20) + end) + it("should handle comprehensions in do block", function() + local result + do + local items = { + 1, + 2, + 3, + 4, + 5 + } + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #items do + local item = items[_index_0] + _accum_0[_len_0] = item * 2 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 2, + 4, + 6, + 8, + 10 + }) + end) + it("should work with try-catch", function() + local success, result = xpcall(function() + error("test error") + return false + end, function(err) + return true + end) + assert.is_false(success) + return assert.is_true(result) + end) + it("should support return statement", function() + local fn + fn = function() + do + local x = 10 + return x * 2 + end + return "never reached" + end + local result = fn() + return assert.same(result, 20) + end) + it("should work with assignment", function() + local result + do + local a, b, c = 1, 2, 3 + result = a + b + c + end + return assert.same(result, 6) + end) + it("should handle destructuring", function() + local result + do + local tb = { + x = 10, + y = 20 + } + local x, y = tb.x, tb.y + result = x + y + end + return assert.same(result, 30) + end) + it("should work with string interpolation", function() + local name = "world" + local result + do + local greeting = "hello" + result = tostring(greeting) .. " " .. tostring(name) + end + return assert.same(result, "hello world") + end) + it("should support implicit return", function() + local result + do + local value = 42 + result = value + end + return assert.same(result, 42) + end) + it("should handle empty do block", function() + local result + do + result = nil + end + return assert.same(result, nil) + end) + return it("should work with backcalls", function() + local map + map = function(f, items) + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #items do + local item = items[_index_0] + _accum_0[_len_0] = f(item) + _len_0 = _len_0 + 1 + end + return _accum_0 + end + local result + do + local items = { + 1, + 2, + 3 + } + result = map(function(x) + return x * 2 + end, items) + end + return assert.same(result, { + 2, + 4, + 6 + }) + end) +end) diff --git a/spec/outputs/test/functions_advanced_spec.lua b/spec/outputs/test/functions_advanced_spec.lua new file mode 100644 index 0000000..4e99023 --- /dev/null +++ b/spec/outputs/test/functions_advanced_spec.lua @@ -0,0 +1,259 @@ +return describe("advanced functions", function() + it("should support fat arrow with self", function() + local obj = { + value = 10, + getValue = function(self) + return self.value + end + } + return assert.same(obj:getValue(), 10) + end) + it("should work with argument defaults", function() + local fn + fn = function(name, height) + if name == nil then + name = "something" + end + if height == nil then + height = 100 + end + return tostring(name) .. ", " .. tostring(height) + end + assert.same(fn(), "something, 100") + assert.same(fn("test"), "test, 100") + return assert.same(fn("test", 50), "test, 50") + end) + it("should handle defaults with previous arguments", function() + local fn + fn = function(x, y) + if x == nil then + x = 100 + end + if y == nil then + y = x + 1000 + end + return x + y + end + assert.same(fn(), 1200) + return assert.same(fn(50), 1100) + end) + it("should work with multi-line arguments", function() + local my_func + my_func = function(a, b, c, d, e, f) + return a + b + c + d + e + f + end + local result = my_func(5, 4, 3, 8, 9, 10) + return assert.same(result, 39) + end) + it("should support nested function calls", function() + local another_func + another_func = function(a, b, c, d, e, f) + return a + b + c + d + e + f + end + local my_func + my_func = function(a, b, c, d, e, f, g) + return a + b + c + d + e + f + g + end + local result = my_func(5, 6, 7, 6, another_func(6, 7, 8, 9, 1, 2), 5, 4) + return assert.same(result, 66) + end) + it("should handle implicit return", function() + local sum + sum = function(x, y) + return x + y + end + return assert.same(sum(10, 20), 30) + end) + it("should work with explicit return", function() + local difference + difference = function(x, y) + return x - y + end + return assert.same(difference(20, 10), 10) + end) + it("should support multiple return values", function() + local mystery + mystery = function(x, y) + return x + y, x - y + end + local a, b = mystery(10, 20) + assert.same(a, 30) + return assert.same(b, -10) + end) + it("should work with function as argument", function() + local apply + apply = function(fn, x, y) + return fn(x, y) + end + local result = apply((function(a, b) + return a + b + end), 5, 10) + return assert.same(result, 15) + end) + it("should handle function returning function", function() + local create_adder + create_adder = function(x) + return function(y) + return x + y + end + end + local add_five = create_adder(5) + return assert.same(add_five(10), 15) + end) + it("should support immediately invoked function", function() + local result = (function(x) + return x * 2 + end)(5) + return assert.same(result, 10) + end) + it("should work with varargs", function() + local sum_all + sum_all = function(...) + local total = 0 + for i = 1, select('#', ...) do + if type(select(i, ...)) == "number" then + total = total + select(i, ...) + end + end + return total + end + return assert.same(sum_all(1, 2, 3, 4, 5), 15) + end) + it("should handle named varargs", function() + local fn + fn = function(...) + local t = { + n = select("#", ...), + ... + } + local count = 0 + for i = 1, t.n do + count = count + 1 + end + return count + end + return assert.same(fn(1, 2, 3), 3) + end) + it("should support prefixed return", function() + local findValue + findValue = function() + local items = { + 1, + 2, + 3 + } + for _index_0 = 1, #items do + local item = items[_index_0] + if item == 5 then + return item + end + end + return "not found" + end + local result = findValue() + return assert.same(result, "not found") + end) + it("should work with parameter destructuring", function() + local fn + fn = function(_arg_0) + local a, b, c + a, b, c = _arg_0.a, _arg_0.b, _arg_0.c + return a + b + c + end + return assert.same(fn({ + a = 1, + b = 2, + c = 3 + }), 6) + end) + it("should handle default values in destructuring", function() + local fn + fn = function(_arg_0) + local a1, b + a1, b = _arg_0.a, _arg_0.b + if a1 == nil then + a1 = 123 + end + if b == nil then + b = 'abc' + end + return a1 .. " " .. b + end + assert.same(fn({ }), "123 abc") + return assert.same(fn({ + a = 456 + }), "456 abc") + end) + it("should support empty function body", function() + local empty_fn + empty_fn = function() end + return assert.same(empty_fn(), nil) + end) + it("should work with function in table", function() + local tb = { + value = 10, + double = function(self) + return self.value * 2 + end + } + return assert.same(tb:double(), 20) + end) + it("should handle function with no arguments", function() + local fn + fn = function() + return "result" + end + assert.same(fn(), "result") + return assert.same(fn(), "result") + end) + it("should support calling function with !", function() + local fn + fn = function() + return 42 + end + return assert.same(fn(), 42) + end) + it("should work with nested functions", function() + local outer + outer = function(x) + local inner + inner = function(y) + return x + y + end + return inner + end + local add_five = outer(5) + return assert.same(add_five(10), 15) + end) + it("should handle function in expression", function() + local result + if (function(x) + return x > 10 + end)(15) then + result = "large" + else + result = "small" + end + return assert.same(result, "large") + end) + return it("should support function as return value", function() + local get_operation + get_operation = function(op) + if "add" == op then + return function(a, b) + return a + b + end + elseif "subtract" == op then + return function(a, b) + return a - b + end + else + return function() + return 0 + end + end + end + local add = get_operation("add") + return assert.same(add(5, 3), 8) + end) +end) diff --git a/spec/outputs/test/implicit_object_spec.lua b/spec/outputs/test/implicit_object_spec.lua new file mode 100644 index 0000000..bd23978 --- /dev/null +++ b/spec/outputs/test/implicit_object_spec.lua @@ -0,0 +1,243 @@ +return describe("implicit object", function() + it("should create list with asterisk", function() + local list = { + 1, + 2, + 3 + } + return assert.same(list, { + 1, + 2, + 3 + }) + end) + it("should create list with dash", function() + local items = { + "a", + "b", + "c" + } + return assert.same(items, { + "a", + "b", + "c" + }) + end) + it("should work with function call", function() + local results = { } + local fn = { + 1, + 2, + 3 + } + for _index_0 = 1, #fn do + local item = fn[_index_0] + table.insert(results, item) + end + return assert.same(results, { + 1, + 2, + 3 + }) + end) + it("should support nested implicit objects", function() + local tb = { + name = "test", + values = { + "a", + "b", + "c" + }, + objects = { + { + name = "first", + value = 1 + }, + { + name = "second", + value = 2 + } + } + } + assert.same(tb.values, { + "a", + "b", + "c" + }) + assert.same(tb.objects[1].name, "first") + return assert.same(tb.objects[2].value, 2) + end) + it("should work with return statement", function() + local fn + fn = function() + return { + 1, + 2, + 3 + } + end + return assert.same(fn(), { + 1, + 2, + 3 + }) + end) + it("should handle mixed content", function() + local tb = { + key = "value", + items = { + 1, + 2 + }, + other = "data" + } + assert.same(tb.key, "value") + assert.same(tb.items, { + 1, + 2 + }) + return assert.same(tb.other, "data") + end) + it("should work in assignment", function() + local list = { + "x", + "y", + "z" + } + return assert.same(list, { + "x", + "y", + "z" + }) + end) + it("should support nested structures with asterisk", function() + local tb = { + 1, + 2, + nested = { + 3, + 4 + } + } + assert.same(tb[1], 1) + assert.same(tb[2], 2) + return assert.same(tb.nested, { + 3, + 4 + }) + end) + it("should handle implicit object in tables", function() + local tb = { + name = "test", + list = { + 1, + 2 + }, + value = 42 + } + return assert.same(tb.list, { + 1, + 2 + }) + end) + it("should work with expressions", function() + local x = 10 + local list = { + x + 1, + x + 2, + x + 3 + } + return assert.same(list, { + 11, + 12, + 13 + }) + end) + it("should support method calls in implicit object", function() + local tb = { + name = "test", + items = { + { + name = "item1", + getName = function(self) + return self.name + end + }, + { + name = "item2", + getName = function(self) + return self.name + end + } + } + } + assert.same(tb.items[1]:getName(), "item1") + return assert.same(tb.items[2]:getName(), "item2") + end) + it("should work with complex nested structures", function() + local config = { + database = { + host = "localhost", + ports = { + 8080, + 8081, + 8082 + } + }, + servers = { + { + name = "server1", + port = 8080 + }, + { + name = "server2", + port = 8081 + } + } + } + assert.same(config.database.ports, { + 8080, + 8081, + 8082 + }) + return assert.same(config.servers[1].name, "server1") + end) + it("should handle empty implicit object", function() + local tb = { + items = { + nil + } + } + return assert.same(tb, { + items = { + nil + } + }) + end) + it("should work in function arguments", function() + local fn + fn = function(items) + return #items + end + local result = fn({ + 1, + 2, + 3 + }) + return assert.same(result, 3) + end) + return it("should support mixed asterisk and dash", function() + local tb = { + values = { + 1, + 2, + 3 + } + } + return assert.same(tb.values, { + 1, + 2, + 3 + }) + end) +end) diff --git a/spec/outputs/test/in_expression_spec.lua b/spec/outputs/test/in_expression_spec.lua index fc118c2..e5af45b 100644 --- a/spec/outputs/test/in_expression_spec.lua +++ b/spec/outputs/test/in_expression_spec.lua @@ -34,34 +34,7 @@ local _anon_func_3 = function(chars) end return false end -local _anon_func_4 = function(obj) - local _val_0 = "x" - for _index_0 = 1, #obj do - if obj[_index_0] == _val_0 then - return true - end - end - return false -end -local _anon_func_5 = function(obj) - local _val_0 = "y" - for _index_0 = 1, #obj do - if obj[_index_0] == _val_0 then - return true - end - end - return false -end -local _anon_func_6 = function(obj) - local _val_0 = "w" - for _index_0 = 1, #obj do - if obj[_index_0] == _val_0 then - return true - end - end - return false -end -local _anon_func_7 = function(items) +local _anon_func_4 = function(items) local _val_0 = 1 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -70,7 +43,7 @@ local _anon_func_7 = function(items) end return false end -local _anon_func_8 = function(items) +local _anon_func_5 = function(items) local _val_0 = "two" for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -79,7 +52,7 @@ local _anon_func_8 = function(items) end return false end -local _anon_func_9 = function(items) +local _anon_func_6 = function(items) local _val_0 = true for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -88,7 +61,7 @@ local _anon_func_9 = function(items) end return false end -local _anon_func_10 = function(items) +local _anon_func_7 = function(items) local _val_0 = false for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -97,7 +70,7 @@ local _anon_func_10 = function(items) end return false end -local _anon_func_11 = function(empty) +local _anon_func_8 = function(empty) local _val_0 = 1 for _index_0 = 1, #empty do if empty[_index_0] == _val_0 then @@ -106,7 +79,7 @@ local _anon_func_11 = function(empty) end return false end -local _anon_func_12 = function(empty) +local _anon_func_9 = function(empty) local _val_0 = "test" for _index_0 = 1, #empty do if empty[_index_0] == _val_0 then @@ -115,7 +88,7 @@ local _anon_func_12 = function(empty) end return false end -local _anon_func_13 = function(items) +local _anon_func_10 = function(items) local _val_0 = 2 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -124,7 +97,7 @@ local _anon_func_13 = function(items) end return false end -local _anon_func_14 = function(items) +local _anon_func_11 = function(items) local _val_0 = 4 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -133,7 +106,7 @@ local _anon_func_14 = function(items) end return false end -local _anon_func_15 = function(items) +local _anon_func_12 = function(items) local _val_0 = 2 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -142,7 +115,7 @@ local _anon_func_15 = function(items) end return false end -local _anon_func_16 = function(nested) +local _anon_func_13 = function(nested) local _val_0 = { 1, 2 @@ -154,7 +127,7 @@ local _anon_func_16 = function(nested) end return false end -local _anon_func_17 = function(nested) +local _anon_func_14 = function(nested) local _val_0 = { 1, 3 @@ -166,7 +139,7 @@ local _anon_func_17 = function(nested) end return false end -local _anon_func_18 = function(bools) +local _anon_func_15 = function(bools) local _val_0 = true for _index_0 = 1, #bools do if bools[_index_0] == _val_0 then @@ -175,7 +148,7 @@ local _anon_func_18 = function(bools) end return false end -local _anon_func_19 = function(bools) +local _anon_func_16 = function(bools) local _val_0 = false for _index_0 = 1, #bools do if bools[_index_0] == _val_0 then @@ -184,7 +157,7 @@ local _anon_func_19 = function(bools) end return false end -local _anon_func_20 = function(i, items) +local _anon_func_17 = function(i, items) for _index_0 = 1, #items do if items[_index_0] == i then return true @@ -192,7 +165,7 @@ local _anon_func_20 = function(i, items) end return false end -local _anon_func_21 = function(key1, tb) +local _anon_func_18 = function(key1, tb) for _index_0 = 1, #tb do if tb[_index_0] == key1 then return true @@ -200,7 +173,7 @@ local _anon_func_21 = function(key1, tb) end return false end -local _anon_func_22 = function(key2, tb) +local _anon_func_19 = function(key2, tb) for _index_0 = 1, #tb do if tb[_index_0] == key2 then return true @@ -208,7 +181,7 @@ local _anon_func_22 = function(key2, tb) end return false end -local _anon_func_23 = function(get_items) +local _anon_func_20 = function(get_items) local _check_0 = get_items() local _val_0 = 2 for _index_0 = 1, #_check_0 do @@ -218,7 +191,7 @@ local _anon_func_23 = function(get_items) end return false end -local _anon_func_24 = function(get_items) +local _anon_func_21 = function(get_items) local _check_0 = get_items() local _val_0 = 5 for _index_0 = 1, #_check_0 do @@ -228,7 +201,7 @@ local _anon_func_24 = function(get_items) end return false end -local _anon_func_25 = function(items) +local _anon_func_22 = function(items) local _val_0 = nil for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -237,7 +210,7 @@ local _anon_func_25 = function(items) end return false end -local _anon_func_26 = function(items) +local _anon_func_23 = function(items) local _val_0 = 1 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -246,7 +219,7 @@ local _anon_func_26 = function(items) end return false end -local _anon_func_27 = function(obj) +local _anon_func_24 = function(obj) local _val_0 = "name" for _index_0 = 1, #obj do if obj[_index_0] == _val_0 then @@ -255,7 +228,7 @@ local _anon_func_27 = function(obj) end return false end -local _anon_func_28 = function(obj) +local _anon_func_25 = function(obj) local _val_0 = "value" for _index_0 = 1, #obj do if obj[_index_0] == _val_0 then @@ -264,7 +237,7 @@ local _anon_func_28 = function(obj) end return false end -local _anon_func_29 = function(obj) +local _anon_func_26 = function(obj) local _val_0 = "missing" for _index_0 = 1, #obj do if obj[_index_0] == _val_0 then @@ -273,7 +246,7 @@ local _anon_func_29 = function(obj) end return false end -local _anon_func_30 = function(items) +local _anon_func_27 = function(items) local _val_0 = 2 for _index_0 = 1, #items do if items[_index_0] == _val_0 then @@ -282,7 +255,7 @@ local _anon_func_30 = function(items) end return false end -local _anon_func_31 = function(allowed, item) +local _anon_func_28 = function(allowed, item) for _index_0 = 1, #allowed do if allowed[_index_0] == item then return true @@ -311,15 +284,14 @@ return describe("in expression", function() assert.is_true(_anon_func_2(chars)) return assert.is_false(_anon_func_3(chars)) end) - it("should check keys in table", function() - local obj = { - x = 1, - y = 2, - z = 3 - } - assert.is_true(_anon_func_4(obj)) - assert.is_true(_anon_func_5(obj)) - return assert.is_false(_anon_func_6(obj)) + it("should check in table literal", function() + local x = 1 + local y = 2 + local z = 3 + local w = 4 + assert.is_true((x == x or y == x or z == x)) + assert.is_true((x == y or y == y or z == y)) + return assert.is_false((x == w or y == w or z == w)) end) it("should work with mixed types", function() local items = { @@ -328,15 +300,15 @@ return describe("in expression", function() true, nil } - assert.is_true(_anon_func_7(items)) - assert.is_true(_anon_func_8(items)) - assert.is_true(_anon_func_9(items)) - return assert.is_false(_anon_func_10(items)) + assert.is_true(_anon_func_4(items)) + assert.is_true(_anon_func_5(items)) + assert.is_true(_anon_func_6(items)) + return assert.is_false(_anon_func_7(items)) end) it("should handle empty table", function() local empty = { } - assert.is_false(_anon_func_11(empty)) - return assert.is_false(_anon_func_12(empty)) + assert.is_false(_anon_func_8(empty)) + return assert.is_false(_anon_func_9(empty)) end) it("should work in conditional", function() local items = { @@ -345,7 +317,7 @@ return describe("in expression", function() 3 } local result - if _anon_func_13(items) then + if _anon_func_10(items) then result = "found" else result = "not found" @@ -358,34 +330,44 @@ return describe("in expression", function() 2, 3 } - assert.is_true(not (_anon_func_14(items))) - return assert.is_false(not (_anon_func_15(items))) + assert.is_true(not (_anon_func_11(items))) + return assert.is_false(not (_anon_func_12(items))) end) it("should work with nested tables", function() + local eq + eq = function(self, other) + return self[1] == other[1] and self[2] == other[2] + end local nested = { - { + setmetatable({ 1, - 2 - }, - { + 2, + }, { + __eq = eq + }), + setmetatable({ 3, - 4 - }, - { + 4, + }, { + __eq = eq + }), + setmetatable({ 5, - 6 - } + 6, + }, { + __eq = eq + }) } - assert.is_true(_anon_func_16(nested)) - return assert.is_false(_anon_func_17(nested)) + assert.is_true(_anon_func_13(nested)) + return assert.is_false(_anon_func_14(nested)) end) it("should handle boolean values", function() local bools = { true, false } - assert.is_true(_anon_func_18(bools)) - return assert.is_true(_anon_func_19(bools)) + assert.is_true(_anon_func_15(bools)) + return assert.is_true(_anon_func_16(bools)) end) it("should work in loop", function() local items = { @@ -397,7 +379,7 @@ return describe("in expression", function() } local count = 0 for i = 1, 10 do - if (#items > 0 and _anon_func_20(i, items)) then + if (#items > 0 and _anon_func_17(i, items)) then count = count + 1 end end @@ -411,11 +393,11 @@ return describe("in expression", function() b = 2 } local tb = { - [key1] = "first", - [key2] = "second" + key1, + key2 } - assert.is_true((#tb > 0 and _anon_func_21(key1, tb))) - return assert.is_true((#tb > 0 and _anon_func_22(key2, tb))) + assert.is_true((#tb > 0 and _anon_func_18(key1, tb))) + return assert.is_true((#tb > 0 and _anon_func_19(key2, tb))) end) it("should work with function results", function() local get_items @@ -426,8 +408,8 @@ return describe("in expression", function() 3 } end - assert.is_true(_anon_func_23(get_items)) - return assert.is_false(_anon_func_24(get_items)) + assert.is_true(_anon_func_20(get_items)) + return assert.is_false(_anon_func_21(get_items)) end) it("should handle nil in table", function() local items = { @@ -435,17 +417,17 @@ return describe("in expression", function() nil, 3 } - assert.is_true(_anon_func_25(items)) - return assert.is_true(_anon_func_26(items)) + assert.is_true(_anon_func_22(items)) + return assert.is_true(_anon_func_23(items)) end) it("should work with string keys", function() local obj = { - name = "test", - value = 42 + "name", + "value" } - assert.is_true(_anon_func_27(obj)) - assert.is_true(_anon_func_28(obj)) - return assert.is_false(_anon_func_29(obj)) + assert.is_true(_anon_func_24(obj)) + assert.is_true(_anon_func_25(obj)) + return assert.is_false(_anon_func_26(obj)) end) it("should support complex expressions", function() local items = { @@ -453,7 +435,7 @@ return describe("in expression", function() 2, 3 } - local result = (_anon_func_30(items)) and "yes" or "no" + local result = (_anon_func_27(items)) and "yes" or "no" return assert.same(result, "yes") end) return it("should work in comprehension", function() @@ -474,7 +456,7 @@ return describe("in expression", function() local _len_0 = 1 for _index_0 = 1, #source do local item = source[_index_0] - if (#allowed > 0 and _anon_func_31(allowed, item)) then + if (#allowed > 0 and _anon_func_28(allowed, item)) then _accum_0[_len_0] = item _len_0 = _len_0 + 1 end diff --git a/spec/outputs/test/multiline_args_spec.lua b/spec/outputs/test/multiline_args_spec.lua new file mode 100644 index 0000000..562c571 --- /dev/null +++ b/spec/outputs/test/multiline_args_spec.lua @@ -0,0 +1,219 @@ +return describe("multiline arguments", function() + it("should split arguments across lines", function() + local sum + sum = function(a, b, c, d, e, f) + return a + b + c + d + e + f + end + local result = sum(5, 4, 3, 8, 9, 10) + return assert.same(result, 39) + end) + it("should handle nested function calls", function() + local outer + outer = function(a, b, c, d, e, f) + return a + b + c + d + e + f + end + local result = outer(5, 6, 7, 6, 2, 3) + return assert.same(result, 29) + end) + it("should work with string arguments", function() + local fn + fn = function(a, b, c, d) + return a .. b .. c .. d + end + local result = fn("hello", " ", "world", "!") + return assert.same(result, "hello world!") + end) + it("should support table arguments", function() + local fn + fn = function(a, b, c) + return { + a, + b, + c + } + end + local result = fn({ + 1, + 2 + }, { + 3, + 4 + }, { + 5, + 6 + }) + return assert.same(result, { + { + 1, + 2 + }, + { + 3, + 4 + }, + { + 5, + 6 + } + }) + end) + it("should handle mixed types", function() + local fn + fn = function(a, b, c, d) + return { + a, + b, + c, + d + } + end + local result = fn("text", 123, true, nil) + return assert.same(result, { + "text", + 123, + true, + nil + }) + end) + it("should work in table literal", function() + local fn + fn = function(a, b) + return a + b + end + local result = { + 1, + 2, + 3, + 4, + fn(4, 5, 5, 6), + 8, + 9, + 10 + } + return assert.same(result, { + 1, + 2, + 3, + 4, + 9, + 8, + 9, + 10 + }) + end) + it("should handle deeply nested indentation", function() + local fn + fn = function(a, b, c, d, e, f, g) + return a + b + c + d + e + f + g + end + local y = { + fn(1, 2, 3, 4, 5, 6, 7) + } + local result = y[1] + return assert.same(result, 28) + end) + it("should work with conditional statements", function() + local fn + fn = function(a, b, c, d, e, f) + return a + b + c + d + e + f + end + local result1 = fn(1, 2, 3, 4, 5, 6) + local result + if result1 > 20 then + result = "yes" + else + result = "no" + end + return assert.same(result, "yes") + end) + it("should support function expressions", function() + local doublePlus + doublePlus = function(x, y) + return x * 2 + y + end + local result = doublePlus(5, 10) + return assert.same(result, 20) + end) + it("should handle chained function calls", function() + local add + add = function(a, b, c, d) + return a + b + c + d + end + local multiply + multiply = function(a, b, c, d) + return a * b * c * d + end + local result = multiply(1, 2, 3, 4) + return assert.same(result, 24) + end) + it("should work with method calls", function() + local obj = { + value = 10, + add = function(self, a, b, c) + return self.value + a + b + c + end + } + local result = obj:add(5, 10, 15) + return assert.same(result, 40) + end) + it("should support many arguments", function() + local sum_many + sum_many = function(...) + local total = 0 + for i = 1, select('#', ...) do + if type(select(i, ...)) == "number" then + total = total + select(i, ...) + end + end + return total + end + local result = sum_many(1, 2, 3, 4, 5, 6, 7, 8, 9) + return assert.same(result, 45) + end) + it("should work with return statement", function() + local fn + fn = function(a, b, c) + return a + b + c + end + local get_value + get_value = function() + return fn(10, 20, 30) + end + local result = get_value() + return assert.same(result, 60) + end) + it("should handle default parameters", function() + local fn + fn = function(a, b, c) + if a == nil then + a = 1 + end + if b == nil then + b = 2 + end + if c == nil then + c = 3 + end + return a + b + c + end + local result = fn(10, 20, 30) + return assert.same(result, 60) + end) + return it("should work with varargs", function() + local collect + collect = function(...) + return { + ... + } + end + local result = collect(1, 2, 3, 4, 5, 6) + return assert.same(result, { + 1, + 2, + 3, + 4, + 5, + 6 + }) + end) +end) diff --git a/spec/outputs/test/named_varargs_spec.lua b/spec/outputs/test/named_varargs_spec.lua index 2a71cea..be35b22 100644 --- a/spec/outputs/test/named_varargs_spec.lua +++ b/spec/outputs/test/named_varargs_spec.lua @@ -187,21 +187,19 @@ return describe("named varargs", function() }) end) it("should support passing named varargs to another function", function() + local inner + inner = function(...) + return { + ... + } + end local outer outer = function(...) local t = { n = select("#", ...), ... } - return inner((table.unpack(t))) - end - local inner - inner = function(a, b, c) - return { - a, - b, - c - } + return inner(t[1], t[2], t[3]) end local result = outer(1, 2, 3) return assert.same(result, { diff --git a/spec/outputs/test/operator_advanced_spec.lua b/spec/outputs/test/operator_advanced_spec.lua new file mode 100644 index 0000000..42e4c30 --- /dev/null +++ b/spec/outputs/test/operator_advanced_spec.lua @@ -0,0 +1,210 @@ +local _anon_func_0 = function(v) + local _cond_0 = v(2) + if not (v(1) < _cond_0) then + return false + else + return _cond_0 <= v(3) + end +end +return describe("advanced operators", function() + it("should support chaining comparisons with functions", function() + local v + v = function(x) + return x + end + return assert.is_true(_anon_func_0(v)) + end) + it("should handle compound assignment with or", function() + local x = nil + x = x or "default" + return assert.same(x, "default") + end) + it("should not overwrite existing value with or", function() + local x = "existing" + x = x or "default" + return assert.same(x, "existing") + end) + it("should support compound string concatenation", function() + local s = "hello" + s = s .. " world" + return assert.same(s, "hello world") + end) + it("should work with table appending", function() + local tab = { + 1, + 2 + } + tab[#tab + 1] = 3 + tab[#tab + 1] = 4 + return assert.same(tab, { + 1, + 2, + 3, + 4 + }) + end) + it("should handle spread append", function() + local tbA = { + 1, + 2 + } + local tbB = { + 3, + 4 + } + local _len_0 = #tbA + 1 + for _index_0 = 1, #tbB do + local _elm_0 = tbB[_index_0] + tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 + end + return assert.same(tbA, { + 1, + 2, + 3, + 4 + }) + end) + it("should support reverse indexing", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + assert.same(items[#items], 5) + assert.same(items[#items - 1], 4) + return assert.same(items[#items - 2], 3) + end) + it("should work with nil coalescing assignment", function() + local x = nil + if x == nil then + x = "default" + end + return assert.same(x, "default") + end) + it("should not assign with ??= when value exists", function() + local x = "existing" + if x == nil then + x = "default" + end + return assert.same(x, "existing") + end) + it("should chain nil coalescing", function() + local a = nil + local b = nil + local c = "value" + local result + if a ~= nil then + result = a + else + if b ~= nil then + result = b + else + result = c + end + end + return assert.same(result, "value") + end) + it("should support compound modulo", function() + local x = 20 + x = x % 3 + return assert.same(x, 2) + end) + it("should handle compound exponentiation", function() + local x = 2 + x = x ^ 3 + return assert.same(x, 8) + end) + it("should work with compound bitwise and", function() + local x = 15 + x = x & 7 + return assert.same(x, 7) + end) + it("should support compound bitwise or", function() + local x = 8 + x = x | 3 + return assert.same(x, 11) + end) + it("should handle compound bitwise xor", function() + local x = 12 + x = x ~ 10 + return assert.same(x, 6) + end) + it("should work with compound left shift", function() + local x = 2 + x = x << 3 + return assert.same(x, 16) + end) + it("should support compound right shift", function() + local x = 16 + x = x >> 2 + return assert.same(x, 4) + end) + it("should handle negation operator", function() + assert.same(-10, -10) + return assert.same + end) + it("should work with length operator on tables", function() + local tab = { + 1, + 2, + 3, + 4, + 5 + } + return assert.same(#tab, 5) + end) + it("should support length on strings", function() + local s = "hello" + return assert.same(#s, 5) + end) + it("should handle chaining assignment", function() + local a = 0 + local b = 0 + local c = 0 + local d = 0 + assert.same(a, 0) + assert.same(b, 0) + assert.same(c, 0) + return assert.same(d, 0) + end) + it("should work with chaining assignment with functions", function() + local f + f = function() + return 42 + end + local x = f() + local y = x + local z = x + assert.same(x, 42) + assert.same(y, 42) + return assert.same(z, 42) + end) + it("should support != as alias for ~=", function() + assert.is_true(1 ~= 2) + return assert.is_false(1 ~= 1) + end) + it("should work with :: for method chaining", function() + local obj = { + value = 10, + add = function(self, n) + self.value = self.value + n + return self + end, + get = function(self) + return self.value + end + } + local result = obj:add(5):get() + return assert.same(result, 15) + end) + it("should handle complex expressions with precedence", function() + local result = 1 + 2 * 3 - 4 / 2 + return assert.same(result, 5) + end) + return it("should support mixed operator types", function() + local result = 10 + 20 * 2 - 5 / 5 + return assert.same(result, 49) + end) +end) diff --git a/spec/outputs/test/param_destructure_spec.lua b/spec/outputs/test/param_destructure_spec.lua new file mode 100644 index 0000000..6aa9907 --- /dev/null +++ b/spec/outputs/test/param_destructure_spec.lua @@ -0,0 +1,369 @@ +local _anon_func_0 = function(_arg_0) + local _accum_0 = { } + local _len_0 = 1 + local _max_0 = #_arg_0 + for _index_0 = 2, _max_0 do + local _item_0 = _arg_0[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + return _accum_0 +end +local _anon_func_1 = function(_arg_0) + local _accum_0 = { } + local _len_0 = 1 + local _max_0 = #_arg_0 + for _index_0 = 1, _max_0 do + local _item_0 = _arg_0[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + return _accum_0 +end +return describe("parameter destructuring", function() + it("should destructure simple object", function() + local f + f = function(_arg_0) + local a, b, c + a, b, c = _arg_0.a, _arg_0.b, _arg_0.c + return { + a, + b, + c + } + end + local result = f({ + a = 1, + b = "2", + c = { } + }) + return assert.same(result, { + 1, + "2", + { } + }) + end) + it("should work with default values", function() + local f + f = function(_arg_0, c) + local a1, b + a1, b = _arg_0.a, _arg_0.b + if a1 == nil then + a1 = 123 + end + if b == nil then + b = 'abc' + end + if c == nil then + c = { } + end + return { + a1, + b, + c + } + end + local result1 = f({ + a = 0 + }, "test") + assert.same(result1, { + 0, + 'abc', + 'test' + }) + local result2 = f({ }) + return assert.same(result2, { + 123, + 'abc', + { } + }) + end) + it("should destructure with mixed syntax", function() + local f + f = function(_arg_0) + local a, b1, c + a, b1, c = _arg_0.a, _arg_0.b, _arg_0.c + return { + a, + b1, + c + } + end + local result = f({ + a = 1, + b = 2, + c = 3 + }) + return assert.same(result, { + 1, + 2, + 3 + }) + end) + it("should work with nested destructuring", function() + local f + f = function(_arg_0) + local x, y + x, y = _arg_0.nested.x, _arg_0.nested.y + return { + x, + y + } + end + local result = f({ + nested = { + x = 10, + y = 20 + } + }) + return assert.same(result, { + 10, + 20 + }) + end) + it("should handle array parameters", function() + local f + f = function(_arg_0) + local a, b, c + a, b, c = _arg_0[1], _arg_0[2], _arg_0[3] + return { + a, + b, + c + } + end + local result = f({ + 1, + 2, + 3 + }) + return assert.same(result, { + 1, + 2, + 3 + }) + end) + it("should support mixed array and object", function() + local f + f = function(_arg_0, _arg_1) + local first + first = _arg_0[1] + local value + value = _arg_1.key.value + return { + first, + value + } + end + local result = f({ + 1 + }, { + key = { + value = "test" + } + }) + return assert.same(result, { + 1, + "test" + }) + end) + it("should work with fat arrow", function() + local obj = { + value = 100, + f = function(self, _arg_0) + local x, y + x, y = _arg_0.x, _arg_0.y + return self.value + x + y + end + } + local result = obj:f({ + x = 10, + y = 20 + }) + return assert.same(result, 130) + end) + it("should handle missing keys", function() + local f + f = function(_arg_0) + local a, b, c + a, b, c = _arg_0.a, _arg_0.b, _arg_0.c + if b == nil then + b = "default" + end + if c == nil then + c = "missing" + end + return { + a, + b, + c + } + end + local result = f({ + a = 1 + }) + return assert.same(result, { + 1, + 'default', + 'missing' + }) + end) + it("should work with complex defaults", function() + local f + f = function(_arg_0) + local a1, b1 + a1, b1 = _arg_0.a, _arg_0.b + if a1 == nil then + a1 = 100 + end + if b1 == nil then + b1 = a1 + 1000 + end + return a1 + b1 + end + local result = f({ }) + return assert.same(result, 1200) + end) + it("should support deep nesting", function() + local f + f = function(_arg_0) + local value + value = _arg_0.data.nested.value + return value + end + local result = f({ + data = { + nested = { + value = 42 + } + } + }) + return assert.same(result, 42) + end) + it("should work with multiple parameters", function() + local f + f = function(_arg_0, extra) + local x, y, z + x, y, z = _arg_0.x, _arg_0.y, _arg_0.z + if extra == nil then + extra = "default" + end + return { + x, + y, + z, + extra + } + end + local result = f({ + x = 1, + y = 2, + z = 3 + }) + return assert.same(result, { + 1, + 2, + 3, + 'default' + }) + end) + it("should handle array destructuring in parameters", function() + local f + f = function(_arg_0) + local first, rest + first, rest = _arg_0[1], _anon_func_0(_arg_0) + return { + first, + rest + } + end + local result = f({ + 1, + 2, + 3, + 4 + }) + return assert.same(result, { + 1, + { + 2, + 3, + 4 + } + }) + end) + it("should support spreading", function() + local f + f = function(_arg_0) + local rest, last + rest, last = _anon_func_1(_arg_0), _arg_0.last + return { + rest, + last + } + end + local result = f({ + 1, + 2, + 3, + last = "final" + }) + return assert.same(result, { + { + 1, + 2, + 3 + }, + 'final' + }) + end) + it("should work with table comprehensions", function() + local f + f = function(_arg_0) + local items + items = _arg_0.items + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #items do + local item = items[_index_0] + _accum_0[_len_0] = item * 2 + _len_0 = _len_0 + 1 + end + return _accum_0 + end + local result = f({ + items = { + 1, + 2, + 3 + } + }) + return assert.same(result, { + 2, + 4, + 6 + }) + end) + return it("should handle nil arguments", function() + local f + f = function(_arg_0) + local a, b + a, b = _arg_0.a, _arg_0.b + if a == nil then + a = "nil_a" + end + if b == nil then + b = "nil_b" + end + return { + a, + b + } + end + local result = f({ }) + return assert.same(result, { + "nil_a", + "nil_b" + }) + end) +end) diff --git a/spec/outputs/test/reverse_index_spec.lua b/spec/outputs/test/reverse_index_spec.lua index 396c3b9..b1d2359 100644 --- a/spec/outputs/test/reverse_index_spec.lua +++ b/spec/outputs/test/reverse_index_spec.lua @@ -116,10 +116,6 @@ return describe("reverse index", function() end return assert.same(last, 3) end) - it("should work with string", function() - local s = "hello" - return assert.same(s[#s], "o") - end) it("should handle negative offsets", function() local tab = { 1, diff --git a/spec/outputs/test/slicing_spec.lua b/spec/outputs/test/slicing_spec.lua new file mode 100644 index 0000000..1db2938 --- /dev/null +++ b/spec/outputs/test/slicing_spec.lua @@ -0,0 +1,324 @@ +return describe("slicing", function() + it("should slice array with basic syntax", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, 3 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 1, + 2, + 3 + }) + end) + it("should slice from beginning", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + local _max_0 = #items + _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 + for _index_0 = 1, _max_0 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 1, + 2, + 3, + 4, + 5 + }) + end) + it("should slice to end", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 3, 5 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 3, + 4, + 5 + }) + end) + it("should handle negative indices", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + local _min_0 = #items + -3 + 1 + local _max_0 = #items + -1 + 1 + for _index_0 = _min_0, _max_0 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 3, + 4, + 5 + }) + end) + it("should slice single element", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 2, 2 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 2 + }) + end) + it("should work with strings", function() + local s = "hello" + local result = s:sub(1, 3) + return assert.same(result, "hel") + end) + it("should handle out of bounds", function() + local items = { + 1, + 2, + 3 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, 10 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 1, + 2, + 3 + }) + end) + it("should create new table", function() + local original = { + 1, + 2, + 3, + 4, + 5 + } + local sliced + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 2, 4 do + local _item_0 = original[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + sliced = _accum_0 + end + sliced[1] = 99 + return assert.same(original[2], 2) + end) + it("should work with nested arrays", function() + local nested = { + { + 1, + 2 + }, + { + 3, + 4 + }, + { + 5, + 6 + } + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, 2 do + local _item_0 = nested[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + { + 1, + 2 + }, + { + 3, + 4 + } + }) + end) + it("should slice with step simulation", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for i = 1, #items, 2 do + _accum_0[_len_0] = items[i] + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { + 1, + 3, + 5 + }) + end) + it("should handle empty slice range", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 6, 10 do + local _item_0 = items[_index_0] + _accum_0[_len_0] = _item_0 + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(result, { }) + end) + it("should work with reverse indexing", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local last = items[#items] + local second_last = items[#items - 1] + assert.same(last, 5) + return assert.same(second_last, 4) + end) + it("should support slice in assignment", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local a, b, c + do + local _accum_0 = { } + local _len_0 = 1 + local _list_0 = { + 1, + 2, + 3 + } + for _index_0 = 1, #_list_0 do + local i = _list_0[_index_0] + _accum_0[_len_0] = items[i] + _len_0 = _len_0 + 1 + end + a, b, c = _accum_0[1], _accum_0[2], _accum_0[3] + end + assert.same(a, 1) + assert.same(b, 2) + return assert.same(c, 3) + end) + return it("should work with table comprehensions", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local result + do + local _tbl_0 = { } + for i = 2, 4 do + _tbl_0[i] = items[i] + end + result = _tbl_0 + end + assert.same(result[2], 2) + assert.same(result[3], 3) + return assert.same(result[4], 4) + end) +end) diff --git a/spec/outputs/test/stub_spec.lua b/spec/outputs/test/stub_spec.lua new file mode 100644 index 0000000..0daf5b6 --- /dev/null +++ b/spec/outputs/test/stub_spec.lua @@ -0,0 +1,148 @@ +local stub_fn +stub_fn = function() + return function() end +end +local _anon_func_0 = function(stub_fn) + stub_fn() + return true +end +return describe("function stub", function() + it("should create empty function", function() + stub_fn() + return assert.is_true(true) + end) + it("should support stub in table", function() + local obj = { + stub = stub_fn() + } + return assert.is_true(true) + end) + it("should work with method stub", function() + local obj = { + method = stub_fn() + } + return assert.is_true(true) + end) + it("should handle stub in assignment", function() + local my_func = stub_fn() + return assert.is_true(true) + end) + it("should support stub in return", function() + local get_stub + get_stub = function() + return stub_fn() + end + local fn = get_stub() + return assert.is_true(true) + end) + it("should work in conditional", function() + if stub_fn() then + return assert.is_true(true) + end + end) + it("should support stub as callback", function() + local call_fn + call_fn = function(fn) + return fn() + end + local result = call_fn(stub_fn()) + return assert.is_true(true) + end) + it("should handle stub in table literal", function() + local tb = { + on_click = stub_fn(), + on_hover = stub_fn() + } + return assert.is_true(true) + end) + it("should work with fat arrow stub", function() + local obj = { + value = 10, + method = stub_fn() + } + local result = obj:method() + return assert.is_true(true) + end) + it("should support stub in array", function() + local callbacks = { + stub_fn(), + stub_fn(), + stub_fn() + } + return assert.same(#callbacks, 3) + end) + it("should handle stub in expression", function() + local result = stub_fn() and true or false + return assert.is_true(result) + end) + it("should work with chained stub calls", function() + stub_fn() + stub_fn() + stub_fn() + return assert.is_true(true) + end) + it("should support stub in comprehension", function() + local result + do + local _accum_0 = { } + local _len_0 = 1 + for i = 1, 3 do + _accum_0[_len_0] = stub_fn() + _len_0 = _len_0 + 1 + end + result = _accum_0 + end + return assert.same(#result, 3) + end) + it("should handle stub in switch", function() + local value = "test" + local result + if "test" == value then + stub_fn() + result = "matched" + else + result = "not matched" + end + return assert.same(result, "matched") + end) + it("should work in with statement", function() + local obj = { + stub = stub_fn() + } + obj.stub() + return assert.is_true(true) + end) + it("should support stub as argument default", function() + local fn + fn = function(callback) + if callback == nil then + callback = stub_fn() + end + return callback() + end + local result = fn() + return assert.is_true(true) + end) + it("should handle stub in varargs", function() + local collect + collect = function(...) + return { + ... + } + end + local result = collect(stub_fn(), stub_fn()) + return assert.same(#result, 2) + end) + it("should work in do block", function() + do + stub_fn() + end + return assert.is_true(true) + end) + return it("should support stub in try block", function() + local success = xpcall(_anon_func_0, function(err) + return false + end, stub_fn) + return assert.is_true(success) + end) +end) diff --git a/spec/outputs/test/table_append_spec.lua b/spec/outputs/test/table_append_spec.lua index 5ce1156..4705161 100644 --- a/spec/outputs/test/table_append_spec.lua +++ b/spec/outputs/test/table_append_spec.lua @@ -72,12 +72,12 @@ return describe("table append", function() 2 }) end) - it("should append nil values", function() + it("should not append nil values", function() local tab = { } tab[#tab + 1] = nil tab[#tab + 1] = "value" - assert.same(tab[1], nil) - return assert.same(tab[2], "value") + assert.same(tab[2], nil) + return assert.same(tab[1], "value") end) it("should work in loop", function() local tab = { } @@ -150,7 +150,14 @@ return describe("table append", function() return 1, 2, 3 end local tab = { } - tab[#tab + 1] = fn() + local _len_0 = #tab + 1 + local _list_0 = { + fn() + } + for _index_0 = 1, #_list_0 do + local _elm_0 = _list_0[_index_0] + tab[_len_0], _len_0 = _elm_0, _len_0 + 1 + end return assert.same(tab, { 1, 2, diff --git a/spec/outputs/test/table_comprehension_spec.lua b/spec/outputs/test/table_comprehension_spec.lua new file mode 100644 index 0000000..90fa647 --- /dev/null +++ b/spec/outputs/test/table_comprehension_spec.lua @@ -0,0 +1,297 @@ +return describe("table comprehension", function() + it("should create simple table copy", function() + local thing = { + color = "red", + name = "fast", + width = 123 + } + local thing_copy + do + local _tbl_0 = { } + for k, v in pairs(thing) do + _tbl_0[k] = v + end + thing_copy = _tbl_0 + end + assert.same(thing_copy.color, thing.color) + assert.same(thing_copy.name, thing.name) + return assert.same(thing_copy.width, thing.width) + end) + it("should filter with when clause", function() + local thing = { + color = "red", + name = "fast", + width = 123 + } + local no_color + do + local _tbl_0 = { } + for k, v in pairs(thing) do + if k ~= "color" then + _tbl_0[k] = v + end + end + no_color = _tbl_0 + end + assert.same(no_color.color, nil) + assert.same(no_color.name, "fast") + return assert.same(no_color.width, 123) + end) + it("should transform values", function() + local numbers = { + a = 1, + b = 2, + c = 3 + } + local doubled + do + local _tbl_0 = { } + for k, v in pairs(numbers) do + _tbl_0[k] = v * 2 + end + doubled = _tbl_0 + end + assert.same(doubled.a, 2) + assert.same(doubled.b, 4) + return assert.same(doubled.c, 6) + end) + it("should transform keys", function() + local data = { + a = 1, + b = 2 + } + local upper_keys + do + local _tbl_0 = { } + for k, v in pairs(data) do + _tbl_0[k:upper()] = v + end + upper_keys = _tbl_0 + end + assert.same(upper_keys.A, 1) + return assert.same(upper_keys.B, 2) + end) + it("should work with ipairs", function() + local items = { + "a", + "b", + "c" + } + local reversed + do + local _tbl_0 = { } + for i, v in ipairs(items) do + _tbl_0[i] = v + end + reversed = _tbl_0 + end + assert.same(reversed[1], "a") + assert.same(reversed[2], "b") + return assert.same(reversed[3], "c") + end) + it("should filter array items", function() + local items = { + 1, + 2, + 3, + 4, + 5 + } + local evens + do + local _tbl_0 = { } + for i, v in ipairs(items) do + if v % 2 == 0 then + _tbl_0[i] = v + end + end + evens = _tbl_0 + end + assert.same(evens[2], 2) + assert.same(evens[4], 4) + return assert.same(evens[1], nil) + end) + it("should work with numeric for loop", function() + local squares + do + local _tbl_0 = { } + for i = 1, 5 do + _tbl_0[i] = i * i + end + squares = _tbl_0 + end + assert.same(squares[1], 1) + assert.same(squares[2], 4) + assert.same(squares[3], 9) + assert.same(squares[4], 16) + return assert.same(squares[5], 25) + end) + it("should support nested comprehensions", function() + local matrix = { + { + 1, + 2 + }, + { + 3, + 4 + }, + { + 5, + 6 + } + } + local flat = { } + for _index_0 = 1, #matrix do + local row = matrix[_index_0] + for i, v in ipairs(row) do + flat[#flat + 1] = v + end + end + return assert.same(flat, { + 1, + 2, + 3, + 4, + 5, + 6 + }) + end) + it("should combine pairs and when", function() + local data = { + a = 1, + b = 2, + c = 3, + d = 4 + } + local greater_than_two + do + local _tbl_0 = { } + for k, v in pairs(data) do + if v > 2 then + _tbl_0[k] = v + end + end + greater_than_two = _tbl_0 + end + assert.same(greater_than_two.a, nil) + assert.same(greater_than_two.b, nil) + assert.same(greater_than_two.c, 3) + return assert.same(greater_than_two.d, 4) + end) + it("should work with string keys", function() + local obj = { + ["key-with-dash"] = "value1", + ["key_with_underscore"] = "value2" + } + local result + do + local _tbl_0 = { } + for k, v in pairs(obj) do + _tbl_0[k] = v + end + result = _tbl_0 + end + assert.same(result["key-with-dash"], "value1") + return assert.same(result["key_with_underscore"], "value2") + end) + it("should handle empty source", function() + local empty = { } + local result + do + local _tbl_0 = { } + for k, v in pairs(empty) do + _tbl_0[k] = v + end + result = _tbl_0 + end + return assert.same(#result, 0) + end) + it("should work with computed keys", function() + local base = { + a = 1, + b = 2 + } + local result + do + local _tbl_0 = { } + for k, v in pairs(base) do + _tbl_0[k .. "_suffix"] = v * 10 + end + result = _tbl_0 + end + assert.same(result.a_suffix, 10) + return assert.same(result.b_suffix, 20) + end) + it("should support nested table transformation", function() + local data = { + first = { + x = 1, + y = 2 + }, + second = { + x = 3, + y = 4 + } + } + local transformed + do + local _tbl_0 = { } + for k, v in pairs(data) do + _tbl_0[k] = v.x + v.y + end + transformed = _tbl_0 + end + assert.same(transformed.first, 3) + return assert.same(transformed.second, 7) + end) + it("should filter with multiple conditions", function() + local numbers = { + a = 1, + b = 2, + c = 3, + d = 4, + e = 5 + } + local result + do + local _tbl_0 = { } + for k, v in pairs(numbers) do + if v > 1 and v < 5 then + _tbl_0[k] = v + end + end + result = _tbl_0 + end + assert.same(result.a, nil) + assert.same(result.b, 2) + assert.same(result.c, 3) + assert.same(result.d, 4) + return assert.same(result.e, nil) + end) + return it("should work with custom iterator", function() + local custom_iter + custom_iter = function() + local state = 0 + return function() + state = state + 1 + if state <= 3 then + return state, state * 10 + else + return nil + end + end + end + local result + do + local _tbl_0 = { } + for k, v in custom_iter() do + _tbl_0[k] = v + end + result = _tbl_0 + end + assert.same(result[1], 10) + assert.same(result[2], 20) + return assert.same(result[3], 30) + end) +end) diff --git a/spec/outputs/test/tables_advanced_spec.lua b/spec/outputs/test/tables_advanced_spec.lua new file mode 100644 index 0000000..de36953 --- /dev/null +++ b/spec/outputs/test/tables_advanced_spec.lua @@ -0,0 +1,260 @@ +return describe("advanced tables", function() + it("should create table with implicit keys", function() + local hair = "golden" + local height = 200 + local person = { + hair = hair, + height = height, + shoe_size = 40 + } + assert.same(person.hair, "golden") + return assert.same(person.height, 200) + end) + it("should work with computed keys", function() + local t = { + [1 + 2] = "hello", + ["key_" .. "suffix"] = "value" + } + assert.same(t[3], "hello") + return assert.same(t["key_suffix"], "value") + end) + it("should support keyword keys", function() + local tbl = { + ["do"] = "something", + ["end"] = "hunger", + ["function"] = "test" + } + assert.same(tbl["do"], "something") + assert.same(tbl["end"], "hunger") + return assert.same(tbl["function"], "test") + end) + it("should handle array syntax with mixed content", function() + local tb = { + 1, + 2, + 3, + name = "superman", + 4, + 5, + 6 + } + assert.same(tb[1], 1) + assert.same(tb.name, "superman") + return assert.same(tb[4], 4) + end) + it("should work with single line table literals", function() + local tb = { + dance = "Tango", + partner = "none" + } + assert.same(tb.dance, "Tango") + return assert.same(tb.partner, "none") + end) + it("should support nested tables", function() + local tb = { + outer = { + inner = { + value = 42 + } + } + } + return assert.same(tb.outer.inner.value, 42) + end) + it("should handle table without braces", function() + local profile = { + height = "4 feet", + shoe_size = 13, + favorite_foods = { + "ice cream", + "donuts" + } + } + assert.same(profile.height, "4 feet") + return assert.same(profile.shoe_size, 13) + end) + it("should work with colon syntax for keys", function() + local t = { + name = "Bill", + age = 200, + ["favorite food"] = "rice" + } + assert.same(t.name, "Bill") + return assert.same(t["favorite food"], "rice") + end) + it("should support implicit object in table", function() + local tb = { + name = "abc", + values = { + "a", + "b", + "c" + } + } + return assert.same(tb.values, { + "a", + "b", + "c" + }) + end) + it("should handle array only table", function() + local some_values = { + 1, + 2, + 3, + 4 + } + assert.same(some_values[1], 1) + return assert.same(some_values[4], 4) + end) + it("should work with trailing comma", function() + local list_with_one = { + 1 + } + return assert.same(list_with_one[1], 1) + end) + it("should support table spreading", function() + local a = { + 1, + 2, + 3, + x = 1 + } + local b = { + 4, + 5, + y = 1 + } + local merge + do + local _tab_0 = { } + local _idx_0 = 1 + for _key_0, _value_0 in pairs(a) do + if _idx_0 == _key_0 then + _tab_0[#_tab_0 + 1] = _value_0 + _idx_0 = _idx_0 + 1 + else + _tab_0[_key_0] = _value_0 + end + end + local _idx_1 = 1 + for _key_0, _value_0 in pairs(b) do + if _idx_1 == _key_0 then + _tab_0[#_tab_0 + 1] = _value_0 + _idx_1 = _idx_1 + 1 + else + _tab_0[_key_0] = _value_0 + end + end + merge = _tab_0 + end + assert.same(merge[1], 1) + assert.same(merge[4], 4) + assert.same(merge.x, 1) + return assert.same(merge.y, 1) + end) + it("should handle mixed spread", function() + local parts = { + "shoulders", + "knees" + } + local lyrics + do + local _tab_0 = { + "head" + } + local _idx_0 = 1 + for _key_0, _value_0 in pairs(parts) do + if _idx_0 == _key_0 then + _tab_0[#_tab_0 + 1] = _value_0 + _idx_0 = _idx_0 + 1 + else + _tab_0[_key_0] = _value_0 + end + end + _tab_0[#_tab_0 + 1] = "and" + _tab_0[#_tab_0 + 1] = "toes" + lyrics = _tab_0 + end + return assert.same(lyrics, { + "head", + "shoulders", + "knees", + "and", + "toes" + }) + end) + it("should work with metatable creation", function() + local mt = { } + local add + add = function(self, right) + return setmetatable({ + value = self.value + right.value + }, mt) + end + mt.__add = add + local a = setmetatable({ + value = 1 + }, mt) + local b = { + value = 2 + } + setmetatable(b, mt) + local c = a + b + return assert.same(c.value, 3) + end) + it("should support metatable accessing", function() + local tb = setmetatable({ }, { + ["value"] = 123 + }) + getmetatable(tb).__index = getmetatable(tb) + return assert.same(tb.value, 123) + end) + it("should handle metatable destructuring", function() + local tb = setmetatable({ + item = "test", + new = function() + return "created" + end, + }, { + __close = function() + return "closed" + end + }) + local item, new = tb.item, tb.new + local close = getmetatable(tb).__close + assert.same(item, "test") + assert.same(new(), "created") + return assert.same(close(), "closed") + end) + it("should work with string keys directly", function() + local t = { + ["hello world"] = true, + ["test-key"] = "value" + } + assert.is_true(t["hello world"]) + return assert.same(t["test-key"], "value") + end) + it("should support number keys", function() + local t = { + [10] = "ten", + [20] = "twenty" + } + assert.same(t[10], "ten") + return assert.same(t[20], "twenty") + end) + it("should handle empty tables", function() + local empty = { } + return assert.same(#empty, 0) + end) + return it("should work with table literals in function calls", function() + local fn + fn = function(tb) + return tb.x + tb.y + end + local result = fn({ + x = 10, + y = 20 + }) + return assert.same(result, 30) + end) +end) diff --git a/spec/outputs/test/varargs_assignment_spec.lua b/spec/outputs/test/varargs_assignment_spec.lua index 60eab29..4d41404 100644 --- a/spec/outputs/test/varargs_assignment_spec.lua +++ b/spec/outputs/test/varargs_assignment_spec.lua @@ -119,9 +119,9 @@ return describe("varargs assignment", function() end) it("should work with table.unpack", function() local tb = { - a = 1, - b = 2, - c = 3 + 1, + 2, + 3 } local fn fn = function() diff --git a/spec/outputs/test/whitespace_spec.lua b/spec/outputs/test/whitespace_spec.lua new file mode 100644 index 0000000..ca9116e --- /dev/null +++ b/spec/outputs/test/whitespace_spec.lua @@ -0,0 +1,159 @@ +return describe("whitespace", function() + it("should support semicolon statement separator", function() + local a = 1 + local b = 2 + local result = a + b + return assert.same(result, 3) + end) + it("should handle multiple statements on one line", function() + local x = 10 + local y = 20 + local z = x + y + return assert.same(z, 30) + end) + it("should work with semicolon in function", function() + local fn + fn = function() + local a = 1 + local b = 2 + return a + b + end + return assert.same(fn(), 3) + end) + it("should support multiline chaining", function() + local obj = { + value = 10, + add = function(self, n) + self.value = self.value + n + return self + end, + get = function(self) + return self.value + end + } + local result = obj:add(5):add(10):get() + return assert.same(result, 25) + end) + it("should handle multiline method calls", function() + local str = " hello " + local result = str:match("^%s*(.-)%s*$"):upper() + return assert.same(result, "HELLO") + end) + it("should work with nested chaining", function() + local obj = { + level1 = { + level2 = { + level3 = function(self) + return "deep" + end + } + } + } + local result = obj.level1.level2:level3() + return assert.same(result, "deep") + end) + it("should support chaining with conditionals", function() + local obj = { + value = 10, + isPositive = function(self) + return self.value > 0 + end + } + local result = obj:isPositive() + return assert.is_true(result) + end) + it("should work with pipe in chaining", function() + local result = table.concat((function(tb) + local _accum_0 = { } + local _len_0 = 1 + for _index_0 = 1, #tb do + local x = tb[_index_0] + _accum_0[_len_0] = x * 2 + _len_0 = _len_0 + 1 + end + return _accum_0 + end)({ + 1, + 2, + 3 + })) + return assert.same(result, "246") + end) + it("should handle mixed separators", function() + local a = 1 + local b = 2 + local c = 3 + local d = 4 + local result = a + b + c + d + return assert.same(result, 10) + end) + it("should support indentation with spaces", function() + local fn + fn = function() + if true then + local result = 10 + return result + end + end + return assert.same(fn(), 10) + end) + it("should work with consistent indentation", function() + local tb = { + a = 1, + b = 2, + nested = { + c = 3, + d = 4 + } + } + assert.same(tb.a, 1) + return assert.same(tb.nested.c, 3) + end) + it("should handle semicolon with comments", function() + local a = 1 + local b = 2 + local result = a + b + return assert.same(result, 3) + end) + it("should work in multiline function call", function() + local sum + sum = function(a, b) + return a + b + end + local result = sum(5, sum(10, sum(3, 7))) + return assert.same(result, 25) + end) + it("should support chaining in assignment", function() + local obj = { + value = 5, + double = function(self) + return self.value * 2 + end + } + local doubled = obj:double() + return assert.same(doubled, 10) + end) + it("should handle complex chaining", function() + local result = ("hello"):upper():sub(1, 3):lower() + return assert.same(result, "hel") + end) + return it("should work with backcalls and whitespace", function() + local readAsync + readAsync = function(file, callback) + return callback("data") + end + local process + process = function(data) + if data then + return true + end + end + local results + do + results = readAsync("data.txt", function(data) + return process(data) + end) + end + return assert.is_true(true) + end) +end) diff --git a/spec/outputs/test/with_statement_spec.lua b/spec/outputs/test/with_statement_spec.lua new file mode 100644 index 0000000..dcd2aa1 --- /dev/null +++ b/spec/outputs/test/with_statement_spec.lua @@ -0,0 +1,279 @@ +return describe("with statement", function() + it("should access properties with dot", function() + local obj = { + x = 10, + y = 20 + } + local result = nil + do + result = obj.x + obj.y + end + return assert.same(result, 30) + end) + it("should chain property access", function() + local obj = { + nested = { + value = 42 + } + } + local result = nil + do + result = obj.nested.value + end + return assert.same(result, 42) + end) + it("should work with method calls", function() + local obj = { + value = 10, + double = function(self) + return self.value * 2 + end + } + local result = nil + do + result = obj:double() + end + return assert.same(result, 20) + end) + it("should handle nested with statements", function() + local obj = { + x = 1 + } + obj.x = 10 + local _with_0 = { + y = 2 + } + obj.nested = _with_0 + _with_0.y = 20 + assert.same(obj.x, 10) + return assert.same(obj.nested.y, 20) + end) + it("should work in expressions", function() + local obj = { + value = 5 + } + local result + do + local _accum_0 + repeat + _accum_0 = obj.value * 2 + break + until true + result = _accum_0 + end + return assert.same(result, 10) + end) + it("should support multiple statements", function() + local obj = { + a = 1, + b = 2 + } + local sum = nil + local product = nil + do + sum = obj.a + obj.b + product = obj.a * obj.b + end + assert.same(sum, 3) + return assert.same(product, 2) + end) + it("should work with table manipulation", function() + local obj = { + items = { + 1, + 2, + 3 + } + } + table.insert(obj.items, 4) + return assert.same(#obj.items, 4) + end) + it("should handle conditional inside with", function() + local obj = { + value = 10 + } + local result = nil + if obj.value > 5 then + result = "large" + else + result = "small" + end + return assert.same(result, "large") + end) + it("should work with loops", function() + local obj = { + items = { + 1, + 2, + 3 + } + } + local sum = nil + do + sum = 0 + local _list_0 = obj.items + for _index_0 = 1, #_list_0 do + local item = _list_0[_index_0] + sum = sum + item + end + end + return assert.same(sum, 6) + end) + it("should support with in assignment", function() + local obj = { + x = 5, + y = 10 + } + local result + do + local _accum_0 + repeat + _accum_0 = obj.x + obj.y + break + until true + result = _accum_0 + end + return assert.same(result, 15) + end) + it("should work with string methods", function() + local s = "hello" + local result + do + local _accum_0 + repeat + _accum_0 = s:upper() + break + until true + result = _accum_0 + end + return assert.same(result, "HELLO") + end) + it("should handle metatable access", function() + local obj = setmetatable({ + value = 10 + }, { + __index = { + extra = 5 + } + }) + local sum = nil + do + sum = obj.value + getmetatable(obj).__index.extra + end + return assert.same(sum, 15) + end) + it("should work in function", function() + local fn + fn = function() + local obj = { + x = 10 + } + local _val_0 + local _accum_0 + repeat + _accum_0 = obj.x * 2 + break + until true + _val_0 = _accum_0 + return _val_0 + end + local result = fn() + return assert.same(result, 20) + end) + it("should support with in return", function() + local get_value + get_value = function() + local obj = { + value = 42 + } + local _val_0 + local _accum_0 + repeat + _accum_0 = obj.value + break + until true + _val_0 = _accum_0 + return _val_0 + end + return assert.same(get_value(), 42) + end) + it("should work with existential operator", function() + local obj = { + value = 10 + } + local result + do + local _accum_0 + repeat + local _exp_0 = obj.value + if _exp_0 ~= nil then + _accum_0 = _exp_0 + else + _accum_0 = 0 + end + break + until true + result = _accum_0 + end + return assert.same(result, 10) + end) + it("should handle nil object safely", function() + local result + do + local _with_0 = nil + do + local _accum_0 + repeat + if _with_0 ~= nil then + _accum_0 = _with_0.value + break + end + until true + result = _accum_0 + end + end + return assert.same(result, nil) + end) + it("should work with method chaining", function() + local obj = { + value = 5, + add = function(self, n) + self.value = self.value + n + end, + get = function(self) + return self.value + end + } + local result + do + local _accum_0 + repeat + obj:add(10) + obj:add(5) + _accum_0 = obj:get() + break + until true + result = _accum_0 + end + return assert.same(result, 20) + end) + return it("should support nested property access", function() + local obj = { + level1 = { + level2 = { + level3 = "deep" + } + } + } + local result + do + local _accum_0 + repeat + _accum_0 = obj.level1.level2.level3 + break + until true + result = _accum_0 + end + return assert.same(result, "deep") + end) +end) diff --git a/spec/outputs/test/yaml_string_spec.lua b/spec/outputs/test/yaml_string_spec.lua index 258ab92..e95ab55 100644 --- a/spec/outputs/test/yaml_string_spec.lua +++ b/spec/outputs/test/yaml_string_spec.lua @@ -1,13 +1,13 @@ return describe("yaml string", function() it("should create basic yaml string", function() local s = "hello\nworld" - assert.is_true(s:match("hello")) - return assert.is_true(s:match("world")) + assert.is_true((s:match("hello") ~= nil)) + return assert.is_true((s:match("world") ~= nil)) end) it("should preserve indentation", function() local s = "key1: value1\nkey2: value2" - assert.is_true(s:match("key1")) - return assert.is_true(s:match("key2")) + assert.is_true((s:match("key1") ~= nil)) + return assert.is_true((s:match("key2") ~= nil)) end) it("should support interpolation", function() local name = "test" @@ -17,22 +17,23 @@ return describe("yaml string", function() it("should handle complex interpolation", function() local x, y = 10, 20 local s = "point:\n\tx: " .. tostring(x) .. "\n\ty: " .. tostring(y) - assert.is_true(s:match("x: 10")) - return assert.is_true(s:match("y: 20")) + assert.is_true((s:match("x: 10") ~= nil)) + return assert.is_true((s:match("y: 20") ~= nil)) end) it("should work with expressions", function() local s = "result: " .. tostring(1 + 2) - return assert.is_true(s:match("result: 3")) + return assert.is_true((s:match("result: 3") ~= nil)) end) it("should support multiline with variables", function() local config = "database:\n\thost: localhost\n\tport: 5432\n\tname: mydb" - assert.is_true(config:match("database:")) - return assert.is_true(config:match("host:")) + assert.is_true((config:match("database:") ~= nil)) + return assert.is_true((config:match("host:") ~= nil)) end) it("should escape special characters", function() + local Hello = "Hello" local s = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" - assert.is_true(s:match("path:")) - return assert.is_true(s:match("note:")) + return assert.same(s, [[path: "C:\Program Files\App" +note: 'He said: "Hello!"']]) end) it("should work in function", function() local fn @@ -41,8 +42,7 @@ return describe("yaml string", function() return str end local result = fn() - assert.is_true(result:match("foo:")) - return assert.is_true(result:match("bar:")) + return assert.same(result, "foo:\n\tbar: baz") end) it("should strip common leading whitespace", function() local fn @@ -51,36 +51,34 @@ return describe("yaml string", function() return s end local result = fn() - assert.is_true(result:match("nested:")) - return assert.is_true(result:match("item:")) + return assert.same(result, "nested:\n item: value") end) it("should support empty lines", function() local s = "line1\nline3" - assert.is_true(s:match("line1")) - return assert.is_true(s:match("line3")) + return assert.same(s, "line1\nline3") end) it("should work with table access in interpolation", function() local t = { value = 100 } local s = "value: " .. tostring(t.value) - return assert.is_true(s:match("value: 100")) + return assert.same(s, "value: 100") end) it("should support function calls in interpolation", function() local s = "result: " .. tostring((function() return 42 end)()) - return assert.is_true(s:match("result: 42")) + return assert.same(s, "result: 42") end) it("should handle quotes correctly", function() local s = "\"quoted\"\n'single quoted'" - assert.is_true(s:match('"quoted"')) - return assert.is_true(s:match("'single quoted'")) + assert.is_true((s:match('"quoted"') ~= nil)) + return assert.is_true((s:match("'single quoted'") ~= nil)) end) it("should work with multiple interpolations", function() local a, b, c = 1, 2, 3 local s = "values: " .. tostring(a) .. ", " .. tostring(b) .. ", " .. tostring(c) - return assert.is_true(s:match("values: 1, 2, 3")) + return assert.same(s, "values: 1, 2, 3") end) return it("should preserve newlines", function() local s = "first line\nsecond line\nthird line" diff --git a/spec/outputs/unicode/string.lua b/spec/outputs/unicode/string.lua index 6bfb033..2fbf0fa 100644 --- a/spec/outputs/unicode/string.lua +++ b/spec/outputs/unicode/string.lua @@ -33,21 +33,21 @@ _u53d8_u91cfa = '你好 #{问候} 你好' _u53d8_u91cfb = '#{问候} 你好' _u53d8_u91cfc = '你好 #{问候}' local _u53d8_u91cf_ = "你好" -local _call_0 = ("你好") +local _call_0 = "你好" _call_0["格式"](_call_0, 1) -local _call_1 = ("你好") +local _call_1 = "你好" _call_1["格式"](_call_1, 1, 2, 3) -local _call_2 = ("你好") +local _call_2 = "你好" _call_2["格式"](_call_2, 1, 2, 3)(1, 2, 3) -local _call_3 = ("你好") +local _call_3 = "你好" _call_3["世界"](_call_3) -local _call_4 = ("你好") +local _call_4 = "你好" _call_4["格式"](_call_4)["问候"](1, 2, 3) -local _call_5 = ("你好") +local _call_5 = "你好" _call_5["格式"](_call_5, 1, 2, 3) local _call_6 = _u67d0_u4e8b("你好") _call_6["世界"](_call_6) return _u67d0_u4e8b((function() - local _call_7 = ("你好") + local _call_7 = "你好" return _call_7["世界"](_call_7) end)()) diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua index f5d5d8a..e897475 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua @@ -77,7 +77,7 @@ _ = _call_2["变量b"](_call_2) _ = f("")["变量c"]() f(("")[_u53d8_u91cfa]) f((function() - local _call_3 = ("") + local _call_3 = "" return _call_3["变量b"](_call_3) end)()) f(("")["变量c"]()) -- cgit v1.2.3-55-g6feb