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/inputs/syntax.yue | 4 +- spec/inputs/test/advanced_macro_spec.yue | 36 ++- spec/inputs/test/close_attribute_spec.yue | 5 +- spec/inputs/test/const_attribute_spec.yue | 20 +- spec/inputs/test/do_statement_spec.yue | 22 +- spec/inputs/test/functions_advanced_spec.yue | 22 +- spec/inputs/test/implicit_object_spec.yue | 4 +- spec/inputs/test/in_expression_spec.yue | 17 +- spec/inputs/test/multiline_args_spec.yue | 52 ++-- spec/inputs/test/named_varargs_spec.yue | 9 +- spec/inputs/test/operator_advanced_spec.yue | 6 +- spec/inputs/test/param_destructure_spec.yue | 20 +- spec/inputs/test/reverse_index_spec.yue | 4 - spec/inputs/test/slicing_spec.yue | 22 +- spec/inputs/test/stub_spec.yue | 3 + spec/inputs/test/table_append_spec.yue | 8 +- spec/inputs/test/table_comprehension_spec.yue | 2 +- spec/inputs/test/tables_advanced_spec.yue | 13 +- spec/inputs/test/varargs_assignment_spec.yue | 2 +- spec/inputs/test/whitespace_spec.yue | 17 +- spec/inputs/test/with_statement_spec.yue | 22 +- spec/inputs/test/yaml_string_spec.yue | 44 +-- spec/inputs/unicode/syntax.yue | 4 +- 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 +- 46 files changed, 3760 insertions(+), 331 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') diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index a63f629..ccf8b01 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue @@ -84,11 +84,11 @@ _ = here(we)"go"[12123] split"abc xyz 123"\map"#"\printAll! -_ = f""[a] +_ = f("")[a] _ = f""\b! _ = f"".c! -f ""[a] +f ("")[a] f ""\b! f "".c! diff --git a/spec/inputs/test/advanced_macro_spec.yue b/spec/inputs/test/advanced_macro_spec.yue index 3d7b10a..d88807f 100644 --- a/spec/inputs/test/advanced_macro_spec.yue +++ b/spec/inputs/test/advanced_macro_spec.yue @@ -15,7 +15,10 @@ describe "advanced macro", -> assert.same result, "hello world" it "should work with conditional compilation", -> + global debugMode = true + $ -> global debugMode = true macro config = (debugging) -> + assert debugMode? global debugMode = debugging == "true" "" @@ -23,7 +26,7 @@ describe "advanced macro", -> assert.is_true debugMode $config false - assert.is_false debugMode + assert.is_true debugMode it "should support macro generating conditional code", -> macro asserts = (cond) -> @@ -39,20 +42,24 @@ describe "advanced macro", -> :code type: "lua" } - - $luaCode "local macro_test_var = 42" + macro_test_var = 42 + $luaCode [[local macro_test_var = 99]] assert.same macro_test_var, 42 it "should support multi-line raw lua", -> macro lua = (code) -> { :code - type: "lua" + type: "text" + locals: ["multiline_var1",] } + multiline_var = "test" $lua[==[ - local multiline_var = "test" + multiline_var = "test work" + local multiline_var1 = "test1" ]==] - assert.same multiline_var, "test" + assert.same multiline_var, "test work" + assert.same multiline_var1, "test1" it "should export macro from module", -> -- This test demonstrates macro export syntax @@ -116,10 +123,14 @@ describe "advanced macro", -> assert.same result, "Red" it "should handle complex macro logic", -> - macro smart_print = (items) -> - "print(#{table.concat [item for item in *items], ', ')})" + my_print = (...) -> ... + macro smart_print = (...items) -> + "my_print(#{table.concat [item for item in *items], ', '})" - $smart_print {"hello", "world", 123} + a, b, c = $smart_print "hello", "world", 123 + assert.same a, "hello" + assert.same b, "world" + assert.same c, 123 it "should work with table manipulation", -> macro create_table = (...) -> @@ -130,12 +141,7 @@ describe "advanced macro", -> assert.same result, {"1", "2", "3"} it "should support string concatenation in macro", -> - macro concat = (...) -> - args = {...} - res = {} - for arg in *args - table.insert res, tostring arg - "'" .. table.concat(res, " .. ") .. "'" + macro concat = (...) -> table.concat {...}, " .. " result = $concat "hello", "world" assert.same result, "helloworld" diff --git a/spec/inputs/test/close_attribute_spec.yue b/spec/inputs/test/close_attribute_spec.yue index 2354df7..ebda27e 100644 --- a/spec/inputs/test/close_attribute_spec.yue +++ b/spec/inputs/test/close_attribute_spec.yue @@ -43,7 +43,7 @@ describe "close attribute", -> closed = false obj = value: 10 - close_method: : => + : => closed = true do @@ -82,9 +82,8 @@ describe "close attribute", -> it "should work with table destructuring", -> closed = false - tb = {close: : -> closed = true} do - {:close} = tb + close tb = {: -> closed = true} assert.is_true closed it "should handle close with return value", -> diff --git a/spec/inputs/test/const_attribute_spec.yue b/spec/inputs/test/const_attribute_spec.yue index e3cc638..24ced21 100644 --- a/spec/inputs/test/const_attribute_spec.yue +++ b/spec/inputs/test/const_attribute_spec.yue @@ -13,7 +13,7 @@ describe "const attribute", -> assert.same name, "test" it "should support const with destructuring", -> - tb = {a: 1, b: 2, c: 3, d: 4} + tb = {a: 1, b: 2, 3, 4} const {:a, :b, c, d} = tb assert.same a, 1 assert.same b, 2 @@ -46,7 +46,7 @@ describe "const attribute", -> it "should handle const functions", -> const add = (a, b) -> a + b - assert.same add 5, 10, 15 + assert.same add(5, 10), 15 it "should work with const tables", -> const config = { @@ -74,28 +74,12 @@ describe "const attribute", -> const calculated = 10 + 20 assert.same calculated, 30 - it "should support const with prefixed return", -> - getDefault: const "default" -> - return nil - - result = getDefault! - assert.same result, nil - it "should work in table comprehension", -> const multiplier = 2 items = [1, 2, 3] result = [item * multiplier for item in *items] assert.same result, {2, 4, 6} - it "should handle const with fat arrow", -> - obj = - value: 100 - getValue: const => - @value - - result = obj\getValue! - assert.same result, 100 - it "should work with complex expressions", -> const complex = { data: [1, 2, 3] diff --git a/spec/inputs/test/do_statement_spec.yue b/spec/inputs/test/do_statement_spec.yue index 0adad20..2611cba 100644 --- a/spec/inputs/test/do_statement_spec.yue +++ b/spec/inputs/test/do_statement_spec.yue @@ -62,7 +62,7 @@ describe "do statement", -> it "should support variable shadowing", -> x = "outer" result = do - x = "inner" + local x = "inner" x assert.same result, "inner" assert.same x, "outer" @@ -74,7 +74,7 @@ describe "do statement", -> result = do with obj - \double! + break \double! assert.same result, 20 it "should handle comprehensions in do block", -> @@ -84,13 +84,13 @@ describe "do statement", -> assert.same result, {2, 4, 6, 8, 10} it "should work with try-catch", -> - result = do - success = try - error "test error" - false - catch err - true - assert.is_true success + success, result = try + error "test error" + false + catch err + true + assert.is_false success + assert.is_true result it "should support return statement", -> fn = -> @@ -125,13 +125,15 @@ describe "do statement", -> it "should support implicit return", -> result = do value = 42 + value assert.same result, 42 it "should handle empty do block", -> - result = do + result = do nil assert.same result, nil it "should work with backcalls", -> + map = (f, items) -> [f item for item in *items] result = do items = [1, 2, 3] (x) <- map _, items diff --git a/spec/inputs/test/functions_advanced_spec.yue b/spec/inputs/test/functions_advanced_spec.yue index d0e0cf5..32f0718 100644 --- a/spec/inputs/test/functions_advanced_spec.yue +++ b/spec/inputs/test/functions_advanced_spec.yue @@ -19,32 +19,32 @@ describe "advanced functions", -> x + y assert.same fn!, 1200 - assert.same fn(50), 1150 + assert.same fn(50), 1100 it "should work with multi-line arguments", -> my_func = (a, b, c, d, e, f) -> a + b + c + d + e + f result = my_func 5, 4, 3, 8, 9, 10 assert.same result, 39 - + it "should support nested function calls", -> + another_func = (a, b, c, d, e, f) -> a + b + c + d + e + f + my_func = (a, b, c, d, e, f, g) -> a + b + c + d + e + f + g + result = my_func 5, 6, 7, 6, another_func 6, 7, 8, 9, 1, 2, 5, 4 - - another_func = (a, b, c, d, e, f) -> a + b + c + d + e + f - my_func = (a, b, c, d, e, f) -> a + b + c + d + e + f - - assert.same result, 52 + + assert.same result, 66 it "should handle implicit return", -> sum = (x, y) -> x + y - assert.same sum 10, 20, 30 + assert.same sum(10, 20), 30 it "should work with explicit return", -> difference = (x, y) -> return x - y - assert.same difference 20, 10, 10 + assert.same difference(20, 10), 10 it "should support multiple return values", -> mystery = (x, y) -> x + y, x - y @@ -85,7 +85,7 @@ describe "advanced functions", -> assert.same fn(1, 2, 3), 3 it "should support prefixed return", -> - findValue: "not found" -> + findValue = (): "not found" -> items = [1, 2, 3] for item in *items if item == 5 @@ -155,4 +155,4 @@ describe "advanced functions", -> -> 0 add = get_operation "add" - assert.same add 5, 3, 8 + assert.same add(5, 3), 8 diff --git a/spec/inputs/test/implicit_object_spec.yue b/spec/inputs/test/implicit_object_spec.yue index cea926e..a0bd331 100644 --- a/spec/inputs/test/implicit_object_spec.yue +++ b/spec/inputs/test/implicit_object_spec.yue @@ -142,9 +142,9 @@ describe "implicit object", -> it "should handle empty implicit object", -> tb = items: - - + - nil - assert.same tb.items, {nil} + assert.same tb, {items: [nil,]} it "should work in function arguments", -> fn = (items) -> #items diff --git a/spec/inputs/test/in_expression_spec.yue b/spec/inputs/test/in_expression_spec.yue index c1f4099..d9e3aec 100644 --- a/spec/inputs/test/in_expression_spec.yue +++ b/spec/inputs/test/in_expression_spec.yue @@ -9,11 +9,11 @@ describe "in expression", -> assert.is_true "b" in chars assert.is_false "z" in chars - it "should check keys in table", -> - obj = {x: 1, y: 2, z: 3} - assert.is_true "x" in obj - assert.is_true "y" in obj - assert.is_false "w" in obj + it "should check in table literal", -> + x = 1; y = 2; z = 3; w = 4 + assert.is_true x in [x, y, z] + assert.is_true y in [x, y, z] + assert.is_false w in [x, y, z] it "should work with mixed types", -> items = {1, "two", true, nil} @@ -41,7 +41,8 @@ describe "in expression", -> assert.is_false not (2 in items) it "should work with nested tables", -> - nested = {{1, 2}, {3, 4}, {5, 6}} + eq = (other) => @[1] == other[1] and @[2] == other[2] + nested = {{1, 2, :}, {3, 4, :}, {5, 6, :}} assert.is_true {1, 2} in nested assert.is_false {1, 3} in nested @@ -60,7 +61,7 @@ describe "in expression", -> it "should support table as value", -> key1 = {a: 1} key2 = {b: 2} - tb = {[key1]: "first", [key2]: "second"} + tb = [key1, key2] -- Note: this tests table reference equality assert.is_true key1 in tb @@ -77,7 +78,7 @@ describe "in expression", -> assert.is_true 1 in items it "should work with string keys", -> - obj = {name: "test", value: 42} + obj = ["name", "value"] assert.is_true "name" in obj assert.is_true "value" in obj assert.is_false "missing" in obj diff --git a/spec/inputs/test/multiline_args_spec.yue b/spec/inputs/test/multiline_args_spec.yue index bbb06f9..add9d2b 100644 --- a/spec/inputs/test/multiline_args_spec.yue +++ b/spec/inputs/test/multiline_args_spec.yue @@ -1,6 +1,6 @@ describe "multiline arguments", -> it "should split arguments across lines", -> - sum = (a, b, c) -> a + b + c + sum = (a, b, c, d, e, f) -> a + b + c + d + e + f result = sum 5, 4, 3, 8, 9, 10 assert.same result, 39 @@ -42,46 +42,46 @@ describe "multiline arguments", -> assert.same result, {1, 2, 3, 4, 9, 8, 9, 10} it "should handle deeply nested indentation", -> - y = [ fn 1, 2, 3, - 4, 5, - 5, 6, 7 - ] - - -- Create the function first + -- Create function first fn = (a, b, c, d, e, f, g) -> a + b + c + d + e + f + g + y = { fn 1, 2, 3, + 4, + 5, 6, 7 + } result = y[1] - assert.same result, 22 + assert.same result, 28 it "should work with conditional statements", -> - fn = (a, b, c, d, e) -> a + b + c + d + e - - result = if fn 1, 2, 3, - "hello", - "world" - "yes" - else - "no" + fn = (a, b, c, d, e, f) -> a + b + c + d + e + f + result1 = fn 1, 2, 3, + 4, 5, + 6 + + result = if result1 > 20 + "yes" + else + "no" assert.same result, "yes" it "should support function expressions", -> - double = (x) -> x * 2 - result = double 5, + doublePlus = (x, y) -> x * 2 + y + result = doublePlus 5, 10 assert.same result, 20 it "should handle chained function calls", -> - add = (a, b) -> a + b - multiply = (a, b) -> a * b - - result = multiply add 1, 2, - add 3, 4 - assert.same result, 21 + add = (a, b, c, d) -> a + b + c + d + multiply = (a, b, c, d) -> a * b * c * d + + result = multiply 1, 2, + 3, 4 + assert.same result, 24 it "should work with method calls", -> obj = value: 10 - add: (a, b) => @value + a + b + add: (a, b, c) => @value + a + b + c result = obj\add 5, 10, 15 @@ -100,7 +100,7 @@ describe "multiline arguments", -> assert.same result, 45 it "should work with return statement", -> - fn = (a, b) -> a + b + fn = (a, b, c) -> a + b + c get_value = -> return fn 10, 20, 30 diff --git a/spec/inputs/test/named_varargs_spec.yue b/spec/inputs/test/named_varargs_spec.yue index a5ab2b1..29869b5 100644 --- a/spec/inputs/test/named_varargs_spec.yue +++ b/spec/inputs/test/named_varargs_spec.yue @@ -97,12 +97,11 @@ describe "named varargs", -> assert.same result, {"a", "b", "c"} it "should support passing named varargs to another function", -> + inner = (...) -> + {...} outer = (...t) -> - inner (table.unpack t) - - inner = (a, b, c) -> - {a, b, c} - + inner t[1], t[2], t[3] + result = outer 1, 2, 3 assert.same result, {1, 2, 3} diff --git a/spec/inputs/test/operator_advanced_spec.yue b/spec/inputs/test/operator_advanced_spec.yue index 8127fd4..8f88d17 100644 --- a/spec/inputs/test/operator_advanced_spec.yue +++ b/spec/inputs/test/operator_advanced_spec.yue @@ -75,7 +75,7 @@ describe "advanced operators", -> it "should handle compound bitwise xor", -> x = 12 -- 1100 in binary - x ~= 10 -- 1010 in binary + x = x~10 -- 1010 in binary assert.same x, 6 -- 0110 in binary it "should work with compound left shift", -> @@ -121,10 +121,10 @@ describe "advanced operators", -> it "should work with :: for method chaining", -> obj = value: 10 - add: (n) => @value += n + add: (n): @ => @value += n get: => @value - result = obj::add 5::get! + result = obj::add(5)::get! assert.same result, 15 it "should handle complex expressions with precedence", -> diff --git a/spec/inputs/test/param_destructure_spec.yue b/spec/inputs/test/param_destructure_spec.yue index 4659031..5b9ef83 100644 --- a/spec/inputs/test/param_destructure_spec.yue +++ b/spec/inputs/test/param_destructure_spec.yue @@ -38,10 +38,10 @@ describe "parameter destructuring", -> assert.same result, {1, 2, 3} it "should support mixed array and object", -> - f = ([first], {key: :value}) -> + f = ([first,], {key: :value}) -> {first, value} - result = f [1], {key: "test"} + result = f [1,], {key: value: "test"} assert.same result, {1, "test"} it "should work with fat arrow", -> @@ -54,7 +54,7 @@ describe "parameter destructuring", -> assert.same result, 130 it "should handle missing keys", -> - f = (:a, :b = "default", :c = "missing") -> + f = ({:a, :b = "default", :c = "missing"}) -> {a, b, c} result = f a: 1 @@ -89,10 +89,10 @@ describe "parameter destructuring", -> assert.same result, {1, {2, 3, 4}} it "should support spreading", -> - f = (...rest, :last) -> + f = ({...rest, :last}) -> {rest, last} - - result = f 1, 2, 3, {last: "final"} + + result = f {1, 2, 3, last: "final"} assert.same result, {{1, 2, 3}, 'final'} it "should work with table comprehensions", -> @@ -103,8 +103,8 @@ describe "parameter destructuring", -> assert.same result, {2, 4, 6} it "should handle nil arguments", -> - f = (:a = "nil_a", :b = "nil_b") -> + f = ({:a = "nil_a", :b = "nil_b"}) -> {a, b} - - result = f nil, nil - assert.same result, {'nil_a', 'nil_b'} + + result = f {} + assert.same result, {"nil_a", "nil_b"} diff --git a/spec/inputs/test/reverse_index_spec.yue b/spec/inputs/test/reverse_index_spec.yue index be67261..3c17d09 100644 --- a/spec/inputs/test/reverse_index_spec.yue +++ b/spec/inputs/test/reverse_index_spec.yue @@ -42,10 +42,6 @@ describe "reverse index", -> last = data.items.nested[#] assert.same last, 3 - it "should work with string", -> - s = "hello" - assert.same s[#], "o" - it "should handle negative offsets", -> tab = [1, 2, 3, 4, 5] assert.same tab[#-3], 2 diff --git a/spec/inputs/test/slicing_spec.yue b/spec/inputs/test/slicing_spec.yue index b0a686b..2f5b1a7 100644 --- a/spec/inputs/test/slicing_spec.yue +++ b/spec/inputs/test/slicing_spec.yue @@ -1,27 +1,27 @@ describe "slicing", -> it "should slice array with basic syntax", -> items = [1, 2, 3, 4, 5] - result = items[1..3] + result = items[1, 3] assert.same result, {1, 2, 3} it "should slice from beginning", -> items = [1, 2, 3, 4, 5] - result = items[1..#items] + result = items[1, #items] assert.same result, {1, 2, 3, 4, 5} it "should slice to end", -> items = [1, 2, 3, 4, 5] - result = items[3..5] + result = items[3, 5] assert.same result, {3, 4, 5} it "should handle negative indices", -> items = [1, 2, 3, 4, 5] - result = items[#items-2..#items] + result = items[-3, -1] assert.same result, {3, 4, 5} it "should slice single element", -> items = [1, 2, 3, 4, 5] - result = items[2..2] + result = items[2, 2] assert.same result, {2} it "should work with strings", -> @@ -31,18 +31,18 @@ describe "slicing", -> it "should handle out of bounds", -> items = [1, 2, 3] - result = items[1..10] + result = items[1, 10] assert.same result, {1, 2, 3} it "should create new table", -> original = [1, 2, 3, 4, 5] - sliced = original[2..4] + sliced = original[2, 4] sliced[1] = 99 assert.same original[2], 2 -- original unchanged it "should work with nested arrays", -> - nested = [[1, 2], [3, 4], [5, 6]] - result = nested[1..2] + nested = [ [1, 2], [3, 4], [5, 6]] + result = nested[1, 2] assert.same result, {{1, 2}, {3, 4}} it "should slice with step simulation", -> @@ -52,8 +52,8 @@ describe "slicing", -> it "should handle empty slice range", -> items = [1, 2, 3, 4, 5] - result = items[6..10] - assert.same result, nil + result = items[6, 10] + assert.same result, {} it "should work with reverse indexing", -> items = [1, 2, 3, 4, 5] diff --git a/spec/inputs/test/stub_spec.yue b/spec/inputs/test/stub_spec.yue index 99345c7..835610b 100644 --- a/spec/inputs/test/stub_spec.yue +++ b/spec/inputs/test/stub_spec.yue @@ -1,3 +1,6 @@ +-- Define stub_fn as a helper function that returns an empty function +stub_fn = -> -> + describe "function stub", -> it "should create empty function", -> stub_fn! diff --git a/spec/inputs/test/table_append_spec.yue b/spec/inputs/test/table_append_spec.yue index ab3d6d2..51c7873 100644 --- a/spec/inputs/test/table_append_spec.yue +++ b/spec/inputs/test/table_append_spec.yue @@ -30,12 +30,12 @@ describe "table append", -> tab[] = ...tb2 assert.same tab, {1, 2} - it "should append nil values", -> + it "should not append nil values", -> tab = [] tab[] = nil tab[] = "value" - assert.same tab[1], nil - assert.same tab[2], "value" + assert.same tab[2], nil + assert.same tab[1], "value" it "should work in loop", -> tab = [] @@ -73,5 +73,5 @@ describe "table append", -> it "should append function results", -> fn = -> 1, 2, 3 tab = [] - tab[] = fn! + tab[] = ...[fn!,] assert.same tab, {1, 2, 3} diff --git a/spec/inputs/test/table_comprehension_spec.yue b/spec/inputs/test/table_comprehension_spec.yue index f4d7cdb..caebdef 100644 --- a/spec/inputs/test/table_comprehension_spec.yue +++ b/spec/inputs/test/table_comprehension_spec.yue @@ -112,7 +112,7 @@ describe "table comprehension", -> assert.same result.e, nil it "should work with custom iterator", -> - custom_iter = -> -> + custom_iter = -> state = 0 -> state += 1 diff --git a/spec/inputs/test/tables_advanced_spec.yue b/spec/inputs/test/tables_advanced_spec.yue index c8cc7d5..82f4d4e 100644 --- a/spec/inputs/test/tables_advanced_spec.yue +++ b/spec/inputs/test/tables_advanced_spec.yue @@ -35,8 +35,9 @@ describe "advanced tables", -> assert.same tb[4], 4 it "should work with single line table literals", -> - my_function dance: "Tango", partner: "none" - assert.is_true true + tb = dance: "Tango", partner: "none" + assert.same tb.dance, "Tango" + assert.same tb.partner, "none" it "should support nested tables", -> tb = @@ -90,10 +91,9 @@ describe "advanced tables", -> assert.same merge.y, 1 it "should handle mixed spread", -> - parts = { + parts = * "shoulders" * "knees" - } lyrics = * "head" * ...parts @@ -108,7 +108,7 @@ describe "advanced tables", -> a = <>: mt, value: 1 b = value: 2 - b.<>, mt + b.<> = mt c = a + b assert.same c.value, 3 @@ -121,11 +121,12 @@ describe "advanced tables", -> tb = { item: "test" new: -> "created" - close: -> "closed" + : -> "closed" } {:item, :new, :} = tb assert.same item, "test" assert.same new!, "created" + assert.same close!, "closed" it "should work with string keys directly", -> t = { diff --git a/spec/inputs/test/varargs_assignment_spec.yue b/spec/inputs/test/varargs_assignment_spec.yue index 1c3b627..dfd606b 100644 --- a/spec/inputs/test/varargs_assignment_spec.yue +++ b/spec/inputs/test/varargs_assignment_spec.yue @@ -46,7 +46,7 @@ describe "varargs assignment", -> assert.same select(3, ...), 2 it "should work with table.unpack", -> - tb = {a: 1, b: 2, c: 3} + tb = [1, 2, 3] fn = -> table.unpack tb ... = fn! count = select '#', ... diff --git a/spec/inputs/test/whitespace_spec.yue b/spec/inputs/test/whitespace_spec.yue index baf3fd5..43b7644 100644 --- a/spec/inputs/test/whitespace_spec.yue +++ b/spec/inputs/test/whitespace_spec.yue @@ -8,13 +8,14 @@ describe "whitespace", -> assert.same z, 30 it "should work with semicolon in function", -> - fn = -> a = 1; b = 2; a + b + fn = -> + a = 1; b = 2; a + b assert.same fn!, 3 it "should support multiline chaining", -> obj = value: 10 - add: (n) => @value += n + add: (n): @ => @value += n get: => @value result = obj @@ -26,7 +27,7 @@ describe "whitespace", -> it "should handle multiline method calls", -> str = " hello " result = str - \trim! + \match "^%s*(.-)%s*$" \upper! assert.same result, "HELLO" @@ -53,7 +54,7 @@ describe "whitespace", -> it "should work with pipe in chaining", -> result = [1, 2, 3] - |> [x * 2 for x in *] + |> ((tb) -> [x * 2 for x in *tb]) |> table.concat assert.same result, "246" @@ -68,7 +69,7 @@ describe "whitespace", -> fn = -> if true result = 10 - result + result assert.same fn!, 10 @@ -91,7 +92,7 @@ describe "whitespace", -> it "should work in multiline function call", -> sum = (a, b) -> a + b - result = sum 5, 10, + result = sum 5, sum 10, sum 3, 7 assert.same result, 25 @@ -105,13 +106,15 @@ describe "whitespace", -> assert.same doubled, 10 it "should handle complex chaining", -> - result = "hello" + result = ("hello") \upper! \sub 1, 3 \lower! assert.same result, "hel" it "should work with backcalls and whitespace", -> + readAsync = (file, callback) -> callback "data" + process = (data) -> true if data results = do data <- readAsync "data.txt" process data diff --git a/spec/inputs/test/with_statement_spec.yue b/spec/inputs/test/with_statement_spec.yue index c2f9b3b..71ac215 100644 --- a/spec/inputs/test/with_statement_spec.yue +++ b/spec/inputs/test/with_statement_spec.yue @@ -27,7 +27,7 @@ describe "with statement", -> obj = {x: 1} with obj .x = 10 - with .nested = {y: 2} + with .nested := {y: 2} .y = 20 assert.same obj.x, 10 assert.same obj.nested.y, 20 @@ -35,7 +35,7 @@ describe "with statement", -> it "should work in expressions", -> obj = {value: 5} result = with obj - .value * 2 + break .value * 2 assert.same result, 10 it "should support multiple statements", -> @@ -76,13 +76,13 @@ describe "with statement", -> it "should support with in assignment", -> obj = {x: 5, y: 10} result = with obj - .x + .y + break .x + .y assert.same result, 15 it "should work with string methods", -> s = "hello" result = with s - \upper! + break \upper! assert.same result, "HELLO" it "should handle metatable access", -> @@ -98,7 +98,7 @@ describe "with statement", -> fn = -> obj = {x: 10} with obj - .x * 2 + break .x * 2 result = fn! assert.same result, 20 @@ -107,19 +107,19 @@ describe "with statement", -> get_value = -> obj = {value: 42} with obj - .value + break .value assert.same get_value!, 42 it "should work with existential operator", -> obj = {value: 10} result = with obj - .value ? 0 + break .value ?? 0 assert.same result, 10 it "should handle nil object safely", -> - result = with nil - .value + result = with? nil + break .value assert.same result, nil it "should work with method chaining", -> @@ -131,7 +131,7 @@ describe "with statement", -> result = with obj \add 10 \add 5 - \get! + break \get! assert.same result, 20 it "should support nested property access", -> @@ -141,5 +141,5 @@ describe "with statement", -> level3: "deep" result = with obj - .level1.level2.level3 + break .level1.level2.level3 assert.same result, "deep" diff --git a/spec/inputs/test/yaml_string_spec.yue b/spec/inputs/test/yaml_string_spec.yue index 1296340..0a7d61b 100644 --- a/spec/inputs/test/yaml_string_spec.yue +++ b/spec/inputs/test/yaml_string_spec.yue @@ -3,15 +3,15 @@ describe "yaml string", -> s = | hello world - assert.is_true s\match "hello" - assert.is_true s\match "world" + assert.is_true s\match("hello")? + assert.is_true s\match("world")? it "should preserve indentation", -> s = | key1: value1 key2: value2 - assert.is_true s\match "key1" - assert.is_true s\match "key2" + assert.is_true s\match("key1")? + assert.is_true s\match("key2")? it "should support interpolation", -> name = "test" @@ -25,13 +25,13 @@ describe "yaml string", -> point: x: #{x} y: #{y} - assert.is_true s\match "x: 10" - assert.is_true s\match "y: 20" + assert.is_true s\match("x: 10")? + assert.is_true s\match("y: 20")? it "should work with expressions", -> s = | result: #{1 + 2} - assert.is_true s\match "result: 3" + assert.is_true s\match("result: 3")? it "should support multiline with variables", -> config = | @@ -39,15 +39,17 @@ describe "yaml string", -> host: localhost port: 5432 name: mydb - assert.is_true config\match "database:" - assert.is_true config\match "host:" + assert.is_true config\match("database:")? + assert.is_true config\match("host:")? it "should escape special characters", -> + Hello = "Hello" s = | path: "C:\Program Files\App" note: 'He said: "#{Hello}!"' - assert.is_true s\match "path:" - assert.is_true s\match "note:" + assert.same s, [[ +path: "C:\Program Files\App" +note: 'He said: "Hello!"']] it "should work in function", -> fn = -> @@ -57,8 +59,7 @@ describe "yaml string", -> return str result = fn! - assert.is_true result\match "foo:" - assert.is_true result\match "bar:" + assert.same result, "foo:\n\tbar: baz" it "should strip common leading whitespace", -> fn = -> @@ -68,40 +69,39 @@ describe "yaml string", -> s result = fn! - assert.is_true result\match "nested:" - assert.is_true result\match "item:" + assert.same result, "nested: + item: value" it "should support empty lines", -> s = | line1 line3 - assert.is_true s\match "line1" - assert.is_true s\match "line3" + assert.same s, "line1\nline3" it "should work with table access in interpolation", -> t = {value: 100} s = | value: #{t.value} - assert.is_true s\match "value: 100" + assert.same s, "value: 100" it "should support function calls in interpolation", -> s = | result: #{(-> 42)!} - assert.is_true s\match "result: 42" + assert.same s, "result: 42" it "should handle quotes correctly", -> s = | "quoted" 'single quoted' - assert.is_true s\match '"quoted"' - assert.is_true s\match "'single quoted'" + assert.is_true s\match('"quoted"')? + assert.is_true s\match("'single quoted'")? it "should work with multiple interpolations", -> a, b, c = 1, 2, 3 s = | values: #{a}, #{b}, #{c} - assert.is_true s\match "values: 1, 2, 3" + assert.same s, "values: 1, 2, 3" it "should preserve newlines", -> s = | diff --git a/spec/inputs/unicode/syntax.yue b/spec/inputs/unicode/syntax.yue index 939579b..b5494f4 100644 --- a/spec/inputs/unicode/syntax.yue +++ b/spec/inputs/unicode/syntax.yue @@ -81,11 +81,11 @@ _ = 这里(我们)"去"[12123] 分裂"abc xyz 123"\映射"#"\打印全部! -_ = f""[变量a] +_ = f("")[变量a] _ = f""\变量b! _ = f"".变量c! -f ""[变量a] +f ("")[变量a] f ""\变量b! f "".变量c! 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