@@ -193,6 +193,22 @@ mutable struct REPLBackend
193193end
194194REPLBackend () = REPLBackend (Channel (1 ), Channel (1 ), false )
195195
196+ # A reference to a backend that is not mutable
197+ struct REPLBackendRef
198+ repl_channel:: Channel{Any}
199+ response_channel:: Channel{Any}
200+ end
201+ REPLBackendRef (backend:: REPLBackend ) = REPLBackendRef (backend. repl_channel, backend. response_channel)
202+
203+ function destroy (ref:: REPLBackendRef , state:: Task )
204+ if istaskfailed (state)
205+ close (ref. repl_channel, TaskFailedException (state))
206+ close (ref. response_channel, TaskFailedException (state))
207+ end
208+ close (ref. repl_channel)
209+ close (ref. response_channel)
210+ end
211+
196212"""
197213 softscope(ex)
198214
@@ -334,12 +350,23 @@ function repl_backend_loop(backend::REPLBackend, get_module::Function)
334350 while true
335351 tls = task_local_storage ()
336352 tls[:SOURCE_PATH ] = nothing
337- ast , show_value = take! (backend. repl_channel)
353+ ast_or_func , show_value = take! (backend. repl_channel)
338354 if show_value == - 1
339355 # exit flag
340356 break
341357 end
342- eval_user_input (ast, backend, get_module ())
358+ if show_value == 2 # 2 indicates a function to be called
359+ f = ast_or_func
360+ try
361+ ret = f ()
362+ put! (backend. response_channel, Pair {Any, Bool} (ret, false ))
363+ catch err
364+ put! (backend. response_channel, Pair {Any, Bool} (err, true ))
365+ end
366+ else
367+ ast = ast_or_func
368+ eval_user_input (ast, backend, get_module ())
369+ end
343370 end
344371 return nothing
345372end
@@ -375,7 +402,7 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
375402 repl. waserror = response[2 ]
376403 with_repl_linfo (repl) do io
377404 io = IOContext (io, :module => Base. active_module (repl):: Module )
378- print_response (io, response, show_value, have_color, specialdisplay (repl))
405+ print_response (io, response, backend (repl), show_value, have_color, specialdisplay (repl))
379406 end
380407 return nothing
381408end
@@ -392,7 +419,7 @@ function repl_display_error(errio::IO, @nospecialize errval)
392419 return nothing
393420end
394421
395- function print_response (errio:: IO , response, show_value:: Bool , have_color:: Bool , specialdisplay:: Union{AbstractDisplay,Nothing} = nothing )
422+ function print_response (errio:: IO , response, backend :: Union{REPLBackendRef,Nothing} , show_value:: Bool , have_color:: Bool , specialdisplay:: Union{AbstractDisplay,Nothing} = nothing )
396423 Base. sigatomic_begin ()
397424 val, iserr = response
398425 while true
@@ -404,15 +431,19 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
404431 repl_display_error (errio, val)
405432 else
406433 if val != = nothing && show_value
407- try
408- if specialdisplay === nothing
434+ val2, iserr = if specialdisplay === nothing
435+ # display calls may require being run on the main thread
436+ eval_with_backend (backend) do
409437 Base. invokelatest (display, val)
410- else
438+ end
439+ else
440+ eval_with_backend (backend) do
411441 Base. invokelatest (display, specialdisplay, val)
412442 end
413- catch
443+ end
444+ if iserr
414445 println (errio, " Error showing value of type " , typeof (val), " :" )
415- rethrow ( )
446+ throw (val2 )
416447 end
417448 end
418449 end
@@ -442,21 +473,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
442473 nothing
443474end
444475
445- # A reference to a backend that is not mutable
446- struct REPLBackendRef
447- repl_channel:: Channel{Any}
448- response_channel:: Channel{Any}
449- end
450- REPLBackendRef (backend:: REPLBackend ) = REPLBackendRef (backend. repl_channel, backend. response_channel)
451476
452- function destroy (ref:: REPLBackendRef , state:: Task )
453- if istaskfailed (state)
454- close (ref. repl_channel, TaskFailedException (state))
455- close (ref. response_channel, TaskFailedException (state))
456- end
457- close (ref. repl_channel)
458- close (ref. response_channel)
459- end
460477
461478"""
462479 run_repl(repl::AbstractREPL)
@@ -977,12 +994,27 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
977994 ! isempty (DEPOT_PATH ) ? joinpath (DEPOT_PATH [1 ], " logs" , " repl_history.jl" ) :
978995 error (" DEPOT_PATH is empty and and ENV[\" JULIA_HISTORY\" ] not set." ))
979996
980- backend (r:: AbstractREPL ) = r . backendref
997+ backend (r:: AbstractREPL ) = hasproperty (r, :backendref ) ? r . backendref : nothing
981998
982- function eval_with_backend (ast, backend:: REPLBackendRef )
983- put! (backend. repl_channel, (ast, 1 ))
999+
1000+ function eval_with_backend (ast:: Expr , backend:: REPLBackendRef )
1001+ put! (backend. repl_channel, (ast, 1 )) # (f, show_value)
1002+ return take! (backend. response_channel) # (val, iserr)
1003+ end
1004+ function eval_with_backend (f, backend:: REPLBackendRef )
1005+ put! (backend. repl_channel, (f, 2 )) # (f, show_value) 2 indicates function (rather than ast)
9841006 return take! (backend. response_channel) # (val, iserr)
9851007end
1008+ # if no backend just eval (used by tests)
1009+ function eval_with_backend (f, backend:: Nothing )
1010+ try
1011+ ret = f ()
1012+ return (ret, false ) # (val, iserr)
1013+ catch err
1014+ return (err, true )
1015+ end
1016+ end
1017+
9861018
9871019function respond (f, repl, main; pass_empty:: Bool = false , suppress_on_semicolon:: Bool = true )
9881020 return function do_respond (s:: MIState , buf, ok:: Bool )
0 commit comments