From 2f6fe8867c7060c2166ea1109e65ea6056e45744 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 10 Dec 2025 12:57:42 -0500 Subject: [PATCH 1/2] Fix fold_rev static dispatch bug --- src/cli/test/fx_platform_test.zig | 20 ++++++++ src/eval/interpreter.zig | 71 ++++++++++++++++++++++------ test/fx/compare_fold_rev.roc | 13 +++++ test/fx/fold_rev_qualified.roc | 15 ++++++ test/fx/fold_rev_static_dispatch.roc | 16 +++++++ test/fx/test_bound_len.roc | 12 +++++ test/fx/test_first.roc | 12 +++++ test/fx/test_first_method.roc | 15 ++++++ test/fx/test_fold_method.roc | 9 ++++ test/fx/test_fold_rev_debug.roc | 18 +++++++ test/fx/test_fold_rev_order.roc | 13 +++++ test/fx/test_fold_rev_simple.roc | 13 +++++ test/fx/test_get.roc | 18 +++++++ test/fx/test_get_qualified.roc | 12 +++++ test/fx/test_last_method.roc | 15 ++++++ test/fx/test_len.roc | 14 ++++++ test/fx/test_method_while.roc | 25 ++++++++++ test/fx/test_simple_method.roc | 21 ++++++++ test/fx/test_sum_method.roc | 30 ++++++++++++ test/fx/test_while_lookup.roc | 24 ++++++++++ test/fx/test_wrap_fold.roc | 16 +++++++ test/fx/test_wrap_method.roc | 17 +++++++ 22 files changed, 404 insertions(+), 15 deletions(-) create mode 100644 test/fx/compare_fold_rev.roc create mode 100644 test/fx/fold_rev_qualified.roc create mode 100644 test/fx/fold_rev_static_dispatch.roc create mode 100644 test/fx/test_bound_len.roc create mode 100644 test/fx/test_first.roc create mode 100644 test/fx/test_first_method.roc create mode 100644 test/fx/test_fold_method.roc create mode 100644 test/fx/test_fold_rev_debug.roc create mode 100644 test/fx/test_fold_rev_order.roc create mode 100644 test/fx/test_fold_rev_simple.roc create mode 100644 test/fx/test_get.roc create mode 100644 test/fx/test_get_qualified.roc create mode 100644 test/fx/test_last_method.roc create mode 100644 test/fx/test_len.roc create mode 100644 test/fx/test_method_while.roc create mode 100644 test/fx/test_simple_method.roc create mode 100644 test/fx/test_sum_method.roc create mode 100644 test/fx/test_while_lookup.roc create mode 100644 test/fx/test_wrap_fold.roc create mode 100644 test/fx/test_wrap_method.roc diff --git a/src/cli/test/fx_platform_test.zig b/src/cli/test/fx_platform_test.zig index 006041d5ec..d274453b91 100644 --- a/src/cli/test/fx_platform_test.zig +++ b/src/cli/test/fx_platform_test.zig @@ -1048,3 +1048,23 @@ test "fx platform index out of bounds in instantiate regression" { // Currently it fails with a panic in instantiate.zig. try checkSuccess(run_result); } + +test "fx platform fold_rev static dispatch regression" { + // Regression test: Calling fold_rev with static dispatch (method syntax) panics, + // but calling it qualified as List.fold_rev(...) works fine. + // + // The panic occurs with: [1].fold_rev([], |elem, acc| acc.append(elem)) + // But this works: List.fold_rev([1], [], |elem, acc| acc.append(elem)) + const allocator = testing.allocator; + + const run_result = try runRoc(allocator, "test/fx/fold_rev_static_dispatch.roc", .{}); + defer allocator.free(run_result.stdout); + defer allocator.free(run_result.stderr); + + try checkSuccess(run_result); + + // Verify the expected output + try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Start reverse") != null); + try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Reversed: 3 elements") != null); + try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Done") != null); +} diff --git a/src/eval/interpreter.zig b/src/eval/interpreter.zig index eea0f505cf..6433f4b28d 100644 --- a/src/eval/interpreter.zig +++ b/src/eval/interpreter.zig @@ -15011,22 +15011,63 @@ pub const Interpreter = struct { try self.active_closures.append(method_func); - // Bind receiver first - try self.bindings.append(.{ - .pattern_idx = params[0], - .value = receiver_value, - .expr_idx = null, // expr_idx not used for method call parameter bindings - .source_env = self.env, - }); + // Save the current flex_type_context before adding parameter mappings + // This will be restored in call_cleanup (like call_invoke_closure does) + var saved_flex_type_context = try self.flex_type_context.clone(); + errdefer saved_flex_type_context.deinit(); - // Bind explicit arguments + // Bind receiver using patternMatchesBind (like call_invoke_closure does) + // This creates a copy of the value for the binding + const receiver_param_rt_var = try self.translateTypeVar(self.env, can.ModuleEnv.varFrom(params[0])); + + // Propagate flex mappings for receiver (needed for polymorphic type propagation) + const receiver_rt_resolved = self.runtime_types.resolveVar(dac.receiver_rt_var); + if (receiver_rt_resolved.desc.content == .structure) { + const receiver_param_ct_var = can.ModuleEnv.varFrom(params[0]); + try self.propagateFlexMappings(self.env, receiver_param_ct_var, dac.receiver_rt_var); + } + + if (!try self.patternMatchesBind(params[0], receiver_value, receiver_param_rt_var, roc_ops, &self.bindings, null)) { + // Pattern match failed - cleanup and error + self.env = saved_env; + _ = self.active_closures.pop(); + method_func.decref(&self.runtime_layout_store, roc_ops); + receiver_value.decref(&self.runtime_layout_store, roc_ops); + for (arg_values) |arg| arg.decref(&self.runtime_layout_store, roc_ops); + if (saved_rigid_subst) |*saved| saved.deinit(); + self.flex_type_context.deinit(); + self.flex_type_context = saved_flex_type_context; + self.poly_context_generation +%= 1; + return error.TypeMismatch; + } + // Decref the original receiver value since patternMatchesBind made a copy + receiver_value.decref(&self.runtime_layout_store, roc_ops); + + // Bind explicit arguments using patternMatchesBind for (arg_values, 0..) |arg, idx| { - try self.bindings.append(.{ - .pattern_idx = params[1 + idx], - .value = arg, - .expr_idx = null, // expr_idx not used for method call parameter bindings - .source_env = self.env, - }); + const param_rt_var = try self.translateTypeVar(self.env, can.ModuleEnv.varFrom(params[1 + idx])); + + // Propagate flex mappings for each argument (needed for polymorphic type propagation) + const arg_rt_resolved = self.runtime_types.resolveVar(arg.rt_var); + if (arg_rt_resolved.desc.content == .structure) { + const param_ct_var = can.ModuleEnv.varFrom(params[1 + idx]); + try self.propagateFlexMappings(self.env, param_ct_var, arg.rt_var); + } + + if (!try self.patternMatchesBind(params[1 + idx], arg, param_rt_var, roc_ops, &self.bindings, null)) { + // Pattern match failed - cleanup and error + self.env = saved_env; + _ = self.active_closures.pop(); + method_func.decref(&self.runtime_layout_store, roc_ops); + for (arg_values[idx..]) |remaining_arg| remaining_arg.decref(&self.runtime_layout_store, roc_ops); + if (saved_rigid_subst) |*saved| saved.deinit(); + self.flex_type_context.deinit(); + self.flex_type_context = saved_flex_type_context; + self.poly_context_generation +%= 1; + return error.TypeMismatch; + } + // Decref the original argument value since patternMatchesBind made a copy + arg.decref(&self.runtime_layout_store, roc_ops); } try work_stack.push(.{ .apply_continuation = .{ .call_cleanup = .{ @@ -15037,7 +15078,7 @@ pub const Interpreter = struct { .did_instantiate = did_instantiate, .call_ret_rt_var = null, .saved_rigid_subst = saved_rigid_subst, - .saved_flex_type_context = null, + .saved_flex_type_context = saved_flex_type_context, .arg_rt_vars_to_free = null, } } }); try work_stack.push(.{ .eval_expr = .{ diff --git a/test/fx/compare_fold_rev.roc b/test/fx/compare_fold_rev.roc new file mode 100644 index 0000000000..c719a20201 --- /dev/null +++ b/test/fx/compare_fold_rev.roc @@ -0,0 +1,13 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + Stdout.line!("Testing qualified fold_rev") + r1 = List.fold_rev([1], 0, |elem, acc| acc + elem) + Stdout.line!("Qualified result: ${r1.to_str()}") + + Stdout.line!("Testing method fold_rev") + r2 = [1].fold_rev(0, |elem, acc| acc + elem) + Stdout.line!("Method result: ${r2.to_str()}") +} diff --git a/test/fx/fold_rev_qualified.roc b/test/fx/fold_rev_qualified.roc new file mode 100644 index 0000000000..5280c1a2d2 --- /dev/null +++ b/test/fx/fold_rev_qualified.roc @@ -0,0 +1,15 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Test that fold_rev works with qualified call +# This should work fine +main! = || { + Stdout.line!("Start reverse (qualified)") + rev = List.fold_rev([1, 2, 3], [], |elem, acc| { + acc.append(elem) + }) + # rev should be [3, 2, 1] + Stdout.line!("Reversed: ${rev.len().to_str()} elements") + Stdout.line!("Done") +} diff --git a/test/fx/fold_rev_static_dispatch.roc b/test/fx/fold_rev_static_dispatch.roc new file mode 100644 index 0000000000..c578ee82f1 --- /dev/null +++ b/test/fx/fold_rev_static_dispatch.roc @@ -0,0 +1,16 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Test that fold_rev works with static dispatch (method syntax) +# Previously this panicked while List.fold_rev(...) worked fine +main! = || { + Stdout.line!("Start reverse") + rev = + [1, 2, 3].fold_rev([], |elem, acc| { + acc.append(elem) + }) + # rev should be [3, 2, 1] + Stdout.line!("Reversed: ${rev.len().to_str()} elements") + Stdout.line!("Done") +} diff --git a/test/fx/test_bound_len.roc b/test/fx/test_bound_len.roc new file mode 100644 index 0000000000..4b991e5bda --- /dev/null +++ b/test/fx/test_bound_len.roc @@ -0,0 +1,12 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +my_len = |list| list.len() + +main! = || { + Stdout.line!("Testing bound list len") + list = [1, 2, 3] + r = my_len(list) + Stdout.line!("Result: ${r.to_str()}") +} diff --git a/test/fx/test_first.roc b/test/fx/test_first.roc new file mode 100644 index 0000000000..d5bb558519 --- /dev/null +++ b/test/fx/test_first.roc @@ -0,0 +1,12 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1, 2, 3] + Stdout.line!("Qualified first") + match List.first(list) { + Ok(v) => Stdout.line!("Qualified first: ${v.to_str()}") + Err(_e) => Stdout.line!("Error") + } +} diff --git a/test/fx/test_first_method.roc b/test/fx/test_first_method.roc new file mode 100644 index 0000000000..21068510d7 --- /dev/null +++ b/test/fx/test_first_method.roc @@ -0,0 +1,15 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1] + Stdout.line!("List created") + + # Try first with method syntax + Stdout.line!("Calling method list.first()") + match list.first() { + Ok(v) => Stdout.line!("First: ${v.to_str()}") + Err(_e) => Stdout.line!("Empty") + } +} diff --git a/test/fx/test_fold_method.roc b/test/fx/test_fold_method.roc new file mode 100644 index 0000000000..9ce457729f --- /dev/null +++ b/test/fx/test_fold_method.roc @@ -0,0 +1,9 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + Stdout.line!("Testing fold (not fold_rev) method") + r = [1, 2, 3].fold(0, |acc, elem| acc + elem) + Stdout.line!("fold method result: ${r.to_str()}") +} diff --git a/test/fx/test_fold_rev_debug.roc b/test/fx/test_fold_rev_debug.roc new file mode 100644 index 0000000000..6f158b12f8 --- /dev/null +++ b/test/fx/test_fold_rev_debug.roc @@ -0,0 +1,18 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1] + Stdout.line!("List created") + + # Try qualified call first (works) + Stdout.line!("Calling List.fold_rev (qualified)") + r1 = List.fold_rev(list, 0, |elem, acc| elem + acc) + Stdout.line!("Qualified result: ${r1.to_str()}") + + # Now try method call (crashes) + Stdout.line!("Calling list.fold_rev (method)") + r2 = list.fold_rev(0, |elem, acc| elem + acc) + Stdout.line!("Method result: ${r2.to_str()}") +} diff --git a/test/fx/test_fold_rev_order.roc b/test/fx/test_fold_rev_order.roc new file mode 100644 index 0000000000..747fcb16ca --- /dev/null +++ b/test/fx/test_fold_rev_order.roc @@ -0,0 +1,13 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1] + Stdout.line!("List created") + + # Method call FIRST this time + Stdout.line!("Calling method list.fold_rev") + r1 = list.fold_rev(0, |elem, acc| elem + acc) + Stdout.line!("Method result: ${r1.to_str()}") +} diff --git a/test/fx/test_fold_rev_simple.roc b/test/fx/test_fold_rev_simple.roc new file mode 100644 index 0000000000..6dc129b6a0 --- /dev/null +++ b/test/fx/test_fold_rev_simple.roc @@ -0,0 +1,13 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1] + Stdout.line!("List created") + + # Simpler fold_rev without append - just sum + Stdout.line!("Calling method fold_rev with sum") + r = list.fold_rev(0, |elem, acc| elem + acc) + Stdout.line!("Result: ${r.to_str()}") +} diff --git a/test/fx/test_get.roc b/test/fx/test_get.roc new file mode 100644 index 0000000000..9b5aea09f5 --- /dev/null +++ b/test/fx/test_get.roc @@ -0,0 +1,18 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1, 2, 3] + Stdout.line!("Method get") + match list.get(0) { + Ok(v) => Stdout.line!("Method get: ${v.to_str()}") + Err(_e) => Stdout.line!("Error") + } + + Stdout.line!("Qualified get") + match List.get(list, 0) { + Ok(v) => Stdout.line!("Qualified get: ${v.to_str()}") + Err(_e) => Stdout.line!("Error") + } +} diff --git a/test/fx/test_get_qualified.roc b/test/fx/test_get_qualified.roc new file mode 100644 index 0000000000..6c6ea3fd7e --- /dev/null +++ b/test/fx/test_get_qualified.roc @@ -0,0 +1,12 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1, 2, 3] + Stdout.line!("Qualified get") + match List.get(list, 0) { + Ok(v) => Stdout.line!("Qualified get: ${v.to_str()}") + Err(_e) => Stdout.line!("Error") + } +} diff --git a/test/fx/test_last_method.roc b/test/fx/test_last_method.roc new file mode 100644 index 0000000000..899885a725 --- /dev/null +++ b/test/fx/test_last_method.roc @@ -0,0 +1,15 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1] + Stdout.line!("List created") + + # Try last with method syntax (also uses list_get_unsafe) + Stdout.line!("Calling method list.last()") + match list.last() { + Ok(v) => Stdout.line!("Last: ${v.to_str()}") + Err(_e) => Stdout.line!("Empty") + } +} diff --git a/test/fx/test_len.roc b/test/fx/test_len.roc new file mode 100644 index 0000000000..0d5cfa6907 --- /dev/null +++ b/test/fx/test_len.roc @@ -0,0 +1,14 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + list = [1, 2, 3] + Stdout.line!("Method len") + len = list.len() + Stdout.line!("Method len: ${len.to_str()}") + + Stdout.line!("Qualified len") + len2 = List.len(list) + Stdout.line!("Qualified len: ${len2.to_str()}") +} diff --git a/test/fx/test_method_while.roc b/test/fx/test_method_while.roc new file mode 100644 index 0000000000..483446c876 --- /dev/null +++ b/test/fx/test_method_while.roc @@ -0,0 +1,25 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Simple function that uses while loop, called via method dispatch +my_while = |start| { + var $i = start + var $result = 0 + while $i > 0 { + $i = $i - 1 + $result = $result + 1 + } + $result +} + +main! = || { + Stdout.line!("Testing method while") + # Call via qualified syntax + r1 = my_while(3) + Stdout.line!("Qualified: ${r1.to_str()}") + + # # Call via method syntax (shouldn't work - my_while not attached to a type) + # Actually can't call my_while via method syntax since it's not a method + Stdout.line!("Done") +} diff --git a/test/fx/test_simple_method.roc b/test/fx/test_simple_method.roc new file mode 100644 index 0000000000..2e556b5b33 --- /dev/null +++ b/test/fx/test_simple_method.roc @@ -0,0 +1,21 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +main! = || { + Stdout.line!("Testing simple methods") + list = [1, 2, 3] + + # len works + Stdout.line!("len: ${list.len().to_str()}") + + # fold works + r1 = list.fold(0, |acc, elem| acc + elem) + Stdout.line!("fold: ${r1.to_str()}") + + # append works? + list2 = list.append(4) + Stdout.line!("append: ${list2.len().to_str()}") + + Stdout.line!("Done") +} diff --git a/test/fx/test_sum_method.roc b/test/fx/test_sum_method.roc new file mode 100644 index 0000000000..143d69704d --- /dev/null +++ b/test/fx/test_sum_method.roc @@ -0,0 +1,30 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +my_sum = |list| { + var $state = 0 + var $index = list.len() + while $index > 0 { + $index = $index - 1 + # Use list.get with method syntax + match list.get($index) { + Ok(elem) => { $state = $state + elem } + Err(_e) => {} + } + } + $state +} + +main! = || { + Stdout.line!("Testing while loop with method lookup") + list = [1, 2, 3] + + Stdout.line!("Using user-defined my_sum") + r1 = my_sum(list) + Stdout.line!("User my_sum: ${r1.to_str()}") + + Stdout.line!("Using my_sum as method") + # This is different - it doesn't go through method dispatch + # because my_sum is in the app module, not List module +} diff --git a/test/fx/test_while_lookup.roc b/test/fx/test_while_lookup.roc new file mode 100644 index 0000000000..9f5bce39e1 --- /dev/null +++ b/test/fx/test_while_lookup.roc @@ -0,0 +1,24 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +my_sum = |list| { + var $state = 0 + var $index = list.len() + while $index > 0 { + $index = $index - 1 + # Use List.get instead of list_get_unsafe (which we can't access) + match List.get(list, $index) { + Ok(elem) => { $state = $state + elem } + Err(_e) => {} + } + } + $state +} + +main! = || { + Stdout.line!("Testing while loop lookup") + list = [1, 2, 3] + r = my_sum(list) + Stdout.line!("Sum: ${r.to_str()}") +} diff --git a/test/fx/test_wrap_fold.roc b/test/fx/test_wrap_fold.roc new file mode 100644 index 0000000000..50e588dbb6 --- /dev/null +++ b/test/fx/test_wrap_fold.roc @@ -0,0 +1,16 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Wrap fold_rev to test if the issue is with method dispatch +my_fold_rev = |list, init, step| List.fold_rev(list, init, step) + +main! = || { + list = [1] + Stdout.line!("List created") + + # Call our wrapper (which uses qualified internally) + Stdout.line!("Calling my_fold_rev") + r = my_fold_rev(list, 0, |elem, acc| elem + acc) + Stdout.line!("Result: ${r.to_str()}") +} diff --git a/test/fx/test_wrap_method.roc b/test/fx/test_wrap_method.roc new file mode 100644 index 0000000000..81db3fe0e7 --- /dev/null +++ b/test/fx/test_wrap_method.roc @@ -0,0 +1,17 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Wrap fold_rev - but can't call this via method syntax since it's in app module +# Let's test if method dispatch on a simple wrapper works +my_wrapper = |list| List.fold_rev(list, 0, |elem, acc| elem + acc) + +main! = || { + list = [1] + Stdout.line!("List created") + + # Call wrapper directly + Stdout.line!("Calling my_wrapper(list)") + r = my_wrapper(list) + Stdout.line!("Result: ${r.to_str()}") +} From 7cbb76b77693d005749611e14a5db9d14ea58095 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 10 Dec 2025 13:00:30 -0500 Subject: [PATCH 2/2] Delete redundant tests --- test/fx/compare_fold_rev.roc | 13 ------------- test/fx/fold_rev_qualified.roc | 15 --------------- test/fx/test_bound_len.roc | 12 ------------ test/fx/test_first.roc | 12 ------------ test/fx/test_first_method.roc | 15 --------------- test/fx/test_fold_method.roc | 9 --------- test/fx/test_fold_rev_debug.roc | 18 ------------------ test/fx/test_fold_rev_order.roc | 13 ------------- test/fx/test_fold_rev_simple.roc | 13 ------------- test/fx/test_get.roc | 18 ------------------ test/fx/test_get_qualified.roc | 12 ------------ test/fx/test_last_method.roc | 15 --------------- test/fx/test_len.roc | 14 -------------- test/fx/test_method_while.roc | 25 ------------------------- test/fx/test_simple_method.roc | 21 --------------------- test/fx/test_sum_method.roc | 30 ------------------------------ test/fx/test_while_lookup.roc | 24 ------------------------ test/fx/test_wrap_fold.roc | 16 ---------------- test/fx/test_wrap_method.roc | 17 ----------------- 19 files changed, 312 deletions(-) delete mode 100644 test/fx/compare_fold_rev.roc delete mode 100644 test/fx/fold_rev_qualified.roc delete mode 100644 test/fx/test_bound_len.roc delete mode 100644 test/fx/test_first.roc delete mode 100644 test/fx/test_first_method.roc delete mode 100644 test/fx/test_fold_method.roc delete mode 100644 test/fx/test_fold_rev_debug.roc delete mode 100644 test/fx/test_fold_rev_order.roc delete mode 100644 test/fx/test_fold_rev_simple.roc delete mode 100644 test/fx/test_get.roc delete mode 100644 test/fx/test_get_qualified.roc delete mode 100644 test/fx/test_last_method.roc delete mode 100644 test/fx/test_len.roc delete mode 100644 test/fx/test_method_while.roc delete mode 100644 test/fx/test_simple_method.roc delete mode 100644 test/fx/test_sum_method.roc delete mode 100644 test/fx/test_while_lookup.roc delete mode 100644 test/fx/test_wrap_fold.roc delete mode 100644 test/fx/test_wrap_method.roc diff --git a/test/fx/compare_fold_rev.roc b/test/fx/compare_fold_rev.roc deleted file mode 100644 index c719a20201..0000000000 --- a/test/fx/compare_fold_rev.roc +++ /dev/null @@ -1,13 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - Stdout.line!("Testing qualified fold_rev") - r1 = List.fold_rev([1], 0, |elem, acc| acc + elem) - Stdout.line!("Qualified result: ${r1.to_str()}") - - Stdout.line!("Testing method fold_rev") - r2 = [1].fold_rev(0, |elem, acc| acc + elem) - Stdout.line!("Method result: ${r2.to_str()}") -} diff --git a/test/fx/fold_rev_qualified.roc b/test/fx/fold_rev_qualified.roc deleted file mode 100644 index 5280c1a2d2..0000000000 --- a/test/fx/fold_rev_qualified.roc +++ /dev/null @@ -1,15 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -# Test that fold_rev works with qualified call -# This should work fine -main! = || { - Stdout.line!("Start reverse (qualified)") - rev = List.fold_rev([1, 2, 3], [], |elem, acc| { - acc.append(elem) - }) - # rev should be [3, 2, 1] - Stdout.line!("Reversed: ${rev.len().to_str()} elements") - Stdout.line!("Done") -} diff --git a/test/fx/test_bound_len.roc b/test/fx/test_bound_len.roc deleted file mode 100644 index 4b991e5bda..0000000000 --- a/test/fx/test_bound_len.roc +++ /dev/null @@ -1,12 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -my_len = |list| list.len() - -main! = || { - Stdout.line!("Testing bound list len") - list = [1, 2, 3] - r = my_len(list) - Stdout.line!("Result: ${r.to_str()}") -} diff --git a/test/fx/test_first.roc b/test/fx/test_first.roc deleted file mode 100644 index d5bb558519..0000000000 --- a/test/fx/test_first.roc +++ /dev/null @@ -1,12 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1, 2, 3] - Stdout.line!("Qualified first") - match List.first(list) { - Ok(v) => Stdout.line!("Qualified first: ${v.to_str()}") - Err(_e) => Stdout.line!("Error") - } -} diff --git a/test/fx/test_first_method.roc b/test/fx/test_first_method.roc deleted file mode 100644 index 21068510d7..0000000000 --- a/test/fx/test_first_method.roc +++ /dev/null @@ -1,15 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1] - Stdout.line!("List created") - - # Try first with method syntax - Stdout.line!("Calling method list.first()") - match list.first() { - Ok(v) => Stdout.line!("First: ${v.to_str()}") - Err(_e) => Stdout.line!("Empty") - } -} diff --git a/test/fx/test_fold_method.roc b/test/fx/test_fold_method.roc deleted file mode 100644 index 9ce457729f..0000000000 --- a/test/fx/test_fold_method.roc +++ /dev/null @@ -1,9 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - Stdout.line!("Testing fold (not fold_rev) method") - r = [1, 2, 3].fold(0, |acc, elem| acc + elem) - Stdout.line!("fold method result: ${r.to_str()}") -} diff --git a/test/fx/test_fold_rev_debug.roc b/test/fx/test_fold_rev_debug.roc deleted file mode 100644 index 6f158b12f8..0000000000 --- a/test/fx/test_fold_rev_debug.roc +++ /dev/null @@ -1,18 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1] - Stdout.line!("List created") - - # Try qualified call first (works) - Stdout.line!("Calling List.fold_rev (qualified)") - r1 = List.fold_rev(list, 0, |elem, acc| elem + acc) - Stdout.line!("Qualified result: ${r1.to_str()}") - - # Now try method call (crashes) - Stdout.line!("Calling list.fold_rev (method)") - r2 = list.fold_rev(0, |elem, acc| elem + acc) - Stdout.line!("Method result: ${r2.to_str()}") -} diff --git a/test/fx/test_fold_rev_order.roc b/test/fx/test_fold_rev_order.roc deleted file mode 100644 index 747fcb16ca..0000000000 --- a/test/fx/test_fold_rev_order.roc +++ /dev/null @@ -1,13 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1] - Stdout.line!("List created") - - # Method call FIRST this time - Stdout.line!("Calling method list.fold_rev") - r1 = list.fold_rev(0, |elem, acc| elem + acc) - Stdout.line!("Method result: ${r1.to_str()}") -} diff --git a/test/fx/test_fold_rev_simple.roc b/test/fx/test_fold_rev_simple.roc deleted file mode 100644 index 6dc129b6a0..0000000000 --- a/test/fx/test_fold_rev_simple.roc +++ /dev/null @@ -1,13 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1] - Stdout.line!("List created") - - # Simpler fold_rev without append - just sum - Stdout.line!("Calling method fold_rev with sum") - r = list.fold_rev(0, |elem, acc| elem + acc) - Stdout.line!("Result: ${r.to_str()}") -} diff --git a/test/fx/test_get.roc b/test/fx/test_get.roc deleted file mode 100644 index 9b5aea09f5..0000000000 --- a/test/fx/test_get.roc +++ /dev/null @@ -1,18 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1, 2, 3] - Stdout.line!("Method get") - match list.get(0) { - Ok(v) => Stdout.line!("Method get: ${v.to_str()}") - Err(_e) => Stdout.line!("Error") - } - - Stdout.line!("Qualified get") - match List.get(list, 0) { - Ok(v) => Stdout.line!("Qualified get: ${v.to_str()}") - Err(_e) => Stdout.line!("Error") - } -} diff --git a/test/fx/test_get_qualified.roc b/test/fx/test_get_qualified.roc deleted file mode 100644 index 6c6ea3fd7e..0000000000 --- a/test/fx/test_get_qualified.roc +++ /dev/null @@ -1,12 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1, 2, 3] - Stdout.line!("Qualified get") - match List.get(list, 0) { - Ok(v) => Stdout.line!("Qualified get: ${v.to_str()}") - Err(_e) => Stdout.line!("Error") - } -} diff --git a/test/fx/test_last_method.roc b/test/fx/test_last_method.roc deleted file mode 100644 index 899885a725..0000000000 --- a/test/fx/test_last_method.roc +++ /dev/null @@ -1,15 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1] - Stdout.line!("List created") - - # Try last with method syntax (also uses list_get_unsafe) - Stdout.line!("Calling method list.last()") - match list.last() { - Ok(v) => Stdout.line!("Last: ${v.to_str()}") - Err(_e) => Stdout.line!("Empty") - } -} diff --git a/test/fx/test_len.roc b/test/fx/test_len.roc deleted file mode 100644 index 0d5cfa6907..0000000000 --- a/test/fx/test_len.roc +++ /dev/null @@ -1,14 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - list = [1, 2, 3] - Stdout.line!("Method len") - len = list.len() - Stdout.line!("Method len: ${len.to_str()}") - - Stdout.line!("Qualified len") - len2 = List.len(list) - Stdout.line!("Qualified len: ${len2.to_str()}") -} diff --git a/test/fx/test_method_while.roc b/test/fx/test_method_while.roc deleted file mode 100644 index 483446c876..0000000000 --- a/test/fx/test_method_while.roc +++ /dev/null @@ -1,25 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -# Simple function that uses while loop, called via method dispatch -my_while = |start| { - var $i = start - var $result = 0 - while $i > 0 { - $i = $i - 1 - $result = $result + 1 - } - $result -} - -main! = || { - Stdout.line!("Testing method while") - # Call via qualified syntax - r1 = my_while(3) - Stdout.line!("Qualified: ${r1.to_str()}") - - # # Call via method syntax (shouldn't work - my_while not attached to a type) - # Actually can't call my_while via method syntax since it's not a method - Stdout.line!("Done") -} diff --git a/test/fx/test_simple_method.roc b/test/fx/test_simple_method.roc deleted file mode 100644 index 2e556b5b33..0000000000 --- a/test/fx/test_simple_method.roc +++ /dev/null @@ -1,21 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -main! = || { - Stdout.line!("Testing simple methods") - list = [1, 2, 3] - - # len works - Stdout.line!("len: ${list.len().to_str()}") - - # fold works - r1 = list.fold(0, |acc, elem| acc + elem) - Stdout.line!("fold: ${r1.to_str()}") - - # append works? - list2 = list.append(4) - Stdout.line!("append: ${list2.len().to_str()}") - - Stdout.line!("Done") -} diff --git a/test/fx/test_sum_method.roc b/test/fx/test_sum_method.roc deleted file mode 100644 index 143d69704d..0000000000 --- a/test/fx/test_sum_method.roc +++ /dev/null @@ -1,30 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -my_sum = |list| { - var $state = 0 - var $index = list.len() - while $index > 0 { - $index = $index - 1 - # Use list.get with method syntax - match list.get($index) { - Ok(elem) => { $state = $state + elem } - Err(_e) => {} - } - } - $state -} - -main! = || { - Stdout.line!("Testing while loop with method lookup") - list = [1, 2, 3] - - Stdout.line!("Using user-defined my_sum") - r1 = my_sum(list) - Stdout.line!("User my_sum: ${r1.to_str()}") - - Stdout.line!("Using my_sum as method") - # This is different - it doesn't go through method dispatch - # because my_sum is in the app module, not List module -} diff --git a/test/fx/test_while_lookup.roc b/test/fx/test_while_lookup.roc deleted file mode 100644 index 9f5bce39e1..0000000000 --- a/test/fx/test_while_lookup.roc +++ /dev/null @@ -1,24 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -my_sum = |list| { - var $state = 0 - var $index = list.len() - while $index > 0 { - $index = $index - 1 - # Use List.get instead of list_get_unsafe (which we can't access) - match List.get(list, $index) { - Ok(elem) => { $state = $state + elem } - Err(_e) => {} - } - } - $state -} - -main! = || { - Stdout.line!("Testing while loop lookup") - list = [1, 2, 3] - r = my_sum(list) - Stdout.line!("Sum: ${r.to_str()}") -} diff --git a/test/fx/test_wrap_fold.roc b/test/fx/test_wrap_fold.roc deleted file mode 100644 index 50e588dbb6..0000000000 --- a/test/fx/test_wrap_fold.roc +++ /dev/null @@ -1,16 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -# Wrap fold_rev to test if the issue is with method dispatch -my_fold_rev = |list, init, step| List.fold_rev(list, init, step) - -main! = || { - list = [1] - Stdout.line!("List created") - - # Call our wrapper (which uses qualified internally) - Stdout.line!("Calling my_fold_rev") - r = my_fold_rev(list, 0, |elem, acc| elem + acc) - Stdout.line!("Result: ${r.to_str()}") -} diff --git a/test/fx/test_wrap_method.roc b/test/fx/test_wrap_method.roc deleted file mode 100644 index 81db3fe0e7..0000000000 --- a/test/fx/test_wrap_method.roc +++ /dev/null @@ -1,17 +0,0 @@ -app [main!] { pf: platform "./platform/main.roc" } - -import pf.Stdout - -# Wrap fold_rev - but can't call this via method syntax since it's in app module -# Let's test if method dispatch on a simple wrapper works -my_wrapper = |list| List.fold_rev(list, 0, |elem, acc| elem + acc) - -main! = || { - list = [1] - Stdout.line!("List created") - - # Call wrapper directly - Stdout.line!("Calling my_wrapper(list)") - r = my_wrapper(list) - Stdout.line!("Result: ${r.to_str()}") -}