From 3ac30b97655cd233a913cb2c606b96898bde1c58 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 11 Feb 2019 17:56:42 -0600 Subject: [PATCH 1/2] Handle rethrow rethrow is only viable inside a `catch`, so we need to intercept it and convert it to an ordinary `throw`. --- src/interpret.jl | 3 +++ test/interpret.jl | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/interpret.jl b/src/interpret.jl index 9ea3977698e0a..d0484dfb075e5 100644 --- a/src/interpret.jl +++ b/src/interpret.jl @@ -172,6 +172,9 @@ function evaluate_call!(stack, frame::JuliaStackFrame, call_expr::Expr, pc) fargs = collect_args(frame, call_expr) if fargs[1] === Core.eval return Core.eval(fargs[2], fargs[3]) # not a builtin, but worth treating specially + elseif fargs[1] === Base.rethrow + err = length(fargs) > 1 ? fargs[2] : frame.last_exception[] + throw(err) end framecode, lenv = get_call_framecode(fargs, frame.code, pc.next_stmt) if lenv === nothing diff --git a/test/interpret.jl b/test/interpret.jl index c12b491ac8f47..0fd88e044708c 100644 --- a/test/interpret.jl +++ b/test/interpret.jl @@ -30,6 +30,55 @@ end fkw(x::Int8; y=0, z="hello") = y @test @interpret(fkw(Int8(1); y=22, z="world")) == fkw(Int8(1); y=22, z="world") +# Throwing exceptions across frames +function f_exc_inner() + error("inner") +end + +f_exc_inner2() = f_exc_inner() + +const caught = Ref(false) +function f_exc_outer1() + try + f_exc_inner() + catch err # with an explicit err capture + caught[] = true + rethrow(err) + end +end + +function f_exc_outer2() + try + f_exc_inner() + catch # implicit err capture + caught[] = true + rethrow() + end +end + +function f_exc_outer3(f) + try + f() + catch err + return err + end +end + +@test !caught[] +ret = @interpret f_exc_outer3(f_exc_outer1) +@test ret == ErrorException("inner") +@test caught[] + +caught[] = false +ret = @interpret f_exc_outer3(f_exc_outer2) +@test ret == ErrorException("inner") +@test caught[] + +caught[] = false +ret = @interpret f_exc_outer3(f_exc_inner2) +@test ret == ErrorException("inner") +@test !caught[] + # issue #3 @test @interpret(joinpath("/home/julia/base", "sysimg.jl")) == "/home/julia/base/sysimg.jl" @test @interpret(10.0^4) == 10.0^4 From 5d986fb8096be072da6b15d6a4702a35b4db6886 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 12 Feb 2019 03:04:37 -0600 Subject: [PATCH 2/2] Add a broken test for stacktraces Ideally atsign-interpret would throw stacktraces identical to those from compiled code. Unfortunately at present the stacktrace points to lines in the interpreter itself. --- test/interpret.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/interpret.jl b/test/interpret.jl index 0fd88e044708c..311c36ddc1b34 100644 --- a/test/interpret.jl +++ b/test/interpret.jl @@ -79,6 +79,15 @@ ret = @interpret f_exc_outer3(f_exc_inner2) @test ret == ErrorException("inner") @test !caught[] + +stc = try f_exc_outer1() catch + stacktrace(catch_backtrace()) +end +sti = try @interpret(f_exc_outer1()) catch + stacktrace(catch_backtrace()) +end +@test_broken stc == sti + # issue #3 @test @interpret(joinpath("/home/julia/base", "sysimg.jl")) == "/home/julia/base/sysimg.jl" @test @interpret(10.0^4) == 10.0^4