Skip to content

Commit 189d94d

Browse files
committed
use sentinal for REPL_MODULE_REF
Working with #undef is unnecessarily trickier and more limited than using a token, which allows more flexibility with updates.
1 parent e621c74 commit 189d94d

File tree

6 files changed

+51
-48
lines changed

6 files changed

+51
-48
lines changed

base/Base.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ delete_method(which(Pair{Any,Any}, (Any, Any)))
224224
end
225225

226226
# The REPL stdlib hooks into Base using this Ref
227-
const REPL_MODULE_REF = Ref{Module}()
227+
const REPL_MODULE_REF = Ref{Module}(Base)
228228

229229
include("checked.jl")
230230
using .Checked

base/client.jl

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -417,18 +417,59 @@ end
417417

418418
global active_repl
419419

420+
function run_fallback_repl(interactive::Bool)
421+
let input = stdin
422+
if isa(input, File) || isa(input, IOStream)
423+
# for files, we can slurp in the whole thing at once
424+
ex = parse_input_line(read(input, String))
425+
if Meta.isexpr(ex, :toplevel)
426+
# if we get back a list of statements, eval them sequentially
427+
# as if we had parsed them sequentially
428+
for stmt in ex.args
429+
eval_user_input(stderr, stmt, true)
430+
end
431+
body = ex.args
432+
else
433+
eval_user_input(stderr, ex, true)
434+
end
435+
else
436+
while !eof(input)
437+
if interactive
438+
print("julia> ")
439+
flush(stdout)
440+
end
441+
try
442+
line = ""
443+
ex = nothing
444+
while !eof(input)
445+
line *= readline(input, keep=true)
446+
ex = parse_input_line(line)
447+
if !(isa(ex, Expr) && ex.head === :incomplete)
448+
break
449+
end
450+
end
451+
eval_user_input(stderr, ex, true)
452+
catch err
453+
isa(err, InterruptException) ? print("\n\n") : rethrow()
454+
end
455+
end
456+
end
457+
end
458+
end
459+
420460
# run the requested sort of evaluation loop on stdio
421461
function run_main_repl(interactive::Bool, quiet::Bool, banner::Symbol, history_file::Bool)
422462
fallback_repl = parse(Bool, get(ENV, "JULIA_FALLBACK_REPL", "false"))
423463
if !fallback_repl && interactive
424464
load_InteractiveUtils()
425-
if !isassigned(REPL_MODULE_REF)
465+
REPL = REPL_MODULE_REF[]
466+
if REPL === Base
426467
load_REPL()
427468
end
428469
end
429-
# TODO cleanup REPL_MODULE_REF
430-
if !fallback_repl && interactive && isassigned(REPL_MODULE_REF)
431-
invokelatest(REPL_MODULE_REF[]) do REPL
470+
REPL = REPL_MODULE_REF[]
471+
if !fallback_repl && interactive && REPL !== Base
472+
invokelatest(REPL) do REPL
432473
term_env = get(ENV, "TERM", @static Sys.iswindows() ? "" : "dumb")
433474
term = REPL.Terminals.TTYTerminal(term_env, stdin, stdout, stderr)
434475
banner == :no || REPL.banner(term, short=banner==:short)
@@ -447,47 +488,10 @@ function run_main_repl(interactive::Bool, quiet::Bool, banner::Symbol, history_f
447488
REPL.run_repl(repl, backend->(global active_repl_backend = backend))
448489
end
449490
else
450-
# otherwise provide a simple fallback
451491
if !fallback_repl && interactive && !quiet
452492
@warn "REPL provider not available: using basic fallback" LOAD_PATH=join(Base.LOAD_PATH, Sys.iswindows() ? ';' : ':')
453493
end
454-
let input = stdin
455-
if isa(input, File) || isa(input, IOStream)
456-
# for files, we can slurp in the whole thing at once
457-
ex = parse_input_line(read(input, String))
458-
if Meta.isexpr(ex, :toplevel)
459-
# if we get back a list of statements, eval them sequentially
460-
# as if we had parsed them sequentially
461-
for stmt in ex.args
462-
eval_user_input(stderr, stmt, true)
463-
end
464-
body = ex.args
465-
else
466-
eval_user_input(stderr, ex, true)
467-
end
468-
else
469-
while !eof(input)
470-
if interactive
471-
print("julia> ")
472-
flush(stdout)
473-
end
474-
try
475-
line = ""
476-
ex = nothing
477-
while !eof(input)
478-
line *= readline(input, keep=true)
479-
ex = parse_input_line(line)
480-
if !(isa(ex, Expr) && ex.head === :incomplete)
481-
break
482-
end
483-
end
484-
eval_user_input(stderr, ex, true)
485-
catch err
486-
isa(err, InterruptException) ? print("\n\n") : rethrow()
487-
end
488-
end
489-
end
490-
end
494+
run_fallback_repl(interactive)
491495
end
492496
nothing
493497
end

base/docs/Docs.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,9 +610,8 @@ function docm(source::LineNumberNode, mod::Module, ex)
610610
@nospecialize ex
611611
if isexpr(ex, :->) && length(ex.args) > 1
612612
return docm(source, mod, ex.args...)
613-
elseif isassigned(Base.REPL_MODULE_REF)
613+
elseif (REPL = Base.REPL_MODULE_REF[]) !== Base
614614
# TODO: this is a shim to continue to allow `@doc` for looking up docstrings
615-
REPL = Base.REPL_MODULE_REF[]
616615
return invokelatest(REPL.lookup_doc, ex)
617616
else
618617
return simple_lookup_doc(ex)

base/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,8 @@ function _show_default(io::IO, @nospecialize(x))
514514
end
515515

516516
function active_module()
517-
isassigned(REPL_MODULE_REF) || return Main
518517
REPL = REPL_MODULE_REF[]
518+
REPL === Base && return Main
519519
return invokelatest(REPL.active_module)::Module
520520
end
521521

stdlib/REPL/src/docview.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ repl_corrections(s) = repl_corrections(stdout, s)
475475
# inverse of latex_symbols Dict, lazily created as needed
476476
const symbols_latex = Dict{String,String}()
477477
function symbol_latex(s::String)
478-
if isempty(symbols_latex) && isassigned(Base.REPL_MODULE_REF)
478+
if isempty(symbols_latex)
479479
for (k,v) in Iterators.flatten((REPLCompletions.latex_symbols,
480480
REPLCompletions.emoji_symbols))
481481
symbols_latex[v] = k

stdlib/REPL/test/repl.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ using Markdown
99

1010
empty!(Base.Experimental._hint_handlers) # unregister error hints so they can be tested separately
1111

12-
@test isassigned(Base.REPL_MODULE_REF)
12+
@test Base.REPL_MODULE_REF[] === REPL
1313

1414
const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test")
1515
isdefined(Main, :FakePTYs) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "FakePTYs.jl"))

0 commit comments

Comments
 (0)