also looking at this
fix(interpreter): keep the return value across deferred user calls
#929
2 files
+203
-84
| @@ -316,12 +316,7 @@ pub const Interpreter = struct { | ||
| 316 | 316 | } |
| 317 | 317 | |
| 318 | 318 | // Execute defers at end of then block |
| 319 | const defers = then_env.getDefers(); | |
| 320 | var i: usize = defers.len; | |
| 321 | while (i > 0) { | |
| 322 | i -= 1; | |
| 323 | _ = self.evaluateExpression(defers[i], &then_env) catch {}; | |
| 324 | } | |
| 319 | self.runDefers(&then_env, then_err); | |
| 325 | 320 | |
| 326 | 321 | if (then_err) |err| return err; |
| 327 | 322 | } else if (if_stmt.else_block) |else_block| { |
| @@ -338,12 +333,7 @@ pub const Interpreter = struct { | ||
| 338 | 333 | } |
| 339 | 334 | |
| 340 | 335 | // Execute defers at end of else block |
| 341 | const defers = else_env.getDefers(); | |
| 342 | var i: usize = defers.len; | |
| 343 | while (i > 0) { | |
| 344 | i -= 1; | |
| 345 | _ = self.evaluateExpression(defers[i], &else_env) catch {}; | |
| 346 | } | |
| 336 | self.runDefers(&else_env, else_err); | |
| 347 | 337 | |
| 348 | 338 | if (else_err) |err| return err; |
| 349 | 339 | } |
| @@ -372,12 +362,7 @@ pub const Interpreter = struct { | ||
| 372 | 362 | } |
| 373 | 363 | |
| 374 | 364 | // Execute defers at end of iteration |
| 375 | const defers = iter_env.getDefers(); | |
| 376 | var i: usize = defers.len; | |
| 377 | while (i > 0) { | |
| 378 | i -= 1; | |
| 379 | _ = self.evaluateExpression(defers[i], &iter_env) catch {}; | |
| 380 | } | |
| 365 | self.runDefers(&iter_env, iter_err); | |
| 381 | 366 | |
| 382 | 367 | // Handle errors after defers |
| 383 | 368 | if (iter_err) |err| { |
| @@ -438,12 +423,7 @@ pub const Interpreter = struct { | ||
| 438 | 423 | } |
| 439 | 424 | |
| 440 | 425 | // Execute defers at end of iteration |
| 441 | const defers = iter_env.getDefers(); | |
| 442 | var di: usize = defers.len; | |
| 443 | while (di > 0) { | |
| 444 | di -= 1; | |
| 445 | _ = self.evaluateExpression(defers[di], &iter_env) catch {}; | |
| 446 | } | |
| 426 | self.runDefers(&iter_env, iter_err); | |
| 447 | 427 | |
| 448 | 428 | if (iter_err) |err| { |
| 449 | 429 | if (err == error.Return) return err; |
| @@ -484,12 +464,7 @@ pub const Interpreter = struct { | ||
| 484 | 464 | }; |
| 485 | 465 | } |
| 486 | 466 | |
| 487 | const defers = iter_env.getDefers(); | |
| 488 | var di: usize = defers.len; | |
| 489 | while (di > 0) { | |
| 490 | di -= 1; | |
| 491 | _ = self.evaluateExpression(defers[di], &iter_env) catch {}; | |
| 492 | } | |
| 467 | self.runDefers(&iter_env, iter_err); | |
| 493 | 468 | |
| 494 | 469 | if (iter_err) |err| { |
| 495 | 470 | if (err == error.Return) return err; |
| @@ -539,12 +514,7 @@ pub const Interpreter = struct { | ||
| 539 | 514 | }; |
| 540 | 515 | } |
| 541 | 516 | |
| 542 | const defers = iter_env.getDefers(); | |
| 543 | var di: usize = defers.len; | |
| 544 | while (di > 0) { | |
| 545 | di -= 1; | |
| 546 | _ = self.evaluateExpression(defers[di], &iter_env) catch {}; | |
| 547 | } | |
| 517 | self.runDefers(&iter_env, iter_err); | |
| 548 | 518 | |
| 549 | 519 | if (iter_err) |err| { |
| 550 | 520 | if (err == error.Return) return err; |
| @@ -587,12 +557,7 @@ pub const Interpreter = struct { | ||
| 587 | 557 | }; |
| 588 | 558 | } |
| 589 | 559 | |
| 590 | const defers = iter_env.getDefers(); | |
| 591 | var di: usize = defers.len; | |
| 592 | while (di > 0) { | |
| 593 | di -= 1; | |
| 594 | _ = self.evaluateExpression(defers[di], &iter_env) catch {}; | |
| 595 | } | |
| 560 | self.runDefers(&iter_env, iter_err); | |
| 596 | 561 | |
| 597 | 562 | if (iter_err) |err| { |
| 598 | 563 | if (err == error.Return) return err; |
| @@ -800,12 +765,7 @@ pub const Interpreter = struct { | ||
| 800 | 765 | } |
| 801 | 766 | |
| 802 | 767 | // Execute defers in reverse order (LIFO) |
| 803 | const defers = block_env.getDefers(); | |
| 804 | var i: usize = defers.len; | |
| 805 | while (i > 0) { | |
| 806 | i -= 1; | |
| 807 | _ = self.evaluateExpression(defers[i], &block_env) catch {}; | |
| 808 | } | |
| 768 | self.runDefers(&block_env, block_err); | |
| 809 | 769 | |
| 810 | 770 | // Propagate any error that occurred |
| 811 | 771 | if (block_err) |err| { |
| @@ -9072,12 +9032,7 @@ pub const Interpreter = struct { | ||
| 9072 | 9032 | } |
| 9073 | 9033 | |
| 9074 | 9034 | // Execute defers in reverse order before returning |
| 9075 | const defers = closure_env.getDefers(); | |
| 9076 | var i: usize = defers.len; | |
| 9077 | while (i > 0) { | |
| 9078 | i -= 1; | |
| 9079 | _ = self.evaluateExpression(defers[i], closure_env) catch {}; | |
| 9080 | } | |
| 9035 | self.runDefers(closure_env, closure_err); | |
| 9081 | 9036 | |
| 9082 | 9037 | // Handle return or error |
| 9083 | 9038 | if (closure_err) |err| { |
| @@ -9132,12 +9087,7 @@ pub const Interpreter = struct { | ||
| 9132 | 9087 | } |
| 9133 | 9088 | |
| 9134 | 9089 | // Execute defers in reverse order before returning |
| 9135 | const defers = closure_env.getDefers(); | |
| 9136 | var i: usize = defers.len; | |
| 9137 | while (i > 0) { | |
| 9138 | i -= 1; | |
| 9139 | _ = self.evaluateExpression(defers[i], &closure_env) catch {}; | |
| 9140 | } | |
| 9090 | self.runDefers(&closure_env, closure_err); | |
| 9141 | 9091 | |
| 9142 | 9092 | // Handle return or error |
| 9143 | 9093 | if (closure_err) |err| { |
| @@ -9229,12 +9179,7 @@ pub const Interpreter = struct { | ||
| 9229 | 9179 | }; |
| 9230 | 9180 | } |
| 9231 | 9181 | |
| 9232 | const defers = closure_env.getDefers(); | |
| 9233 | var i: usize = defers.len; | |
| 9234 | while (i > 0) { | |
| 9235 | i -= 1; | |
| 9236 | _ = self.evaluateExpression(defers[i], &closure_env) catch {}; | |
| 9237 | } | |
| 9182 | self.runDefers(&closure_env, closure_err); | |
| 9238 | 9183 | |
| 9239 | 9184 | if (closure_err) |err| { |
| 9240 | 9185 | if (err == error.Return) { |
| @@ -10948,6 +10893,22 @@ pub const Interpreter = struct { | ||
| 10948 | 10893 | return error.UndefinedFunction; |
| 10949 | 10894 | } |
| 10950 | 10895 | |
| 10896 | /// Run `env`'s deferred expressions in reverse order. `scope_err` is the | |
| 10897 | /// error the scope is exiting with. A deferred call to a user function | |
| 10898 | /// clears `return_value`, so when the scope is unwinding a `return` and the | |
| 10899 | /// defers leave the slot empty, the pending value is put back. | |
| 10900 | fn runDefers(self: *Interpreter, env: *Environment, scope_err: ?InterpreterError) void { | |
| 10901 | const pending_return = self.return_value; | |
| 10902 | const defers = env.getDefers(); | |
| 10903 | var i: usize = defers.len; | |
| 10904 | while (i > 0) { | |
| 10905 | i -= 1; | |
| 10906 | _ = self.evaluateExpression(defers[i], env) catch {}; | |
| 10907 | } | |
| 10908 | const returning = if (scope_err) |err| err == error.Return else false; | |
| 10909 | if (returning and self.return_value == null) self.return_value = pending_return; | |
| 10910 | } | |
| 10911 | ||
| 10951 | 10912 | fn calculateRangeLength(range: .RangeValue) i64 { |
| 10952 | 10913 | if (range.step == 0) return 0; |
| 10953 | 10914 | const diff = range.end - range.start; |
| @@ -11041,12 +11002,7 @@ pub const Interpreter = struct { | ||
| 11041 | 11002 | } |
| 11042 | 11003 | |
| 11043 | 11004 | // Execute defers in reverse order before returning |
| 11044 | const defers = func_env.getDefers(); | |
| 11045 | var i: usize = defers.len; | |
| 11046 | while (i > 0) { | |
| 11047 | i -= 1; | |
| 11048 | _ = self.evaluateExpression(defers[i], &func_env) catch {}; | |
| 11049 | } | |
| 11005 | self.runDefers(&func_env, func_err); | |
| 11050 | 11006 | |
| 11051 | 11007 | // Handle return or error |
| 11052 | 11008 | if (func_err) |err| { |
| @@ -11122,12 +11078,7 @@ pub const Interpreter = struct { | ||
| 11122 | 11078 | } |
| 11123 | 11079 | |
| 11124 | 11080 | // Execute defers in reverse order before returning |
| 11125 | const defers = method_env.getDefers(); | |
| 11126 | var i: usize = defers.len; | |
| 11127 | while (i > 0) { | |
| 11128 | i -= 1; | |
| 11129 | _ = self.evaluateExpression(defers[i], &method_env) catch {}; | |
| 11130 | } | |
| 11081 | self.runDefers(&method_env, method_err); | |
| 11131 | 11082 | |
| 11132 | 11083 | // Handle return or error |
| 11133 | 11084 | if (method_err) |err| { |
| @@ -11178,12 +11129,7 @@ pub const Interpreter = struct { | ||
| 11178 | 11129 | } |
| 11179 | 11130 | |
| 11180 | 11131 | // Execute defers in reverse order before returning |
| 11181 | const defers = method_env.getDefers(); | |
| 11182 | var i: usize = defers.len; | |
| 11183 | while (i > 0) { | |
| 11184 | i -= 1; | |
| 11185 | _ = self.evaluateExpression(defers[i], &method_env) catch {}; | |
| 11186 | } | |
| 11132 | self.runDefers(&method_env, method_err); | |
| 11187 | 11133 | |
| 11188 | 11134 | // Handle return or error |
| 11189 | 11135 | if (method_err) |err| { |