@@ -120,6 +120,22 @@ mutable struct REPLBackend
120
120
end
121
121
REPLBackend () = REPLBackend (Channel (1 ), Channel (1 ), false )
122
122
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
+
123
139
"""
124
140
softscope(ex)
125
141
@@ -418,12 +434,23 @@ function repl_backend_loop(backend::REPLBackend, get_module::Function)
418
434
while true
419
435
tls = task_local_storage ()
420
436
tls[:SOURCE_PATH ] = nothing
421
- ast , show_value = take! (backend. repl_channel)
437
+ ast_or_func , show_value = take! (backend. repl_channel)
422
438
if show_value == - 1
423
439
# exit flag
424
440
break
425
441
end
426
- eval_user_input (ast, backend, get_module ())
442
+ if ast_or_func isa Expr
443
+ ast = ast_or_func
444
+ eval_user_input (ast, backend, get_module ())
445
+ else
446
+ f = ast_or_func
447
+ try
448
+ ret = f ()
449
+ put! (backend. response_channel, Pair {Any, Bool} (ret, false ))
450
+ catch err
451
+ put! (backend. response_channel, Pair {Any, Bool} (err, true ))
452
+ end
453
+ end
427
454
end
428
455
return nothing
429
456
end
@@ -526,7 +553,7 @@ function print_response(repl::AbstractREPL, response, show_value::Bool, have_col
526
553
repl. waserror = response[2 ]
527
554
with_repl_linfo (repl) do io
528
555
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))
530
557
end
531
558
return nothing
532
559
end
@@ -543,7 +570,7 @@ function repl_display_error(errio::IO, @nospecialize errval)
543
570
return nothing
544
571
end
545
572
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 )
547
574
Base. sigatomic_begin ()
548
575
val, iserr = response
549
576
while true
@@ -557,9 +584,14 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
557
584
if val != = nothing && show_value
558
585
try
559
586
if specialdisplay === nothing
560
- Base. invokelatest (display, val)
587
+ # display calls may require being run on the main thread
588
+ eval_with_backend (backend) do
589
+ Base. invokelatest (display, val)
590
+ end
561
591
else
562
- Base. invokelatest (display, specialdisplay, val)
592
+ eval_with_backend (backend) do
593
+ Base. invokelatest (display, specialdisplay, val)
594
+ end
563
595
end
564
596
catch
565
597
println (errio, " Error showing value of type " , typeof (val), " :" )
@@ -593,21 +625,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
593
625
nothing
594
626
end
595
627
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)
602
628
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
611
629
612
630
"""
613
631
run_repl(repl::AbstractREPL)
@@ -1130,10 +1148,25 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
1130
1148
1131
1149
backend (r:: AbstractREPL ) = r. backendref
1132
1150
1133
- function eval_with_backend (ast, backend:: REPLBackendRef )
1134
- put! (backend. repl_channel, (ast, 1 ))
1151
+
1152
+ function eval_with_backend (ast:: Expr , backend:: REPLBackendRef )
1153
+ put! (backend. repl_channel, (ast, 1 )) # (f, show_value)
1154
+ return take! (backend. response_channel) # (val, iserr)
1155
+ end
1156
+ function eval_with_backend (f, backend:: REPLBackendRef )
1157
+ put! (backend. repl_channel, (f, false )) # (f, show_value)
1135
1158
return take! (backend. response_channel) # (val, iserr)
1136
1159
end
1160
+ # if no backend just eval (used by tests)
1161
+ function eval_with_backend (f, backend:: Nothing )
1162
+ try
1163
+ ret = f ()
1164
+ return (ret, false ) # (val, iserr)
1165
+ catch err
1166
+ return (err, true )
1167
+ end
1168
+ end
1169
+
1137
1170
1138
1171
function respond (f, repl, main; pass_empty:: Bool = false , suppress_on_semicolon:: Bool = true )
1139
1172
return function do_respond (s:: MIState , buf, ok:: Bool )
0 commit comments