ibex-runtime 0.2.0 → 0.4.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 +100 -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
data/lib/ibex/runtime/parser.rb
CHANGED
|
@@ -4,26 +4,34 @@
|
|
|
4
4
|
require_relative "location_span" unless defined?(Ibex::Runtime::LocationSpan)
|
|
5
5
|
require_relative "observation" unless defined?(Ibex::Runtime::Observation)
|
|
6
6
|
require_relative "resource_limits" unless defined?(Ibex::Runtime::ResourceLimits)
|
|
7
|
+
require_relative "syntax_session" unless defined?(Ibex::Runtime::SyntaxSession)
|
|
7
8
|
require_relative "repair" unless defined?(Ibex::Runtime::RepairPolicy)
|
|
8
9
|
require_relative "repair_search" unless defined?(Ibex::Runtime::RepairSearch)
|
|
10
|
+
require_relative "syntax_repair" unless defined?(Ibex::Runtime::SyntaxRepairer)
|
|
9
11
|
require_relative "parser_sync_recovery" unless defined?(Ibex::Runtime::ParserSyncRecovery)
|
|
10
12
|
require_relative "table_format" unless defined?(Ibex::Runtime::PARSER_TABLE_FORMAT_VERSION)
|
|
11
13
|
|
|
12
14
|
module Ibex
|
|
13
15
|
module Runtime
|
|
16
|
+
# Semantic values and lexer locations intentionally cross the runtime
|
|
17
|
+
# boundary without a closed application type. Keep that boundary named so
|
|
18
|
+
# the rest of the parser remains structurally typed.
|
|
19
|
+
# @rbs!
|
|
20
|
+
# type runtime_value = untyped
|
|
21
|
+
|
|
14
22
|
# Raised by the default parser error handler.
|
|
15
23
|
class ParseError < StandardError
|
|
16
24
|
attr_reader :token_id #: Integer?
|
|
17
25
|
attr_reader :token_name #: String?
|
|
18
|
-
attr_reader :token_value #:
|
|
26
|
+
attr_reader :token_value #: runtime_value
|
|
19
27
|
attr_reader :expected_tokens #: Array[String]
|
|
20
|
-
attr_reader :location #:
|
|
28
|
+
attr_reader :location #: runtime_value
|
|
21
29
|
attr_reader :state #: Integer?
|
|
22
30
|
attr_reader :suggestions #: Array[String]
|
|
23
31
|
attr_reader :error_id #: String?
|
|
24
32
|
|
|
25
33
|
# rubocop:disable Layout/LineLength
|
|
26
|
-
# @rbs (?String? message, ?token_id: Integer?, ?token_name: String?, ?token_value:
|
|
34
|
+
# @rbs (?String? message, ?token_id: Integer?, ?token_name: String?, ?token_value: runtime_value, ?expected_tokens: Array[String], ?location: runtime_value, ?state: Integer?, ?suggestions: Array[String], ?error_id: String?, ?detail: String?) -> void
|
|
27
35
|
# rubocop:enable Layout/LineLength
|
|
28
36
|
def initialize(
|
|
29
37
|
message = nil,
|
|
@@ -72,7 +80,7 @@ module Ibex
|
|
|
72
80
|
message
|
|
73
81
|
end
|
|
74
82
|
|
|
75
|
-
# @rbs (Symbol key) ->
|
|
83
|
+
# @rbs (Symbol key) -> runtime_value
|
|
76
84
|
def location_value(key)
|
|
77
85
|
return nil unless @location
|
|
78
86
|
return @location.public_send(key) if @location.respond_to?(key)
|
|
@@ -88,7 +96,7 @@ module Ibex
|
|
|
88
96
|
attr_reader :limit #: Integer
|
|
89
97
|
attr_reader :observed #: Integer
|
|
90
98
|
|
|
91
|
-
# @rbs (resource: Symbol, limit: Integer, observed: Integer, state: Integer?, location:
|
|
99
|
+
# @rbs (resource: Symbol, limit: Integer, observed: Integer, state: Integer?, location: runtime_value) -> void
|
|
92
100
|
def initialize(resource:, limit:, observed:, state:, location:)
|
|
93
101
|
@resource = resource
|
|
94
102
|
@limit = limit
|
|
@@ -99,7 +107,7 @@ module Ibex
|
|
|
99
107
|
)
|
|
100
108
|
end
|
|
101
109
|
|
|
102
|
-
# @rbs () -> Hash[Symbol,
|
|
110
|
+
# @rbs () -> Hash[Symbol, runtime_value]
|
|
103
111
|
def to_h
|
|
104
112
|
{
|
|
105
113
|
type: :resource_limit, resource: @resource, limit: @limit, observed: @observed,
|
|
@@ -250,14 +258,14 @@ module Ibex
|
|
|
250
258
|
REPAIR_PENDING_OUTCOME = [:repair_pending].freeze #: [:repair_pending]
|
|
251
259
|
TERMINAL_OUTCOMES = %i[accepted done].freeze #: Array[Symbol]
|
|
252
260
|
COMPACT_ACCEPTED = Object.new.freeze #: Object
|
|
253
|
-
empty_row = {} # @type var empty_row: Hash[Integer,
|
|
261
|
+
empty_row = {} # @type var empty_row: Hash[Integer, runtime_value]
|
|
254
262
|
empty_location_names = {} # @type var empty_location_names: Hash[Symbol, Integer]
|
|
255
|
-
empty_locations = [] # @type var empty_locations: Array[
|
|
263
|
+
empty_locations = [] # @type var empty_locations: Array[runtime_value]
|
|
256
264
|
empty_green_trivia = [] # @type var empty_green_trivia: Array[CST::GreenTrivia]
|
|
257
265
|
|
|
258
|
-
EMPTY_ROW = empty_row.freeze #: Hash[Integer,
|
|
266
|
+
EMPTY_ROW = empty_row.freeze #: Hash[Integer, runtime_value]
|
|
259
267
|
EMPTY_LOCATION_NAMES = empty_location_names.freeze #: Hash[Symbol, Integer]
|
|
260
|
-
EMPTY_LOCATIONS = empty_locations.freeze #: Array[
|
|
268
|
+
EMPTY_LOCATIONS = empty_locations.freeze #: Array[runtime_value]
|
|
261
269
|
EMPTY_GREEN_TRIVIA = empty_green_trivia.freeze #: Array[CST::GreenTrivia]
|
|
262
270
|
private_constant :ERROR_ACTION, :SYNC_RECOVER_ACTION, :CONTINUE_OUTCOME, :REPAIR_PENDING_OUTCOME,
|
|
263
271
|
:TERMINAL_OUTCOMES, :COMPACT_ACCEPTED, :FAST_PATH_HOOK_NAMES, :FAST_PATH_HOOK_REFERENCES,
|
|
@@ -265,15 +273,15 @@ module Ibex
|
|
|
265
273
|
|
|
266
274
|
# @rbs @yydebug: bool
|
|
267
275
|
# @rbs @yydebug_output: IO
|
|
268
|
-
# @rbs @source:
|
|
276
|
+
# @rbs @source: runtime_value
|
|
269
277
|
# @rbs @state_stack: Array[Integer]
|
|
270
|
-
# @rbs @value_stack: Array[
|
|
271
|
-
# @rbs @vstack: Array[
|
|
272
|
-
# @rbs @racc_vstack: Array[
|
|
273
|
-
# @rbs @location_stack: Array[
|
|
274
|
-
# @rbs @lookahead:
|
|
275
|
-
# @rbs @lookahead_value:
|
|
276
|
-
# @rbs @lookahead_location:
|
|
278
|
+
# @rbs @value_stack: Array[runtime_value]
|
|
279
|
+
# @rbs @vstack: Array[runtime_value]
|
|
280
|
+
# @rbs @racc_vstack: Array[runtime_value]
|
|
281
|
+
# @rbs @location_stack: Array[runtime_value]?
|
|
282
|
+
# @rbs @lookahead: runtime_value
|
|
283
|
+
# @rbs @lookahead_value: runtime_value
|
|
284
|
+
# @rbs @lookahead_location: runtime_value
|
|
277
285
|
# @rbs @recovery_shifts: Integer
|
|
278
286
|
# @rbs @semantic_error: bool
|
|
279
287
|
# @rbs @accept_requested: bool
|
|
@@ -284,27 +292,27 @@ module Ibex
|
|
|
284
292
|
# @rbs @runtime_driver_thread: Thread?
|
|
285
293
|
# @rbs @runtime_observers: Hash[Observation::Subscription, Proc]?
|
|
286
294
|
# @rbs @runtime_event_sequence: Integer
|
|
287
|
-
# @rbs @runtime_lookahead_token_display:
|
|
295
|
+
# @rbs @runtime_lookahead_token_display: String?
|
|
288
296
|
# @rbs @runtime_observation_mutex: Mutex
|
|
289
297
|
# @rbs @repair_policy: RepairPolicy?
|
|
290
298
|
# @rbs @repair_input_buffer: Array[RepairInput]?
|
|
291
299
|
# @rbs @repair_selected: bool
|
|
292
|
-
# @rbs @semantic_locations: Array[
|
|
300
|
+
# @rbs @semantic_locations: Array[runtime_value]?
|
|
293
301
|
# @rbs @semantic_location_names: Hash[Symbol, Integer]?
|
|
294
|
-
# @rbs @semantic_result_location:
|
|
295
|
-
# @rbs @trace_value_printer: (^(
|
|
296
|
-
# @rbs @sync_recovery_context: Hash[Symbol,
|
|
297
|
-
# @rbs @sync_recovery_token_data: Hash[String,
|
|
302
|
+
# @rbs @semantic_result_location: runtime_value
|
|
303
|
+
# @rbs @trace_value_printer: (^(runtime_value) -> runtime_value)?
|
|
304
|
+
# @rbs @sync_recovery_context: Hash[Symbol, runtime_value]?
|
|
305
|
+
# @rbs @sync_recovery_token_data: Hash[String, runtime_value]?
|
|
298
306
|
# @rbs @sync_recovery_observers: Array[Proc]?
|
|
299
307
|
# @rbs @green_builder: CST::GreenBuilder?
|
|
300
308
|
# @rbs @green_kinds: CST::Kind?
|
|
301
309
|
# @rbs @green_cache: CST::NodeCache?
|
|
302
310
|
# @rbs @syntax_root: CST::SyntaxNode?
|
|
303
|
-
# @rbs @syntax_diagnostics: Array[
|
|
311
|
+
# @rbs @syntax_diagnostics: Array[runtime_value]
|
|
304
312
|
# @rbs @green_pending_skipped: Array[CST::GreenTrivia]
|
|
305
313
|
# @rbs @resource_limits: ResourceLimits
|
|
306
314
|
# @rbs @recovery_attempts: Integer
|
|
307
|
-
# @rbs @runtime_parser_tables: Hash[Symbol,
|
|
315
|
+
# @rbs @runtime_parser_tables: Hash[Symbol, runtime_value]?
|
|
308
316
|
# @rbs @runtime_fast_path: bool
|
|
309
317
|
# @rbs @runtime_fast_path_tracker_installed: bool
|
|
310
318
|
# @rbs @runtime_fast_path_hooks_mutated: bool
|
|
@@ -322,7 +330,41 @@ module Ibex
|
|
|
322
330
|
attr_reader :syntax_parse_memo #: CST::ParseMemo?
|
|
323
331
|
attr_reader :incremental_reused_descendants #: Integer
|
|
324
332
|
|
|
333
|
+
# Report the trust boundary of syntax-only operations for this loaded
|
|
334
|
+
# parser class. Current generated artifacts can contain user sections
|
|
335
|
+
# and Ruby lexer actions, so they are always trusted application code.
|
|
336
|
+
# @rbs skip
|
|
337
|
+
def self.syntax_execution_profile
|
|
338
|
+
:trusted_application_code
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Open a generated-language syntax session backed by the existing
|
|
342
|
+
# incremental Red/Green CST engine. The execution profile must be passed
|
|
343
|
+
# explicitly because generated lexer actions execute in this path.
|
|
344
|
+
# @rbs skip
|
|
345
|
+
def self.syntax_session(
|
|
346
|
+
source,
|
|
347
|
+
execution_profile: nil,
|
|
348
|
+
resource_limits: nil,
|
|
349
|
+
limits: nil,
|
|
350
|
+
cancellation: nil,
|
|
351
|
+
blender: true
|
|
352
|
+
)
|
|
353
|
+
SyntaxSession.new(
|
|
354
|
+
self,
|
|
355
|
+
source,
|
|
356
|
+
execution_profile: execution_profile,
|
|
357
|
+
resource_limits: resource_limits,
|
|
358
|
+
limits: limits,
|
|
359
|
+
cancellation: cancellation,
|
|
360
|
+
blender: blender
|
|
361
|
+
)
|
|
362
|
+
end
|
|
363
|
+
|
|
325
364
|
# Start a syntax-only incremental session backed by a generated lexer.
|
|
365
|
+
# Parser production actions are suppressed, but generated lexer actions
|
|
366
|
+
# still execute. The generated class is trusted application code, not a
|
|
367
|
+
# sandbox.
|
|
326
368
|
# @rbs (CST::SourceText source_text, ?resource_limits: ResourceLimits?, ?blender: bool) ->
|
|
327
369
|
# CST::IncrementalParseSession
|
|
328
370
|
def self.incremental_session(source_text, resource_limits: nil, blender: true)
|
|
@@ -403,13 +445,17 @@ module Ibex
|
|
|
403
445
|
end
|
|
404
446
|
end
|
|
405
447
|
|
|
406
|
-
# Pull tokens from `next_token` and
|
|
407
|
-
#
|
|
448
|
+
# Pull tokens from `next_token` and execute parser production actions.
|
|
449
|
+
# A generated-lexer `next_token` executes lexer actions; a handwritten
|
|
450
|
+
# implementation does not invoke the generated lexer.
|
|
451
|
+
# @rbs () -> runtime_value
|
|
408
452
|
def do_parse
|
|
409
453
|
drive_parser(nil)
|
|
410
454
|
end
|
|
411
455
|
|
|
412
456
|
# Parse through `next_token` and return both the semantic value and Red root.
|
|
457
|
+
# Parser production actions execute. Generated lexer actions execute only
|
|
458
|
+
# when `next_token` is supplied by the generated lexer.
|
|
413
459
|
# @rbs () -> CST::ParseResult
|
|
414
460
|
def parse_with_syntax
|
|
415
461
|
syntax_parse_result(do_parse)
|
|
@@ -422,8 +468,10 @@ module Ibex
|
|
|
422
468
|
@syntax_root
|
|
423
469
|
end
|
|
424
470
|
|
|
425
|
-
# Parse tokens yielded by `receiver.method_id
|
|
426
|
-
#
|
|
471
|
+
# Parse tokens yielded by `receiver.method_id` and execute parser
|
|
472
|
+
# production actions. This caller-fed path does not invoke generated
|
|
473
|
+
# lexer actions.
|
|
474
|
+
# @rbs (runtime_value receiver, Symbol method_id) -> runtime_value
|
|
427
475
|
def yyparse(receiver, method_id)
|
|
428
476
|
stream = Enumerator.new do |tokens|
|
|
429
477
|
receiver.__send__(method_id) { |token| tokens << token }
|
|
@@ -432,11 +480,11 @@ module Ibex
|
|
|
432
480
|
end
|
|
433
481
|
|
|
434
482
|
# Supply one token to a caller-driven parser session.
|
|
483
|
+
# Committed reductions execute parser production actions; this token-fed
|
|
484
|
+
# path does not invoke generated lexer actions.
|
|
435
485
|
# Returns `:need_more` after consuming it, `[:accepted, result]` after
|
|
436
486
|
# acceptance, or `[:rejected, result]` after recovery terminates.
|
|
437
|
-
#
|
|
438
|
-
# @rbs (untyped token, ?untyped value, ?untyped location) -> (:need_more | [:accepted, untyped] | [:rejected, untyped])
|
|
439
|
-
# rubocop:enable Layout/LineLength
|
|
487
|
+
# @rbs (runtime_value token, ?runtime_value value, ?runtime_value location) -> runtime_value
|
|
440
488
|
def push(token, value = nil, location = nil)
|
|
441
489
|
raise ParseError, "(input):1:1: push requires a token; call finish for EOF" if token.nil? || token == false
|
|
442
490
|
|
|
@@ -457,7 +505,9 @@ module Ibex
|
|
|
457
505
|
end
|
|
458
506
|
|
|
459
507
|
# Supply EOF to a caller-driven parser session and return its result.
|
|
460
|
-
#
|
|
508
|
+
# Committed reductions execute parser production actions; this token-fed
|
|
509
|
+
# path does not invoke generated lexer actions.
|
|
510
|
+
# @rbs (?location: runtime_value) -> runtime_value
|
|
461
511
|
def finish(location: nil)
|
|
462
512
|
run_push_driver do
|
|
463
513
|
start_push_session
|
|
@@ -505,14 +555,14 @@ module Ibex
|
|
|
505
555
|
|
|
506
556
|
# Override in pull parsers. Return `[token, value]`,
|
|
507
557
|
# `[token, value, location]`, `false`, or `nil`.
|
|
508
|
-
# @rbs () -> ([
|
|
558
|
+
# @rbs () -> ([runtime_value, runtime_value] | [runtime_value, runtime_value, runtime_value] | false | nil)
|
|
509
559
|
def next_token
|
|
510
560
|
raise NotImplementedError, "(input):1:1: next_token must be implemented"
|
|
511
561
|
end
|
|
512
562
|
|
|
513
563
|
# Override to recover from syntax errors. The default raises unless a
|
|
514
564
|
# bounded automatic repair has already been selected.
|
|
515
|
-
# @rbs (Integer token_id,
|
|
565
|
+
# @rbs (Integer token_id, runtime_value value, Array[runtime_value] value_stack) -> runtime_value
|
|
516
566
|
def on_error(token_id, value, _value_stack)
|
|
517
567
|
return if @repair_selected
|
|
518
568
|
return if cst_enabled?
|
|
@@ -537,40 +587,40 @@ module Ibex
|
|
|
537
587
|
|
|
538
588
|
# Called after an ordinary input token is shifted. Override to observe
|
|
539
589
|
# the internal token id, semantic value, and destination state.
|
|
540
|
-
# @rbs (Integer token_id,
|
|
590
|
+
# @rbs (Integer token_id, runtime_value value, Integer state) -> void
|
|
541
591
|
def on_shift(_token_id, _value, _state); end
|
|
542
592
|
|
|
543
593
|
# Location-aware shift observer. The compatible hook above retains its
|
|
544
594
|
# original signature and runs first.
|
|
545
|
-
# @rbs (Integer token_id,
|
|
595
|
+
# @rbs (Integer token_id, runtime_value value, Integer state, runtime_value location) -> void
|
|
546
596
|
def on_shift_location(_token_id, _value, _state, _location); end
|
|
547
597
|
|
|
548
598
|
# Called after a production's semantic action and goto are committed.
|
|
549
599
|
# Override to observe its id, RHS values, and semantic result.
|
|
550
|
-
# @rbs (Integer production_id, Array[
|
|
600
|
+
# @rbs (Integer production_id, Array[runtime_value] values, runtime_value result) -> void
|
|
551
601
|
def on_reduce(_production_id, _values, _result); end
|
|
552
602
|
|
|
553
603
|
# Location-aware reduction observer.
|
|
554
|
-
# @rbs (Integer production_id, Array[
|
|
555
|
-
# Array[
|
|
604
|
+
# @rbs (Integer production_id, Array[runtime_value] values, runtime_value result,
|
|
605
|
+
# Array[runtime_value] locations, runtime_value result_location) -> void
|
|
556
606
|
def on_reduce_location(_production_id, _values, _result, _locations, _result_location); end
|
|
557
607
|
|
|
558
608
|
# Called after the synthetic error token enters a recovery state.
|
|
559
609
|
# The payload describes the original error before recovery popped stacks.
|
|
560
|
-
# @rbs (Integer token_id,
|
|
610
|
+
# @rbs (Integer token_id, runtime_value value, Array[runtime_value] value_stack) -> void
|
|
561
611
|
def on_error_recover(_token_id, _value, _value_stack); end
|
|
562
612
|
|
|
563
613
|
# Location-aware recovery observer.
|
|
564
|
-
# @rbs (Integer token_id,
|
|
565
|
-
#
|
|
614
|
+
# @rbs (Integer token_id, runtime_value value, Array[runtime_value] value_stack,
|
|
615
|
+
# runtime_value location, Integer state) -> void
|
|
566
616
|
def on_error_recover_location(_token_id, _value, _value_stack, _location, _state); end
|
|
567
617
|
|
|
568
618
|
# Called when yacc recovery discards an application token.
|
|
569
|
-
# @rbs (Integer token_id,
|
|
619
|
+
# @rbs (Integer token_id, runtime_value value, runtime_value location, Symbol reason) -> void
|
|
570
620
|
def on_discard(_token_id, _value, _location, _reason); end
|
|
571
621
|
|
|
572
622
|
# Install an opt-in value formatter for human-readable yydebug traces.
|
|
573
|
-
# @rbs ((^(
|
|
623
|
+
# @rbs ((^(runtime_value) -> runtime_value)? printer) -> (^(runtime_value) -> runtime_value)?
|
|
574
624
|
def trace_value_printer=(printer)
|
|
575
625
|
ensure_runtime_initialized!
|
|
576
626
|
unless printer.nil? || printer.respond_to?(:call)
|
|
@@ -646,7 +696,7 @@ module Ibex
|
|
|
646
696
|
|
|
647
697
|
# Return the location of a one-based RHS position or named reference
|
|
648
698
|
# while a semantic action is running.
|
|
649
|
-
# @rbs (Integer | Symbol | String reference) ->
|
|
699
|
+
# @rbs (Integer | Symbol | String reference) -> runtime_value
|
|
650
700
|
def loc(reference)
|
|
651
701
|
locations = @semantic_locations
|
|
652
702
|
raise ParseError, "(runtime):1:1: loc is only available inside a semantic action" unless locations
|
|
@@ -665,7 +715,7 @@ module Ibex
|
|
|
665
715
|
end
|
|
666
716
|
|
|
667
717
|
# Return the synthesized span of the reduction being evaluated.
|
|
668
|
-
# @rbs () ->
|
|
718
|
+
# @rbs () -> runtime_value
|
|
669
719
|
def result_loc
|
|
670
720
|
unless @semantic_locations
|
|
671
721
|
raise ParseError, "(runtime):1:1: result_loc is only available inside a semantic action"
|
|
@@ -725,6 +775,9 @@ module Ibex
|
|
|
725
775
|
@repair_policy = nil unless preserve_existing && defined?(@repair_policy)
|
|
726
776
|
@repair_input_buffer = nil unless preserve_existing && defined?(@repair_input_buffer)
|
|
727
777
|
@repair_selected = false unless preserve_existing && defined?(@repair_selected)
|
|
778
|
+
unless preserve_existing && defined?(@repair_search_results)
|
|
779
|
+
@repair_search_results = [] #: Array[RepairSearchResult]
|
|
780
|
+
end
|
|
728
781
|
@semantic_locations = nil unless preserve_existing && defined?(@semantic_locations)
|
|
729
782
|
@semantic_location_names = nil unless preserve_existing && defined?(@semantic_location_names)
|
|
730
783
|
@semantic_result_location = nil unless preserve_existing && defined?(@semantic_result_location)
|
|
@@ -736,8 +789,8 @@ module Ibex
|
|
|
736
789
|
@green_kinds = nil unless preserve_existing && defined?(@green_kinds)
|
|
737
790
|
@green_cache = nil unless preserve_existing && defined?(@green_cache)
|
|
738
791
|
@syntax_root = nil unless preserve_existing && defined?(@syntax_root)
|
|
739
|
-
@syntax_diagnostics =
|
|
740
|
-
@green_pending_skipped =
|
|
792
|
+
@syntax_diagnostics = EMPTY_LOCATIONS unless preserve_existing && defined?(@syntax_diagnostics)
|
|
793
|
+
@green_pending_skipped = EMPTY_GREEN_TRIVIA unless preserve_existing && defined?(@green_pending_skipped)
|
|
741
794
|
@recovery_attempts = 0 unless preserve_existing && defined?(@recovery_attempts)
|
|
742
795
|
@runtime_parser_tables = nil unless preserve_existing && defined?(@runtime_parser_tables)
|
|
743
796
|
@runtime_fast_path = false unless preserve_existing && defined?(@runtime_fast_path)
|
|
@@ -749,8 +802,8 @@ module Ibex
|
|
|
749
802
|
preserve_existing && defined?(@runtime_fast_path_singleton_ancestors)
|
|
750
803
|
@syntax_only = false unless preserve_existing && defined?(@syntax_only)
|
|
751
804
|
@green_cache_override = nil unless preserve_existing && defined?(@green_cache_override)
|
|
752
|
-
@green_token_states =
|
|
753
|
-
@green_memo_stack =
|
|
805
|
+
@green_token_states = EMPTY_LOCATIONS unless preserve_existing && defined?(@green_token_states)
|
|
806
|
+
@green_memo_stack = EMPTY_LOCATIONS unless preserve_existing && defined?(@green_memo_stack)
|
|
754
807
|
@green_parse_memo_valid = false unless preserve_existing && defined?(@green_parse_memo_valid)
|
|
755
808
|
@green_initial_state = 0 unless preserve_existing && defined?(@green_initial_state)
|
|
756
809
|
@syntax_parse_memo = nil unless preserve_existing && defined?(@syntax_parse_memo)
|
|
@@ -769,7 +822,7 @@ module Ibex
|
|
|
769
822
|
|
|
770
823
|
# Keep the two historical value-stack names as read-compatible aliases.
|
|
771
824
|
# Applications must not mutate or replace these internal arrays.
|
|
772
|
-
# @rbs (Array[
|
|
825
|
+
# @rbs (Array[runtime_value] values) -> void
|
|
773
826
|
def install_value_stack(values)
|
|
774
827
|
@value_stack = values
|
|
775
828
|
@vstack = values
|
|
@@ -809,7 +862,7 @@ module Ibex
|
|
|
809
862
|
(stack_depth + parser_state_count(tables) + 1) * (production_count + 1)
|
|
810
863
|
end
|
|
811
864
|
|
|
812
|
-
# @rbs (Hash[Symbol,
|
|
865
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> Integer
|
|
813
866
|
def parser_state_count(tables)
|
|
814
867
|
state_count = tables[:state_count]
|
|
815
868
|
return state_count if state_count.is_a?(Integer)
|
|
@@ -848,7 +901,7 @@ module Ibex
|
|
|
848
901
|
true
|
|
849
902
|
end
|
|
850
903
|
|
|
851
|
-
# @rbs (
|
|
904
|
+
# @rbs (runtime_value source, ?initial_state: Integer?) -> runtime_value
|
|
852
905
|
def drive_parser(source, initial_state: nil)
|
|
853
906
|
ensure_runtime_initialized!
|
|
854
907
|
@runtime_observation_mutex.synchronize do
|
|
@@ -892,7 +945,7 @@ module Ibex
|
|
|
892
945
|
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
893
946
|
# Direct comparisons avoid predicate-method dispatch inside the parser loop.
|
|
894
947
|
# rubocop:disable Style/BitwisePredicate, Style/NumericPredicate
|
|
895
|
-
# @rbs (Hash[Symbol,
|
|
948
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> runtime_value
|
|
896
949
|
def drive_compact_fast_parser(tables)
|
|
897
950
|
actions = tables.fetch(:actions)
|
|
898
951
|
gotos = tables.fetch(:gotos)
|
|
@@ -1132,7 +1185,7 @@ module Ibex
|
|
|
1132
1185
|
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
1133
1186
|
# rubocop:enable Style/BitwisePredicate, Style/NumericPredicate
|
|
1134
1187
|
|
|
1135
|
-
# @rbs (Hash[Symbol,
|
|
1188
|
+
# @rbs (Hash[Symbol, runtime_value]? tables) -> bool
|
|
1136
1189
|
def compact_fast_driver_eligible?(tables)
|
|
1137
1190
|
return false unless @runtime_fast_path && tables
|
|
1138
1191
|
return false unless tables[:compact_fast_driver] == true
|
|
@@ -1156,7 +1209,7 @@ module Ibex
|
|
|
1156
1209
|
@push_status = :active
|
|
1157
1210
|
end
|
|
1158
1211
|
|
|
1159
|
-
# @rbs () ->
|
|
1212
|
+
# @rbs () -> runtime_value
|
|
1160
1213
|
def run_push_lookahead
|
|
1161
1214
|
loop do
|
|
1162
1215
|
outcome = perform(action_for_current_state)
|
|
@@ -1179,7 +1232,7 @@ module Ibex
|
|
|
1179
1232
|
end
|
|
1180
1233
|
end
|
|
1181
1234
|
|
|
1182
|
-
# @rbs () { () ->
|
|
1235
|
+
# @rbs () { () -> runtime_value } -> runtime_value
|
|
1183
1236
|
def run_push_driver
|
|
1184
1237
|
ensure_runtime_initialized!
|
|
1185
1238
|
@runtime_observation_mutex.synchronize do
|
|
@@ -1225,7 +1278,7 @@ module Ibex
|
|
|
1225
1278
|
clear_sync_recovery
|
|
1226
1279
|
end
|
|
1227
1280
|
|
|
1228
|
-
# @rbs ((^() ->
|
|
1281
|
+
# @rbs ((^() -> runtime_value)? source, ?initial_state: Integer?) -> void
|
|
1229
1282
|
def prepare_parse(source, initial_state: nil)
|
|
1230
1283
|
@runtime_parser_tables = load_parser_tables
|
|
1231
1284
|
tables = validate_parser_table_format!
|
|
@@ -1267,10 +1320,11 @@ module Ibex
|
|
|
1267
1320
|
@semantic_error = false
|
|
1268
1321
|
@repair_input_buffer = @repair_policy ? [] : nil
|
|
1269
1322
|
@repair_selected = false
|
|
1323
|
+
@repair_search_results = [] #: Array[RepairSearchResult]
|
|
1270
1324
|
clear_sync_recovery
|
|
1271
1325
|
end
|
|
1272
1326
|
|
|
1273
|
-
# @rbs (Hash[Symbol,
|
|
1327
|
+
# @rbs (Hash[Symbol, runtime_value] tables, Integer? requested) -> Integer
|
|
1274
1328
|
def resolve_initial_state(tables, requested)
|
|
1275
1329
|
initial_state = requested || tables[:initial_state] || 0
|
|
1276
1330
|
return initial_state if initial_state.is_a?(Integer) &&
|
|
@@ -1279,7 +1333,7 @@ module Ibex
|
|
|
1279
1333
|
raise ParseError, "(tables):1:1: parser initial state #{initial_state.inspect} is invalid"
|
|
1280
1334
|
end
|
|
1281
1335
|
|
|
1282
|
-
# @rbs () -> Hash[Symbol,
|
|
1336
|
+
# @rbs () -> Hash[Symbol, runtime_value]
|
|
1283
1337
|
def validate_parser_table_format!
|
|
1284
1338
|
tables = parser_tables
|
|
1285
1339
|
unless tables.key?(:format_version)
|
|
@@ -1296,19 +1350,19 @@ module Ibex
|
|
|
1296
1350
|
"regenerate the parser with the installed Ibex version"
|
|
1297
1351
|
end
|
|
1298
1352
|
|
|
1299
|
-
validate_current_cst_tables!(tables
|
|
1300
|
-
|
|
1301
|
-
validate_generated_action_contracts!(tables
|
|
1353
|
+
validate_current_cst_tables!(tables)
|
|
1354
|
+
unless generated_action_contracts_validated?(tables)
|
|
1355
|
+
validate_generated_action_contracts!(tables)
|
|
1302
1356
|
cache_generated_action_contracts!(tables)
|
|
1303
1357
|
end
|
|
1304
1358
|
tables
|
|
1305
1359
|
end
|
|
1306
1360
|
|
|
1307
|
-
# @rbs (Hash[Symbol,
|
|
1308
|
-
def validate_current_cst_tables!(tables
|
|
1361
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
1362
|
+
def validate_current_cst_tables!(tables)
|
|
1309
1363
|
cst = tables[:cst]
|
|
1310
1364
|
return if cst.nil? || cst == false
|
|
1311
|
-
return if
|
|
1365
|
+
return if cst.is_a?(Hash)
|
|
1312
1366
|
|
|
1313
1367
|
raise ParseError,
|
|
1314
1368
|
"(tables):1:1: legacy CST parser tables are unsupported; " \
|
|
@@ -1319,7 +1373,7 @@ module Ibex
|
|
|
1319
1373
|
# Ractor boundary. Their action-marker contract only needs one scan per
|
|
1320
1374
|
# parser class and exact table object, including across parser instances.
|
|
1321
1375
|
# Mutable application tables remain intentionally uncached.
|
|
1322
|
-
# @rbs (Hash[Symbol,
|
|
1376
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> bool
|
|
1323
1377
|
def generated_action_contracts_validated?(tables)
|
|
1324
1378
|
return false unless generated_action_contract_cache_accessible?
|
|
1325
1379
|
|
|
@@ -1327,7 +1381,7 @@ module Ibex
|
|
|
1327
1381
|
cached.equal?(tables)
|
|
1328
1382
|
end
|
|
1329
1383
|
|
|
1330
|
-
# @rbs (Hash[Symbol,
|
|
1384
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
1331
1385
|
def cache_generated_action_contracts!(tables)
|
|
1332
1386
|
shareable = defined?(Ractor) && Ractor.respond_to?(:shareable?) && Ractor.shareable?(tables)
|
|
1333
1387
|
return unless shareable
|
|
@@ -1353,58 +1407,62 @@ module Ibex
|
|
|
1353
1407
|
true
|
|
1354
1408
|
end
|
|
1355
1409
|
|
|
1356
|
-
# @rbs (Hash[Symbol,
|
|
1357
|
-
def validate_generated_action_contracts!(tables
|
|
1410
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
1411
|
+
def validate_generated_action_contracts!(tables)
|
|
1358
1412
|
tables.fetch(:productions).each_with_index do |production, index|
|
|
1359
|
-
validate_composition_action_contract!(production, index
|
|
1360
|
-
validate_values_action_contract!(production, index
|
|
1361
|
-
validate_positional_action_contract!(production, index
|
|
1413
|
+
validate_composition_action_contract!(production, index)
|
|
1414
|
+
validate_values_action_contract!(production, index)
|
|
1415
|
+
validate_positional_action_contract!(production, index)
|
|
1362
1416
|
end
|
|
1363
1417
|
end
|
|
1364
1418
|
|
|
1365
|
-
# @rbs (Hash[Symbol,
|
|
1366
|
-
def validate_composition_action_contract!(production, index
|
|
1419
|
+
# @rbs (Hash[Symbol, runtime_value] production, Integer index) -> void
|
|
1420
|
+
def validate_composition_action_contract!(production, index)
|
|
1367
1421
|
return unless production[:composition_action] == true
|
|
1368
1422
|
return if production[:location_action] == true && generated_action_symbol?(production[:action])
|
|
1369
1423
|
|
|
1370
1424
|
raise ParseError,
|
|
1371
|
-
"(tables):1:1: parser table format version #{
|
|
1425
|
+
"(tables):1:1: parser table format version #{PARSER_TABLE_FORMAT_VERSION} " \
|
|
1426
|
+
"production #{index} has an inconsistent " \
|
|
1372
1427
|
":composition_action marker; a generated action Symbol with :location_action is required"
|
|
1373
1428
|
end
|
|
1374
1429
|
|
|
1375
|
-
# @rbs (Hash[Symbol,
|
|
1376
|
-
def validate_values_action_contract!(production, index
|
|
1430
|
+
# @rbs (Hash[Symbol, runtime_value] production, Integer index) -> void
|
|
1431
|
+
def validate_values_action_contract!(production, index)
|
|
1377
1432
|
borrowed = production[:borrowed_values_action] == true
|
|
1378
1433
|
if borrowed && production[:values_action] != true
|
|
1379
1434
|
raise ParseError,
|
|
1380
|
-
"(tables):1:1: parser table format version #{
|
|
1435
|
+
"(tables):1:1: parser table format version #{PARSER_TABLE_FORMAT_VERSION} " \
|
|
1436
|
+
"production #{index} has an inconsistent " \
|
|
1381
1437
|
":borrowed_values_action marker; :values_action is required"
|
|
1382
1438
|
end
|
|
1383
|
-
return if
|
|
1439
|
+
return if production[:values_action] != true
|
|
1384
1440
|
return if generated_action_symbol?(production[:action]) &&
|
|
1385
1441
|
production[:location_action] != true &&
|
|
1386
1442
|
production[:composition_action] != true &&
|
|
1387
1443
|
production.fetch(:location_context_length, 0).zero?
|
|
1388
1444
|
|
|
1389
1445
|
raise ParseError,
|
|
1390
|
-
"(tables):1:1: parser table format version #{
|
|
1446
|
+
"(tables):1:1: parser table format version #{PARSER_TABLE_FORMAT_VERSION} " \
|
|
1447
|
+
"production #{index} has an inconsistent " \
|
|
1391
1448
|
":values_action marker; a generated action Symbol without location, composition, or context " \
|
|
1392
1449
|
"markers is required"
|
|
1393
1450
|
end
|
|
1394
1451
|
|
|
1395
|
-
# @rbs (Hash[Symbol,
|
|
1396
|
-
def validate_positional_action_contract!(production, index
|
|
1397
|
-
return
|
|
1452
|
+
# @rbs (Hash[Symbol, runtime_value] production, Integer index) -> void
|
|
1453
|
+
def validate_positional_action_contract!(production, index)
|
|
1454
|
+
return unless production[:positional_action] == true
|
|
1398
1455
|
|
|
1399
1456
|
return if positional_action_contract?(production)
|
|
1400
1457
|
|
|
1401
1458
|
raise ParseError,
|
|
1402
|
-
"(tables):1:1: parser table format version #{
|
|
1459
|
+
"(tables):1:1: parser table format version #{PARSER_TABLE_FORMAT_VERSION} " \
|
|
1460
|
+
"production #{index} has an inconsistent " \
|
|
1403
1461
|
":positional_action marker; a generated action Symbol with zero to four RHS values and no other " \
|
|
1404
1462
|
"action ABI markers is required"
|
|
1405
1463
|
end
|
|
1406
1464
|
|
|
1407
|
-
# @rbs (Hash[Symbol,
|
|
1465
|
+
# @rbs (Hash[Symbol, runtime_value] production) -> bool
|
|
1408
1466
|
def positional_action_contract?(production)
|
|
1409
1467
|
production[:length].is_a?(Integer) &&
|
|
1410
1468
|
production[:length].between?(0, 4) &&
|
|
@@ -1416,7 +1474,7 @@ module Ibex
|
|
|
1416
1474
|
production.fetch(:location_context_length, 0).zero?
|
|
1417
1475
|
end
|
|
1418
1476
|
|
|
1419
|
-
# @rbs () ->
|
|
1477
|
+
# @rbs () -> runtime_value
|
|
1420
1478
|
def action_for_current_state
|
|
1421
1479
|
loop do
|
|
1422
1480
|
if @lookahead.equal?(NO_LOOKAHEAD)
|
|
@@ -1439,7 +1497,7 @@ module Ibex
|
|
|
1439
1497
|
end
|
|
1440
1498
|
end
|
|
1441
1499
|
|
|
1442
|
-
# @rbs (
|
|
1500
|
+
# @rbs (runtime_value action) -> runtime_value
|
|
1443
1501
|
def perform(action)
|
|
1444
1502
|
case action.first
|
|
1445
1503
|
when :shift
|
|
@@ -1481,7 +1539,7 @@ module Ibex
|
|
|
1481
1539
|
CONTINUE_OUTCOME
|
|
1482
1540
|
end
|
|
1483
1541
|
|
|
1484
|
-
# @rbs (Hash[Symbol,
|
|
1542
|
+
# @rbs (Hash[Symbol, runtime_value] production, runtime_value length) -> bool
|
|
1485
1543
|
def fast_reduction_eligible?(production, length)
|
|
1486
1544
|
action = production[:action]
|
|
1487
1545
|
return false if action && !generated_values_action?(production, action)
|
|
@@ -1490,7 +1548,7 @@ module Ibex
|
|
|
1490
1548
|
length <= @value_stack.length && length < @state_stack.length
|
|
1491
1549
|
end
|
|
1492
1550
|
|
|
1493
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1551
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Integer length) -> [:continue]
|
|
1494
1552
|
def fast_reduce(production_id, production, length)
|
|
1495
1553
|
action = production[:action]
|
|
1496
1554
|
return fast_values_reduce(production_id, production, length, action) if action
|
|
@@ -1511,7 +1569,8 @@ module Ibex
|
|
|
1511
1569
|
CONTINUE_OUTCOME
|
|
1512
1570
|
end
|
|
1513
1571
|
|
|
1514
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1572
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Integer length,
|
|
1573
|
+
# Symbol action) -> runtime_value
|
|
1515
1574
|
def fast_values_reduce(production_id, production, length, action)
|
|
1516
1575
|
hook_values = @value_stack.last(length)
|
|
1517
1576
|
values = hook_values.dup
|
|
@@ -1544,7 +1603,7 @@ module Ibex
|
|
|
1544
1603
|
CONTINUE_OUTCOME
|
|
1545
1604
|
end
|
|
1546
1605
|
|
|
1547
|
-
# @rbs (Integer next_state) ->
|
|
1606
|
+
# @rbs (Integer next_state) -> runtime_value
|
|
1548
1607
|
def shift(next_state)
|
|
1549
1608
|
token_id = @lookahead
|
|
1550
1609
|
value = @lookahead_value
|
|
@@ -1577,7 +1636,7 @@ module Ibex
|
|
|
1577
1636
|
CONTINUE_OUTCOME
|
|
1578
1637
|
end
|
|
1579
1638
|
|
|
1580
|
-
# @rbs (Integer production_id, ?Hash[Symbol,
|
|
1639
|
+
# @rbs (Integer production_id, ?Hash[Symbol, runtime_value]? prefetched_production) -> runtime_value
|
|
1581
1640
|
def reduce(production_id, prefetched_production = nil) # rubocop:disable Metrics -- allocation-free hot path.
|
|
1582
1641
|
production = prefetched_production || parser_tables.fetch(:productions).fetch(production_id)
|
|
1583
1642
|
length = production.fetch(:length)
|
|
@@ -1622,23 +1681,23 @@ module Ibex
|
|
|
1622
1681
|
CONTINUE_OUTCOME
|
|
1623
1682
|
end
|
|
1624
1683
|
|
|
1625
|
-
# @rbs (Integer next_state,
|
|
1684
|
+
# @rbs (Integer next_state, runtime_value result, runtime_value location) -> void
|
|
1626
1685
|
def push_reduction_result(next_state, result, location)
|
|
1627
1686
|
@state_stack << next_state
|
|
1628
1687
|
push_location(location)
|
|
1629
1688
|
@value_stack << result
|
|
1630
1689
|
end
|
|
1631
1690
|
|
|
1632
|
-
# @rbs (Integer production_id, Integer length, Integer lhs,
|
|
1691
|
+
# @rbs (Integer production_id, Integer length, Integer lhs, runtime_value result, Integer next_state) -> void
|
|
1633
1692
|
def trace_reduction(production_id, length, lhs, result, next_state)
|
|
1634
1693
|
return unless @yydebug
|
|
1635
1694
|
|
|
1636
1695
|
trace("reduce #{production_id} (#{length})#{trace_value_suffix(result, lhs)} -> state #{next_state}")
|
|
1637
1696
|
end
|
|
1638
1697
|
|
|
1639
|
-
# @rbs (Array[Proc]? observers, Integer production_id, Hash[Symbol,
|
|
1640
|
-
# Integer? pre_state, Integer? post_state, Integer next_state,
|
|
1641
|
-
# LocationSpan? location) -> Hash[String,
|
|
1698
|
+
# @rbs (Array[Proc]? observers, Integer production_id, Hash[Symbol, runtime_value] production, Integer length,
|
|
1699
|
+
# Integer? pre_state, Integer? post_state, Integer next_state, runtime_value result,
|
|
1700
|
+
# LocationSpan? location) -> Hash[String, runtime_value]?
|
|
1642
1701
|
def build_reduce_event_data(
|
|
1643
1702
|
observers, production_id, production, length, pre_state, post_state, next_state, result, location
|
|
1644
1703
|
)
|
|
@@ -1649,9 +1708,9 @@ module Ibex
|
|
|
1649
1708
|
)
|
|
1650
1709
|
end
|
|
1651
1710
|
|
|
1652
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1653
|
-
# Integer? pre_state, Integer? post_state, Integer next_state,
|
|
1654
|
-
# LocationSpan? location) -> Hash[String,
|
|
1711
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Integer length,
|
|
1712
|
+
# Integer? pre_state, Integer? post_state, Integer next_state, runtime_value result,
|
|
1713
|
+
# LocationSpan? location) -> Hash[String, runtime_value]
|
|
1655
1714
|
def runtime_reduce_data(production_id, production, length, pre_state, post_state, next_state, result, location)
|
|
1656
1715
|
{
|
|
1657
1716
|
"production_id" => production_id,
|
|
@@ -1665,15 +1724,15 @@ module Ibex
|
|
|
1665
1724
|
}.freeze
|
|
1666
1725
|
end
|
|
1667
1726
|
|
|
1668
|
-
# @rbs (
|
|
1727
|
+
# @rbs (runtime_value result) -> [:accepted, runtime_value]
|
|
1669
1728
|
def accept_reduction(result)
|
|
1670
1729
|
result = finalize_cst(result)
|
|
1671
1730
|
emit_accept_event(EventSanitizer.value(result), "semantic") if @runtime_observers
|
|
1672
1731
|
[:accepted, result]
|
|
1673
1732
|
end
|
|
1674
1733
|
|
|
1675
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1676
|
-
# Array[
|
|
1734
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Array[runtime_value] values,
|
|
1735
|
+
# Array[runtime_value] locations, LocationSpan? location) -> runtime_value
|
|
1677
1736
|
def reduction_value(production_id, production, values, locations, location) # rubocop:disable Metrics -- explicit hot path.
|
|
1678
1737
|
previous_locations = @semantic_locations
|
|
1679
1738
|
previous_names = @semantic_location_names
|
|
@@ -1721,8 +1780,8 @@ module Ibex
|
|
|
1721
1780
|
@semantic_result_location = previous_result_location
|
|
1722
1781
|
end
|
|
1723
1782
|
|
|
1724
|
-
# @rbs (Hash[Symbol,
|
|
1725
|
-
# Array[
|
|
1783
|
+
# @rbs (Hash[Symbol, runtime_value] production, Symbol action, Array[runtime_value] values,
|
|
1784
|
+
# Array[runtime_value] locations, LocationSpan? location) -> runtime_value
|
|
1726
1785
|
def values_reduction_value(production, action, values, locations, location)
|
|
1727
1786
|
previous_locations = @semantic_locations
|
|
1728
1787
|
previous_names = @semantic_location_names
|
|
@@ -1737,41 +1796,37 @@ module Ibex
|
|
|
1737
1796
|
@semantic_result_location = previous_result_location
|
|
1738
1797
|
end
|
|
1739
1798
|
|
|
1740
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1741
|
-
# Array[
|
|
1799
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Array[runtime_value] values,
|
|
1800
|
+
# Array[runtime_value] locations, LocationSpan? location) -> runtime_value
|
|
1742
1801
|
def actionless_reduction_value(_production_id, _production, values, _locations, _location)
|
|
1743
1802
|
values.first
|
|
1744
1803
|
end
|
|
1745
1804
|
|
|
1746
|
-
# @rbs (Hash[Symbol,
|
|
1805
|
+
# @rbs (Hash[Symbol, runtime_value] production, runtime_value action) -> bool
|
|
1747
1806
|
def generated_location_action?(production, action)
|
|
1748
|
-
|
|
1749
|
-
production[:location_action] == true &&
|
|
1807
|
+
production[:location_action] == true &&
|
|
1750
1808
|
generated_action_symbol?(action)
|
|
1751
1809
|
end
|
|
1752
1810
|
|
|
1753
|
-
# @rbs (Hash[Symbol,
|
|
1811
|
+
# @rbs (Hash[Symbol, runtime_value] production, runtime_value action) -> bool
|
|
1754
1812
|
def generated_values_action?(production, action)
|
|
1755
|
-
|
|
1756
|
-
production[:values_action] == true &&
|
|
1813
|
+
production[:values_action] == true &&
|
|
1757
1814
|
generated_action_symbol?(action)
|
|
1758
1815
|
end
|
|
1759
1816
|
|
|
1760
|
-
# @rbs (Hash[Symbol,
|
|
1817
|
+
# @rbs (Hash[Symbol, runtime_value] production, runtime_value action) -> bool
|
|
1761
1818
|
def generated_positional_action?(production, action)
|
|
1762
|
-
|
|
1763
|
-
production[:positional_action] == true &&
|
|
1819
|
+
production[:positional_action] == true &&
|
|
1764
1820
|
generated_action_symbol?(action)
|
|
1765
1821
|
end
|
|
1766
1822
|
|
|
1767
|
-
# @rbs (Hash[Symbol,
|
|
1823
|
+
# @rbs (Hash[Symbol, runtime_value] production, runtime_value action) -> bool
|
|
1768
1824
|
def generated_composition_action?(production, action)
|
|
1769
|
-
|
|
1770
|
-
production[:composition_action] == true &&
|
|
1825
|
+
production[:composition_action] == true &&
|
|
1771
1826
|
generated_location_action?(production, action)
|
|
1772
1827
|
end
|
|
1773
1828
|
|
|
1774
|
-
# @rbs (
|
|
1829
|
+
# @rbs (runtime_value action) -> bool
|
|
1775
1830
|
def generated_action_symbol?(action)
|
|
1776
1831
|
action.is_a?(Symbol) && action.name.match?(GENERATED_ACTION_NAME)
|
|
1777
1832
|
end
|
|
@@ -1781,7 +1836,7 @@ module Ibex
|
|
|
1781
1836
|
parser_tables[:cst].is_a?(Hash)
|
|
1782
1837
|
end
|
|
1783
1838
|
|
|
1784
|
-
# @rbs (Integer token_id,
|
|
1839
|
+
# @rbs (Integer token_id, runtime_value value, runtime_value location, Symbol reason) -> void
|
|
1785
1840
|
def capture_cst_error(token_id, value, location, reason)
|
|
1786
1841
|
return unless cst_enabled?
|
|
1787
1842
|
return if token_id == EOF_TOKEN
|
|
@@ -1791,7 +1846,7 @@ module Ibex
|
|
|
1791
1846
|
}.freeze
|
|
1792
1847
|
end
|
|
1793
1848
|
|
|
1794
|
-
# @rbs (
|
|
1849
|
+
# @rbs (runtime_value value) -> runtime_value
|
|
1795
1850
|
def finalize_cst(value)
|
|
1796
1851
|
return value unless cst_enabled?
|
|
1797
1852
|
|
|
@@ -1811,7 +1866,7 @@ module Ibex
|
|
|
1811
1866
|
nil
|
|
1812
1867
|
end
|
|
1813
1868
|
|
|
1814
|
-
# @rbs (
|
|
1869
|
+
# @rbs (runtime_value location, Symbol key) -> runtime_value
|
|
1815
1870
|
def cst_location_value(location, key)
|
|
1816
1871
|
if location.is_a?(Hash)
|
|
1817
1872
|
value = location[key]
|
|
@@ -1825,20 +1880,28 @@ module Ibex
|
|
|
1825
1880
|
nil
|
|
1826
1881
|
end
|
|
1827
1882
|
|
|
1828
|
-
# @rbs (Hash[Symbol,
|
|
1829
|
-
def prepare_green_cst(tables)
|
|
1883
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
1884
|
+
def prepare_green_cst(tables) # rubocop:disable Metrics/MethodLength
|
|
1830
1885
|
@syntax_root = nil
|
|
1831
1886
|
@syntax_parse_memo = nil
|
|
1832
|
-
@syntax_diagnostics.clear
|
|
1833
|
-
@green_pending_skipped.clear
|
|
1834
1887
|
config = tables[:cst]
|
|
1835
1888
|
unless config.is_a?(Hash)
|
|
1836
1889
|
@green_builder = nil
|
|
1837
1890
|
@green_kinds = nil
|
|
1838
1891
|
@green_cache = nil
|
|
1892
|
+
@syntax_diagnostics = EMPTY_LOCATIONS
|
|
1893
|
+
@green_pending_skipped = EMPTY_GREEN_TRIVIA
|
|
1894
|
+
@green_token_states = EMPTY_LOCATIONS
|
|
1895
|
+
@green_memo_stack = EMPTY_LOCATIONS
|
|
1839
1896
|
return
|
|
1840
1897
|
end
|
|
1841
1898
|
|
|
1899
|
+
@syntax_diagnostics = [] if @syntax_diagnostics.frozen?
|
|
1900
|
+
@green_pending_skipped = [] if @green_pending_skipped.frozen?
|
|
1901
|
+
@green_token_states = [] if @green_token_states.frozen?
|
|
1902
|
+
@green_memo_stack = [] if @green_memo_stack.frozen?
|
|
1903
|
+
@syntax_diagnostics.clear
|
|
1904
|
+
@green_pending_skipped.clear
|
|
1842
1905
|
kinds = tables[:cst_kinds]
|
|
1843
1906
|
kinds = CST::Kind.new(config.fetch(:kinds), slots: config.fetch(:slots)) unless kinds.is_a?(CST::Kind)
|
|
1844
1907
|
cache = @green_cache_override || CST::NodeCache.new
|
|
@@ -1853,13 +1916,13 @@ module Ibex
|
|
|
1853
1916
|
@green_builder = CST::GreenBuilder.new(kinds: kinds, cache: cache)
|
|
1854
1917
|
end
|
|
1855
1918
|
|
|
1856
|
-
# @rbs (Hash[Symbol,
|
|
1919
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
1857
1920
|
def reset_cst_results(tables)
|
|
1858
1921
|
prepare_green_cst(tables)
|
|
1859
1922
|
end
|
|
1860
1923
|
|
|
1861
1924
|
# rubocop:disable Metrics/PerceivedComplexity -- generated locations have a deliberate allocation-free path.
|
|
1862
|
-
# @rbs (Integer token_id,
|
|
1925
|
+
# @rbs (Integer token_id, runtime_value value, runtime_value location, Integer from_state) -> void
|
|
1863
1926
|
def shift_green_token(token_id, value, location, from_state)
|
|
1864
1927
|
builder = @green_builder
|
|
1865
1928
|
kinds = @green_kinds
|
|
@@ -1889,7 +1952,7 @@ module Ibex
|
|
|
1889
1952
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
1890
1953
|
|
|
1891
1954
|
# @rbs (CST::GreenBuilder builder, CST::Kind kinds, Integer token_id, Integer from_state,
|
|
1892
|
-
# Array[CST::GreenTrivia] trailing, Array[CST::GreenTrivia] location_leading,
|
|
1955
|
+
# Array[CST::GreenTrivia] trailing, Array[CST::GreenTrivia] location_leading, runtime_value repair,
|
|
1893
1956
|
# String token_text, Symbol lexer_state) -> void
|
|
1894
1957
|
def commit_green_token_shift(
|
|
1895
1958
|
builder, kinds, token_id, from_state, trailing, location_leading, repair, token_text, lexer_state
|
|
@@ -1918,7 +1981,7 @@ module Ibex
|
|
|
1918
1981
|
@green_reused_right_edge = false
|
|
1919
1982
|
end
|
|
1920
1983
|
|
|
1921
|
-
# @rbs (Integer production_id, Hash[Symbol,
|
|
1984
|
+
# @rbs (Integer production_id, Hash[Symbol, runtime_value] production, Integer length, Integer left_state) -> void
|
|
1922
1985
|
def reduce_green(production_id, production, length, left_state)
|
|
1923
1986
|
builder = @green_builder
|
|
1924
1987
|
return unless builder
|
|
@@ -1936,7 +1999,7 @@ module Ibex
|
|
|
1936
1999
|
@green_memo_stack << entry
|
|
1937
2000
|
end
|
|
1938
2001
|
|
|
1939
|
-
# @rbs (
|
|
2002
|
+
# @rbs (runtime_value value, runtime_value location) -> String
|
|
1940
2003
|
def green_token_text(value, location)
|
|
1941
2004
|
text = if location.is_a?(Hash) && location.key?(:ibex_lexer_start_state)
|
|
1942
2005
|
location[:ibex_cst_text]
|
|
@@ -1949,7 +2012,7 @@ module Ibex
|
|
|
1949
2012
|
""
|
|
1950
2013
|
end
|
|
1951
2014
|
|
|
1952
|
-
# @rbs (
|
|
2015
|
+
# @rbs (runtime_value location, Symbol key) -> Array[CST::GreenTrivia]
|
|
1953
2016
|
def green_location_trivia(location, key)
|
|
1954
2017
|
trivia = if location.is_a?(Hash) && location.key?(:ibex_lexer_start_state)
|
|
1955
2018
|
location[key]
|
|
@@ -1963,7 +2026,7 @@ module Ibex
|
|
|
1963
2026
|
trivia.grep(CST::GreenTrivia)
|
|
1964
2027
|
end
|
|
1965
2028
|
|
|
1966
|
-
# @rbs (
|
|
2029
|
+
# @rbs (runtime_value value) -> runtime_value
|
|
1967
2030
|
def finalize_red_green_cst(value)
|
|
1968
2031
|
builder = @green_builder || raise(ParseError, "(cst):1:1: Green builder is unavailable")
|
|
1969
2032
|
kinds = @green_kinds || raise(ParseError, "(cst):1:1: kind metadata is unavailable")
|
|
@@ -2065,7 +2128,7 @@ module Ibex
|
|
|
2065
2128
|
)
|
|
2066
2129
|
end
|
|
2067
2130
|
|
|
2068
|
-
# @rbs (
|
|
2131
|
+
# @rbs (runtime_value value) -> CST::ParseResult
|
|
2069
2132
|
def syntax_parse_result(value)
|
|
2070
2133
|
root = @syntax_root
|
|
2071
2134
|
raise ParseError, "(cst):1:1: parse_with_syntax requires a format-v6 CST parser" unless root
|
|
@@ -2095,7 +2158,7 @@ module Ibex
|
|
|
2095
2158
|
)
|
|
2096
2159
|
end
|
|
2097
2160
|
|
|
2098
|
-
# @rbs (
|
|
2161
|
+
# @rbs (runtime_value location) -> Symbol
|
|
2099
2162
|
def green_lexer_state(location)
|
|
2100
2163
|
state = if location.is_a?(Hash) && location.key?(:ibex_lexer_start_state)
|
|
2101
2164
|
location[:ibex_lexer_start_state]
|
|
@@ -2105,7 +2168,7 @@ module Ibex
|
|
|
2105
2168
|
state ? state.to_sym : :INITIAL
|
|
2106
2169
|
end
|
|
2107
2170
|
|
|
2108
|
-
# @rbs (CST::NodeCache cache) { () ->
|
|
2171
|
+
# @rbs (CST::NodeCache cache) { () -> runtime_value } -> runtime_value
|
|
2109
2172
|
def with_syntax_only(cache)
|
|
2110
2173
|
previous_mode = @syntax_only
|
|
2111
2174
|
previous_cache = @green_cache_override
|
|
@@ -2118,7 +2181,7 @@ module Ibex
|
|
|
2118
2181
|
@green_cache_override = previous_cache
|
|
2119
2182
|
end
|
|
2120
2183
|
|
|
2121
|
-
# @rbs (
|
|
2184
|
+
# @rbs (runtime_value source, CST::NodeCache cache) -> CST::SyntaxResult
|
|
2122
2185
|
def parse_syntax_token_source(source, cache)
|
|
2123
2186
|
with_syntax_only(cache) do
|
|
2124
2187
|
value = drive_parser(source)
|
|
@@ -2152,7 +2215,7 @@ module Ibex
|
|
|
2152
2215
|
@incremental_reused_descendants += subtree.green.descendant_count
|
|
2153
2216
|
end
|
|
2154
2217
|
|
|
2155
|
-
# @rbs (Symbol type, Hash[
|
|
2218
|
+
# @rbs (Symbol type, Hash[runtime_value, runtime_value] data) -> void
|
|
2156
2219
|
def emit_incremental_event(type, data)
|
|
2157
2220
|
emit_runtime_event(type, data) if @runtime_observers
|
|
2158
2221
|
end
|
|
@@ -2177,7 +2240,7 @@ module Ibex
|
|
|
2177
2240
|
)
|
|
2178
2241
|
end
|
|
2179
2242
|
|
|
2180
|
-
# @rbs (?report: bool) ->
|
|
2243
|
+
# @rbs (?report: bool) -> runtime_value
|
|
2181
2244
|
def recover(report: true)
|
|
2182
2245
|
@runtime_fast_path = false
|
|
2183
2246
|
materialize_lookahead_token_display! unless @lookahead.equal?(NO_LOOKAHEAD)
|
|
@@ -2187,7 +2250,7 @@ module Ibex
|
|
|
2187
2250
|
begin_recovery(report)
|
|
2188
2251
|
end
|
|
2189
2252
|
|
|
2190
|
-
# @rbs () ->
|
|
2253
|
+
# @rbs () -> runtime_value
|
|
2191
2254
|
def continue_recovery
|
|
2192
2255
|
return reject_recovery_eof if @lookahead == EOF_TOKEN
|
|
2193
2256
|
|
|
@@ -2214,7 +2277,7 @@ module Ibex
|
|
|
2214
2277
|
[:done, cst_enabled? ? failed_cst : nil]
|
|
2215
2278
|
end
|
|
2216
2279
|
|
|
2217
|
-
# @rbs (String token_display) -> Hash[String,
|
|
2280
|
+
# @rbs (String token_display) -> Hash[String, runtime_value]
|
|
2218
2281
|
def runtime_discard_data(token_display)
|
|
2219
2282
|
runtime_token_data(
|
|
2220
2283
|
token_id: @lookahead,
|
|
@@ -2225,7 +2288,7 @@ module Ibex
|
|
|
2225
2288
|
).merge("reason" => "recovery").freeze
|
|
2226
2289
|
end
|
|
2227
2290
|
|
|
2228
|
-
# @rbs (bool report) ->
|
|
2291
|
+
# @rbs (bool report) -> runtime_value
|
|
2229
2292
|
def begin_recovery(report)
|
|
2230
2293
|
consume_recovery_attempt!
|
|
2231
2294
|
repair = report ? selected_repair : nil
|
|
@@ -2240,7 +2303,7 @@ module Ibex
|
|
|
2240
2303
|
fallback_recovery(context, token_data, recovery_observers)
|
|
2241
2304
|
end
|
|
2242
2305
|
|
|
2243
|
-
# @rbs (bool report) -> Hash[Symbol,
|
|
2306
|
+
# @rbs (bool report) -> Hash[Symbol, runtime_value]
|
|
2244
2307
|
def recovery_context(report)
|
|
2245
2308
|
{
|
|
2246
2309
|
token_id: @lookahead,
|
|
@@ -2253,7 +2316,7 @@ module Ibex
|
|
|
2253
2316
|
}
|
|
2254
2317
|
end
|
|
2255
2318
|
|
|
2256
|
-
# @rbs (Hash[Symbol,
|
|
2319
|
+
# @rbs (Hash[Symbol, runtime_value] context) -> [Hash[String, runtime_value]?, Array[Proc]?]
|
|
2257
2320
|
def publish_error_context(context)
|
|
2258
2321
|
error_observers = runtime_observer_snapshot if @runtime_observers
|
|
2259
2322
|
if error_observers
|
|
@@ -2267,7 +2330,7 @@ module Ibex
|
|
|
2267
2330
|
[token_data, (runtime_observer_snapshot if @runtime_observers)]
|
|
2268
2331
|
end
|
|
2269
2332
|
|
|
2270
|
-
# @rbs (Hash[Symbol,
|
|
2333
|
+
# @rbs (Hash[Symbol, runtime_value] context, runtime_value repair) -> void
|
|
2271
2334
|
def notify_error_handler(context, repair)
|
|
2272
2335
|
@repair_selected = repair.is_a?(RepairPlan)
|
|
2273
2336
|
begin
|
|
@@ -2284,8 +2347,8 @@ module Ibex
|
|
|
2284
2347
|
CONTINUE_OUTCOME
|
|
2285
2348
|
end
|
|
2286
2349
|
|
|
2287
|
-
# @rbs (Hash[Symbol,
|
|
2288
|
-
# Array[Proc]? recovery_observers) ->
|
|
2350
|
+
# @rbs (Hash[Symbol, runtime_value] context, Hash[String, runtime_value]? token_data,
|
|
2351
|
+
# Array[Proc]? recovery_observers) -> runtime_value
|
|
2289
2352
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
2290
2353
|
# Green restoration mirrors the existing state/value/location transactional fallback.
|
|
2291
2354
|
def fallback_recovery(context, token_data, recovery_observers)
|
|
@@ -2316,8 +2379,8 @@ module Ibex
|
|
|
2316
2379
|
end
|
|
2317
2380
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
2318
2381
|
|
|
2319
|
-
# @rbs (
|
|
2320
|
-
# Integer state) -> Hash[String,
|
|
2382
|
+
# @rbs (runtime_value token_id, runtime_value token_display, runtime_value value, runtime_value location,
|
|
2383
|
+
# Integer state) -> Hash[String, runtime_value]
|
|
2321
2384
|
def runtime_original_token_data(token_id, token_display, value, location, state)
|
|
2322
2385
|
runtime_token_data(
|
|
2323
2386
|
token_id: token_id,
|
|
@@ -2328,8 +2391,8 @@ module Ibex
|
|
|
2328
2391
|
)
|
|
2329
2392
|
end
|
|
2330
2393
|
|
|
2331
|
-
# @rbs (
|
|
2332
|
-
# Integer original_state, Hash[String,
|
|
2394
|
+
# @rbs (runtime_value token_id, runtime_value token_display, runtime_value value, runtime_value location,
|
|
2395
|
+
# Integer original_state, Hash[String, runtime_value]? token_data,
|
|
2333
2396
|
# Array[Proc]? observers) -> [:done, nil]
|
|
2334
2397
|
def reject_without_recovery(token_id, token_display, value, location, original_state, token_data, observers)
|
|
2335
2398
|
if observers
|
|
@@ -2345,8 +2408,8 @@ module Ibex
|
|
|
2345
2408
|
[:done, cst_enabled? ? failed_cst : nil]
|
|
2346
2409
|
end
|
|
2347
2410
|
|
|
2348
|
-
# @rbs (
|
|
2349
|
-
# Integer original_state, Array[
|
|
2411
|
+
# @rbs (runtime_value token_id, runtime_value token_display, runtime_value value, runtime_value location,
|
|
2412
|
+
# Integer original_state, Array[runtime_value] value_stack, Hash[String, runtime_value]? token_data,
|
|
2350
2413
|
# String reason, Array[Proc]? observers) -> [:continue]
|
|
2351
2414
|
def finish_recovery(
|
|
2352
2415
|
token_id, token_display, value, location, original_state, value_stack, token_data, reason, observers
|
|
@@ -2372,8 +2435,8 @@ module Ibex
|
|
|
2372
2435
|
CONTINUE_OUTCOME
|
|
2373
2436
|
end
|
|
2374
2437
|
|
|
2375
|
-
# @rbs (token_id:
|
|
2376
|
-
# location:
|
|
2438
|
+
# @rbs (token_id: runtime_value, token_display: runtime_value, value: runtime_value,
|
|
2439
|
+
# location: runtime_value, state: Integer) -> Hash[String, runtime_value]
|
|
2377
2440
|
def runtime_token_data(token_id:, token_display:, value:, location:, state:)
|
|
2378
2441
|
if token_id.equal?(NO_LOOKAHEAD)
|
|
2379
2442
|
return {
|
|
@@ -2394,7 +2457,7 @@ module Ibex
|
|
|
2394
2457
|
}.freeze
|
|
2395
2458
|
end
|
|
2396
2459
|
|
|
2397
|
-
# @rbs () -> Hash[String,
|
|
2460
|
+
# @rbs () -> Hash[String, runtime_value]
|
|
2398
2461
|
def runtime_current_token_data
|
|
2399
2462
|
runtime_token_data(
|
|
2400
2463
|
token_id: @lookahead,
|
|
@@ -2405,7 +2468,7 @@ module Ibex
|
|
|
2405
2468
|
)
|
|
2406
2469
|
end
|
|
2407
2470
|
|
|
2408
|
-
# @rbs (
|
|
2471
|
+
# @rbs (runtime_value result_summary, String reason) -> void
|
|
2409
2472
|
def emit_accept_event(result_summary, reason)
|
|
2410
2473
|
emit_runtime_event(
|
|
2411
2474
|
:accept,
|
|
@@ -2413,7 +2476,7 @@ module Ibex
|
|
|
2413
2476
|
)
|
|
2414
2477
|
end
|
|
2415
2478
|
|
|
2416
|
-
# @rbs (String reason, Hash[String,
|
|
2479
|
+
# @rbs (String reason, Hash[String, runtime_value] token_data, ?observers: Array[Proc]?) -> void
|
|
2417
2480
|
def emit_reject_event(reason, token_data, observers: runtime_observer_snapshot)
|
|
2418
2481
|
emit_runtime_event(
|
|
2419
2482
|
:reject,
|
|
@@ -2434,10 +2497,13 @@ module Ibex
|
|
|
2434
2497
|
@state_stack << action.fetch(1)
|
|
2435
2498
|
push_location(@lookahead_location)
|
|
2436
2499
|
@value_stack << nil
|
|
2437
|
-
@green_builder
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2500
|
+
builder = @green_builder
|
|
2501
|
+
if builder
|
|
2502
|
+
builder.absorb_into_error(popped)
|
|
2503
|
+
empty = [] #: Array[CST::ParseMemo::Entry]
|
|
2504
|
+
children = popped.zero? ? empty : @green_memo_stack.pop(popped)
|
|
2505
|
+
@green_memo_stack << CST::ParseMemo::Entry.new(@state_stack.last, children: children)
|
|
2506
|
+
end
|
|
2441
2507
|
return true
|
|
2442
2508
|
end
|
|
2443
2509
|
return false if @state_stack.length == 1
|
|
@@ -2480,8 +2546,21 @@ module Ibex
|
|
|
2480
2546
|
return unless policy
|
|
2481
2547
|
|
|
2482
2548
|
tokens, complete = repair_search_tokens(policy)
|
|
2483
|
-
RepairSearch.new(parser_tables, policy, tokens, complete: complete).
|
|
2549
|
+
result = RepairSearch.new(parser_tables, policy, tokens, complete: complete).search_result(@state_stack)
|
|
2550
|
+
@repair_search_results << result
|
|
2551
|
+
return result.plan if result.selected?
|
|
2552
|
+
return RepairSearch::NEED_INPUT if result.status == :need_input
|
|
2553
|
+
|
|
2554
|
+
nil
|
|
2555
|
+
end
|
|
2556
|
+
|
|
2557
|
+
# @rbs skip
|
|
2558
|
+
# steep:ignore Ruby::UndeclaredMethodDefinition
|
|
2559
|
+
# steep:ignore:start
|
|
2560
|
+
def syntax_repair_search_results
|
|
2561
|
+
@repair_search_results.dup.freeze
|
|
2484
2562
|
end
|
|
2563
|
+
# steep:ignore:end
|
|
2485
2564
|
|
|
2486
2565
|
# @rbs (RepairPolicy policy) -> [Array[RepairInput], bool]
|
|
2487
2566
|
def repair_search_tokens(policy)
|
|
@@ -2520,6 +2599,16 @@ module Ibex
|
|
|
2520
2599
|
)
|
|
2521
2600
|
end
|
|
2522
2601
|
|
|
2602
|
+
# Snapshot the original buffered prefix before a selected repair is
|
|
2603
|
+
# replayed. Syntax tooling consumes locations and token identities only.
|
|
2604
|
+
# @rbs skip
|
|
2605
|
+
# steep:ignore Ruby::UndeclaredMethodDefinition
|
|
2606
|
+
# steep:ignore:start
|
|
2607
|
+
def syntax_repair_inputs
|
|
2608
|
+
([current_repair_input] + (@repair_input_buffer || [])).freeze
|
|
2609
|
+
end
|
|
2610
|
+
# steep:ignore:end
|
|
2611
|
+
|
|
2523
2612
|
# @rbs (Array[RepairInput] source, Array[RepairEdit] edits) -> Array[RepairInput]
|
|
2524
2613
|
def replay_repair_edits(source, edits)
|
|
2525
2614
|
by_position = edits.group_by(&:position)
|
|
@@ -2578,13 +2667,13 @@ module Ibex
|
|
|
2578
2667
|
@runtime_lookahead_token_display = nil
|
|
2579
2668
|
end
|
|
2580
2669
|
|
|
2581
|
-
# @rbs (RepairEdit edit, value:
|
|
2670
|
+
# @rbs (RepairEdit edit, value: runtime_value, location: runtime_value) -> RepairInput
|
|
2582
2671
|
def synthetic_repair_input(edit, value:, location:)
|
|
2583
2672
|
location = cst_repair_location(location, edit.kind) if cst_enabled?
|
|
2584
2673
|
RepairInput.new(token_id: edit.token_id, token_name: edit.token_name, value: value, location: location)
|
|
2585
2674
|
end
|
|
2586
2675
|
|
|
2587
|
-
# @rbs (
|
|
2676
|
+
# @rbs (runtime_value location, Symbol kind) -> Hash[Symbol, runtime_value]
|
|
2588
2677
|
def cst_repair_location(location, kind)
|
|
2589
2678
|
return location.merge(ibex_repair: kind).freeze if location.is_a?(Hash)
|
|
2590
2679
|
|
|
@@ -2626,7 +2715,7 @@ module Ibex
|
|
|
2626
2715
|
def read_compatible_lookahead
|
|
2627
2716
|
token = read_external_token
|
|
2628
2717
|
refresh_runtime_fast_path_after_user_code!
|
|
2629
|
-
if token.is_a?(CST::ReusableSubtree)
|
|
2718
|
+
if defined?(CST::ReusableSubtree) && token.is_a?(CST::ReusableSubtree)
|
|
2630
2719
|
push_reusable_green_subtree(token)
|
|
2631
2720
|
return
|
|
2632
2721
|
end
|
|
@@ -2665,7 +2754,7 @@ module Ibex
|
|
|
2665
2754
|
@runtime_lookahead_token_display = token_to_str(@lookahead)
|
|
2666
2755
|
end
|
|
2667
2756
|
|
|
2668
|
-
# @rbs (
|
|
2757
|
+
# @rbs (runtime_value external_token, runtime_value value, runtime_value location) -> RepairInput
|
|
2669
2758
|
def repair_input(external_token, value, location)
|
|
2670
2759
|
token_id = parser_tables.fetch(:tokens)[external_token]
|
|
2671
2760
|
if token_id
|
|
@@ -2682,7 +2771,7 @@ module Ibex
|
|
|
2682
2771
|
)
|
|
2683
2772
|
end
|
|
2684
2773
|
|
|
2685
|
-
# @rbs (
|
|
2774
|
+
# @rbs (runtime_value token) -> RepairInput
|
|
2686
2775
|
def repair_input_from_external(token)
|
|
2687
2776
|
if token.nil? || token == false
|
|
2688
2777
|
return RepairInput.new(token_id: EOF_TOKEN, token_name: token_to_str(EOF_TOKEN), value: nil, location: nil)
|
|
@@ -2723,7 +2812,7 @@ module Ibex
|
|
|
2723
2812
|
trace("read #{input.token_name}") if @yydebug
|
|
2724
2813
|
end
|
|
2725
2814
|
|
|
2726
|
-
# @rbs () ->
|
|
2815
|
+
# @rbs () -> runtime_value
|
|
2727
2816
|
def read_external_token
|
|
2728
2817
|
source = @source
|
|
2729
2818
|
return next_token unless source
|
|
@@ -2734,7 +2823,7 @@ module Ibex
|
|
|
2734
2823
|
false
|
|
2735
2824
|
end
|
|
2736
2825
|
|
|
2737
|
-
# @rbs (
|
|
2826
|
+
# @rbs (runtime_value external_token) -> Integer
|
|
2738
2827
|
def internal_token_id(external_token)
|
|
2739
2828
|
token_id = parser_tables.fetch(:tokens)[external_token]
|
|
2740
2829
|
return token_id if token_id
|
|
@@ -2743,7 +2832,7 @@ module Ibex
|
|
|
2743
2832
|
@unknown_token_id = -external_token.object_id.abs
|
|
2744
2833
|
end
|
|
2745
2834
|
|
|
2746
|
-
# @rbs () -> Hash[Symbol,
|
|
2835
|
+
# @rbs () -> Hash[Symbol, runtime_value]
|
|
2747
2836
|
def parser_tables
|
|
2748
2837
|
tables = @runtime_parser_tables
|
|
2749
2838
|
return tables if tables
|
|
@@ -2751,19 +2840,19 @@ module Ibex
|
|
|
2751
2840
|
load_parser_tables
|
|
2752
2841
|
end
|
|
2753
2842
|
|
|
2754
|
-
# @rbs () -> Hash[Symbol,
|
|
2843
|
+
# @rbs () -> Hash[Symbol, runtime_value]
|
|
2755
2844
|
def load_parser_tables
|
|
2756
2845
|
self.class.__send__(:parser_tables)
|
|
2757
2846
|
rescue NoMethodError
|
|
2758
2847
|
raise ParseError, "(tables):1:1: #{self.class} must define .parser_tables"
|
|
2759
2848
|
end
|
|
2760
2849
|
|
|
2761
|
-
# @rbs (
|
|
2850
|
+
# @rbs (runtime_value action) -> bool
|
|
2762
2851
|
def error_action?(action)
|
|
2763
2852
|
action.nil? || action.first == :error
|
|
2764
2853
|
end
|
|
2765
2854
|
|
|
2766
|
-
# @rbs (
|
|
2855
|
+
# @rbs (runtime_value configured) -> [String?, String?]
|
|
2767
2856
|
def configured_error_message(configured)
|
|
2768
2857
|
return [nil, configured] unless configured.is_a?(Hash)
|
|
2769
2858
|
|
|
@@ -2807,17 +2896,17 @@ module Ibex
|
|
|
2807
2896
|
previous.last
|
|
2808
2897
|
end
|
|
2809
2898
|
|
|
2810
|
-
# @rbs (Integer state) ->
|
|
2899
|
+
# @rbs (Integer state) -> runtime_value
|
|
2811
2900
|
def default_action(state)
|
|
2812
2901
|
parser_tables.fetch(:default_actions, EMPTY_ROW)[state]
|
|
2813
2902
|
end
|
|
2814
2903
|
|
|
2815
|
-
# @rbs (Hash[Symbol,
|
|
2904
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> bool
|
|
2816
2905
|
def track_locations?(tables)
|
|
2817
2906
|
tables.fetch(:uses_locations, false) || !@runtime_observers.nil?
|
|
2818
2907
|
end
|
|
2819
2908
|
|
|
2820
|
-
# @rbs (Hash[Symbol,
|
|
2909
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> void
|
|
2821
2910
|
def initialize_runtime_fast_path(tables)
|
|
2822
2911
|
@location_stack = track_locations?(tables) ? [] : nil
|
|
2823
2912
|
@runtime_fast_path = runtime_fast_path_eligible?(tables)
|
|
@@ -2829,11 +2918,29 @@ module Ibex
|
|
|
2829
2918
|
|
|
2830
2919
|
# @rbs (?Class? singleton) -> void
|
|
2831
2920
|
def install_runtime_fast_path_tracker!(singleton = nil)
|
|
2832
|
-
singleton
|
|
2833
|
-
|
|
2921
|
+
if singleton
|
|
2922
|
+
prepend_lookup = Module.instance_method(:prepend)
|
|
2923
|
+
elsif RUBY_ENGINE == "ruby"
|
|
2924
|
+
thread = ::Thread.current
|
|
2925
|
+
singleton_lookup = thread.thread_variable_get(:__ibex_runtime_parser_singleton_class_lookup)
|
|
2926
|
+
unless singleton_lookup.is_a?(UnboundMethod)
|
|
2927
|
+
singleton_lookup = Object.instance_method(:singleton_class)
|
|
2928
|
+
thread.thread_variable_set(:__ibex_runtime_parser_singleton_class_lookup, singleton_lookup)
|
|
2929
|
+
end
|
|
2930
|
+
singleton = singleton_lookup.bind_call(self)
|
|
2931
|
+
prepend_lookup = thread.thread_variable_get(:__ibex_runtime_parser_module_prepend_lookup)
|
|
2932
|
+
unless prepend_lookup.is_a?(UnboundMethod)
|
|
2933
|
+
prepend_lookup = Module.instance_method(:prepend)
|
|
2934
|
+
thread.thread_variable_set(:__ibex_runtime_parser_module_prepend_lookup, prepend_lookup)
|
|
2935
|
+
end
|
|
2936
|
+
else
|
|
2937
|
+
singleton = Object.instance_method(:singleton_class).bind_call(self)
|
|
2938
|
+
prepend_lookup = Module.instance_method(:prepend)
|
|
2939
|
+
end
|
|
2940
|
+
prepend_lookup.bind_call(singleton, FastPathMutationTracker)
|
|
2834
2941
|
@runtime_fast_path_tracker_installed = true
|
|
2835
2942
|
@runtime_fast_path_hooks_mutated = false
|
|
2836
|
-
@runtime_fast_path_singleton_ancestors =
|
|
2943
|
+
@runtime_fast_path_singleton_ancestors = nil
|
|
2837
2944
|
rescue FrozenError, TypeError
|
|
2838
2945
|
@runtime_fast_path = false
|
|
2839
2946
|
end
|
|
@@ -2844,7 +2951,9 @@ module Ibex
|
|
|
2844
2951
|
return if parser_class.instance_variable_get(:@__ibex_fast_path_class_tracker_installed) == true
|
|
2845
2952
|
|
|
2846
2953
|
singleton = parser_class.singleton_class
|
|
2847
|
-
|
|
2954
|
+
# Keep the same module object out of both a class and its superclass
|
|
2955
|
+
# callback chains; TruffleRuby can re-enter `super` in that topology.
|
|
2956
|
+
singleton.prepend(FastPathClassMutationTracker.dup)
|
|
2848
2957
|
parser_class.instance_variable_set(:@__ibex_fast_path_hook_version, 0)
|
|
2849
2958
|
parser_class.instance_variable_set(:@__ibex_fast_path_class_tracker_installed, true)
|
|
2850
2959
|
rescue FrozenError, TypeError
|
|
@@ -2853,7 +2962,7 @@ module Ibex
|
|
|
2853
2962
|
|
|
2854
2963
|
# The generic driver remains authoritative whenever a public runtime
|
|
2855
2964
|
# extension can observe a committed shift or reduction.
|
|
2856
|
-
# @rbs (Hash[Symbol,
|
|
2965
|
+
# @rbs (Hash[Symbol, runtime_value] tables) -> bool
|
|
2857
2966
|
def runtime_fast_path_eligible?(tables)
|
|
2858
2967
|
!@syntax_only &&
|
|
2859
2968
|
!@yydebug &&
|
|
@@ -2866,11 +2975,20 @@ module Ibex
|
|
|
2866
2975
|
end
|
|
2867
2976
|
|
|
2868
2977
|
# @rbs () -> bool
|
|
2869
|
-
def runtime_fast_path_hooks_eligible?
|
|
2978
|
+
def runtime_fast_path_hooks_eligible? # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
2870
2979
|
cached = cached_runtime_fast_path_hooks_eligibility
|
|
2871
2980
|
return cached unless cached.nil?
|
|
2872
2981
|
|
|
2873
2982
|
lookup = Object.instance_method(:method)
|
|
2983
|
+
if RUBY_ENGINE == "ruby"
|
|
2984
|
+
thread = ::Thread.current
|
|
2985
|
+
cached_lookup = thread.thread_variable_get(:__ibex_runtime_parser_object_method_lookup)
|
|
2986
|
+
if cached_lookup.is_a?(UnboundMethod)
|
|
2987
|
+
lookup = cached_lookup
|
|
2988
|
+
else
|
|
2989
|
+
thread.thread_variable_set(:__ibex_runtime_parser_object_method_lookup, lookup)
|
|
2990
|
+
end
|
|
2991
|
+
end
|
|
2874
2992
|
hooks_unchanged =
|
|
2875
2993
|
runtime_method_unchanged?(lookup, :on_shift, :__ibex_fast_path_on_shift) &&
|
|
2876
2994
|
runtime_method_unchanged?(lookup, :on_shift_location, :__ibex_fast_path_on_shift_location) &&
|
|
@@ -2970,7 +3088,7 @@ module Ibex
|
|
|
2970
3088
|
# Keep allocation out of the ordinary two-element lexer path. If a
|
|
2971
3089
|
# location first appears after values have already shifted, backfill the
|
|
2972
3090
|
# parallel prefix with nil exactly once.
|
|
2973
|
-
# @rbs (
|
|
3091
|
+
# @rbs (runtime_value location) -> void
|
|
2974
3092
|
def push_location(location)
|
|
2975
3093
|
stack = @location_stack
|
|
2976
3094
|
if stack
|
|
@@ -2982,7 +3100,7 @@ module Ibex
|
|
|
2982
3100
|
end
|
|
2983
3101
|
end
|
|
2984
3102
|
|
|
2985
|
-
# @rbs (Integer length) -> Array[
|
|
3103
|
+
# @rbs (Integer length) -> Array[runtime_value]
|
|
2986
3104
|
def pop_reduction_locations(length)
|
|
2987
3105
|
stack = @location_stack
|
|
2988
3106
|
return Array.new(length) unless stack
|
|
@@ -2992,7 +3110,7 @@ module Ibex
|
|
|
2992
3110
|
locations
|
|
2993
3111
|
end
|
|
2994
3112
|
|
|
2995
|
-
# @rbs (
|
|
3113
|
+
# @rbs (runtime_value table, Integer row, Integer column) -> runtime_value
|
|
2996
3114
|
def table_lookup(table, row, column)
|
|
2997
3115
|
return table.lookup(row, column) if table.respond_to?(:lookup)
|
|
2998
3116
|
|
|
@@ -3004,7 +3122,7 @@ module Ibex
|
|
|
3004
3122
|
@yydebug_output.puts("ibex: #{message}") if @yydebug
|
|
3005
3123
|
end
|
|
3006
3124
|
|
|
3007
|
-
# @rbs (
|
|
3125
|
+
# @rbs (runtime_value value, Integer symbol_id) -> String
|
|
3008
3126
|
def trace_value_suffix(value, symbol_id)
|
|
3009
3127
|
return "" unless @yydebug
|
|
3010
3128
|
|