ibex 0.1.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.
Files changed (603) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +89 -123
  3. data/docs/architecture.md +477 -31
  4. data/docs/bison-import.md +103 -0
  5. data/docs/comparison-policy.md +127 -0
  6. data/docs/configuration-model.md +59 -0
  7. data/docs/configuration-report.md +28 -0
  8. data/docs/conflict-explanation-reviews/v1/records/README.md +28 -0
  9. data/docs/conflict-explanation-study.md +62 -0
  10. data/docs/construction-profiling.md +157 -0
  11. data/docs/cst-migration.md +106 -0
  12. data/docs/cst.md +237 -0
  13. data/docs/decisions/0000-template.md +24 -0
  14. data/docs/decisions/0001-separate-ir-pipeline.md +34 -0
  15. data/docs/decisions/0002-opaque-user-code-boundary.md +32 -0
  16. data/docs/decisions/0003-self-hosted-grammar-frontend.md +32 -0
  17. data/docs/decisions/0004-shared-semantic-and-lossless-source-model.md +33 -0
  18. data/docs/decisions/0005-contained-grammar-composition.md +34 -0
  19. data/docs/decisions/0006-bounded-structural-grammar-lowering.md +32 -0
  20. data/docs/decisions/0007-shared-parser-construction-pipeline.md +33 -0
  21. data/docs/decisions/0008-versioned-runtime-package-boundary.md +36 -0
  22. data/docs/decisions/0009-isolated-parser-sessions.md +34 -0
  23. data/docs/decisions/0010-committed-runtime-observation.md +34 -0
  24. data/docs/decisions/0011-versioned-semantic-action-boundary.md +37 -0
  25. data/docs/decisions/0012-bounded-nonexecuting-analysis.md +37 -0
  26. data/docs/decisions/0013-transactional-generation-publication.md +37 -0
  27. data/docs/decisions/0014-versioned-generated-lexer.md +35 -0
  28. data/docs/decisions/0015-worker-isolated-browser-analysis.md +32 -0
  29. data/docs/decisions/0016-red-green-concrete-syntax.md +34 -0
  30. data/docs/decisions/0017-persistent-syntax-artifacts.md +35 -0
  31. data/docs/decisions/0018-conservative-incremental-syntax-reuse.md +38 -0
  32. data/docs/decisions/0019-runtime-syntax-session-boundary.md +51 -0
  33. data/docs/decisions/0020-grammar-ir-parser-contract.md +65 -0
  34. data/docs/decisions/0021-data-only-parser-table-sidecar.md +50 -0
  35. data/docs/decisions/0022-manifest-bound-verification-report.md +77 -0
  36. data/docs/decisions/0023-syntax-only-repair-results.md +48 -0
  37. data/docs/decisions/0024-direct-ielr-construction.md +42 -0
  38. data/docs/decisions/README.md +74 -0
  39. data/docs/declarative-configuration.md +262 -0
  40. data/docs/development.md +306 -0
  41. data/docs/direct-ielr-decision.md +120 -0
  42. data/docs/direct-multi-entry-decision.md +82 -0
  43. data/docs/editor-setup.md +26 -0
  44. data/docs/error-ux-review-rubric-v1.md +117 -0
  45. data/docs/error-ux-reviews/v1/records/README.md +22 -0
  46. data/docs/error-ux-round2-review-status-v1.json +27 -0
  47. data/docs/error-ux-round2-reviews/v1/records/README.md +30 -0
  48. data/docs/error-ux-round2-v1.json +1581 -0
  49. data/docs/error-ux-round2.md +111 -0
  50. data/docs/error-ux.md +114 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +629 -18
  53. data/docs/ielr-design.md +43 -0
  54. data/docs/ielr.md +92 -0
  55. data/docs/ja/bison-import.md +51 -0
  56. data/docs/ja/stable-api.md +53 -0
  57. data/docs/lexer-construction-profile.md +109 -0
  58. data/docs/lexer-migration.md +56 -0
  59. data/docs/maturity.md +128 -0
  60. data/docs/project-site-strategy.md +54 -0
  61. data/docs/racc-migration-evidence.md +45 -0
  62. data/docs/racc-migration.md +45 -6
  63. data/docs/release-readiness.md +221 -0
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +234 -0
  67. data/docs/status.md +43 -0
  68. data/docs/syntax-sessions.md +183 -0
  69. data/docs/table-artifact.md +125 -0
  70. data/docs/test-interactions.md +219 -0
  71. data/docs/verification-report.md +137 -0
  72. data/docs/verifier-trust-boundary.md +199 -0
  73. data/docs/workloads.md +132 -0
  74. data/examples/README.md +60 -0
  75. data/examples/calculator.y +44 -0
  76. data/examples/csv.y +32 -0
  77. data/examples/ini.y +70 -0
  78. data/examples/json.y +48 -0
  79. data/examples/tiny_language.y +75 -0
  80. data/lib/ibex/analysis/digraph.rb +128 -0
  81. data/lib/ibex/analysis/sets.rb +5 -4
  82. data/lib/ibex/analysis.rb +1 -0
  83. data/lib/ibex/artifact_set.rb +63 -0
  84. data/lib/ibex/bison_import/importer.rb +516 -0
  85. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  86. data/lib/ibex/bison_import.rb +200 -0
  87. data/lib/ibex/bounded_subprocess.rb +171 -0
  88. data/lib/ibex/cli/ambiguity.rb +75 -0
  89. data/lib/ibex/cli/analysis.rb +134 -0
  90. data/lib/ibex/cli/bison_import.rb +121 -0
  91. data/lib/ibex/cli/config.rb +128 -0
  92. data/lib/ibex/cli/counterexample_options.rb +6 -2
  93. data/lib/ibex/cli/coverage.rb +173 -0
  94. data/lib/ibex/cli/debug.rb +106 -0
  95. data/lib/ibex/cli/diagnostics.rb +136 -0
  96. data/lib/ibex/cli/documentation.rb +70 -0
  97. data/lib/ibex/cli/equiv.rb +169 -0
  98. data/lib/ibex/cli/error_messages.rb +184 -0
  99. data/lib/ibex/cli/explain.rb +85 -0
  100. data/lib/ibex/cli/fix.rb +203 -0
  101. data/lib/ibex/cli/formatting.rb +387 -0
  102. data/lib/ibex/cli/fuzz.rb +200 -0
  103. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  104. data/lib/ibex/cli/generation_artifacts.rb +189 -0
  105. data/lib/ibex/cli/generation_error_messages.rb +39 -0
  106. data/lib/ibex/cli/grammar_tests.rb +140 -0
  107. data/lib/ibex/cli/ir_tools.rb +128 -0
  108. data/lib/ibex/cli/lsp.rb +33 -0
  109. data/lib/ibex/cli/outputs.rb +133 -23
  110. data/lib/ibex/cli/racc_migration.rb +87 -0
  111. data/lib/ibex/cli/reduce.rb +202 -0
  112. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  113. data/lib/ibex/cli/samples.rb +118 -0
  114. data/lib/ibex/cli/verify.rb +116 -0
  115. data/lib/ibex/cli/watch.rb +104 -0
  116. data/lib/ibex/cli.rb +825 -55
  117. data/lib/ibex/codegen/action_locations.rb +103 -0
  118. data/lib/ibex/codegen/action_method_source.rb +209 -0
  119. data/lib/ibex/codegen/action_source.rb +119 -0
  120. data/lib/ibex/codegen/ambiguity.rb +174 -0
  121. data/lib/ibex/codegen/cst_metadata.rb +171 -0
  122. data/lib/ibex/codegen/documentation.rb +170 -0
  123. data/lib/ibex/codegen/explain.rb +380 -0
  124. data/lib/ibex/codegen/generated_action_abi.rb +293 -0
  125. data/lib/ibex/codegen/html.rb +94 -10
  126. data/lib/ibex/codegen/mermaid.rb +43 -0
  127. data/lib/ibex/codegen/railroad.rb +197 -0
  128. data/lib/ibex/codegen/railroad_documentation.rb +59 -0
  129. data/lib/ibex/codegen/rbs.rb +331 -2
  130. data/lib/ibex/codegen/report.rb +67 -15
  131. data/lib/ibex/codegen/ruby.rb +305 -66
  132. data/lib/ibex/codegen/ruby_actions.rb +146 -0
  133. data/lib/ibex/codegen/ruby_ast.rb +121 -0
  134. data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
  135. data/lib/ibex/codegen/ruby_lexer.rb +83 -0
  136. data/lib/ibex/codegen/ruby_syntax.rb +96 -0
  137. data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
  138. data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
  139. data/lib/ibex/codegen/symbol_labels.rb +1 -1
  140. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  141. data/lib/ibex/configuration/explanation.rb +421 -0
  142. data/lib/ibex/configuration/inspector.rb +232 -0
  143. data/lib/ibex/configuration.rb +580 -0
  144. data/lib/ibex/coverage/collector.rb +198 -0
  145. data/lib/ibex/coverage/event_stream.rb +103 -0
  146. data/lib/ibex/coverage/report.rb +267 -0
  147. data/lib/ibex/coverage/runtime_event_validator.rb +169 -0
  148. data/lib/ibex/coverage.rb +13 -0
  149. data/lib/ibex/delta_reducer.rb +99 -0
  150. data/lib/ibex/diff.rb +140 -0
  151. data/lib/ibex/equiv/machine.rb +135 -0
  152. data/lib/ibex/equiv.rb +373 -0
  153. data/lib/ibex/error_messages/parser.rb +159 -0
  154. data/lib/ibex/error_messages/parser_v2.rb +198 -0
  155. data/lib/ibex/error_messages/renderer.rb +65 -0
  156. data/lib/ibex/error_messages/sentence_search.rb +196 -0
  157. data/lib/ibex/error_messages/update.rb +169 -0
  158. data/lib/ibex/error_messages.rb +165 -0
  159. data/lib/ibex/fix.rb +557 -0
  160. data/lib/ibex/frontend/ast.rb +166 -7
  161. data/lib/ibex/frontend/bootstrap_parser.rb +40 -4
  162. data/lib/ibex/frontend/diagnostic.rb +81 -0
  163. data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
  164. data/lib/ibex/frontend/dsl.rb +66 -7
  165. data/lib/ibex/frontend/formatter.rb +453 -0
  166. data/lib/ibex/frontend/generated_parser.rb +644 -190
  167. data/lib/ibex/frontend/generated_parser_base.rb +170 -32
  168. data/lib/ibex/frontend/generated_parser_includes.rb +51 -0
  169. data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
  170. data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
  171. data/lib/ibex/frontend/generation.rb +33 -0
  172. data/lib/ibex/frontend/lexer.rb +162 -10
  173. data/lib/ibex/frontend/lexer_recovery.rb +84 -0
  174. data/lib/ibex/frontend/parser/declarations.rb +262 -11
  175. data/lib/ibex/frontend/parser/parameters.rb +82 -0
  176. data/lib/ibex/frontend/parser/rules.rb +43 -6
  177. data/lib/ibex/frontend/parser.rb +182 -4
  178. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  179. data/lib/ibex/frontend/regenerator.rb +27 -1
  180. data/lib/ibex/frontend/resolution.rb +70 -0
  181. data/lib/ibex/frontend/resolver.rb +217 -0
  182. data/lib/ibex/frontend/rule_documentation.rb +104 -0
  183. data/lib/ibex/frontend/source_cursor.rb +133 -9
  184. data/lib/ibex/frontend/source_document.rb +229 -0
  185. data/lib/ibex/frontend/source_loader.rb +150 -0
  186. data/lib/ibex/frontend/source_span.rb +89 -0
  187. data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
  188. data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
  189. data/lib/ibex/frontend/token_adapter/declaration_state.rb +244 -22
  190. data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
  191. data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
  192. data/lib/ibex/frontend/token_adapter.rb +18 -3
  193. data/lib/ibex/frontend.rb +14 -2
  194. data/lib/ibex/fuzz.rb +219 -0
  195. data/lib/ibex/generation_input.rb +57 -0
  196. data/lib/ibex/generation_manifest.rb +211 -0
  197. data/lib/ibex/generation_transaction.rb +261 -0
  198. data/lib/ibex/generation_transaction_recovery.rb +109 -0
  199. data/lib/ibex/generation_transaction_validation.rb +196 -0
  200. data/lib/ibex/grammar_tests.rb +206 -0
  201. data/lib/ibex/ir/automaton_ir.rb +86 -11
  202. data/lib/ibex/ir/grammar_ir.rb +170 -26
  203. data/lib/ibex/ir/lexer_ir.rb +76 -0
  204. data/lib/ibex/ir/parser_contract.rb +135 -0
  205. data/lib/ibex/ir/serialize.rb +268 -50
  206. data/lib/ibex/ir/validator/automaton.rb +375 -0
  207. data/lib/ibex/ir/validator/base.rb +147 -0
  208. data/lib/ibex/ir/validator/grammar.rb +634 -0
  209. data/lib/ibex/ir/validator/lexer.rb +113 -0
  210. data/lib/ibex/ir/validator.rb +63 -0
  211. data/lib/ibex/ir.rb +71 -5
  212. data/lib/ibex/lalr/build_metrics.rb +71 -0
  213. data/lib/ibex/lalr/builder.rb +514 -52
  214. data/lib/ibex/lalr/conflict.rb +1 -0
  215. data/lib/ibex/lalr/conflict_search.rb +26 -9
  216. data/lib/ibex/lalr/counterexample.rb +38 -18
  217. data/lib/ibex/lalr/direct_lookaheads.rb +289 -0
  218. data/lib/ibex/lalr/goto_follows.rb +229 -0
  219. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  220. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  221. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  222. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  223. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  224. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  225. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  226. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  227. data/lib/ibex/lalr/ielr_partition.rb +166 -0
  228. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  229. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  230. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  231. data/lib/ibex/lalr/on_error_reductions.rb +74 -0
  232. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  233. data/lib/ibex/lalr.rb +59 -1
  234. data/lib/ibex/location.rb +129 -0
  235. data/lib/ibex/lsp/document_handlers.rb +68 -0
  236. data/lib/ibex/lsp/document_store.rb +264 -0
  237. data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
  238. data/lib/ibex/lsp/document_store_validation.rb +61 -0
  239. data/lib/ibex/lsp/initialization_handlers.rb +80 -0
  240. data/lib/ibex/lsp/navigation_handlers.rb +70 -0
  241. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  242. data/lib/ibex/lsp/position_codec.rb +113 -0
  243. data/lib/ibex/lsp/protocol_error.rb +33 -0
  244. data/lib/ibex/lsp/request_handlers.rb +46 -0
  245. data/lib/ibex/lsp/request_support.rb +94 -0
  246. data/lib/ibex/lsp/server.rb +148 -0
  247. data/lib/ibex/lsp/symbol_index.rb +241 -0
  248. data/lib/ibex/lsp/symbol_index_builder.rb +277 -0
  249. data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
  250. data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
  251. data/lib/ibex/lsp/symbol_occurrence.rb +23 -0
  252. data/lib/ibex/lsp/transport.rb +128 -0
  253. data/lib/ibex/lsp/workspace.rb +128 -0
  254. data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
  255. data/lib/ibex/lsp.rb +33 -0
  256. data/lib/ibex/messages/en.yml +28 -0
  257. data/lib/ibex/messages/ja.yml +28 -0
  258. data/lib/ibex/messages.rb +68 -0
  259. data/lib/ibex/metrics.rb +175 -0
  260. data/lib/ibex/normalize/declarations.rb +142 -7
  261. data/lib/ibex/normalize/diagnostics.rb +94 -24
  262. data/lib/ibex/normalize/expander.rb +64 -59
  263. data/lib/ibex/normalize/expression.rb +63 -40
  264. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  265. data/lib/ibex/normalize/inline_expansion.rb +465 -0
  266. data/lib/ibex/normalize/inline_validation.rb +174 -0
  267. data/lib/ibex/normalize/lexer.rb +131 -0
  268. data/lib/ibex/normalize/named_references.rb +60 -0
  269. data/lib/ibex/normalize/nodes.rb +46 -0
  270. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +70 -0
  271. data/lib/ibex/normalize/parameter_lowering.rb +143 -0
  272. data/lib/ibex/normalize/parameter_substitution.rb +125 -0
  273. data/lib/ibex/normalize/parameter_validation.rb +140 -0
  274. data/lib/ibex/normalize/parameters.rb +226 -0
  275. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  276. data/lib/ibex/normalize/recovery_declarations.rb +84 -0
  277. data/lib/ibex/normalize.rb +172 -17
  278. data/lib/ibex/racc_migration/checker.rb +122 -0
  279. data/lib/ibex/racc_migration/harness.rb +177 -0
  280. data/lib/ibex/racc_migration/report.rb +97 -0
  281. data/lib/ibex/racc_migration.rb +12 -0
  282. data/lib/ibex/rake_task.rb +116 -0
  283. data/lib/ibex/samples.rb +216 -0
  284. data/lib/ibex/table_artifact/builder.rb +266 -0
  285. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  286. data/lib/ibex/table_artifact/document.rb +39 -0
  287. data/lib/ibex/table_artifact/executor.rb +187 -0
  288. data/lib/ibex/table_artifact/serializer.rb +57 -0
  289. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  290. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  291. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  292. data/lib/ibex/table_artifact/validator.rb +253 -0
  293. data/lib/ibex/table_artifact.rb +88 -0
  294. data/lib/ibex/table_simulation/result.rb +55 -0
  295. data/lib/ibex/table_simulation/simulator.rb +253 -0
  296. data/lib/ibex/table_simulation/step.rb +62 -0
  297. data/lib/ibex/table_simulation/text.rb +31 -0
  298. data/lib/ibex/table_simulation.rb +13 -0
  299. data/lib/ibex/tables.rb +22 -69
  300. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  301. data/lib/ibex/verification_report/builder.rb +159 -0
  302. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  303. data/lib/ibex/verification_report/logical_path.rb +68 -0
  304. data/lib/ibex/verification_report/validator.rb +329 -0
  305. data/lib/ibex/verification_report.rb +69 -0
  306. data/lib/ibex/verify/action_correspondence.rb +138 -0
  307. data/lib/ibex/verify/language_witness.rb +295 -0
  308. data/lib/ibex/verify/reference_collection.rb +190 -0
  309. data/lib/ibex/verify/result.rb +73 -0
  310. data/lib/ibex/verify/verifier.rb +598 -0
  311. data/lib/ibex/verify.rb +15 -0
  312. data/lib/ibex/version.rb +1 -1
  313. data/lib/ibex/watch/runner.rb +181 -0
  314. data/lib/ibex/watch/source_snapshot.rb +98 -0
  315. data/lib/ibex/watch.rb +11 -0
  316. data/lib/ibex.rb +35 -1
  317. data/schema/automaton-ir-definitions.schema.json +401 -0
  318. data/schema/automaton-ir.schema.json +65 -0
  319. data/schema/benchmark-v1.schema.json +212 -0
  320. data/schema/benchmark-v2.schema.json +61 -0
  321. data/schema/bison-import-v1.schema.json +106 -0
  322. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  323. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  324. data/schema/construction-profile-v1.schema.json +779 -0
  325. data/schema/cst-v1.json +170 -0
  326. data/schema/diff-v1.schema.json +41 -0
  327. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  328. data/schema/equiv-v1.schema.json +64 -0
  329. data/schema/error-ux-review-v1.schema.json +609 -0
  330. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  331. data/schema/error-ux-round2-v1.schema.json +519 -0
  332. data/schema/error-ux-v1.schema.json +258 -0
  333. data/schema/explain-v1.schema.json +495 -0
  334. data/schema/fix-v1.schema.json +64 -0
  335. data/schema/fix-v2.schema.json +66 -0
  336. data/schema/fix-v3.schema.json +101 -0
  337. data/schema/frontend-diagnostics-v1.schema.json +154 -0
  338. data/schema/fuzz-regression-v1.schema.json +79 -0
  339. data/schema/fuzz-v1.schema.json +114 -0
  340. data/schema/generation-manifest-v1.schema.json +115 -0
  341. data/schema/grammar-ir-extensions.schema.json +734 -0
  342. data/schema/grammar-ir-foundation.schema.json +426 -0
  343. data/schema/grammar-ir.schema.json +271 -0
  344. data/schema/ielr-benchmark-v1.schema.json +85 -0
  345. data/schema/lexer-ir-v1.schema.json +215 -0
  346. data/schema/lexer-profile-v1.schema.json +491 -0
  347. data/schema/metrics-v1.schema.json +60 -0
  348. data/schema/migration-check-v1.schema.json +60 -0
  349. data/schema/performance-comparison-v1.schema.json +395 -0
  350. data/schema/public-performance-comparison-v1.schema.json +506 -0
  351. data/schema/public-performance-profile-v1.schema.json +360 -0
  352. data/schema/reduce-v1.schema.json +22 -0
  353. data/schema/reduce-v2.schema.json +63 -0
  354. data/schema/runtime-coverage-v1.schema.json +86 -0
  355. data/schema/runtime-event-v1.schema.json +308 -0
  356. data/schema/table-artifact-v1.schema.json +377 -0
  357. data/schema/table-simulation-v1.schema.json +70 -0
  358. data/schema/verification-report-v1.schema.json +222 -0
  359. data/schema/verify-v1.schema.json +42 -0
  360. data/sig/ibex/analysis/digraph.rbs +19 -0
  361. data/sig/ibex/artifact_set.rbs +37 -0
  362. data/sig/ibex/bison_import/importer.rbs +140 -0
  363. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  364. data/sig/ibex/bison_import.rbs +95 -0
  365. data/sig/ibex/bounded_subprocess.rbs +76 -0
  366. data/sig/ibex/cli/ambiguity.rbs +28 -0
  367. data/sig/ibex/cli/analysis.rbs +43 -0
  368. data/sig/ibex/cli/bison_import.rbs +32 -0
  369. data/sig/ibex/cli/config.rbs +35 -0
  370. data/sig/ibex/cli/counterexample_options.rbs +2 -0
  371. data/sig/ibex/cli/coverage.rbs +53 -0
  372. data/sig/ibex/cli/debug.rbs +28 -0
  373. data/sig/ibex/cli/diagnostics.rbs +51 -0
  374. data/sig/ibex/cli/documentation.rbs +29 -0
  375. data/sig/ibex/cli/equiv.rbs +49 -0
  376. data/sig/ibex/cli/error_messages.rbs +63 -0
  377. data/sig/ibex/cli/explain.rbs +31 -0
  378. data/sig/ibex/cli/fix.rbs +53 -0
  379. data/sig/ibex/cli/formatting.rbs +107 -0
  380. data/sig/ibex/cli/fuzz.rbs +47 -0
  381. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  382. data/sig/ibex/cli/generation_artifacts.rbs +69 -0
  383. data/sig/ibex/cli/generation_error_messages.rbs +19 -0
  384. data/sig/ibex/cli/grammar_tests.rbs +48 -0
  385. data/sig/ibex/cli/ir_tools.rbs +39 -0
  386. data/sig/ibex/cli/lsp.rbs +14 -0
  387. data/sig/ibex/cli/outputs.rbs +26 -3
  388. data/sig/ibex/cli/racc_migration.rbs +30 -0
  389. data/sig/ibex/cli/reduce.rbs +60 -0
  390. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  391. data/sig/ibex/cli/samples.rbs +38 -0
  392. data/sig/ibex/cli/verify.rbs +28 -0
  393. data/sig/ibex/cli/watch.rbs +43 -0
  394. data/sig/ibex/cli.rbs +182 -9
  395. data/sig/ibex/codegen/action_locations.rbs +45 -0
  396. data/sig/ibex/codegen/action_method_source.rbs +65 -0
  397. data/sig/ibex/codegen/action_source.rbs +50 -0
  398. data/sig/ibex/codegen/ambiguity.rbs +60 -0
  399. data/sig/ibex/codegen/cst_metadata.rbs +59 -0
  400. data/sig/ibex/codegen/documentation.rbs +50 -0
  401. data/sig/ibex/codegen/explain.rbs +105 -0
  402. data/sig/ibex/codegen/generated_action_abi.rbs +105 -0
  403. data/sig/ibex/codegen/html.rbs +18 -2
  404. data/sig/ibex/codegen/mermaid.rbs +16 -0
  405. data/sig/ibex/codegen/railroad.rbs +82 -0
  406. data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
  407. data/sig/ibex/codegen/rbs.rbs +86 -4
  408. data/sig/ibex/codegen/report.rbs +16 -8
  409. data/sig/ibex/codegen/ruby.rbs +105 -28
  410. data/sig/ibex/codegen/ruby_actions.rbs +54 -0
  411. data/sig/ibex/codegen/ruby_ast.rbs +34 -0
  412. data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
  413. data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
  414. data/sig/ibex/codegen/ruby_syntax.rbs +27 -0
  415. data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
  416. data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
  417. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  418. data/sig/ibex/configuration/explanation.rbs +195 -0
  419. data/sig/ibex/configuration/inspector.rbs +53 -0
  420. data/sig/ibex/configuration.rbs +242 -0
  421. data/sig/ibex/coverage/collector.rbs +78 -0
  422. data/sig/ibex/coverage/event_stream.rbs +44 -0
  423. data/sig/ibex/coverage/report.rbs +102 -0
  424. data/sig/ibex/coverage/runtime_event_validator.rbs +70 -0
  425. data/sig/ibex/coverage.rbs +7 -0
  426. data/sig/ibex/delta_reducer.rbs +38 -0
  427. data/sig/ibex/diff.rbs +47 -0
  428. data/sig/ibex/equiv/machine.rbs +54 -0
  429. data/sig/ibex/equiv.rbs +129 -0
  430. data/sig/ibex/error_messages/parser.rbs +58 -0
  431. data/sig/ibex/error_messages/parser_v2.rbs +67 -0
  432. data/sig/ibex/error_messages/renderer.rbs +23 -0
  433. data/sig/ibex/error_messages/sentence_search.rbs +80 -0
  434. data/sig/ibex/error_messages/update.rbs +43 -0
  435. data/sig/ibex/error_messages.rbs +85 -0
  436. data/sig/ibex/fix.rbs +138 -0
  437. data/sig/ibex/frontend/ast.rbs +237 -22
  438. data/sig/ibex/frontend/bootstrap_parser.rbs +13 -0
  439. data/sig/ibex/frontend/diagnostic.rbs +53 -0
  440. data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
  441. data/sig/ibex/frontend/dsl.rbs +33 -4
  442. data/sig/ibex/frontend/formatter.rbs +143 -0
  443. data/sig/ibex/frontend/generated_parser.rbs +228 -68
  444. data/sig/ibex/frontend/generated_parser_base.rbs +65 -12
  445. data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
  446. data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
  447. data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
  448. data/sig/ibex/frontend/generation.rbs +6 -0
  449. data/sig/ibex/frontend/lexer.rbs +49 -2
  450. data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
  451. data/sig/ibex/frontend/parser/declarations.rbs +57 -0
  452. data/sig/ibex/frontend/parser/parameters.rbs +28 -0
  453. data/sig/ibex/frontend/parser/rules.rbs +3 -0
  454. data/sig/ibex/frontend/parser.rbs +66 -0
  455. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  456. data/sig/ibex/frontend/regenerator.rbs +11 -0
  457. data/sig/ibex/frontend/resolution.rbs +34 -0
  458. data/sig/ibex/frontend/resolver.rbs +91 -0
  459. data/sig/ibex/frontend/rule_documentation.rbs +42 -0
  460. data/sig/ibex/frontend/source_cursor.rbs +38 -5
  461. data/sig/ibex/frontend/source_document.rbs +119 -0
  462. data/sig/ibex/frontend/source_loader.rbs +66 -0
  463. data/sig/ibex/frontend/source_span.rbs +56 -0
  464. data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
  465. data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
  466. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +83 -3
  467. data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
  468. data/sig/ibex/frontend/token_adapter.rbs +11 -2
  469. data/sig/ibex/frontend.rbs +1 -1
  470. data/sig/ibex/fuzz.rbs +71 -0
  471. data/sig/ibex/generation_input.rbs +37 -0
  472. data/sig/ibex/generation_manifest.rbs +70 -0
  473. data/sig/ibex/generation_transaction.rbs +82 -0
  474. data/sig/ibex/generation_transaction_recovery.rbs +36 -0
  475. data/sig/ibex/generation_transaction_validation.rbs +65 -0
  476. data/sig/ibex/grammar_tests.rbs +93 -0
  477. data/sig/ibex/ir/automaton_ir.rbs +35 -10
  478. data/sig/ibex/ir/grammar_ir.rbs +96 -22
  479. data/sig/ibex/ir/lexer_ir.rbs +57 -0
  480. data/sig/ibex/ir/parser_contract.rbs +69 -0
  481. data/sig/ibex/ir/serialize.rbs +75 -23
  482. data/sig/ibex/ir/validator/automaton.rbs +112 -0
  483. data/sig/ibex/ir/validator/base.rbs +69 -0
  484. data/sig/ibex/ir/validator/grammar.rbs +195 -0
  485. data/sig/ibex/ir/validator/lexer.rbs +37 -0
  486. data/sig/ibex/ir/validator.rbs +16 -0
  487. data/sig/ibex/ir.rbs +45 -5
  488. data/sig/ibex/lalr/build_metrics.rbs +60 -0
  489. data/sig/ibex/lalr/builder.rbs +150 -19
  490. data/sig/ibex/lalr/conflict_search.rbs +12 -5
  491. data/sig/ibex/lalr/counterexample.rbs +20 -14
  492. data/sig/ibex/lalr/direct_lookaheads.rbs +93 -0
  493. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  494. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  495. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  496. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  497. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  498. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  499. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  500. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  501. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  502. data/sig/ibex/lalr/ielr_partition.rbs +71 -0
  503. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  504. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  505. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  506. data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
  507. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  508. data/sig/ibex/lalr.rbs +17 -1
  509. data/sig/ibex/location.rbs +67 -0
  510. data/sig/ibex/lsp/document_handlers.rbs +24 -0
  511. data/sig/ibex/lsp/document_store.rbs +94 -0
  512. data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
  513. data/sig/ibex/lsp/document_store_validation.rbs +26 -0
  514. data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
  515. data/sig/ibex/lsp/navigation_handlers.rbs +33 -0
  516. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  517. data/sig/ibex/lsp/position_codec.rbs +44 -0
  518. data/sig/ibex/lsp/protocol_error.rbs +32 -0
  519. data/sig/ibex/lsp/request_handlers.rbs +26 -0
  520. data/sig/ibex/lsp/request_support.rbs +40 -0
  521. data/sig/ibex/lsp/server.rbs +55 -0
  522. data/sig/ibex/lsp/symbol_index.rbs +77 -0
  523. data/sig/ibex/lsp/symbol_index_builder.rbs +88 -0
  524. data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
  525. data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
  526. data/sig/ibex/lsp/symbol_occurrence.rbs +31 -0
  527. data/sig/ibex/lsp/transport.rbs +47 -0
  528. data/sig/ibex/lsp/workspace.rbs +42 -0
  529. data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
  530. data/sig/ibex/lsp.rbs +7 -0
  531. data/sig/ibex/messages.rbs +26 -0
  532. data/sig/ibex/metrics.rbs +50 -0
  533. data/sig/ibex/normalize/declarations.rbs +31 -0
  534. data/sig/ibex/normalize/diagnostics.rbs +13 -4
  535. data/sig/ibex/normalize/expander.rbs +22 -16
  536. data/sig/ibex/normalize/expression.rbs +11 -9
  537. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  538. data/sig/ibex/normalize/inline_expansion.rbs +129 -0
  539. data/sig/ibex/normalize/inline_validation.rbs +40 -0
  540. data/sig/ibex/normalize/lexer.rbs +37 -0
  541. data/sig/ibex/normalize/named_references.rbs +20 -0
  542. data/sig/ibex/normalize/nodes.rbs +14 -0
  543. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +33 -0
  544. data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
  545. data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
  546. data/sig/ibex/normalize/parameter_validation.rbs +44 -0
  547. data/sig/ibex/normalize/parameters.rbs +51 -0
  548. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  549. data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
  550. data/sig/ibex/normalize.rbs +129 -18
  551. data/sig/ibex/racc_migration/checker.rbs +36 -0
  552. data/sig/ibex/racc_migration/harness.rbs +16 -0
  553. data/sig/ibex/racc_migration/report.rbs +55 -0
  554. data/sig/ibex/racc_migration.rbs +8 -0
  555. data/sig/ibex/rake_task.rbs +51 -0
  556. data/sig/ibex/samples.rbs +60 -0
  557. data/sig/ibex/table_artifact/builder.rbs +93 -0
  558. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  559. data/sig/ibex/table_artifact/document.rbs +27 -0
  560. data/sig/ibex/table_artifact/executor.rbs +66 -0
  561. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  562. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  563. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  564. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  565. data/sig/ibex/table_artifact/validator.rbs +66 -0
  566. data/sig/ibex/table_artifact.rbs +32 -0
  567. data/sig/ibex/table_simulation/result.rbs +36 -0
  568. data/sig/ibex/table_simulation/simulator.rbs +98 -0
  569. data/sig/ibex/table_simulation/step.rbs +42 -0
  570. data/sig/ibex/table_simulation/text.rbs +14 -0
  571. data/sig/ibex/table_simulation.rbs +7 -0
  572. data/sig/ibex/tables.rbs +10 -35
  573. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  574. data/sig/ibex/verification_report/builder.rbs +53 -0
  575. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  576. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  577. data/sig/ibex/verification_report/validator.rbs +114 -0
  578. data/sig/ibex/verification_report.rbs +44 -0
  579. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  580. data/sig/ibex/verify/language_witness.rbs +112 -0
  581. data/sig/ibex/verify/reference_collection.rbs +63 -0
  582. data/sig/ibex/verify/result.rbs +52 -0
  583. data/sig/ibex/verify/verifier.rbs +170 -0
  584. data/sig/ibex/verify.rbs +6 -0
  585. data/sig/ibex/watch/runner.rbs +58 -0
  586. data/sig/ibex/watch/source_snapshot.rbs +46 -0
  587. data/sig/ibex/watch.rbs +7 -0
  588. data/sig/ibex.rbs +2 -0
  589. metadata +524 -19
  590. data/.rubocop.yml +0 -43
  591. data/CHANGELOG.md +0 -30
  592. data/Rakefile +0 -25
  593. data/Steepfile +0 -10
  594. data/docs/compat-notes.md +0 -37
  595. data/docs/lexer-coverage.md +0 -14
  596. data/docs/phase10-extensions.md +0 -27
  597. data/gemfiles/Gemfile +0 -7
  598. data/gemfiles/Gemfile.lock +0 -98
  599. data/lib/ibex/frontend/grammar.y +0 -156
  600. data/lib/ibex/runtime/parser.rb +0 -360
  601. data/lib/ibex/runtime.rb +0 -8
  602. data/sig/ibex/runtime/parser.rbs +0 -167
  603. data/sig/ibex/runtime.rbs +0 -6
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ module Coverage
6
+ # Dependency-free structural validation for runtime-event schema version 1.
7
+ module RuntimeEventValidator
8
+ # @rbs!
9
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
10
+
11
+ TOKEN_KEYS = %w[location state token token_id value].freeze #: Array[String]
12
+ LOCATION_KEYS = %w[column end_column end_line file line].freeze #: Array[String]
13
+ VALIDATORS = {
14
+ "start" => :valid_start?,
15
+ "shift" => :valid_shift?,
16
+ "reduce" => :valid_reduce?,
17
+ "error" => :valid_error?,
18
+ "recover" => :valid_recover?,
19
+ "discard" => :valid_discard?,
20
+ "accept" => :valid_accept?,
21
+ "reject" => :valid_reject?
22
+ }.freeze #: Hash[String, Symbol]
23
+
24
+ class << self
25
+ # @rbs (Hash[String, json_value] document) -> bool
26
+ def valid?(document)
27
+ data = document["data"]
28
+ return false unless data.is_a?(Hash) && data.keys.all?(String)
29
+
30
+ event_data = data #: Hash[String, json_value]
31
+
32
+ event = document["event"]
33
+ return false unless event.is_a?(String)
34
+
35
+ validator = VALIDATORS[event]
36
+ validator ? send(validator, event_data) : false
37
+ end
38
+
39
+ private
40
+
41
+ # @rbs (Hash[String, json_value] data) -> bool
42
+ def valid_start?(data)
43
+ return false unless exact_keys?(
44
+ data,
45
+ %w[driver grammar_digest initial_state production_count state_count table_format_version]
46
+ )
47
+
48
+ integer_fields = %w[initial_state table_format_version]
49
+ optional_integer_fields = %w[state_count production_count]
50
+ %w[pull push].include?(data["driver"]) &&
51
+ integer_fields.all? { |key| integer?(data[key]) } &&
52
+ optional_integer_fields.all? { |key| optional_integer?(data[key]) } &&
53
+ optional_string?(data["grammar_digest"])
54
+ end
55
+
56
+ # @rbs (Hash[String, json_value] data) -> bool
57
+ def valid_shift?(data)
58
+ exact_keys?(data, TOKEN_KEYS + %w[from_state]) &&
59
+ valid_token_fields?(data) &&
60
+ integer?(data["from_state"])
61
+ end
62
+
63
+ # @rbs (Hash[String, json_value] data) -> bool
64
+ def valid_reduce?(data)
65
+ keys = %w[goto_state lhs location post_state pre_state production_id result rhs_length]
66
+ rhs_length = data["rhs_length"]
67
+ exact_keys?(data, keys) &&
68
+ %w[goto_state lhs post_state pre_state production_id].all? { |key| integer?(data[key]) } &&
69
+ rhs_length.is_a?(Integer) && rhs_length >= 0 &&
70
+ summary?(data["result"]) && location?(data["location"])
71
+ end
72
+
73
+ # @rbs (Hash[String, json_value] data, reasons: Array[String]) -> bool
74
+ def valid_token_event?(data, reasons:)
75
+ exact_keys?(data, TOKEN_KEYS + %w[reason]) &&
76
+ valid_token_fields?(data) &&
77
+ reasons.include?(data["reason"])
78
+ end
79
+
80
+ # @rbs (Hash[String, json_value] data) -> bool
81
+ def valid_error?(data)
82
+ valid_token_event?(data, reasons: %w[syntax semantic])
83
+ end
84
+
85
+ # @rbs (Hash[String, json_value] data) -> bool
86
+ def valid_discard?(data)
87
+ valid_token_event?(data, reasons: %w[recovery])
88
+ end
89
+
90
+ # @rbs (Hash[String, json_value] data) -> bool
91
+ def valid_reject?(data)
92
+ valid_token_event?(data, reasons: %w[eof_during_recovery no_recovery_state])
93
+ end
94
+
95
+ # @rbs (Hash[String, json_value] data) -> bool
96
+ def valid_recover?(data)
97
+ exact_keys?(data, TOKEN_KEYS + %w[from_state reason]) &&
98
+ valid_token_fields?(data) &&
99
+ integer?(data["from_state"]) &&
100
+ %w[syntax semantic].include?(data["reason"])
101
+ end
102
+
103
+ # @rbs (Hash[String, json_value] data) -> bool
104
+ def valid_accept?(data)
105
+ exact_keys?(data, %w[reason result state]) &&
106
+ integer?(data["state"]) &&
107
+ summary?(data["result"]) &&
108
+ %w[table semantic].include?(data["reason"])
109
+ end
110
+
111
+ # @rbs (Hash[String, json_value] data) -> bool
112
+ def valid_token_fields?(data)
113
+ integer?(data["state"]) &&
114
+ optional_integer?(data["token_id"]) &&
115
+ summary?(data["token"]) &&
116
+ summary?(data["value"]) &&
117
+ location?(data["location"])
118
+ end
119
+
120
+ # @rbs (json_value value) -> bool
121
+ def summary?(value)
122
+ case value
123
+ when nil, true, false, Integer then true
124
+ when Float then value.finite?
125
+ when String then value.length <= 256
126
+ else composite_summary?(value)
127
+ end
128
+ end
129
+
130
+ # @rbs (json_value value) -> bool
131
+ def composite_summary?(value)
132
+ return value.length <= 17 && value.all? { |entry| summary?(entry) } if value.is_a?(Array)
133
+ return false unless value.is_a?(Hash)
134
+
135
+ value.keys.all?(String) && value.length <= 17 && value.values.all? { |entry| summary?(entry) }
136
+ end
137
+
138
+ # @rbs (json_value value) -> bool
139
+ def location?(value)
140
+ return true if value.nil?
141
+ return false unless value.is_a?(Hash) && value.keys.all?(String)
142
+ return value["unavailable"].is_a?(String) if value.keys == ["unavailable"]
143
+
144
+ (value.keys - LOCATION_KEYS).empty? && value.values.all? { |entry| summary?(entry) }
145
+ end
146
+
147
+ # @rbs (Hash[String, json_value] data, Array[String] keys) -> bool
148
+ def exact_keys?(data, keys)
149
+ data.keys.sort == keys.sort
150
+ end
151
+
152
+ # @rbs (json_value value) -> bool
153
+ def integer?(value)
154
+ value.is_a?(Integer)
155
+ end
156
+
157
+ # @rbs (json_value value) -> bool
158
+ def optional_integer?(value)
159
+ value.nil? || integer?(value)
160
+ end
161
+
162
+ # @rbs (json_value value) -> bool
163
+ def optional_string?(value)
164
+ value.nil? || value.is_a?(String)
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ require_relative "coverage/runtime_event_validator"
5
+ require_relative "coverage/event_stream"
6
+ require_relative "coverage/report"
7
+ require_relative "coverage/collector"
8
+
9
+ module Ibex
10
+ # Deterministic state and production coverage derived from runtime event streams.
11
+ module Coverage
12
+ end
13
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ # Deterministic, trial-bounded delta debugging over an ordered sequence.
6
+ class DeltaReducer
7
+ # Immutable outcome of a bounded reduction.
8
+ class Result
9
+ attr_reader :items #: Array[untyped]
10
+ attr_reader :trials #: Integer
11
+ attr_reader :complete #: bool
12
+ attr_reader :original_size #: Integer
13
+
14
+ # @rbs (items: Array[untyped], trials: Integer, complete: bool, original_size: Integer) -> void
15
+ def initialize(items:, trials:, complete:, original_size:)
16
+ @items = items.freeze
17
+ @trials = trials
18
+ @complete = complete
19
+ @original_size = original_size
20
+ freeze
21
+ end
22
+ end
23
+
24
+ # @rbs (?max_trials: Integer) -> void
25
+ def initialize(max_trials: 1_000)
26
+ raise ArgumentError, "max_trials must be positive" unless max_trials.positive?
27
+
28
+ @max_trials = max_trials
29
+ end
30
+
31
+ # `failure` must return true while the failure of interest is preserved.
32
+ # @rbs [T] (Array[T] items) { (Array[T]) -> bool } -> Result
33
+ def minimize(items, &failure)
34
+ raise ArgumentError, "a failure predicate is required" unless failure
35
+
36
+ current = items.dup
37
+ original_size = current.length
38
+ trials = 0
39
+ trials = checked_trial!(trials)
40
+ unless failure.call(current.freeze)
41
+ raise Ibex::Error, "(reduce):1:1: original input does not reproduce the failure"
42
+ end
43
+
44
+ granularity = 2
45
+ while current.length >= 1
46
+ chunks = partitions(current.length, granularity)
47
+ reduced = false
48
+ chunks.each do |range|
49
+ return result(current, trials, false, original_size) if trials >= @max_trials
50
+
51
+ candidate = current.dup
52
+ candidate.slice!(range)
53
+ trials = checked_trial!(trials)
54
+ next unless failure.call(candidate.freeze)
55
+
56
+ current = candidate
57
+ granularity = [granularity - 1, 2].max
58
+ reduced = true
59
+ break
60
+ end
61
+ next if reduced
62
+ break if granularity >= current.length
63
+
64
+ granularity = [granularity * 2, current.length].min
65
+ end
66
+
67
+ result(current, trials, true, original_size)
68
+ end
69
+
70
+ private
71
+
72
+ # @rbs (Integer length, Integer count) -> Array[Range[Integer]]
73
+ def partitions(length, count)
74
+ width = (length.to_f / count).ceil
75
+ ranges = [] #: Array[Range[Integer]]
76
+ count.times do |index|
77
+ start = index * width
78
+ break if start >= length
79
+
80
+ ranges << (start...[start + width, length].min)
81
+ end
82
+ ranges
83
+ end
84
+
85
+ # @rbs (Integer trials) -> Integer
86
+ def checked_trial!(trials)
87
+ raise Ibex::Error, "(reduce):1:1: trial limit of #{@max_trials} is exhausted" if trials >= @max_trials
88
+
89
+ trials + 1
90
+ end
91
+
92
+ # @rbs (Array[untyped] items, Integer trials, bool complete, Integer original_size) -> Result
93
+ def result(items, trials, complete, original_size)
94
+ Result.new(
95
+ items: items.dup.freeze, trials: trials, complete: complete, original_size: original_size
96
+ ).freeze
97
+ end
98
+ end
99
+ end
data/lib/ibex/diff.rb ADDED
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ # Deterministic grammar and automaton change classification.
6
+ class Diff
7
+ # @rbs (IR::Automaton before, IR::Automaton after) -> void
8
+ def initialize(before, after)
9
+ @before = before
10
+ @after = after
11
+ end
12
+
13
+ # @rbs () -> Hash[Symbol, Object?]
14
+ def to_h
15
+ {
16
+ ibex_report: "diff", schema_version: 1,
17
+ symbols: classify(symbol_records(@before.grammar), symbol_records(@after.grammar)),
18
+ rules: classify(rule_records(@before.grammar), rule_records(@after.grammar)),
19
+ conflicts: classify(conflict_records(@before), conflict_records(@after)),
20
+ warnings: classify(warning_records(@before.grammar), warning_records(@after.grammar)),
21
+ metrics: numeric_metrics
22
+ }
23
+ end
24
+
25
+ private
26
+
27
+ # @rbs (Hash[String, Object?] before, Hash[String, Object?] after) -> Hash[Symbol, Object?]
28
+ def classify(before, after)
29
+ common = before.keys & after.keys
30
+ {
31
+ added: (after.keys - before.keys).sort.map { |key| { id: key, value: after.fetch(key) } },
32
+ removed: (before.keys - after.keys).sort.map { |key| { id: key, value: before.fetch(key) } },
33
+ changed: common.sort.filter_map do |key|
34
+ next if before.fetch(key) == after.fetch(key)
35
+
36
+ { id: key, before: before.fetch(key), after: after.fetch(key) }
37
+ end
38
+ }
39
+ end
40
+
41
+ # @rbs (IR::Grammar grammar) -> Hash[String, Object?]
42
+ def symbol_records(grammar)
43
+ grammar.symbols.to_h do |symbol|
44
+ [
45
+ symbol.name,
46
+ {
47
+ kind: symbol.kind, reserved: symbol.reserved, display_name: symbol.display_name,
48
+ semantic_type: symbol.semantic_type, precedence: symbol.precedence
49
+ }
50
+ ]
51
+ end
52
+ end
53
+
54
+ # @rbs (IR::Grammar grammar) -> Hash[String, Object?]
55
+ def rule_records(grammar)
56
+ grammar.productions.group_by(&:lhs).to_h do |lhs, productions|
57
+ name = grammar.symbol_by_id(lhs)&.name || lhs.to_s
58
+ alternatives = productions.map { |production| production_record(grammar, production) }
59
+ [name, alternatives]
60
+ end
61
+ end
62
+
63
+ # @rbs (IR::Grammar grammar, IR::Production production) -> Hash[Symbol, Object?]
64
+ def production_record(grammar, production)
65
+ precedence = production.precedence_override
66
+ {
67
+ rhs: production.rhs.map { |id| symbol_name(grammar, id) },
68
+ precedence: precedence && symbol_name(grammar, precedence),
69
+ node: production.node && {
70
+ name: production.node.fetch(:name), fields: production.node.fetch(:fields)
71
+ }
72
+ }
73
+ end
74
+
75
+ # @rbs (IR::Automaton automaton) -> Hash[String, Object?]
76
+ def conflict_records(automaton)
77
+ grouped = Hash.new { |hash, key| hash[key] = [] } #: Hash[String, Array[Object?]]
78
+ automaton.states.each do |state|
79
+ state.conflicts.each do |conflict|
80
+ identity = conflict_identity(automaton.grammar, conflict)
81
+ grouped[identity] << conflict.fetch(:resolution)
82
+ end
83
+ end
84
+ grouped.transform_values { |resolutions| resolutions.sort_by(&:inspect) }
85
+ end
86
+
87
+ # @rbs (IR::Grammar grammar, IR::conflict conflict) -> String
88
+ def conflict_identity(grammar, conflict)
89
+ if conflict.fetch(:type).to_sym == :shift_reduce
90
+ shift_reduce = conflict #: IR::shift_reduce_conflict
91
+ reduction = production_shape(grammar, shift_reduce.fetch(:reduce))
92
+ "shift_reduce:#{shift_reduce.fetch(:symbol)}:#{reduction}"
93
+ else
94
+ reduce_reduce = conflict #: IR::reduce_reduce_conflict
95
+ reductions = reduce_reduce.fetch(:reductions).map { |id| production_shape(grammar, id) }.sort
96
+ "reduce_reduce:#{reduce_reduce.fetch(:symbol)}:#{reductions.join('|')}"
97
+ end
98
+ end
99
+
100
+ # @rbs (IR::Grammar grammar, Integer id) -> String
101
+ def production_shape(grammar, id)
102
+ production = grammar.productions.fetch(id)
103
+ lhs = symbol_name(grammar, production.lhs)
104
+ rhs = production.rhs.map { |symbol| symbol_name(grammar, symbol) }
105
+ "#{lhs}->#{rhs.join(' ')}"
106
+ end
107
+
108
+ # @rbs (IR::Grammar grammar, Integer id) -> String
109
+ def symbol_name(grammar, id)
110
+ grammar.symbol_by_id(id)&.name || id.to_s
111
+ end
112
+
113
+ # @rbs (IR::Grammar grammar) -> Hash[String, Object?]
114
+ def warning_records(grammar)
115
+ grouped = Hash.new { |hash, key| hash[key] = [] } #: Hash[String, Array[Object?]]
116
+ grammar.warnings.each do |warning|
117
+ value = warning.except(:loc)
118
+ identity = [warning.fetch(:type), value.except(:message).inspect].join(":")
119
+ grouped[identity] << value
120
+ end
121
+ grouped.transform_values { |values| values.sort_by(&:inspect) }
122
+ end
123
+
124
+ # @rbs () -> Hash[Symbol, Hash[Symbol, Integer]]
125
+ def numeric_metrics
126
+ {
127
+ states: change(@before.states.length, @after.states.length),
128
+ productions: change(@before.grammar.productions.length, @after.grammar.productions.length),
129
+ warnings: change(@before.grammar.warnings.length, @after.grammar.warnings.length),
130
+ shift_reduce: change(@before.conflict_summary.fetch(:sr), @after.conflict_summary.fetch(:sr)),
131
+ reduce_reduce: change(@before.conflict_summary.fetch(:rr), @after.conflict_summary.fetch(:rr))
132
+ }
133
+ end
134
+
135
+ # @rbs (Integer before, Integer after) -> Hash[Symbol, Integer]
136
+ def change(before, after)
137
+ { before: before, after: after, delta: after - before }
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ class Equiv
6
+ # Immutable, semantic-action-free LR state-stack machine.
7
+ class Machine
8
+ class BudgetExceeded < Ibex::Error; end
9
+
10
+ # One product-search component.
11
+ class Configuration
12
+ attr_reader :stack #: Array[Integer]
13
+ attr_reader :status #: Symbol?
14
+ attr_reader :actions #: Integer
15
+ attr_reader :reductions #: Array[Integer]
16
+
17
+ # @rbs (stack: Array[Integer], status: Symbol?, actions: Integer, ?reductions: Array[Integer]) -> void
18
+ def initialize(stack:, status:, actions:, reductions: [])
19
+ @stack = stack.freeze
20
+ @status = status
21
+ @actions = actions
22
+ @reductions = reductions.freeze
23
+ freeze
24
+ end
25
+ end
26
+
27
+ # @rbs (IR::Automaton automaton, max_actions: Integer, max_stack: Integer) -> void
28
+ def initialize(automaton, max_actions:, max_stack:)
29
+ @automaton = automaton
30
+ @max_actions = max_actions
31
+ @max_stack = max_stack
32
+ @terminals = automaton.grammar.terminals.to_h { |symbol| [symbol.name, symbol.id] }
33
+ @eof_id = @terminals.fetch("$eof")
34
+ end
35
+
36
+ # @rbs () -> Configuration
37
+ def start
38
+ entry = @automaton.entry_states.fetch(@automaton.grammar.start)
39
+ Configuration.new(stack: [entry], status: nil, actions: 0, reductions: [])
40
+ end
41
+
42
+ # @rbs (Array[String] tokens) -> Configuration
43
+ def run(tokens)
44
+ tokens.reduce(start) { |configuration, token| push(configuration, token) }
45
+ end
46
+
47
+ # @rbs (Configuration configuration, String token) -> Configuration
48
+ def push(configuration, token)
49
+ return configuration if configuration.status
50
+
51
+ token_id = @terminals[token]
52
+ unless token_id
53
+ return Configuration.new(
54
+ stack: configuration.stack, status: :error, actions: configuration.actions,
55
+ reductions: configuration.reductions
56
+ )
57
+ end
58
+
59
+ consume(configuration, token_id, eof: false)
60
+ end
61
+
62
+ # @rbs (Configuration configuration) -> Configuration
63
+ def finish(configuration)
64
+ return configuration if configuration.status
65
+
66
+ consume(configuration, @eof_id, eof: true)
67
+ end
68
+
69
+ private
70
+
71
+ # @rbs (Configuration configuration, Integer token_id, eof: bool) -> Configuration
72
+ def consume(configuration, token_id, eof:)
73
+ stack = configuration.stack.dup
74
+ actions = configuration.actions
75
+ reductions = configuration.reductions.dup
76
+ loop do
77
+ actions += 1
78
+ enforce_action_budget!(actions)
79
+ state = @automaton.states.fetch(stack.fetch(-1))
80
+ action = state.actions.fetch(token_id, state.default_action || { type: :error })
81
+ case action.fetch(:type)
82
+ when :shift
83
+ shift = action #: IR::shift_action
84
+ stack << shift.fetch(:state)
85
+ enforce_stack_budget!(stack)
86
+ return Configuration.new(stack: stack, status: nil, actions: actions, reductions: reductions) unless eof
87
+ when :reduce
88
+ reduce = action #: IR::reduce_action
89
+ production_id = reduce.fetch(:production)
90
+ apply_reduction!(stack, production_id)
91
+ reductions << production_id
92
+ enforce_stack_budget!(stack)
93
+ when :accept
94
+ return Configuration.new(
95
+ stack: stack, status: :accepted, actions: actions, reductions: reductions
96
+ )
97
+ when :error
98
+ return Configuration.new(stack: stack, status: :error, actions: actions, reductions: reductions)
99
+ else
100
+ raise Ibex::Error, "(equiv):1:1: unknown parser action #{action.inspect}"
101
+ end
102
+ end
103
+ end
104
+
105
+ # @rbs (Array[Integer] stack, Integer production_id) -> void
106
+ def apply_reduction!(stack, production_id)
107
+ production = @automaton.grammar.productions.fetch(production_id)
108
+ if production.rhs.length >= stack.length
109
+ raise Ibex::Error, "(equiv):1:1: production #{production_id} underflows the state stack"
110
+ end
111
+
112
+ stack.pop(production.rhs.length)
113
+ state = @automaton.states.fetch(stack.fetch(-1))
114
+ target = state.gotos[production.lhs]
115
+ raise Ibex::Error, "(equiv):1:1: missing goto after production #{production_id}" unless target
116
+
117
+ stack << target
118
+ end
119
+
120
+ # @rbs (Integer actions) -> void
121
+ def enforce_action_budget!(actions)
122
+ return if actions <= @max_actions
123
+
124
+ raise BudgetExceeded, "(equiv):1:1: simulation exceeded #{@max_actions} actions"
125
+ end
126
+
127
+ # @rbs (Array[Integer] stack) -> void
128
+ def enforce_stack_budget!(stack)
129
+ return if stack.length <= @max_stack
130
+
131
+ raise BudgetExceeded, "(equiv):1:1: simulation exceeded stack depth #{@max_stack}"
132
+ end
133
+ end
134
+ end
135
+ end