[ruby/irb] Reduce internal operations' exposure to benchmarking

(https://github.com/ruby/irb/pull/618)

* Test last value is assigned with measure enabled

* Remove unnecessary `result` variable

`Context#evaluate` always assigns the result of the evaluation to `_` so
we don't need to do it in `Irb#eval_input`.

* Move benchmarking logic into `Context#evaluate`

Current location of the benchmarking logic is too high up and includes
operations like command loading and argument transformation, which should
be excluded. So this commit moves it into `Context#evaluate` to reduce the
noise.

We don't move it further down to `Workspace#evaluate` because `Context`
is an argument of the measure block, which is not available in `Workspace`.
This commit is contained in:
Stan Lo 2023-06-30 18:41:56 +01:00 коммит произвёл git
Родитель 94788a6d13
Коммит 136fcd5118
3 изменённых файлов: 53 добавлений и 19 удалений

Просмотреть файл

@ -558,26 +558,10 @@ module IRB
@scanner.each_top_level_statement do |line, line_no|
signal_status(:IN_EVAL) do
begin
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
IRB.set_measure_callback
end
# Assignment expression check should be done before evaluate_line to handle code like `a /2#/ if false; a = 1`
is_assignment = assignment_expression?(line)
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
result = nil
last_proc = proc{ result = evaluate_line(line, line_no) }
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) { |chain, item|
_name, callback, arg = item
proc {
callback.(@context, line, line_no, arg) do
chain.call
end
}
}.call
@context.set_last_value(result)
else
evaluate_line(line, line_no)
end
evaluate_line(line, line_no)
if @context.echo?
if is_assignment
if @context.echo_on_assignment?

Просмотреть файл

@ -475,7 +475,29 @@ module IRB
def evaluate(line, line_no) # :nodoc:
@line_no = line_no
set_last_value(@workspace.evaluate(line, irb_path, line_no))
result = nil
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
IRB.set_measure_callback
end
if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
last_proc = proc do
result = @workspace.evaluate(line, irb_path, line_no)
end
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
_name, callback, arg = item
proc do
callback.(self, line, line_no, arg) do
chain.call
end
end
end.call
else
result = @workspace.evaluate(line, irb_path, line_no)
end
set_last_value(result)
end
def inspect_last_value # :nodoc:

Просмотреть файл

@ -252,6 +252,34 @@ module TestIRB
assert_empty(c.class_variables)
end
def test_measure_keeps_previous_value
conf = {
PROMPT: {
DEFAULT: {
PROMPT_I: '> ',
PROMPT_S: '> ',
PROMPT_C: '> ',
PROMPT_N: '> '
}
},
PROMPT_MODE: :DEFAULT,
MEASURE: false
}
c = Class.new(Object)
out, err = execute_lines(
"measure\n",
"3\n",
"_\n",
conf: conf,
main: c
)
assert_empty err
assert_match(/\ATIME is added\.\n=> nil\nprocessing time: .+\n=> 3\nprocessing time: .+\n=> 3/, out)
assert_empty(c.class_variables)
end
def test_measure_enabled_by_rc
conf = {
PROMPT: {