mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-07-30 16:26:28 +08:00
Address review: revert := deep-copy change, keep reference-assign semantics
Reverts the arithmetic deep-copy added to := in chaiscript_eval.hpp, restoring its original reference-assign behavior as requested. The optimizer fix (heap-allocated loop counter) remains and is sufficient to prevent the #635 segfault. Updated tests to use correct expected values for reference-assign semantics and added more thorough coverage: nested loops, multiple async calls, and value-assign comparison. Requested by @lefticus in PR #671 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f430afd470
commit
276fa9d13a
@ -473,11 +473,7 @@ namespace chaiscript {
|
||||
}
|
||||
} else if (this->text == ":=") {
|
||||
if (params[0].is_undef() || Boxed_Value::type_match(params[0], params[1])) {
|
||||
if (params[1].get_type_info().is_arithmetic() && params[0].get_type_info().is_arithmetic()) {
|
||||
params[0].assign(Boxed_Number::clone(params[1]));
|
||||
} else {
|
||||
params[0].assign(params[1]);
|
||||
}
|
||||
params[0].assign(params[1]);
|
||||
params[0].reset_return_value();
|
||||
} else {
|
||||
throw exception::eval_error("Mismatched types in equation");
|
||||
|
||||
@ -1,7 +1,41 @@
|
||||
// Verify that := performs a value copy, not an alias
|
||||
var a = 10
|
||||
var b = 20
|
||||
a := b
|
||||
++b
|
||||
assert_equal(20, a)
|
||||
assert_equal(21, b)
|
||||
// Issue #635: optimized for loop with := must not produce dangling values
|
||||
// := is reference-assign, so ret aliases i and sees the loop exit value
|
||||
|
||||
// Basic: capture loop variable via :=
|
||||
var ret = 0
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
ret := i
|
||||
}
|
||||
assert_equal(100, ret)
|
||||
|
||||
// Return from function containing optimized for loop
|
||||
def loop_result() {
|
||||
var ret = 0
|
||||
for (var i = 0; i < 200; ++i) {
|
||||
ret := i
|
||||
}
|
||||
return ret
|
||||
}
|
||||
assert_equal(200, loop_result())
|
||||
|
||||
// Multiple calls return consistent results
|
||||
assert_equal(loop_result(), loop_result())
|
||||
|
||||
// Nested optimized for loops
|
||||
var outer_val = 0
|
||||
var inner_val = 0
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
for (var j = 0; j < 10; ++j) {
|
||||
inner_val := j
|
||||
}
|
||||
outer_val := i
|
||||
}
|
||||
assert_equal(10, outer_val)
|
||||
assert_equal(10, inner_val)
|
||||
|
||||
// Value-assign (=) captures last body-iteration value, not exit value
|
||||
var ret2 = 0
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
ret2 = i
|
||||
}
|
||||
assert_equal(99, ret2)
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
// Issue #635: async + optimized for loop must not segfault from dangling pointer
|
||||
// := is reference-assign, so ret aliases i and sees the loop exit value
|
||||
|
||||
var func = fun(){
|
||||
var ret = 0;
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
@ -9,5 +12,14 @@ var func = fun(){
|
||||
var&fut1 = async(func);
|
||||
var fut2 = async(func);
|
||||
|
||||
assert_equal(999, fut1.get())
|
||||
assert_equal(999, fut2.get())
|
||||
assert_equal(1000, fut1.get())
|
||||
assert_equal(1000, fut2.get())
|
||||
|
||||
// Multiple concurrent async calls to stress the scenario
|
||||
var results = []
|
||||
for (var n = 0; n < 5; ++n) {
|
||||
results.push_back(async(func))
|
||||
}
|
||||
for (var n = 0; n < 5; ++n) {
|
||||
assert_equal(1000, results[n].get())
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user