ibex-runtime 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +95 -272
- data/lib/ibex/runtime/cst/green/node.rb +1 -1
- data/lib/ibex/runtime/cst/green/token.rb +1 -1
- data/lib/ibex/runtime/cst/green/trivia.rb +1 -1
- data/lib/ibex/runtime/cst/incremental/blender.rb +1 -1
- data/lib/ibex/runtime/cst/incremental/lexed_syntax.rb +2 -2
- data/lib/ibex/runtime/cst/incremental/parse_memo.rb +2 -2
- data/lib/ibex/runtime/cst/incremental/relexer.rb +3 -0
- data/lib/ibex/runtime/cst/incremental/session.rb +26 -2
- data/lib/ibex/runtime/cst/parse_result.rb +7 -7
- data/lib/ibex/runtime/cst/serialize.rb +6 -3
- data/lib/ibex/runtime/cst/syntax_node.rb +4 -4
- data/lib/ibex/runtime/cst/syntax_token.rb +5 -5
- data/lib/ibex/runtime/cst/typed_node.rb +1 -1
- data/lib/ibex/runtime/cst/validator.rb +40 -30
- data/lib/ibex/runtime/embedded_source.rb +98 -0
- data/lib/ibex/runtime/event.rb +7 -4
- data/lib/ibex/runtime/event_jsonl_tracer.rb +1 -1
- data/lib/ibex/runtime/event_sanitizer.rb +32 -26
- data/lib/ibex/runtime/generated_lexer.rb +23 -16
- data/lib/ibex/runtime/lexer_input.rb +1 -1
- data/lib/ibex/runtime/location_span.rb +15 -15
- data/lib/ibex/runtime/observation.rb +1 -1
- data/lib/ibex/runtime/parser.rb +309 -191
- data/lib/ibex/runtime/parser_sync_recovery.rb +19 -15
- data/lib/ibex/runtime/repair.rb +36 -5
- data/lib/ibex/runtime/repair_priority_queue.rb +10 -6
- data/lib/ibex/runtime/repair_search.rb +92 -29
- data/lib/ibex/runtime/syntax_repair.rb +490 -0
- data/lib/ibex/runtime/syntax_session.rb +416 -0
- data/lib/ibex/runtime/table_format.rb +1 -1
- data/lib/ibex/runtime/version.rb +1 -1
- data/lib/ibex/runtime.rb +2 -1
- data/lib/ibex/tables/compact.rb +16 -12
- data/lib/ibex/tables/compact_actions.rb +45 -33
- data/lib/ibex/tables/compact_productions.rb +18 -15
- data/sig/ibex/runtime/cst/green/node.rbs +2 -2
- data/sig/ibex/runtime/cst/green/token.rbs +2 -2
- data/sig/ibex/runtime/cst/green/trivia.rbs +2 -2
- data/sig/ibex/runtime/cst/incremental/blender.rbs +2 -2
- data/sig/ibex/runtime/cst/incremental/lexed_syntax.rbs +3 -3
- data/sig/ibex/runtime/cst/incremental/parse_memo.rbs +4 -4
- data/sig/ibex/runtime/cst/incremental/session.rbs +8 -2
- data/sig/ibex/runtime/cst/parse_result.rbs +9 -9
- data/sig/ibex/runtime/cst/serialize.rbs +8 -6
- data/sig/ibex/runtime/cst/syntax_node.rbs +6 -6
- data/sig/ibex/runtime/cst/syntax_token.rbs +10 -10
- data/sig/ibex/runtime/cst/typed_node.rbs +2 -2
- data/sig/ibex/runtime/cst/validator.rbs +46 -42
- data/sig/ibex/runtime/embedded_source.rbs +21 -0
- data/sig/ibex/runtime/event.rbs +7 -5
- data/sig/ibex/runtime/event_jsonl_tracer.rbs +1 -1
- data/sig/ibex/runtime/event_sanitizer.rbs +50 -44
- data/sig/ibex/runtime/generated_lexer.rbs +31 -24
- data/sig/ibex/runtime/lexer_input.rbs +2 -2
- data/sig/ibex/runtime/location_span.rbs +28 -28
- data/sig/ibex/runtime/observation.rbs +2 -2
- data/sig/ibex/runtime/parser.rbs +266 -252
- data/sig/ibex/runtime/parser_sync_recovery.rbs +15 -15
- data/sig/ibex/runtime/repair.rbs +28 -8
- data/sig/ibex/runtime/repair_priority_queue.rbs +9 -7
- data/sig/ibex/runtime/repair_search.rbs +38 -19
- data/sig/ibex/runtime/syntax_repair.rbs +177 -0
- data/sig/ibex/runtime/syntax_session.rbs +186 -0
- data/sig/ibex/tables/compact.rbs +12 -12
- data/sig/ibex/tables/compact_actions.rbs +10 -17
- data/sig/ibex/tables/compact_productions.rbs +19 -19
- metadata +12 -6
- data/lib/ibex/runtime/jsonl_tracer.rb +0 -75
- data/sig/ibex/runtime/jsonl_tracer.rbs +0 -42
|
@@ -10,15 +10,15 @@ module Ibex
|
|
|
10
10
|
private_constant :ERROR_ACTION
|
|
11
11
|
|
|
12
12
|
# @rbs!
|
|
13
|
-
# private def parser_tables: () -> Hash[Symbol,
|
|
14
|
-
# private def table_lookup: (
|
|
15
|
-
# private def default_action: (Integer) ->
|
|
16
|
-
# private def token_to_str: (
|
|
13
|
+
# private def parser_tables: () -> Hash[Symbol, Object?]
|
|
14
|
+
# private def table_lookup: (Object?, Integer, Integer) -> IR::runtime_action?
|
|
15
|
+
# private def default_action: (Integer) -> IR::runtime_action?
|
|
16
|
+
# private def token_to_str: (Object?) -> String
|
|
17
17
|
# private def trace: (String) -> void
|
|
18
|
-
# private def continue_recovery: () ->
|
|
18
|
+
# private def continue_recovery: () -> ([ :continue ] | [ :done, nil ])
|
|
19
19
|
# private def reject_recovery_eof: () -> [:done, nil]
|
|
20
|
-
# private def finish_recovery: (
|
|
21
|
-
# Hash[String,
|
|
20
|
+
# private def finish_recovery: (Object?, Object?, Object?, Object?, Integer, Array[Object?],
|
|
21
|
+
# Hash[String, Object?]?, String, Array[Proc]?) -> [:continue]
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
@@ -33,8 +33,8 @@ module Ibex
|
|
|
33
33
|
!@sync_recovery_context.nil?
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
# @rbs (Hash[Symbol,
|
|
37
|
-
# Array[Proc]? observers) ->
|
|
36
|
+
# @rbs (Hash[Symbol, Object?] context, Hash[String, Object?]? token_data,
|
|
37
|
+
# Array[Proc]? observers) -> ([ :continue ] | [ :done, nil ])
|
|
38
38
|
def begin_sync_recovery(context, token_data, observers)
|
|
39
39
|
@sync_recovery_context = context
|
|
40
40
|
@sync_recovery_token_data = token_data
|
|
@@ -42,7 +42,7 @@ module Ibex
|
|
|
42
42
|
continue_sync_recovery
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
# @rbs () ->
|
|
45
|
+
# @rbs () -> ([ :continue ] | [ :done, nil ])
|
|
46
46
|
def continue_sync_recovery
|
|
47
47
|
return reject_sync_recovery_eof if @lookahead == Parser::EOF_TOKEN
|
|
48
48
|
return finish_sync_recovery if sync_token?(@lookahead) && synchronize_for_current_token
|
|
@@ -50,7 +50,7 @@ module Ibex
|
|
|
50
50
|
continue_recovery
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
# @rbs (
|
|
53
|
+
# @rbs (Integer token_id) -> bool
|
|
54
54
|
def sync_token?(token_id)
|
|
55
55
|
tokens = parser_tables[:recovery_sync_tokens]
|
|
56
56
|
tokens.is_a?(Array) && tokens.include?(token_id)
|
|
@@ -70,9 +70,10 @@ module Ibex
|
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
# @rbs (Integer state, Integer token_id) ->
|
|
73
|
+
# @rbs (Integer state, Integer token_id) -> IR::runtime_action
|
|
74
74
|
def sync_action(state, token_id)
|
|
75
|
-
|
|
75
|
+
token_names = parser_tables.fetch(:token_names)
|
|
76
|
+
return ERROR_ACTION unless token_names.is_a?(Hash) && token_names.key?(token_id)
|
|
76
77
|
|
|
77
78
|
table_lookup(parser_tables.fetch(:actions), state, token_id) || default_action(state) || ERROR_ACTION
|
|
78
79
|
end
|
|
@@ -85,9 +86,12 @@ module Ibex
|
|
|
85
86
|
clear_sync_recovery
|
|
86
87
|
@recovery_shifts = Parser::RECOVERY_SHIFTS
|
|
87
88
|
trace("recover: synchronized before #{token_to_str(@lookahead)} in state #{@state_stack.last}") if @yydebug
|
|
89
|
+
value_stack = context.fetch(:value_stack) #: Array[Object?]
|
|
90
|
+
state = context.fetch(:state) #: Integer
|
|
91
|
+
reason = context.fetch(:reason) #: String
|
|
88
92
|
finish_recovery(
|
|
89
|
-
context[:token_id], context[:token_display], context[:value], context[:location],
|
|
90
|
-
|
|
93
|
+
context[:token_id], context[:token_display], context[:value], context[:location], state,
|
|
94
|
+
value_stack, token_data, reason, observers
|
|
91
95
|
)
|
|
92
96
|
end
|
|
93
97
|
|
data/lib/ibex/runtime/repair.rb
CHANGED
|
@@ -40,6 +40,8 @@ module Ibex
|
|
|
40
40
|
|
|
41
41
|
# One immutable insertion, deletion, or replacement.
|
|
42
42
|
class RepairEdit
|
|
43
|
+
# @rbs! type document_value = Symbol | Integer | String
|
|
44
|
+
|
|
43
45
|
KINDS = %i[insert delete replace].freeze #: Array[Symbol]
|
|
44
46
|
|
|
45
47
|
attr_reader :kind #: Symbol
|
|
@@ -62,7 +64,7 @@ module Ibex
|
|
|
62
64
|
freeze
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
# @rbs () -> Hash[Symbol,
|
|
67
|
+
# @rbs () -> Hash[Symbol, document_value]
|
|
66
68
|
def to_h
|
|
67
69
|
{ kind: @kind, position: @position, token_id: @token_id, token_name: @token_name, cost: @cost }.freeze
|
|
68
70
|
end
|
|
@@ -84,20 +86,49 @@ module Ibex
|
|
|
84
86
|
freeze
|
|
85
87
|
end
|
|
86
88
|
|
|
87
|
-
# @rbs () -> Hash[Symbol,
|
|
89
|
+
# @rbs () -> Hash[Symbol, Integer | Array[Hash[Symbol, RepairEdit::document_value]]]
|
|
88
90
|
def to_h
|
|
89
91
|
{ cost: @cost, configurations: @configurations, edits: @edits.map(&:to_h).freeze }.freeze
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
|
|
95
|
+
# Closed internal outcome for callers that must distinguish bounded search
|
|
96
|
+
# exhaustion from a complete search with no repair.
|
|
97
|
+
class RepairSearchResult
|
|
98
|
+
STATUSES = %i[selected need_input exhausted not_found].freeze #: Array[Symbol]
|
|
99
|
+
|
|
100
|
+
attr_reader :status #: Symbol
|
|
101
|
+
attr_reader :plan #: RepairPlan?
|
|
102
|
+
attr_reader :configurations #: Integer
|
|
103
|
+
|
|
104
|
+
# @rbs (status: Symbol, plan: RepairPlan?, configurations: Integer) -> void
|
|
105
|
+
def initialize(status:, plan:, configurations:)
|
|
106
|
+
raise ArgumentError, "unknown repair search status #{status.inspect}" unless STATUSES.include?(status)
|
|
107
|
+
unless configurations.is_a?(Integer) && configurations >= 0
|
|
108
|
+
raise ArgumentError, "repair search configurations must be nonnegative"
|
|
109
|
+
end
|
|
110
|
+
unless (status == :selected) == plan.is_a?(RepairPlan)
|
|
111
|
+
raise ArgumentError, "selected repair search status and plan must agree"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
@status = status
|
|
115
|
+
@plan = plan
|
|
116
|
+
@configurations = configurations
|
|
117
|
+
freeze
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @rbs () -> bool
|
|
121
|
+
def selected? = @status == :selected
|
|
122
|
+
end
|
|
123
|
+
|
|
93
124
|
# Internal normalized input record retained while repair looks ahead.
|
|
94
125
|
class RepairInput
|
|
95
126
|
attr_reader :token_id #: Integer
|
|
96
127
|
attr_reader :token_name #: String
|
|
97
|
-
attr_reader :value #:
|
|
98
|
-
attr_reader :location #:
|
|
128
|
+
attr_reader :value #: Object?
|
|
129
|
+
attr_reader :location #: Object?
|
|
99
130
|
|
|
100
|
-
# @rbs (token_id: Integer, token_name: String, value:
|
|
131
|
+
# @rbs (token_id: Integer, token_name: String, value: Object?, location: Object?) -> void
|
|
101
132
|
def initialize(token_id:, token_name:, value:, location:)
|
|
102
133
|
@token_id = token_id
|
|
103
134
|
@token_name = token_name.dup.freeze
|
|
@@ -5,7 +5,9 @@ module Ibex
|
|
|
5
5
|
module Runtime
|
|
6
6
|
# Minimal binary heap ordered by an immutable Array priority.
|
|
7
7
|
class RepairPriorityQueue
|
|
8
|
-
# @rbs
|
|
8
|
+
# @rbs!
|
|
9
|
+
# type priority = Array[untyped]
|
|
10
|
+
# @rbs @entries: Array[[priority, Object?]]
|
|
9
11
|
|
|
10
12
|
# @rbs () -> void
|
|
11
13
|
def initialize
|
|
@@ -15,9 +17,9 @@ module Ibex
|
|
|
15
17
|
# @rbs () -> bool
|
|
16
18
|
def empty? = @entries.empty?
|
|
17
19
|
|
|
18
|
-
# @rbs (
|
|
20
|
+
# @rbs (priority priority, Object? value) -> void
|
|
19
21
|
def push(priority, value)
|
|
20
|
-
entry = [priority, value] #: [
|
|
22
|
+
entry = [priority, value] #: [priority, Object?]
|
|
21
23
|
@entries << entry
|
|
22
24
|
index = @entries.length - 1
|
|
23
25
|
while index.positive?
|
|
@@ -30,7 +32,7 @@ module Ibex
|
|
|
30
32
|
@entries[index] = entry
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
# @rbs () -> [
|
|
35
|
+
# @rbs () -> [priority, Object?]?
|
|
34
36
|
def pop
|
|
35
37
|
first = @entries.first
|
|
36
38
|
tail = @entries.pop
|
|
@@ -51,9 +53,11 @@ module Ibex
|
|
|
51
53
|
|
|
52
54
|
private
|
|
53
55
|
|
|
54
|
-
# @rbs ([
|
|
56
|
+
# @rbs ([priority, Object?] left, [priority, Object?] right) -> Integer
|
|
55
57
|
def compare(left, right)
|
|
56
|
-
|
|
58
|
+
left_priority = left.fetch(0) #: priority
|
|
59
|
+
right_priority = right.fetch(0) #: priority
|
|
60
|
+
(left_priority <=> right_priority) || 0
|
|
57
61
|
end
|
|
58
62
|
end
|
|
59
63
|
end
|
|
@@ -8,20 +8,34 @@ module Ibex
|
|
|
8
8
|
# Bounded Dijkstra search over LR state stacks. Semantic actions never run.
|
|
9
9
|
# rubocop:disable Metrics/ClassLength -- queue policy and LR transitions form one bounded search invariant.
|
|
10
10
|
class RepairSearch
|
|
11
|
+
# @rbs!
|
|
12
|
+
# type configuration_key = [Array[Integer], Integer, Integer, bool]
|
|
13
|
+
# type priority = Array[untyped]
|
|
14
|
+
# type lookup_table = Tables::action_table | Tables::goto_table
|
|
15
|
+
# type lookup_value = IR::runtime_action | Integer?
|
|
16
|
+
|
|
11
17
|
NEED_INPUT = Object.new.freeze #: Object
|
|
12
18
|
LIMIT = Object.new.freeze #: Object
|
|
13
|
-
Configuration = Struct.new(
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
Configuration = Struct.new(
|
|
20
|
+
:stack, #: Array[Integer]
|
|
21
|
+
:input_index, #: Integer
|
|
22
|
+
:shifts, #: Integer
|
|
23
|
+
:cost, #: Integer
|
|
24
|
+
:edits, #: Array[RepairEdit]
|
|
25
|
+
:goal, #: bool
|
|
26
|
+
keyword_init: true
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# @rbs @tables: Hash[Symbol, Object?]
|
|
16
30
|
# @rbs @policy: RepairPolicy
|
|
17
31
|
# @rbs @tokens: Array[RepairInput]
|
|
18
32
|
# @rbs @complete: bool
|
|
19
33
|
# @rbs @configurations: Integer
|
|
20
34
|
# @rbs @heap: RepairPriorityQueue
|
|
21
|
-
# @rbs @best: Hash[
|
|
35
|
+
# @rbs @best: Hash[configuration_key, priority]
|
|
22
36
|
# @rbs @candidate_ids: Array[Integer]
|
|
23
37
|
|
|
24
|
-
# @rbs (Hash[Symbol,
|
|
38
|
+
# @rbs (Hash[Symbol, Object?] tables, RepairPolicy policy, Array[RepairInput] tokens,
|
|
25
39
|
# complete: bool) -> void
|
|
26
40
|
def initialize(tables, policy, tokens, complete:)
|
|
27
41
|
@tables = tables
|
|
@@ -32,11 +46,23 @@ module Ibex
|
|
|
32
46
|
@heap = RepairPriorityQueue.new
|
|
33
47
|
@best = {}
|
|
34
48
|
reserved = [Parser::EOF_TOKEN, Parser::ERROR_TOKEN]
|
|
35
|
-
|
|
49
|
+
token_names = tables.fetch(:token_names) #: Hash[Integer, String]
|
|
50
|
+
@candidate_ids = token_names.keys.reject { |id| reserved.include?(id) }.sort.freeze
|
|
36
51
|
end
|
|
37
52
|
|
|
53
|
+
# Compatibility projection used by the semantic runtime path.
|
|
38
54
|
# @rbs (Array[Integer] state_stack) -> (RepairPlan | Object | nil)
|
|
39
55
|
def search(state_stack)
|
|
56
|
+
result = search_result(state_stack)
|
|
57
|
+
return result.plan if result.selected?
|
|
58
|
+
return NEED_INPUT if result.status == :need_input
|
|
59
|
+
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Preserve the bounded outcome for syntax tooling and diagnostics.
|
|
64
|
+
# @rbs (Array[Integer] state_stack) -> RepairSearchResult
|
|
65
|
+
def search_result(state_stack)
|
|
40
66
|
empty_edits = [] #: Array[RepairEdit]
|
|
41
67
|
push(
|
|
42
68
|
Configuration.new(
|
|
@@ -51,16 +77,16 @@ module Ibex
|
|
|
51
77
|
needs_input = false
|
|
52
78
|
until @heap.empty?
|
|
53
79
|
configuration = pop
|
|
54
|
-
return
|
|
80
|
+
return outcome(:exhausted) if configuration.equal?(LIMIT)
|
|
55
81
|
next unless configuration.is_a?(Configuration)
|
|
56
82
|
|
|
57
83
|
result = visit(configuration)
|
|
58
|
-
return
|
|
59
|
-
return result if result.is_a?(RepairPlan)
|
|
84
|
+
return outcome(:exhausted) if result.equal?(LIMIT)
|
|
85
|
+
return outcome(:selected, plan: result) if result.is_a?(RepairPlan)
|
|
60
86
|
|
|
61
87
|
needs_input = true if result.equal?(NEED_INPUT)
|
|
62
88
|
end
|
|
63
|
-
needs_input ?
|
|
89
|
+
outcome(needs_input ? :need_input : :not_found)
|
|
64
90
|
end
|
|
65
91
|
|
|
66
92
|
private
|
|
@@ -206,11 +232,18 @@ module Ibex
|
|
|
206
232
|
action = action_for(states.last, token_id)
|
|
207
233
|
case action.first
|
|
208
234
|
when :shift
|
|
209
|
-
|
|
235
|
+
target = action.fetch(1)
|
|
236
|
+
return nil unless target.is_a?(Integer)
|
|
237
|
+
|
|
238
|
+
states << target
|
|
210
239
|
return nil if states.length > @policy.max_stack
|
|
211
240
|
|
|
212
241
|
return RepairAdvance.new(status: :shift, stack: states.freeze)
|
|
213
|
-
when :reduce
|
|
242
|
+
when :reduce
|
|
243
|
+
production_id = action.fetch(1)
|
|
244
|
+
return nil unless production_id.is_a?(Integer)
|
|
245
|
+
|
|
246
|
+
return nil unless apply_reduction(states, production_id)
|
|
214
247
|
when :accept then return RepairAdvance.new(status: :accept, stack: states.freeze)
|
|
215
248
|
else return nil
|
|
216
249
|
end
|
|
@@ -219,31 +252,53 @@ module Ibex
|
|
|
219
252
|
|
|
220
253
|
# @rbs (Array[Integer] states, Integer production_id) -> Array[Integer]?
|
|
221
254
|
def apply_reduction(states, production_id)
|
|
222
|
-
|
|
223
|
-
|
|
255
|
+
productions = @tables.fetch(:productions) #: Array[Hash[Symbol, Object?]]
|
|
256
|
+
production = productions.fetch(production_id)
|
|
257
|
+
length = production.fetch(:length) #: Integer
|
|
224
258
|
return if length >= states.length
|
|
225
259
|
|
|
226
260
|
states.pop(length)
|
|
227
|
-
|
|
228
|
-
|
|
261
|
+
gotos = @tables.fetch(:gotos) #: Tables::goto_table
|
|
262
|
+
lhs = production.fetch(:lhs) #: Integer
|
|
263
|
+
goto = goto_table_lookup(gotos, states.last, lhs)
|
|
264
|
+
return unless goto.is_a?(Integer)
|
|
229
265
|
|
|
230
266
|
states << goto
|
|
231
267
|
states if states.length <= @policy.max_stack
|
|
232
268
|
end
|
|
233
269
|
|
|
234
|
-
# @rbs (Integer state, Integer token_id) ->
|
|
270
|
+
# @rbs (Integer state, Integer token_id) -> IR::runtime_action
|
|
235
271
|
def action_for(state, token_id)
|
|
236
|
-
|
|
272
|
+
actions = @tables.fetch(:actions) #: Tables::action_table
|
|
273
|
+
explicit = action_table_lookup(actions, state, token_id)
|
|
237
274
|
return explicit if explicit
|
|
238
275
|
|
|
239
|
-
@tables.fetch(:default_actions, Parser::EMPTY_ROW)
|
|
276
|
+
defaults = @tables.fetch(:default_actions, Parser::EMPTY_ROW) #: Array[IR::runtime_action?]
|
|
277
|
+
defaults[state] || [:error]
|
|
240
278
|
end
|
|
241
279
|
|
|
242
|
-
# @rbs (
|
|
243
|
-
def
|
|
244
|
-
|
|
280
|
+
# @rbs (Tables::action_table table, Integer row, Integer column) -> IR::runtime_action?
|
|
281
|
+
def action_table_lookup(table, row, column)
|
|
282
|
+
if table.is_a?(Tables::CompactActions)
|
|
283
|
+
value = table.__send__(:lookup, row, column)
|
|
284
|
+
return value #: IR::runtime_action?
|
|
285
|
+
end
|
|
245
286
|
|
|
246
|
-
table
|
|
287
|
+
rows = table #: Array[Hash[Integer, IR::runtime_action]]
|
|
288
|
+
empty_row = Parser::EMPTY_ROW #: Hash[Integer, IR::runtime_action]
|
|
289
|
+
rows.fetch(row, empty_row)[column]
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# @rbs (Tables::goto_table table, Integer row, Integer column) -> Integer?
|
|
293
|
+
def goto_table_lookup(table, row, column)
|
|
294
|
+
if table.is_a?(Tables::Compact)
|
|
295
|
+
value = table.__send__(:lookup, row, column)
|
|
296
|
+
return value #: Integer?
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
rows = table #: Array[Hash[Integer, Integer]]
|
|
300
|
+
empty_row = Parser::EMPTY_ROW #: Hash[Integer, Integer]
|
|
301
|
+
rows.fetch(row, empty_row)[column]
|
|
247
302
|
end
|
|
248
303
|
|
|
249
304
|
# @rbs (Configuration source, ?stack: Array[Integer], ?input_index: Integer, ?shifts: Integer,
|
|
@@ -260,15 +315,22 @@ module Ibex
|
|
|
260
315
|
RepairPlan.new(edits: edits, configurations: @configurations)
|
|
261
316
|
end
|
|
262
317
|
|
|
318
|
+
# @rbs (Symbol status, ?plan: RepairPlan?) -> RepairSearchResult
|
|
319
|
+
def outcome(status, plan: nil)
|
|
320
|
+
RepairSearchResult.new(status: status, plan: plan, configurations: @configurations)
|
|
321
|
+
end
|
|
322
|
+
|
|
263
323
|
# @rbs (Integer token_id) -> String
|
|
264
324
|
def token_name(token_id)
|
|
265
|
-
@tables.fetch(:token_names)
|
|
325
|
+
token_names = @tables.fetch(:token_names) #: Hash[Integer, String]
|
|
326
|
+
token_names.fetch(token_id, token_id.to_s)
|
|
266
327
|
end
|
|
267
328
|
|
|
268
329
|
# @rbs (Configuration configuration) -> void
|
|
269
330
|
def push(configuration)
|
|
270
331
|
priority = priority_for(configuration)
|
|
271
|
-
key = [configuration.stack, configuration.input_index, configuration.shifts,
|
|
332
|
+
key = [configuration.stack, configuration.input_index, configuration.shifts,
|
|
333
|
+
configuration.goal] #: configuration_key
|
|
272
334
|
previous = @best[key]
|
|
273
335
|
comparison = previous <=> priority if previous
|
|
274
336
|
return if comparison && comparison <= 0
|
|
@@ -286,23 +348,24 @@ module Ibex
|
|
|
286
348
|
priority, configuration = entry
|
|
287
349
|
return LIMIT unless configuration.is_a?(Configuration)
|
|
288
350
|
|
|
289
|
-
key = [configuration.stack, configuration.input_index, configuration.shifts,
|
|
351
|
+
key = [configuration.stack, configuration.input_index, configuration.shifts,
|
|
352
|
+
configuration.goal] #: configuration_key
|
|
290
353
|
return configuration if @best[key] == priority
|
|
291
354
|
end
|
|
292
355
|
end
|
|
293
356
|
|
|
294
|
-
# @rbs (Configuration configuration) ->
|
|
357
|
+
# @rbs (Configuration configuration) -> priority
|
|
295
358
|
def priority_for(configuration)
|
|
296
359
|
edit_key = configuration.edits.map do |edit|
|
|
297
360
|
rank = { delete: 0, insert: 1, replace: 2 }.fetch(edit.kind)
|
|
298
|
-
[edit.position, rank, edit.token_id]
|
|
361
|
+
[edit.position, rank, edit.token_id] #: [Integer, Integer, Integer]
|
|
299
362
|
end
|
|
300
363
|
goal_rank = configuration.goal ? 0 : 1
|
|
301
364
|
risk = configuration.edits.sum { |edit| semantic_value_risk(edit) }
|
|
302
365
|
[
|
|
303
366
|
configuration.cost, risk, edit_key, goal_rank, -configuration.shifts,
|
|
304
367
|
configuration.input_index, configuration.stack
|
|
305
|
-
]
|
|
368
|
+
] #: priority
|
|
306
369
|
end
|
|
307
370
|
|
|
308
371
|
# Prefer punctuation edits when equal-cost repairs are otherwise
|