|
| 1 | +using JuliaInterpreter, Test |
| 2 | +using JuliaInterpreter: enter_call, enter_call_expr, get_return |
| 3 | + |
| 4 | +function step_through(frame) |
| 5 | + r = root(frame) |
| 6 | + @test debug_command(JuliaInterpreter.finish_and_return!, frame, "c") === nothing |
| 7 | + @test r.callee === nothing |
| 8 | + return get_return(r) |
| 9 | +end |
| 10 | + |
| 11 | +@generated function generatedfoo(T) |
| 12 | + :(return $T) |
| 13 | +end |
| 14 | +callgenerated() = generatedfoo(1) |
| 15 | + |
| 16 | +macro insert_some_calls() |
| 17 | + esc(quote |
| 18 | + x = sin(b) |
| 19 | + y = asin(x) |
| 20 | + z = sin(y) |
| 21 | + end) |
| 22 | +end |
| 23 | + |
| 24 | +# @testset "Debug" begin |
| 25 | + @testset "Basics" begin |
| 26 | + frame = enter_call(map, x->2x, 1:10) |
| 27 | + @test debug_command(frame, "finish") === nothing |
| 28 | + @test frame.caller === frame.callee === nothing |
| 29 | + @test get_return(frame) == map(x->2x, 1:10) |
| 30 | + |
| 31 | + function complicated_keyword_stuff(args...; kw...) |
| 32 | + args[1] == args[1] |
| 33 | + (args..., kw...) |
| 34 | + end |
| 35 | + for (args, kwargs) in (((1,), ()), ((1, 2), (x=7, y=33))) |
| 36 | + frame = enter_call(complicated_keyword_stuff, args...; kwargs...) |
| 37 | + f, pc = debug_command(frame, "n") |
| 38 | + @test f === frame |
| 39 | + @test isa(pc, Int) |
| 40 | + @test debug_command(frame, "finish") === nothing |
| 41 | + @test frame.caller === frame.callee === nothing |
| 42 | + @test get_return(frame) == complicated_keyword_stuff(args...; kwargs...) |
| 43 | + end |
| 44 | + |
| 45 | + f22() = string(:(a+b)) |
| 46 | + @test step_through(enter_call(f22)) == "a + b" |
| 47 | + f22() = string(QuoteNode(:a)) |
| 48 | + @test step_through(enter_call(f22)) == ":a" |
| 49 | + |
| 50 | + @test step_through(enter_call_expr(:($(+)(1,2.5)))) == 3.5 |
| 51 | + @test step_through(enter_call_expr(:($(sin)(1)))) == sin(1) |
| 52 | + @test step_through(enter_call_expr(:($(gcd)(10,20)))) == gcd(10, 20) |
| 53 | + end |
| 54 | + |
| 55 | + @testset "generated" begin |
| 56 | + frame = enter_call_expr(:($(callgenerated)())) |
| 57 | + f, pc = debug_command(frame, "s") |
| 58 | + @test isa(pc, BreakpointRef) |
| 59 | + @test JuliaInterpreter.scopeof(f).name == :generatedfoo |
| 60 | + stmt = JuliaInterpreter.pc_expr(f) |
| 61 | + @test stmt.head == :return && stmt.args[1] === Int |
| 62 | + @test debug_command(frame, "c") === nothing |
| 63 | + @test frame.callee === nothing |
| 64 | + @test get_return(frame) === Int |
| 65 | + # This time, step into the generated function itself |
| 66 | + frame = enter_call_expr(:($(callgenerated)())) |
| 67 | + f, pc = debug_command(frame, "sg") |
| 68 | + @test isa(pc, BreakpointRef) |
| 69 | + @test JuliaInterpreter.scopeof(f).name == :generatedfoo |
| 70 | + stmt = JuliaInterpreter.pc_expr(f) |
| 71 | + @test stmt.head == :return && JuliaInterpreter.@lookup(f, stmt.args[1]) === 1 |
| 72 | + f2, pc = debug_command(f, "finish") |
| 73 | + @test JuliaInterpreter.scopeof(f2).name == :callgenerated |
| 74 | + # Now finish the regular function |
| 75 | + @test debug_command(frame, "finish") === nothing |
| 76 | + @test frame.callee === nothing |
| 77 | + @test get_return(frame) === 1 |
| 78 | + end |
| 79 | + |
| 80 | + @testset "Optional arguments" begin |
| 81 | + function optional(n = sin(1)) |
| 82 | + x = asin(n) |
| 83 | + cos(x) |
| 84 | + end |
| 85 | + frame = JuliaInterpreter.enter_call_expr(:($(optional)())) |
| 86 | + # First call steps in and executes the first statement |
| 87 | + f, pc = debug_command(frame, "n") |
| 88 | + @test frame !== f |
| 89 | + # cos(1.0) |
| 90 | + debug_command(f, "n") |
| 91 | + # return |
| 92 | + f2, pc = debug_command(f, "n") |
| 93 | + @test f2 === frame |
| 94 | + @test debug_command(frame, "n") === nothing |
| 95 | + end |
| 96 | + |
| 97 | + @testset "Macros" begin |
| 98 | + # Work around the fact that we can't detect macro expansions if the macro |
| 99 | + # is defined in the same file |
| 100 | + include_string(Main, """ |
| 101 | + function test_macro() |
| 102 | + a = sin(5) |
| 103 | + b = asin(a) |
| 104 | + @insert_some_calls |
| 105 | + z |
| 106 | + end |
| 107 | + ""","file.jl") |
| 108 | + frame = JuliaInterpreter.enter_call_expr(:($(test_macro)())) |
| 109 | + f, pc = debug_command(frame, "n") # a is set |
| 110 | + f, pc = debug_command(f, "n") # b is set |
| 111 | + f, pc = debug_command(f, "n") # x is set |
| 112 | + f, pc = debug_command(f, "n") # y is set |
| 113 | + f, pc = debug_command(f, "n") # z is set |
| 114 | + @test debug_command(f, "n") === nothing # return |
| 115 | + end |
| 116 | + |
| 117 | + @testset "Keyword arguments" begin |
| 118 | + f(x; b = 1) = x+b |
| 119 | + g() = f(1; b = 2) |
| 120 | + frame = JuliaInterpreter.enter_call_expr(:($(g)())); |
| 121 | + fr, pc = debug_command(frame, "nc") |
| 122 | + fr, pc = debug_command(fr, "nc") |
| 123 | + fr, pc = debug_command(fr, "nc") |
| 124 | + fr, pc = debug_command(fr, "s") |
| 125 | + fr, pc = debug_command(fr, "finish") |
| 126 | + @test debug_command(fr, "finish") === nothing |
| 127 | + @test frame.callee === nothing |
| 128 | + @test get_return(frame) == 3 |
| 129 | + end |
| 130 | + |
| 131 | +# end |
0 commit comments