@@ -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 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
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
@@ -555,15 +582,19 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
555
582
repl_display_error (errio, val)
556
583
else
557
584
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
560
588
Base. invokelatest (display, val)
561
- else
589
+ end
590
+ else
591
+ eval_with_backend (backend) do
562
592
Base. invokelatest (display, specialdisplay, val)
563
593
end
564
- catch
594
+ end
595
+ if iserr
565
596
println (errio, " Error showing value of type " , typeof (val), " :" )
566
- rethrow ( )
597
+ throw (val2 )
567
598
end
568
599
end
569
600
end
@@ -593,21 +624,7 @@ function print_response(errio::IO, response, show_value::Bool, have_color::Bool,
593
624
nothing
594
625
end
595
626
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
627
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
628
612
629
"""
613
630
run_repl(repl::AbstractREPL)
@@ -1128,12 +1145,27 @@ find_hist_file() = get(ENV, "JULIA_HISTORY",
1128
1145
! isempty (DEPOT_PATH ) ? joinpath (DEPOT_PATH [1 ], " logs" , " repl_history.jl" ) :
1129
1146
error (" DEPOT_PATH is empty and ENV[\" JULIA_HISTORY\" ] not set." ))
1130
1147
1131
- backend (r:: AbstractREPL ) = r . backendref
1148
+ backend (r:: AbstractREPL ) = hasproperty (r, :backendref ) ? r . backendref : nothing
1132
1149
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)
1135
1157
return take! (backend. response_channel) # (val, iserr)
1136
1158
end
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
+
1137
1169
1138
1170
function respond (f, repl, main; pass_empty:: Bool = false , suppress_on_semicolon:: Bool = true )
1139
1171
return function do_respond (s:: MIState , buf, ok:: Bool )
0 commit comments