/* Test file for table enhancements Comprehensive test suite for APL-inspired broadcasting and immutable operations Based on design/TABLE_ENHANCEMENTS.md NOTE: This file contains tests for features that have NOT been implemented yet. These tests will fail until the features are implemented. */ /* ===== BASIC TABLE CREATION ===== */ numbers : {1, 2, 3, 4, 5}; person : {name: "Alice", age: 30, active: true}; mixed_table : {a: 1, b: "hello", c: true, d: 42.5}; /* ===== ENHANCED BROADCASTING COMBINATORS ===== */ /* Test enhanced map with APL-inspired broadcasting */ double : x -> x * 2; doubled : map @double numbers; /* Expected: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10} */ square : x -> x * x; squared : map @square numbers; /* Expected: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25} */ /* Test map with mixed data types */ isNumber : x -> typeof x == "number"; type_check : map @isNumber mixed_table; /* Expected: {a: true, b: false, c: false, d: true} */ /* ===== TABLE-SPECIFIC COMBINATORS (t. namespace) ===== */ /* Test t.map for table-specific operations */ t_doubled : t.map @double numbers; /* Expected: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10} */ /* Test t.filter for table filtering */ isEven : x -> x % 2 == 0; even_numbers : t.filter @isEven numbers; /* Expected: {2: 2, 4: 4} */ isPositive : x -> x > 0; positive_numbers : t.filter @isPositive numbers; /* Expected: {1: 1, 2: 2, 3: 3, 4: 4, 5: 5} */ /* Test t.reduce for table reduction */ sum : x y -> x + y; total : t.reduce @sum 0 numbers; /* Expected: 15 */ max : x y -> x > y ? x : y; maximum : t.reduce @max numbers.1 numbers; /* Expected: 5 */ /* ===== IMMUTABLE TABLE OPERATIONS (t. namespace) ===== */ /* Test t.set for immutable updates */ updated_person : t.set person "age" 31; /* Expected: {name: "Alice", age: 31, active: true} */ added_city : t.set person "city" "New York"; /* Expected: {name: "Alice", age: 30, active: true, city: "New York"} */ /* Test t.delete for immutable deletion */ without_age : t.delete person "age"; /* Expected: {name: "Alice", active: true} */ without_nonexistent : t.delete person "email"; /* Expected: {name: "Alice", age: 30, active: true} (unchanged) */ /* Test t.merge for immutable merging */ person2 : {city: "New York", country: "USA"}; merged : t.merge person person2; /* Expected: {name: "Alice", age: 30, active: true, city: "New York", country: "USA"} */ overwrite_merge : t.merge person {age: 25, city: "Boston"}; /* Expected: {name: "Alice", age: 25, active: true, city: "Boston"} */ /* ===== TABLE INFORMATION OPERATIONS (t. namespace) ===== */ /* Test t.pairs for getting key-value pairs */ all_pairs : t.pairs person; /* Expected: [["name", "Alice"], ["age", 30], ["active", true]] */ /* Test t.keys for getting keys */ all_keys : t.keys person; /* Expected: ["name", "age", "active"] */ /* Test t.values for getting values */ all_values : t.values person; /* Expected: ["Alice", 30, true] */ /* Test t.length for getting table size */ table_size : t.length person; /* Expected: 3 */ /* Test t.has for checking key existence */ has_name : t.has person "name"; /* Expected: true */ has_email : t.has person "email"; /* Expected: false */ /* Test t.get for safe property access */ age_or_default : t.get person "age" 0; /* Expected: 30 */ email_or_default : t.get person "email" "unknown"; /* Expected: "unknown" */ /* ===== APL-INSPIRED ELEMENT-WISE OPERATIONS ===== */ /* Test each combinator for multi-argument element-wise operations */ /* No tables - apply normally */ normal_add : each @add 5 3; /* Expected: 8 */ /* Single table - element-wise */ add_ten : x -> x + 10; each_result : each @add_ten numbers; /* Expected: {1: 11, 2: 12, 3: 13, 4: 14, 5: 15} */ /* Mixed table and scalar */ mixed_operation : each @add numbers 10; /* Expected: {1: 11, 2: 12, 3: 13, 4: 14, 5: 15} */ /* Multiple tables */ table1 : {a: 1, b: 2, c: 3}; table2 : {a: 10, b: 20, c: 30}; multi_table_sum : each @add table1 table2; /* Expected: {a: 11, b: 22, c: 33} */ /* Three tables */ table3 : {a: 100, b: 200, c: 300}; triple_sum : each @add table1 table2 table3; /* Expected: {a: 111, b: 222, c: 333} */ /* Mixed types (table + scalar) */ mixed_types : each @add table1 5; /* Expected: {a: 6, b: 7, c: 8} */ mixed_types2 : each @add 5 table1; /* Expected: {a: 6, b: 7, c: 8} */ /* ===== NESTED TABLE HANDLING ===== */ /* Test nested table operations */ nested : { data: {a: 1, b: 2, c: 3}, meta: {type: "numbers", count: 3}, flags: {active: true, visible: false} }; /* Top-level only (nested tables unchanged) */ top_level_only : each @double nested; /* Expected: {data: {a: 1, b: 2, c: 3}, meta: {type: "numbers", count: 3}, flags: {active: true, visible: false}} */ /* Nested operations with explicit composition */ nested_doubled : each (each @double) nested; /* Expected: {data: {a: 2, b: 4, c: 6}, meta: {type: "numbers", count: 3}, flags: {active: true, visible: false}} */ /* Nested operations with t.map */ nested_with_t_map : t.map (t.map @double) nested; /* Expected: {data: {a: 2, b: 4, c: 6}, meta: {type: "numbers", count: 3}, flags: {active: true, visible: false}} */ /* Deep nested structure */ deep_nested : { level1: { level2: { level3: {x: 1, y: 2, z: 3} } } }; /* Deep nested operations */ deep_doubled : each (each (each @double)) deep_nested; /* Expected: {level1: {level2: {level3: {x: 2, y: 4, z: 6}}}} */ deep_with_t_map : t.map (t.map (t.map @double)) deep_nested; /* Expected: {level1: {level2: {level3: {x: 2, y: 4, z: 6}}}} */ /* ===== EMBEDDED COMPLEX STRUCTURES ===== */ /* Test functions and when expressions in tables */ calculator : { add: x y -> x + y, multiply: x y -> x * y, classify: x -> when x is 0 then "zero" 1 then "one" _ then "other" }; /* Usage of embedded functions */ calc_result : calculator.add 5 3; /* Expected: 8 */ calc_multiply : calculator.multiply 4 7; /* Expected: 28 */ calc_classify_zero : calculator.classify 0; /* Expected: "zero" */ calc_classify_one : calculator.classify 1; /* Expected: "one" */ calc_classify_other : calculator.classify 42; /* Expected: "other" */ /* ===== EDGE CASES AND ERROR HANDLING ===== */ /* Test empty table operations */ empty_table : {}; empty_pairs : t.pairs empty_table; /* Expected: [] */ empty_keys : t.keys empty_table; /* Expected: [] */ empty_values : t.values empty_table; /* Expected: [] */ empty_length : t.length empty_table; /* Expected: 0 */ /* Test safe operations (should not error) */ safe_get : t.get person "nonexistent" "default"; /* Expected: "default" */ safe_pairs : t.pairs empty_table; /* Expected: [] */ /* Test boolean keys (existing feature) */ boolean_table : {true: "enabled", false: "disabled"}; boolean_keys : t.keys boolean_table; /* Expected: [true, false] */ boolean_values : t.values boolean_table; /* Expected: ["enabled", "disabled"] */ /* Test numeric keys */ numeric_table : {1: "one", 2: "two", 3: "three"}; numeric_keys : t.keys numeric_table; /* Expected: [1, 2, 3] */ /* ===== FUNCTION COMPOSITION WITH TABLES ===== */ /* Test table operations with function composition */ transform : compose @t.map @double @t.filter @isPositive; transformed : transform numbers; /* Expected: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10} */ pipe_transform : pipe @t.filter @isPositive @t.map @double; pipe_result : pipe_transform numbers; /* Expected: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10} */ /* Test each with function composition */ triple : x -> x * 3; each_with_functions : each @double table1; /* Expected: {a: 2, b: 4, c: 6} */ each_with_composition : each (compose @double @triple) table1; /* Expected: {a: 6, b: 12, c: 18} */ /* ===== COMPLEX DATA STRUCTURES ===== */ /* Test with complex nested data */ data : { users: {1: {name: "Alice", age: 30}, 2: {name: "Bob", age: 25}}, scores: {1: 85, 2: 92}, active: {1: true, 2: false} }; /* Element-wise operations over nested structure */ get_name : user -> user.name; user_names : t.map @get_name data.users; /* Expected: {1: "Alice", 2: "Bob"} */ /* Test table operations on complex data */ user_count : t.length data.users; /* Expected: 2 */ active_users : t.filter @identity data.active; /* Expected: {1: true} */ /* ===== BACKWARD COMPATIBILITY TESTS ===== */ /* Test that existing table operations still work */ existing_table : {x: 1, y: 2, z: 3}; existing_access : existing_table.x; /* Expected: 1 */ existing_chained : {outer: {inner: {value: 42}}}; chained_access : existing_chained.outer.inner.value; /* Expected: 42 */ /* Test that existing map works with non-table values */ existing_map_result : map @double 5; /* Expected: 10 */ /* Test that existing reduce works with non-table values */ existing_reduce_result : reduce @add 0 5; /* Expected: 5 */ /* ===== PERFORMANCE AND STRESS TESTS ===== */ /* Test with larger tables (for performance validation) */ large_table : {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}; large_doubled : t.map @double large_table; /* Expected: {1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18, 10: 20} */ large_filtered : t.filter @isEven large_table; /* Expected: {2: 2, 4: 4, 6: 6, 8: 8, 10: 10} */ large_reduced : t.reduce @sum 0 large_table; /* Expected: 55 */ /* Test nested operations on large structures */ large_nested : { data1: large_table, data2: large_table, data3: large_table }; large_nested_doubled : t.map (t.map @double) large_nested; /* Expected: {data1: {1: 2, 2: 4, ...}, data2: {1: 2, 2: 4, ...}, data3: {1: 2, 2: 4, ...}} */ /* ===== ASSERTION VALIDATION TESTS ===== */ /* Validate enhanced broadcasting results */ ..assert doubled.1 == 2; ..assert doubled.2 == 4; ..assert doubled.3 == 6; ..assert doubled.4 == 8; ..assert doubled.5 == 10; ..assert squared.1 == 1; ..assert squared.2 == 4; ..assert squared.3 == 9; ..assert squared.4 == 16; ..assert squared.5 == 25; ..assert type_check.a == true; ..assert type_check.b == false; ..assert type_check.c == false; ..assert type_check.d == true; /* Validate table-specific operations */ ..assert t_doubled.1 == 2; ..assert t_doubled.2 == 4; ..assert t_doubled.3 == 6; ..assert t_doubled.4 == 8; ..assert t_doubled.5 == 10; ..assert even_numbers.2 == 2; ..assert even_numbers.4 == 4; ..assert t.has even_numbers 1 == false; ..assert t.has even_numbers 3 == false; ..assert positive_numbers.1 == 1; ..assert positive_numbers.2 == 2; ..assert positive_numbers.3 == 3; ..assert positive_numbers.4 == 4; ..assert positive_numbers.5 == 5; ..assert total == 15; ..assert maximum == 5; /* Validate immutable operations */ ..assert updated_person.age == 31; ..assert updated_person.name == "Alice"; ..assert updated_person.active == true; ..assert added_city.city == "New York"; ..assert added_city.name == "Alice"; ..assert added_city.age == 30; ..assert t.has without_age "age" == false; ..assert without_age.name == "Alice"; ..assert without_age.active == true; ..assert without_nonexistent.name == "Alice"; ..assert without_nonexistent.age == 30; ..assert without_nonexistent.active == true; ..assert merged.name == "Alice"; ..assert merged.age == 30; ..assert merged.active == true; ..assert merged.city == "New York"; ..assert merged.country == "USA"; ..assert overwrite_merge.name == "Alice"; ..assert overwrite_merge.age == 25; ..assert overwrite_merge.active == true; ..assert overwrite_merge.city == "Boston"; /* Validate table information operations */ ..assert t.length all_pairs == 3; ..assert all_pairs[0][0] == "name"; ..assert all_pairs[0][1] == "Alice"; ..assert all_pairs[1][0] == "age"; ..assert all_pairs[1][1] == 30; ..assert all_pairs[2][0] == "active"; ..assert all_pairs[2][1] == true; ..assert t.length all_keys == 3; ..assert all_keys[0] == "name"; ..assert all_keys[1] == "age"; ..assert all_keys[2] == "active"; ..assert t.length all_values == 3; ..assert all_values[0] == "Alice"; ..assert all_values[1] == 30; ..assert all_values[2] == true; ..assert table_size == 3; ..assert has_name == true; ..assert has_email == false; ..assert age_or_default == 30; ..assert email_or_default == "unknown"; /* Validate element-wise operations */ ..assert normal_add == 8; ..assert each_result.1 == 11; ..assert each_result.2 == 12; ..assert each_result.3 == 13; ..assert each_result.4 == 14; ..assert each_result.5 == 15; ..assert mixed_operation.1 == 11; ..assert mixed_operation.2 == 12; ..assert mixed_operation.3 == 13; ..assert mixed_operation.4 == 14; ..assert mixed_operation.5 == 15; ..assert multi_table_sum.a == 11; ..assert multi_table_sum.b == 22; ..assert multi_table_sum.c == 33; ..assert triple_sum.a == 111; ..assert triple_sum.b == 222; ..assert triple_sum.c == 333; ..assert mixed_types.a == 6; ..assert mixed_types.b == 7; ..assert mixed_types.c == 8; ..assert mixed_types2.a == 6; ..assert mixed_types2.b == 7; ..assert mixed_types2.c == 8; /* Validate nested table operations */ ..assert top_level_only.data.a == 1; ..assert top_level_only.data.b == 2; ..assert top_level_only.data.c == 3; ..assert top_level_only.meta.type == "numbers"; ..assert top_level_only.meta.count == 3; ..assert top_level_only.flags.active == true; ..assert top_level_only.flags.visible == false; ..assert nested_doubled.data.a == 2; ..assert nested_doubled.data.b == 4; ..assert nested_doubled.data.c == 6; ..assert nested_doubled.meta.type == "numbers"; ..assert nested_doubled.meta.count == 3; ..assert nested_doubled.flags.active == true; ..assert nested_doubled.flags.visible == false; ..assert nested_with_t_map.data.a == 2; ..assert nested_with_t_map.data.b == 4; ..assert nested_with_t_map.data.c == 6; ..assert nested_with_t_map.meta.type == "numbers"; ..assert nested_with_t_map.meta.count == 3; ..assert nested_with_t_map.flags.active == true; ..assert nested_with_t_map.flags.visible == false; ..assert deep_doubled.level1.level2.level3.x == 2; ..assert deep_doubled.level1.level2.level3.y == 4; ..assert deep_doubled.level1.level2.level3.z == 6; ..assert deep_with_t_map.level1.level2.level3.x == 2; ..assert deep_with_t_map.level1.level2.level3.y == 4; ..assert deep_with_t_map.level1.level2.level3.z == 6; /* Validate embedded functions */ ..assert calc_result == 8; ..assert calc_multiply == 28; ..assert calc_classify_zero == "zero"; ..assert calc_classify_one == "one"; ..assert calc_classify_other == "other"; /* Validate edge cases */ ..assert t.length empty_pairs == 0; ..assert t.length empty_keys == 0; ..assert t.length empty_values == 0; ..assert empty_length == 0; ..assert safe_get == "default"; ..assert t.length safe_pairs == 0; ..assert t.length boolean_keys == 2; ..assert boolean_keys[0] == true; ..assert boolean_keys[1] == false; ..assert t.length boolean_values == 2; ..assert boolean_values[0] == "enabled"; ..assert boolean_values[1] == "disabled"; ..assert t.length numeric_keys == 3; ..assert numeric_keys[0] == 1; ..assert numeric_keys[1] == 2; ..assert numeric_keys[2] == 3; /* Validate function composition */ ..assert transformed.1 == 2; ..assert transformed.2 == 4; ..assert transformed.3 == 6; ..assert transformed.4 == 8; ..assert transformed.5 == 10; ..assert pipe_result.1 == 2; ..assert pipe_result.2 == 4; ..assert pipe_result.3 == 6; ..assert pipe_result.4 == 8; ..assert pipe_result.5 == 10; ..assert each_with_functions.a == 2; ..assert each_with_functions.b == 4; ..assert each_with_functions.c == 6; ..assert each_with_composition.a == 6; ..assert each_with_composition.b == 12; ..assert each_with_composition.c == 18; /* Validate complex data structures */ ..assert user_names.1 == "Alice"; ..assert user_names.2 == "Bob"; ..assert user_count == 2; ..assert active_users.1 == true; ..assert t.has active_users 2 == false; /* Validate backward compatibility */ ..assert existing_access == 1; ..assert chained_access == 42; ..assert existing_map_result == 10; ..assert existing_reduce_result == 5; /* Validate performance tests */ ..assert large_doubled.1 == 2; ..assert large_doubled.10 == 20; ..assert t.length large_doubled == 10; ..assert large_filtered.2 == 2; ..assert large_filtered.4 == 4; ..assert large_filtered.6 == 6; ..assert large_filtered.8 == 8; ..assert large_filtered.10 == 10; ..assert t.length large_filtered == 5; ..assert large_reduced == 55; ..assert large_nested_doubled.data1.1 == 2; ..assert large_nested_doubled.data1.10 == 20; ..assert large_nested_doubled.data2.1 == 2; ..assert large_nested_doubled.data3.1 == 2; /* ===== OUTPUT ALL RESULTS ===== */ ..out "=== BASIC TABLE CREATION ==="; ..out "Numbers:"; ..out numbers; ..out "Person:"; ..out person; ..out "Mixed table:"; ..out mixed_table; ..out "=== ENHANCED BROADCASTING ==="; ..out "Doubled numbers:"; ..out doubled; ..out "Squared numbers:"; ..out squared; ..out "Type check:"; ..out type_check; ..out "=== TABLE-SPECIFIC OPERATIONS ==="; ..out "t.map doubled:"; ..out t_doubled; ..out "Even numbers:"; ..out even_numbers; ..out "Positive numbers:"; ..out positive_numbers; ..out "Sum total:"; ..out total; ..out "Maximum:"; ..out maximum; ..out "=== IMMUTABLE OPERATIONS ==="; ..out "Updated person:"; ..out updated_person; ..out "Added city:"; ..out added_city; ..out "Without age:"; ..out without_age; ..out "Without nonexistent:"; ..out without_nonexistent; ..out "Merged:"; ..out merged; ..out "Overwrite merge:"; ..out overwrite_merge; ..out "=== TABLE INFORMATION ==="; ..out "All pairs:"; ..out all_pairs; ..out "All keys:"; ..out all_keys; ..out "All values:"; ..out all_values; ..out "Table size:"; ..out table_size; ..out "Has name:"; ..out has_name; ..out "Has email:"; ..out has_email; ..out "Age or default:"; ..out age_or_default; ..out "Email or default:"; ..out email_or_default; ..out "=== ELEMENT-WISE OPERATIONS ==="; ..out "Normal add:"; ..out normal_add; ..out "Each result:"; ..out each_result; ..out "Mixed operation:"; ..out mixed_operation; ..out "Multi-table sum:"; ..out multi_table_sum; ..out "Triple sum:"; ..out triple_sum; ..out "Mixed types:"; ..out mixed_types; ..out "Mixed types2:"; ..out mixed_types2; ..out "=== NESTED TABLE OPERATIONS ==="; ..out "Top-level only:"; ..out top_level_only; ..out "Nested doubled:"; ..out nested_doubled; ..out "Nested with t.map:"; ..out nested_with_t_map; ..out "Deep doubled:"; ..out deep_doubled; ..out "Deep with t.map:"; ..out deep_with_t_map; ..out "=== EMBEDDED FUNCTIONS ==="; ..out "Calculator add:"; ..out calc_result; ..out "Calculator multiply:"; ..out calc_multiply; ..out "Classify zero:"; ..out calc_classify_zero; ..out "Classify one:"; ..out calc_classify_one; ..out "Classify other:"; ..out calc_classify_other; ..out "=== EDGE CASES ==="; ..out "Empty pairs:"; ..out empty_pairs; ..out "Empty keys:"; ..out empty_keys; ..out "Empty values:"; ..out empty_values; ..out "Empty length:"; ..out empty_length; ..out "Safe get:"; ..out safe_get; ..out "Safe pairs:"; ..out safe_pairs; ..out "=== BOOLEAN AND NUMERIC KEYS ==="; ..out "Boolean keys:"; ..out boolean_keys; ..out "Boolean values:"; ..out boolean_values; ..out "Numeric keys:"; ..out numeric_keys; ..out "=== FUNCTION COMPOSITION ==="; ..out "Transformed:"; ..out transformed; ..out "Pipe result:"; ..out pipe_result; ..out "Each with functions:"; ..out each_with_functions; ..out "Each with composition:"; ..out each_with_composition; ..out "=== COMPLEX DATA STRUCTURES ==="; ..out "User names:"; ..out user_names; ..out "User count:"; ..out user_count; ..out "Active users:"; ..out active_users; ..out "=== BACKWARD COMPATIBILITY ==="; ..out "Existing access:"; ..out existing_access; ..out "Chained access:"; ..out chained_access; ..out "Existing map result:"; ..out existing_map_result; ..out "Existing reduce result:"; ..out existing_reduce_result; ..out "=== PERFORMANCE TESTS ==="; ..out "Large doubled:"; ..out large_doubled; ..out "Large filtered:"; ..out large_filtered; ..out "Large reduced:"; ..out large_reduced; ..out "Large nested doubled:"; ..out large_nested_doubled; /* ===== ERROR HANDLING TESTS ===== */ /* These tests demonstrate expected error behavior */ /* Uncomment individual lines to test specific error cases */ /* Type validation errors */ /* tableSet_error : t.set "not_a_table" "key" "value"; */ /* tableGet_error : t.get "not_a_table" "key"; */ /* tableHas_error : t.has "not_a_table" "key"; */ /* tableMerge_error : t.merge "not_a_table" person; */ /* Missing argument errors */ /* tableSet_missing : t.set person "key"; */ /* tableGet_missing : t.get person; */ /* tableHas_missing : t.has person; */ /* Function validation errors */ /* each_no_function : each "not_a_function" table1; */ /* each_mixed_errors : each @add "string" table1; */ /* Null/undefined handling */ /* null_table : t.set null "key" "value"; */ /* undefined_key : t.get person undefined; */ /* ===== FINAL VALIDATION ===== */ ..assert "All table enhancement tests completed successfully!" == "All table enhancement tests completed successfully!"; ..out "=== TEST COMPLETION ==="; ..out "All table enhancement tests completed successfully!"; ..out "All assertions passed!";