@@ -120,6 +120,22 @@ mutable struct REPLBackend
120120end
121121REPLBackend () = REPLBackend (Channel (1 ), Channel (1 ), false )
122122
123+ # A reference to a backend that is not mutable
124+ struct REPLBackendRef
125+ repl_channel:: Channel{Any}
126+ response_channel:: Channel{Any}
127+ end
128+ REPLBackendRef (backend:: REPLBackend ) = REPLBackendRef (backend. repl_channel, backend. response_channel)
129+
130+ function destroy (ref:: REPLBackendRef , state:: Task )
131+ if istaskfailed (state)
132+ close (ref. repl_channel, TaskFailedException (state))
133+ close (ref. response_channel, TaskFailedException (state))
134+ end
135+ close (ref. repl_channel)
136+ close (ref. response_channel)
137+ end
138+
123139"""
124140 softscope(ex)
125141
@@ -418,12 +434,23 @@ function repl_backend_loop(backend::REPLBackend, get_module::Function)
418434 while true
419435 tls = task_local_storage ()
420436 tls[:SOURCE_PATH ] = nothing
421- ast , show_value = take! (backend. repl_channel)
437+ ast_or_func , show_value = take! (backend. repl_channel)
422438 if show_value == - 1
423439 # exit flag
424440 break
425441 end
426- eval_user_input (ast, backend, get_module ())
442+ if show_value == 2 # 2 indicates a function to be called
443+ f = ast_or_func
444+ try
445+ ret = f ()
446+ put! (backend. response_channel, Pair {Any, Bool} (ret, false ))
447+ catch err
448+ put! (backend. response_channel, Pair {Any, Bool} (err, true ))
449+ end
450+ else
451+ ast = ast_or_func
452+ eval_user_input (ast, backend, get_module ())
453+ end
427454 end
428455 return nothing
429456end
@@ -526,7 +553,7 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
526553 repl. waserror = response[2 ]
527554 with_repl_linfo (repl) do io
528555 io = IOContext (io, :module => Base. active_module (repl):: Module )
529- print_response (io, response, show_value, have_color, specialdisplay (repl))
556+ print_response (io, response, backend (repl), show_value, have_color, specialdisplay (repl))
530557 end
531558 return nothing
532559end
@@ -543,7 +570,7 @@ function repl_display_error(errio::IO, @nospecialize errval)
543570 return nothing
544571end
545572
546- function print_response (errio:: IO , response, show_value:: Bool , have_color:: Bool , specialdisplay:: Union{AbstractDisplay,Nothing} = nothing )
573+ function print_response (errio:: IO , response, backend :: Union{REPLBackendRef,Nothing} , show_value:: Bool , have_color:: Bool , specialdisplay:: Union{AbstractDisplay,Nothing} = nothing )
547574 Base. sigatomic_begin ()
548575 val, iserr = response
549576 while true
@@ -555,15 +582,19 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
555582 repl_display_error (errio, val)
556583 else
557584 if val != = nothing && show_value
558- try
559- if specialdisplay === nothing
585+ val2, iserr = if specialdisplay === nothing
586+ # display calls may require being run on the main thread
587+ eval_with_backend (backend) do
560588 Base. invokelatest (display, val)
561- else
589+ end
590+ else
591+ eval_with_backend (backend) do
562592 Base. invokelatest (display, specialdisplay, val)
563593 end
564- catch
594+ end
595+ if iserr
565596 println (errio, " Error showing value of type " , typeof (val), " :" )
566- rethrow ( )
597+ throw (val2 )
567598 end
568599 end
569600 end
@@ -593,21 +624,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
593624 nothing
594625end
595626
596- # A reference to a backend that is not mutable
597- struct REPLBackendRef
598- repl_channel:: Channel{Any}
599- response_channel:: Channel{Any}
600- end
601- REPLBackendRef (backend:: REPLBackend ) = REPLBackendRef (backend. repl_channel, backend. response_channel)
602627
603- function destroy (ref:: REPLBackendRef , state:: Task )
604- if istaskfailed (state)
605- close (ref. repl_channel, TaskFailedException (state))
606- close (ref. response_channel, TaskFailedException (state))
607- end
608- close (ref. repl_channel)
609- close (ref. response_channel)
610- end
611628
612629"""
613630 run_repl(repl::AbstractREPL)
@@ -1128,12 +1145,27 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
11281145 ! isempty (DEPOT_PATH ) ? joinpath (DEPOT_PATH [1 ], " logs" , " repl_history.jl" ) :
11291146 error (" DEPOT_PATH is empty and ENV[\" JULIA_HISTORY\" ] not set." ))
11301147
1131- backend (r:: AbstractREPL ) = r . backendref
1148+ backend (r:: AbstractREPL ) = hasproperty (r, :backendref ) ? r . backendref : nothing
11321149
1133- function eval_with_backend (ast, backend:: REPLBackendRef )
1134- put! (backend. repl_channel, (ast, 1 ))
1150+
1151+ function eval_with_backend (ast:: Expr , backend:: REPLBackendRef )
1152+ put! (backend. repl_channel, (ast, 1 )) # (f, show_value)
1153+ return take! (backend. response_channel) # (val, iserr)
1154+ end
1155+ function eval_with_backend (f, backend:: REPLBackendRef )
1156+ put! (backend. repl_channel, (f, 2 )) # (f, show_value) 2 indicates function (rather than ast)
11351157 return take! (backend. response_channel) # (val, iserr)
11361158end
1159+ # if no backend just eval (used by tests)
1160+ function eval_with_backend (f, backend:: Nothing )
1161+ try
1162+ ret = f ()
1163+ return (ret, false ) # (val, iserr)
1164+ catch err
1165+ return (err, true )
1166+ end
1167+ end
1168+
11371169
11381170function respond (f, repl, main; pass_empty:: Bool = false , suppress_on_semicolon:: Bool = true )
11391171 return function do_respond (s:: MIState , buf, ok:: Bool )
0 commit comments