Skip to content

Commit 5996c14

Browse files
authored
Merge pull request rails#54504 from byroot/opt-gtg-move
Flatten the transition table state arrays
2 parents d3e1fb4 + 46b7642 commit 5996c14

File tree

3 files changed

+30
-15
lines changed

3 files changed

+30
-15
lines changed

actionpack/lib/action_dispatch/journey/gtg/simulator.rb

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Simulator # :nodoc:
2020
STATIC_TOKENS["?".ord] = "?"
2121
STATIC_TOKENS.freeze
2222

23-
INITIAL_STATE = [ [0, nil] ].freeze
23+
INITIAL_STATE = [0, nil].freeze
2424

2525
attr_reader :tt
2626

@@ -50,9 +50,17 @@ def memos(string)
5050
end
5151
end
5252

53-
acceptance_states = state.each_with_object([]) do |s_d, memos|
54-
s, idx = s_d
55-
memos.concat(tt.memo(s)) if idx.nil? && tt.accepting?(s)
53+
acceptance_states = []
54+
states_count = state.size
55+
i = 0
56+
while i < states_count
57+
if state[i + 1].nil?
58+
s = state[i]
59+
if tt.accepting?(s)
60+
acceptance_states.concat(tt.memo(s))
61+
end
62+
end
63+
i += 2
5664
end
5765

5866
acceptance_states.empty? ? yield : acceptance_states

actionpack/lib/action_dispatch/journey/gtg/transition_table.rb

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,22 @@ def move(t, full_string, token, start_index, token_matches_default)
5252

5353
next_states = []
5454

55-
t.each { |s, previous_start|
55+
transitions_count = t.size
56+
i = 0
57+
while i < transitions_count
58+
s = t[i]
59+
previous_start = t[i + 1]
5660
if previous_start.nil?
5761
# In the simple case of a "default" param regex do this fast-path and add all
5862
# next states.
5963
if token_matches_default && std_state = @stdparam_states[s]
60-
next_states << [std_state, nil].freeze
64+
next_states << std_state << nil
6165
end
6266

6367
# When we have a literal string, we can just pull the next state
6468
if states = @string_states[s]
65-
next_states << [states[token], nil].freeze unless states[token].nil?
69+
state = states[token]
70+
next_states << state << nil unless state.nil?
6671
end
6772
end
6873

@@ -82,14 +87,16 @@ def move(t, full_string, token, start_index, token_matches_default)
8287

8388
states.each { |re, v|
8489
# if we match, we can try moving past this
85-
next_states << [v, nil].freeze if !v.nil? && re.match?(curr_slice)
90+
next_states << v << nil if !v.nil? && re.match?(curr_slice)
8691
}
8792

8893
# and regardless, we must continue accepting tokens and retrying this regexp. we
8994
# need to remember where we started as well so we can take bigger slices.
90-
next_states << [s, slice_start].freeze
95+
next_states << s << slice_start
9196
end
92-
}
97+
98+
i += 2
99+
end
93100

94101
next_states
95102
end

actionpack/test/journey/gtg/builder_test.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ module GTG
88
class TestBuilder < ActiveSupport::TestCase
99
def test_following_states_multi
1010
table = tt ["a|a"]
11-
assert_equal 1, table.move([[0, nil]], "a", "a", 0, true).length
11+
assert_equal 1, table.move([0, nil], "a", "a", 0, true).each_slice(2).count
1212
end
1313

1414
def test_following_states_multi_regexp
1515
table = tt [":a|b"]
16-
assert_equal 1, table.move([[0, nil]], "fooo", "fooo", 0, true).length
17-
assert_equal 2, table.move([[0, nil]], "b", "b", 0, true).length
16+
assert_equal 1, table.move([0, nil], "fooo", "fooo", 0, true).each_slice(2).count
17+
assert_equal 2, table.move([0, nil], "b", "b", 0, true).each_slice(2).count
1818
end
1919

2020
def test_multi_path
@@ -25,9 +25,9 @@ def test_multi_path
2525
[2, "b"],
2626
[2, "/"],
2727
[1, "c"],
28-
].inject([[0, nil]]) { |state, (exp, sym)|
28+
].inject([0, nil]) { |state, (exp, sym)|
2929
new = table.move(state, sym, sym, 0, sym != "/")
30-
assert_equal exp, new.length
30+
assert_equal exp, new.each_slice(2).count
3131
new
3232
}
3333
end

0 commit comments

Comments
 (0)