Skip to content

Commit 91cd0db

Browse files
authored
Merge pull request #58 from JuliaDebug/teh/rename_pt
Rename prepare_toplevel -> split_expressions
2 parents bfbee01 + 535e429 commit 91cd0db

File tree

8 files changed

+49
-43
lines changed

8 files changed

+49
-43
lines changed

docs/src/dev_reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ JuliaInterpreter.determine_method_for_expr
1616
JuliaInterpreter.prepare_args
1717
JuliaInterpreter.prepare_call
1818
JuliaInterpreter.prepare_thunk
19-
JuliaInterpreter.prepare_toplevel
19+
JuliaInterpreter.split_expressions
2020
JuliaInterpreter.get_call_framecode
2121
JuliaInterpreter.optimize!
2222
```

docs/src/internals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ Here's a more fine-grained look at what's happening under the hood (and a robust
246246
for more complex situations where there may be nested calls of new methods):
247247
248248
```julia
249-
modexs, _ = JuliaInterpreter.prepare_toplevel(Main, ex)
249+
modexs, _ = JuliaInterpreter.split_expressions(Main, ex)
250250
stack = JuliaStackFrame[]
251251
for (mod, e) in modexs
252252
frame = JuliaInterpreter.prepare_thunk(mod, e)

src/JuliaInterpreter.jl

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ end
362362
frame = prepare_thunk(mod::Module, expr::Expr)
363363
364364
Prepare `expr` for evaluation in `mod`. `expr` should be a "straightforward" expression,
365-
one that does not require special top-level handling (see [`JuliaInterpreter.prepare_toplevel`](@ref)).
365+
one that does not require special top-level handling (see [`JuliaInterpreter.split_expressions`](@ref)).
366366
"""
367367
function prepare_thunk(mod::Module, thunk::Expr, recursive=false)
368368
if isexpr(thunk, :thunk)
@@ -382,7 +382,7 @@ function prepare_thunk((mod, ex)::Tuple{Module,Expr})
382382
if isexpr(lwr, :thunk)
383383
return prepare_thunk(mod, lwr)
384384
# elseif isexpr(lwr, :toplevel)
385-
# return prepare_toplevel!(frames, docexprs, lex, mod, lwr; extract_docexprs=extract_docexprs, filename=filename)
385+
# return split_expressions!(frames, docexprs, lex, mod, lwr; extract_docexprs=extract_docexprs, filename=filename)
386386
# elseif isa(lwr, Expr) && (lwr.head == :export || lwr.head == :using || lwr.head == :import)
387387
# @show lwr
388388
# push!(modexs, (mod, ex, lwr))
@@ -394,15 +394,20 @@ function prepare_thunk((mod, ex)::Tuple{Module,Expr})
394394
end
395395

396396
"""
397-
modexs, docexprs = prepare_toplevel(mod::Module, expr::Expr; extract_docexprs=false)
397+
modexs, docexprs = split_expressions(mod::Module, expr::Expr; extract_docexprs=false)
398398
399-
Break `expr` into a list `modexs` of blocks to be successively executed at top level.
400-
This is used when `expr` defines new structs, new methods, or new modules.
399+
Break `expr` into a list `modexs` of sequential blocks. This is often needed when `expr`
400+
needs to be evaluated at top level.
401401
402-
`modexs[i]` is a `(Module, Expr)` tuple. A prototype of how to use these is:
402+
`modexs[i]` is a `(mod::Module, ex::Expr)` tuple, where `ex` is to be evaluated in `mod`.
403+
404+
# Toplevel evaluation
405+
406+
For code that defines new structs, new methods, or new macros, it can be important to evaluate
407+
these expressions carefully:
403408
404409
stack = JuliaStackFrame[]
405-
for modex in modexs
410+
for modex in modexs # or use `for (mod, ex) in modexs` to split the tuple
406411
frame = JuliaInterpreter.prepare_thunk(modex)
407412
while true
408413
JuliaInterpreter.through_methoddef_or_done!(stack, frame) === nothing && break
@@ -412,21 +417,22 @@ This is used when `expr` defines new structs, new methods, or new modules.
412417
The `while` loop here deserves some explanation. Occasionally, a frame may define new methods
413418
(e.g., anonymous or local functions) and then call those methods. In such cases, running
414419
the entire frame as a single block (e.g., with [`JuliaInterpreter.finish_and_return!`](@ref)
415-
can trigger "method is too new..." errors. Instead, this runs each frame, but returns to the caller
416-
after any new method is defined. When this loop is running at top level (e.g., in the REPL),
417-
this allows the world age to update and thus avoid "method is too new..." errors.
420+
can trigger "method is too new..." errors. Instead, the approach above runs each frame,
421+
but returns to the caller after any new method is defined. When this loop is running at
422+
top level (e.g., in the REPL), this allows the world age to update and thus avoid
423+
"method is too new..." errors.
418424
419-
Putting the above nested loop inside a function defeats the entire purpose of
420-
`prepare_toplevel`. If necessary, run that loop as
425+
Putting the above nested loop inside a function defeats its purpose, because inside a
426+
compiled function the world age will not update. If necessary, use the following strategy:
421427
422428
Core.eval(somemodule, Expr(:toplevel, quote
423429
body
424430
))
425431
426-
where `body` executes the loop plus any preparatory statements required to make the
432+
where `body` contains the nested loop, plus any preparatory statements required to make the
427433
necessary variables available at top level in `somemodule`.
428434
"""
429-
function prepare_toplevel(mod::Module, expr::Expr; filename=nothing, kwargs...)
435+
function split_expressions(mod::Module, expr::Expr; filename=nothing, kwargs...)
430436
modexs = Tuple{Module,Expr}[]
431437
docexprs = Dict{Module,Vector{Expr}}()
432438
if filename === nothing
@@ -437,7 +443,7 @@ function prepare_toplevel(mod::Module, expr::Expr; filename=nothing, kwargs...)
437443
filename="toplevel"
438444
end
439445
end
440-
return prepare_toplevel!(modexs, docexprs, mod, expr; filename=filename, kwargs...)
446+
return split_expressions!(modexs, docexprs, mod, expr; filename=filename, kwargs...)
441447
end
442448

443449
"""
@@ -459,18 +465,18 @@ function isdocexpr(ex)
459465
return false
460466
end
461467

462-
prepare_toplevel!(modexs, docexprs, mod::Module, ex::Expr; kwargs...) =
463-
prepare_toplevel!(modexs, docexprs, Expr(:block), mod, ex; kwargs...)
468+
split_expressions!(modexs, docexprs, mod::Module, ex::Expr; kwargs...) =
469+
split_expressions!(modexs, docexprs, Expr(:block), mod, ex; kwargs...)
464470

465-
function prepare_toplevel!(modexs, docexprs, lex::Expr, mod::Module, ex::Expr; extract_docexprs=false, filename="toplevel")
471+
function split_expressions!(modexs, docexprs, lex::Expr, mod::Module, ex::Expr; extract_docexprs=false, filename="toplevel")
466472
# lex is the expression we'll lower; it will accumulate LineNumberNodes and a
467473
# single top-level expression. We split blocks, module defs, etc.
468474
if ex.head == :toplevel || ex.head == :block
469-
prepare_toplevel!(modexs, docexprs, lex, mod, ex.args; extract_docexprs=extract_docexprs, filename=filename)
475+
split_expressions!(modexs, docexprs, lex, mod, ex.args; extract_docexprs=extract_docexprs, filename=filename)
470476
elseif ex.head == :module
471477
modname = ex.args[2]::Symbol
472478
newmod = isdefined(mod, modname) ? getfield(mod, modname) : Core.eval(mod, :(module $modname end))
473-
prepare_toplevel!(modexs, docexprs, lex, newmod, ex.args[3]; extract_docexprs=extract_docexprs, filename=filename)
479+
split_expressions!(modexs, docexprs, lex, newmod, ex.args[3]; extract_docexprs=extract_docexprs, filename=filename)
474480
elseif extract_docexprs && isdocexpr(ex)
475481
docexs = get(docexprs, mod, nothing)
476482
if docexs === nothing
@@ -479,7 +485,7 @@ function prepare_toplevel!(modexs, docexprs, lex::Expr, mod::Module, ex::Expr; e
479485
push!(docexs, ex)
480486
body = ex.args[4]
481487
if isa(body, Expr) && body.head != :call
482-
prepare_toplevel!(modexs, docexprs, lex, mod, body; extract_docexprs=extract_docexprs, filename=filename)
488+
split_expressions!(modexs, docexprs, lex, mod, body; extract_docexprs=extract_docexprs, filename=filename)
483489
end
484490
else
485491
if isempty(lex.args)
@@ -492,10 +498,10 @@ function prepare_toplevel!(modexs, docexprs, lex::Expr, mod::Module, ex::Expr; e
492498
return modexs, docexprs
493499
end
494500

495-
function prepare_toplevel!(frames, docexprs, lex, mod::Module, args::Vector{Any}; filename="toplevel", kwargs...)
501+
function split_expressions!(frames, docexprs, lex, mod::Module, args::Vector{Any}; filename="toplevel", kwargs...)
496502
for a in args
497503
if isa(a, Expr)
498-
prepare_toplevel!(frames, docexprs, lex, mod, a; filename=filename, kwargs...)
504+
split_expressions!(frames, docexprs, lex, mod, a; filename=filename, kwargs...)
499505
elseif isa(a, LineNumberNode)
500506
if a.file === nothing # happens with toplevel expressions on Julia 1.2
501507
push!(lex.args, LineNumberNode(a.line, Symbol(filename)))

src/interpret.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ function _step_expr!(stack, frame, @nospecialize(node), pc::JuliaProgramCounter,
380380
elseif node.head == :primitive_type
381381
evaluate_primitivetype!(stack, frame, node, pc)
382382
elseif node.head == :module
383-
error("this should have been handled by prepare_toplevel")
383+
error("this should have been handled by split_expressions")
384384
elseif node.head == :using || node.head == :import || node.head == :export
385385
Core.eval(moduleof(frame), node)
386386
elseif node.head == :const
@@ -409,7 +409,7 @@ function _step_expr!(stack, frame, @nospecialize(node), pc::JuliaProgramCounter,
409409
elseif node.head == :toplevel
410410
mod = moduleof(frame)
411411
newstack = similar(stack, 0)
412-
modexs, _ = prepare_toplevel(mod, node)
412+
modexs, _ = split_expressions(mod, node)
413413
Core.eval(mod, Expr(:toplevel,
414414
:(for modex in $modexs
415415
newframe = ($prepare_thunk)(modex)
@@ -477,7 +477,7 @@ function handle_err(frame, err)
477477
if (err.world != typemax(UInt) &&
478478
hasmethod(err.f, arg_types) &&
479479
!hasmethod(err.f, arg_types, world = err.world))
480-
@warn "likely failure to return to toplevel, try JuliaInterpreter.prepare_toplevel"
480+
@warn "likely failure to return to toplevel, try JuliaInterpreter.split_expressions"
481481
rethrow(err)
482482
end
483483
end

src/precompile.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function _precompile_()
2323
precompile(Tuple{typeof(f), Compiled, JuliaStackFrame, JuliaProgramCounter, Bool})
2424
precompile(Tuple{typeof(f), Vector{JuliaStackFrame}, JuliaStackFrame, JuliaProgramCounter, Bool})
2525
end
26-
precompile(Tuple{typeof(prepare_toplevel), Module, Expr})
26+
precompile(Tuple{typeof(split_expressions), Module, Expr})
2727
precompile(Tuple{typeof(prepare_thunk), Module, Expr})
2828
precompile(Tuple{typeof(prepare_locals), JuliaFrameCode, Vector{Any}})
2929
precompile(Tuple{typeof(prepare_args), Any, Vector{Any}, Vector{Any}})

test/limits.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ using Test
1515
end
1616
@elapsed sum(rand(5))
1717
"""; filename="fake.jl")
18-
modexs, _ = JuliaInterpreter.prepare_toplevel(Main, ex; filename="fake.jl")
18+
modexs, _ = JuliaInterpreter.split_expressions(Main, ex; filename="fake.jl")
1919
# find the 3rd assignment statement in the 2nd frame (corresponding to the x += 1 line)
2020
frame = JuliaInterpreter.prepare_thunk(modexs[2])
2121
i = 0
@@ -51,7 +51,7 @@ module EvalLimited end
5151
s += 1
5252
end
5353
""")
54-
modexs, _ = JuliaInterpreter.prepare_toplevel(EvalLimited, ex)
54+
modexs, _ = JuliaInterpreter.split_expressions(EvalLimited, ex)
5555
nstmts = 1000 # enough to ensure it finishes
5656
for modex in modexs
5757
frame = JuliaInterpreter.prepare_thunk(modex)
@@ -78,7 +78,7 @@ module EvalLimited end
7878
insert!(ex.args, 2, LineNumberNode(2, Symbol("fake.jl")))
7979
insert!(ex.args, 1, LineNumberNode(1, Symbol("fake.jl")))
8080
end
81-
modexs, _ = JuliaInterpreter.prepare_toplevel(EvalLimited, ex)
81+
modexs, _ = JuliaInterpreter.split_expressions(EvalLimited, ex)
8282
nstmts = 100 # enough to ensure it gets into the loop but doesn't finish
8383
for modex in modexs
8484
frame = JuliaInterpreter.prepare_thunk(modex)
@@ -96,7 +96,7 @@ module EvalLimited end
9696

9797
# Now try again with recursive stack
9898
empty!(aborts)
99-
modexs, _ = JuliaInterpreter.prepare_toplevel(EvalLimited, ex)
99+
modexs, _ = JuliaInterpreter.split_expressions(EvalLimited, ex)
100100
for modex in modexs
101101
frame = JuliaInterpreter.prepare_thunk(modex)
102102
@test isa(frame, JuliaStackFrame)

test/toplevel.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module Toplevel end
1717

1818
@testset "toplevel" begin
1919
stack = JuliaInterpreter.JuliaStackFrame[]
20-
modexs, _ = JuliaInterpreter.prepare_toplevel(Toplevel, read_and_parse("toplevel_script.jl"))
20+
modexs, _ = JuliaInterpreter.split_expressions(Toplevel, read_and_parse("toplevel_script.jl"))
2121
for modex in modexs
2222
frame = JuliaInterpreter.prepare_thunk(modex)
2323
while true
@@ -167,7 +167,7 @@ module Toplevel end
167167
end
168168
end
169169
end
170-
modexs, _ = JuliaInterpreter.prepare_toplevel(Toplevel, ex)
170+
modexs, _ = JuliaInterpreter.split_expressions(Toplevel, ex)
171171
for modex in modexs
172172
frame = JuliaInterpreter.prepare_thunk(modex)
173173
while true
@@ -208,7 +208,7 @@ ex = quote
208208
test_15703()
209209
end
210210
end
211-
modexs, _ = JuliaInterpreter.prepare_toplevel(IncTest, ex)
211+
modexs, _ = JuliaInterpreter.split_expressions(IncTest, ex)
212212
stack = JuliaStackFrame[]
213213
for (i, modex) in enumerate(modexs)
214214
frame = JuliaInterpreter.prepare_thunk(modex)
@@ -226,7 +226,7 @@ end
226226
EnumChild0
227227
EnumChild1
228228
end))
229-
modexs, _ = JuliaInterpreter.prepare_toplevel(Toplevel, ex)
229+
modexs, _ = JuliaInterpreter.split_expressions(Toplevel, ex)
230230
stack = JuliaStackFrame[]
231231
for modex in modexs
232232
frame = JuliaInterpreter.prepare_thunk(modex)
@@ -250,7 +250,7 @@ end
250250
ret[] = map(x->parse(Int16, x), AbstractString[])
251251
end
252252
stack = JuliaStackFrame[]
253-
modexs, _ = JuliaInterpreter.prepare_toplevel(LowerAnon, ex1)
253+
modexs, _ = JuliaInterpreter.split_expressions(LowerAnon, ex1)
254254
for modex in modexs
255255
frame = JuliaInterpreter.prepare_thunk(modex)
256256
while true
@@ -259,7 +259,7 @@ end
259259
end
260260
@test isa(LowerAnon.ret[], Vector{Int16})
261261
LowerAnon.ret[] = nothing
262-
modexs, _ = JuliaInterpreter.prepare_toplevel(LowerAnon, ex2)
262+
modexs, _ = JuliaInterpreter.split_expressions(LowerAnon, ex2)
263263
for modex in modexs
264264
frame = JuliaInterpreter.prepare_thunk(modex)
265265
while true
@@ -272,7 +272,7 @@ end
272272
ex3 = quote
273273
const BitIntegerType = Union{map(T->Type{T}, Base.BitInteger_types)...}
274274
end
275-
modexs, _ = JuliaInterpreter.prepare_toplevel(LowerAnon, ex3)
275+
modexs, _ = JuliaInterpreter.split_expressions(LowerAnon, ex3)
276276
for modex in modexs
277277
frame = JuliaInterpreter.prepare_thunk(modex)
278278
while true
@@ -286,7 +286,7 @@ end
286286
z = map(x->x^2+y, [1,2,3])
287287
y = 4
288288
end
289-
modexs, _ = JuliaInterpreter.prepare_toplevel(LowerAnon, ex4)
289+
modexs, _ = JuliaInterpreter.split_expressions(LowerAnon, ex4)
290290
for modex in modexs
291291
frame = JuliaInterpreter.prepare_thunk(modex)
292292
while true
@@ -319,7 +319,7 @@ end
319319
end
320320
end
321321
Core.eval(Toplevel, Expr(:toplevel, ex.args...))
322-
modexs, docexprs = JuliaInterpreter.prepare_toplevel(Toplevel, ex; extract_docexprs=true)
322+
modexs, docexprs = JuliaInterpreter.split_expressions(Toplevel, ex; extract_docexprs=true)
323323
for (mod, ex) in modexs
324324
frame = JuliaInterpreter.prepare_thunk(mod, ex)
325325
while true

test/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ function run_test_by_eval(test, fullpath, nstmts)
168168
ts = Test.DefaultTestSet($test)
169169
Test.push_testset(ts)
170170
current_task().storage[:SOURCE_PATH] = $fullpath
171-
modexs, _ = JuliaInterpreter.prepare_toplevel(JuliaTests, ex)
171+
modexs, _ = JuliaInterpreter.split_expressions(JuliaTests, ex)
172172
stack = JuliaStackFrame[]
173173
for (i, modex) in enumerate(modexs) # having the index can be useful for debugging
174174
nstmtsleft = $nstmts

0 commit comments

Comments
 (0)