Skip to content

Commit 57a083b

Browse files
committed
Update the docs for the new API
1 parent 5d7a838 commit 57a083b

File tree

5 files changed

+72
-69
lines changed

5 files changed

+72
-69
lines changed

docs/src/dev_reference.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ JuliaInterpreter.get_call_framecode
2121
JuliaInterpreter.optimize!
2222
```
2323

24+
## Frame traversal
25+
26+
```@docs
27+
root
28+
leaf
29+
```
30+
2431
## Frame execution
2532

2633
```@docs
@@ -35,6 +42,8 @@ JuliaInterpreter.through_methoddef_or_done!
3542
JuliaInterpreter.evaluate_call!
3643
JuliaInterpreter.evaluate_foreigncall
3744
JuliaInterpreter.maybe_evaluate_builtin
45+
JuliaInterpreter.maybe_next_call!
46+
JuliaInterpreter.handle_err
3847
```
3948

4049
## Breakpoints
@@ -45,6 +54,7 @@ breakpoint
4554
enable
4655
disable
4756
remove
57+
JuliaInterpreter.dummy_breakpoint
4858
```
4959

5060
## Types
@@ -53,6 +63,7 @@ remove
5363
JuliaInterpreter.Frame
5464
JuliaInterpreter.FrameCode
5565
JuliaInterpreter.FrameData
66+
JuliaInterpreter.FrameInstance
5667
JuliaInterpreter.BreakpointState
5768
JuliaInterpreter.BreakpointRef
5869
```
@@ -72,8 +83,9 @@ JuliaInterpreter.@lookup
7283
JuliaInterpreter.is_wrapper_call
7384
JuliaInterpreter.is_doc_expr
7485
JuliaInterpreter.is_global_ref
86+
CodeTracking.whereis
87+
JuliaInterpreter.linenumber
7588
JuliaInterpreter.statementnumber
7689
JuliaInterpreter.Variable
7790
JuliaInterpreter.locals
78-
CodeTracking.whereis
7991
```

docs/src/internals.md

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,25 @@ let's build a frame:
99

1010
```julia
1111
julia> frame = JuliaInterpreter.enter_call(summer, A)
12-
Frame(JuliaInterpreter.FrameCode(summer(A::AbstractArray{T,N} where N) where T in Main at REPL[1]:2, CodeInfo(
13-
1 ─ s = ($(QuoteNode(zero)))($(Expr(:static_parameter, 1)))
14-
%2 = A
15-
#temp# = ($(QuoteNode(iterate)))(%2)
16-
%4 = ($(QuoteNode(===)))(#temp#, nothing)
17-
%5 = ($(QuoteNode(not_int)))(%4)
18-
└── goto #4 if not %5
19-
2%7 = #temp#
20-
│ a = ($(QuoteNode(getfield)))(%7, 1)
21-
%9 = ($(QuoteNode(getfield)))(%7, 2)
22-
│ s = ($(QuoteNode(+)))(s, a)
23-
#temp# = ($(QuoteNode(iterate)))(%2, %9)
24-
%12 = ($(QuoteNode(===)))(#temp#, nothing)
25-
%13 = ($(QuoteNode(not_int)))(%12)
26-
└── goto #4 if not %13
27-
3 ─ goto #2
28-
4return s
29-
), Core.TypeMapEntry[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef], BitSet([2, 4, 5, 7, 9, 12, 13]), false, false, true), Union{Nothing, Some{Any}}[Some(summer), Some([1, 2, 5]), nothing, nothing, nothing], Any[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef], Any[Int64], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict{Symbol,Int64}(), Any[])
12+
Frame for summer(A::AbstractArray{T,N} where N) where T in Main at REPL[2]:2
13+
1* 2 1 ─ s = (zero)($(Expr(:static_parameter, 1)))
14+
2 3%2 = A
15+
3 3#temp# = (iterate)(%2)
16+
17+
A = [1, 2, 5]
18+
T = Int64
3019
```
3120

32-
This is a [`JuliaInterpreter.Frame`](@ref). The `CodeInfo` is the most prominent part of this display,
33-
and extractable as `code = frame.framecode.code`. (It's a slightly modified form of one returned by `@code_lowered`,
21+
This is a [`Frame`](@ref). Only a portion of the `CodeInfo` is shown, a small region surrounding
22+
the current statement (marked with `*` or in yellow text). The full `CodeInfo` can be extracted
23+
as `code = frame.framecode.src`. (It's a slightly modified form of one returned by `@code_lowered`,
3424
in that it has been processed by [`JuliaInterpreter.optimize!`](@ref) to speed up run-time execution.)
3525

36-
Much of the rest of the `frame` holds values needed for or generated by execution.
26+
`frame` has another field, `framedata`, that holds values needed for or generated by execution.
3727
The input arguments are in `locals`:
3828

3929
```julia
40-
julia> frame.locals
30+
julia> frame.framedata.locals
4131
5-element Array{Union{Nothing, Some{Any}},1}:
4232
Some(summer)
4333
Some([1, 2, 5])
@@ -62,7 +52,7 @@ The `Expr(:static_parameter, 1)` statement refers to this value.
6252
The other main storage is for the generated SSA values:
6353

6454
```julia
65-
julia> frame.ssavalues
55+
julia> frame.framedata.ssavalues
6656
16-element Array{Any,1}:
6757
#undef
6858
#undef
@@ -89,31 +79,25 @@ which just indicates the next statement to be executed:
8979

9080
```julia
9181
julia> frame.pc
92-
JuliaProgramCounter(1)
82+
1
9383
```
9484

95-
This is stored as a `Ref` so that it can be updated as execution progresses.
96-
97-
Let's try executing the first statement. So that we can recurse into calls (e.g., `iterate`, `+`, etc.,),
98-
we'll create a [stack](https://en.wikipedia.org/wiki/Call_stack) of frames and then run the first statement:
85+
Let's try executing the first statement:
9986

10087
```julia
101-
julia> stack = JuliaInterpreter.Frame[]
102-
0-element Array{Frame,1}
103-
104-
julia> JuliaInterpreter.step_expr!(stack, frame)
105-
JuliaProgramCounter(2)
88+
julia> JuliaInterpreter.step_expr!(frame)
89+
2
10690
```
10791

10892
This indicates that it ran statement 1 and is prepared to run statement 2.
10993
(It's worth noting that the first line included a `call` to `zero`, so behind the scenes
110-
JuliaInterpreter pushed this frame onto `stack`, created a new frame for `zero`,
111-
executed all the statements, and then popped the stack.)
94+
JuliaInterpreter created a new frame for `zero`, executed all the statements, and then popped
95+
back to `frame`.)
11296
Since the first statement is an assignment of a local variable, let's check the
11397
locals again:
11498

11599
```julia
116-
julia> frame.locals
100+
julia> frame.framedata.locals
117101
5-element Array{Union{Nothing, Some{Any}},1}:
118102
Some(summer)
119103
Some([1, 2, 5])
@@ -128,10 +112,10 @@ The next statement just retrieves one of the slots (the input argument `A`) and
128112
it in an SSA value:
129113

130114
```julia
131-
julia> JuliaInterpreter.step_expr!(stack, frame)
132-
JuliaProgramCounter(3)
115+
julia> JuliaInterpreter.step_expr!(frame)
116+
3
133117

134-
julia> frame.ssavalues
118+
julia> frame.framedata.ssavalues
135119
16-element Array{Any,1}:
136120
#undef
137121
[1, 2, 5]
@@ -152,9 +136,9 @@ julia> frame.ssavalues
152136
```
153137

154138
One can easily continue this until execution completes, which is indicated when `step_expr!`
155-
returns `nothing`. Alternatively, use the higher-level `JuliaInterpreter.finish!(stack, frame)`
139+
returns `nothing`. Alternatively, use the higher-level `JuliaInterpreter.finish!(frame)`
156140
to step through the entire frame,
157-
or `JuliaInterpreter.finish_and_return!(stack, frame)` to also obtain the return value.
141+
or `JuliaInterpreter.finish_and_return!(frame)` to also obtain the return value.
158142

159143
## More complex expressions
160144

@@ -171,7 +155,7 @@ ex = quote
171155
end
172156
173157
frame = JuliaInterpreter.prepare_thunk(Main, ex)
174-
JuliaInterpreter.finish_and_return!(Frame[], frame)
158+
JuliaInterpreter.finish_and_return!(frame)
175159
176160
# output
177161
@@ -196,7 +180,7 @@ Here's a demonstration of the problem:
196180
```julia
197181
ex = :(map(x->x^2, [1, 2, 3]))
198182
frame = JuliaInterpreter.prepare_thunk(Main, ex)
199-
julia> JuliaInterpreter.finish_and_return!(Frame[], frame)
183+
julia> JuliaInterpreter.finish_and_return!(frame)
200184
ERROR: this frame needs to be run a top level
201185
```
202186

@@ -235,7 +219,7 @@ function" for this type, equivalent to `(##17#18)(x) = x^2`.
235219
In some cases one can fix this simply by indicating that we want to run this frame at top level:
236220
237221
```julia
238-
julia> JuliaInterpreter.finish_and_return!(Frame[], frame, true)
222+
julia> JuliaInterpreter.finish_and_return!(frame, true)
239223
3-element Array{Int64,1}:
240224
1
241225
4
@@ -247,11 +231,10 @@ for more complex situations where there may be nested calls of new methods):
247231
248232
```julia
249233
modexs, _ = JuliaInterpreter.split_expressions(Main, ex)
250-
stack = Frame[]
251234
for (mod, e) in modexs
252235
frame = JuliaInterpreter.prepare_thunk(mod, e)
253236
while true
254-
JuliaInterpreter.through_methoddef_or_done!(stack, frame) === nothing && break
237+
JuliaInterpreter.through_methoddef_or_done!(frame) === nothing && break
255238
end
256239
JuliaInterpreter.get_return(frame)
257240
end

src/construct.jl

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,7 @@ mymethod (generic function with 1 method)
188188
julia> framecode, frameargs, lenv, argtypes = JuliaInterpreter.prepare_call(mymethod, [mymethod, [1.0,2.0]]);
189189
190190
julia> framecode
191-
JuliaInterpreter.FrameCode(mymethod(x::Array{T,1}) where T in Main at none:1, CodeInfo(
192-
1 ─ return 1
193-
), Union{Compiled, TypeMapEntry}[#undef], JuliaInterpreter.BreakpointState[#undef], BitSet([]), false, false, true)
191+
1 1 1 ─ return 1
194192
195193
julia> frameargs
196194
2-element Array{Any,1}:
@@ -477,10 +475,10 @@ julia> mymethod(x) = x+1
477475
mymethod (generic function with 1 method)
478476
479477
julia> JuliaInterpreter.enter_call_expr(:(\$mymethod(1)))
480-
Frame(JuliaInterpreter.FrameCode(mymethod(x) in Main at none:1, CodeInfo(
481-
1 ─ %1 = ($(QuoteNode(+)))(x, 1)
482-
└── return %1
483-
), Union{Compiled, TypeMapEntry}[#undef, #undef], JuliaInterpreter.BreakpointState[#undef, #undef], BitSet([1]), false, false, true), Union{Nothing, Some{Any}}[Some(mymethod), Some(1)], Any[#undef, #undef], Any[], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict(Symbol("#self#")=>1,:x=>2), Any[])
478+
Frame for mymethod(x) in Main at none:1
479+
1* 1 1 ─ %1 = (+)(x, 1)
480+
2 1 └── return %1
481+
x = 1
484482
485483
julia> mymethod(x::Vector{T}) where T = 1
486484
mymethod (generic function with 2 methods)
@@ -491,9 +489,10 @@ julia> a = [1.0, 2.0]
491489
2.0
492490
493491
julia> JuliaInterpreter.enter_call_expr(:(\$mymethod(\$a)))
494-
Frame(JuliaInterpreter.FrameCode(mymethod(x::Array{T,1}) where T in Main at none:1, CodeInfo(
495-
1 ─ return 1
496-
), Union{Compiled, TypeMapEntry}[#undef], JuliaInterpreter.BreakpointState[#undef], BitSet([]), false, false, true), Union{Nothing, Some{Any}}[Some(mymethod), Some([1.0, 2.0])], Any[#undef], Any[Float64], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict(Symbol("#self#")=>1,:x=>2), Any[])
492+
Frame for mymethod(x::Array{T,1}) where T in Main at none:1
493+
1* 1 1 ─ return 1
494+
x = [1.0, 2.0]
495+
T = Float64
497496
```
498497
499498
See [`enter_call`](@ref) for a similar approach not based on expressions.
@@ -518,18 +517,19 @@ julia> mymethod(x) = x+1
518517
mymethod (generic function with 1 method)
519518
520519
julia> JuliaInterpreter.enter_call(mymethod, 1)
521-
Frame(JuliaInterpreter.FrameCode(mymethod(x) in Main at none:1, CodeInfo(
522-
1 ─ %1 = ($(QuoteNode(+)))(x, 1)
523-
└── return %1
524-
), Union{Compiled, TypeMapEntry}[#undef, #undef], JuliaInterpreter.BreakpointState[#undef, #undef], BitSet([1]), false, false, true), Union{Nothing, Some{Any}}[Some(mymethod), Some(1)], Any[#undef, #undef], Any[], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict(Symbol("#self#")=>1,:x=>2), Any[])
520+
Frame for mymethod(x) in Main at none:1
521+
1* 1 1 ─ %1 = (+)(x, 1)
522+
2 1 └── return %1
523+
x = 1
525524
526525
julia> mymethod(x::Vector{T}) where T = 1
527526
mymethod (generic function with 2 methods)
528527
529528
julia> JuliaInterpreter.enter_call(mymethod, [1.0, 2.0])
530-
Frame(JuliaInterpreter.FrameCode(mymethod(x::Array{T,1}) where T in Main at none:1, CodeInfo(
531-
1 ─ return 1
532-
), Union{Compiled, TypeMapEntry}[#undef], JuliaInterpreter.BreakpointState[#undef], BitSet([]), false, false, true), Union{Nothing, Some{Any}}[Some(mymethod), Some([1.0, 2.0])], Any[#undef], Any[Float64], Int64[], Base.RefValue{Any}(nothing), Base.RefValue{JuliaInterpreter.JuliaProgramCounter}(JuliaProgramCounter(1)), Dict(Symbol("#self#")=>1,:x=>2), Any[])
529+
Frame for mymethod(x::Array{T,1}) where T in Main at none:1
530+
1* 1 1 ─ return 1
531+
x = [1.0, 2.0]
532+
T = Float64
533533
```
534534
535535
For a `@generated` function you can use `enter_call((f, true), args...; kwargs...)`

src/types.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,8 @@ function Base.show(io::IO, frame::Frame)
185185
range = get(io, :limit, false) ? (max(1, pc-2):min(ns, pc+2)) : (1:ns)
186186
first(range) > 1 && println(io, "")
187187
print_framecode(io, frame.framecode; pc=pc, range=range)
188-
last(range) < ns && print(io, "")
189-
for lv in locals(frame)
190-
println(IOContext(io, :limit=>true, :compact=>true), '\n', lv)
191-
end
188+
last(range) < ns && print(io, "\n")
189+
print_vars(IOContext(io, :limit=>true, :compact=>true), locals(frame))
192190
if caller(frame) !== nothing
193191
print(io, "\ncaller: ", scopeof(caller(frame)))
194192
end

src/utils.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,12 @@ function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements
225225
ndline = isempty(lt) ? 0 : ndigits(lt[end].line + offset)
226226
nullline = " "^ndline
227227
code = framecode_lines(framecode)
228+
isfirst = true
228229
for (stmtidx, stmtline) in enumerate(code)
229230
stmtidx range || continue
230231
bpc = breakpointchar(framecode, stmtidx)
232+
isfirst || print(io, '\n')
233+
isfirst = false
231234
print(io, bpc, ' ')
232235
if iscolor
233236
color = stmtidx == pc ? Base.warn_color() : :normal
@@ -236,7 +239,7 @@ function print_framecode(io::IO, framecode::FrameCode; pc=0, range=1:nstatements
236239
print(io, lpad(stmtidx, ndstmt), stmtidx == pc ? '*' : ' ')
237240
end
238241
line = linenumber(framecode, stmtidx)
239-
println(io, ' ', line === nothing ? nullline : lpad(line, ndline), " ", stmtline)
242+
print(io, ' ', line === nothing ? nullline : lpad(line, ndline), " ", stmtline)
240243
end
241244
end
242245

@@ -261,6 +264,13 @@ function locals(frame::Frame)
261264
return vars
262265
end
263266

267+
function print_vars(io::IO, vars::Vector{Variable})
268+
for v in vars
269+
v.name == Symbol("#self#") && (isa(v.value, Type) || sizeof(v.value) == 0) && continue
270+
print(io, '\n', v)
271+
end
272+
end
273+
264274
function show_stackloc(io::IO, frame)
265275
indent = ""
266276
fr = root(frame)

0 commit comments

Comments
 (0)