ibex 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +95 -272
  3. data/docs/architecture.md +187 -35
  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 +3 -4
  12. data/docs/cst.md +24 -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 +179 -2
  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 +2 -1
  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 +54 -0
  51. data/docs/getting-started.md +80 -0
  52. data/docs/grammar-reference.md +184 -13
  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 +5 -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 +11 -0
  63. data/docs/release-readiness.md +126 -68
  64. data/docs/repair-semantics.md +123 -0
  65. data/docs/runtime-abi-evolution.md +307 -0
  66. data/docs/stability.md +144 -34
  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/lib/ibex/analysis/digraph.rb +128 -0
  75. data/lib/ibex/analysis.rb +1 -0
  76. data/lib/ibex/bison_import/importer.rb +516 -0
  77. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  78. data/lib/ibex/bison_import.rb +200 -0
  79. data/lib/ibex/bounded_subprocess.rb +171 -0
  80. data/lib/ibex/cli/ambiguity.rb +14 -5
  81. data/lib/ibex/cli/analysis.rb +134 -0
  82. data/lib/ibex/cli/bison_import.rb +121 -0
  83. data/lib/ibex/cli/config.rb +128 -0
  84. data/lib/ibex/cli/diagnostics.rb +31 -11
  85. data/lib/ibex/cli/documentation.rb +11 -8
  86. data/lib/ibex/cli/equiv.rb +169 -0
  87. data/lib/ibex/cli/error_messages.rb +11 -4
  88. data/lib/ibex/cli/explain.rb +14 -5
  89. data/lib/ibex/cli/fix.rb +203 -0
  90. data/lib/ibex/cli/formatting.rb +11 -10
  91. data/lib/ibex/cli/fuzz.rb +200 -0
  92. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  93. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  94. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  95. data/lib/ibex/cli/grammar_tests.rb +32 -14
  96. data/lib/ibex/cli/ir_tools.rb +5 -61
  97. data/lib/ibex/cli/outputs.rb +60 -33
  98. data/lib/ibex/cli/reduce.rb +202 -0
  99. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  100. data/lib/ibex/cli/samples.rb +49 -23
  101. data/lib/ibex/cli/verify.rb +116 -0
  102. data/lib/ibex/cli/watch.rb +6 -5
  103. data/lib/ibex/cli.rb +357 -56
  104. data/lib/ibex/codegen/action_locations.rb +1 -1
  105. data/lib/ibex/codegen/action_method_source.rb +5 -6
  106. data/lib/ibex/codegen/action_source.rb +3 -2
  107. data/lib/ibex/codegen/ambiguity.rb +5 -4
  108. data/lib/ibex/codegen/explain.rb +123 -55
  109. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  110. data/lib/ibex/codegen/rbs.rb +15 -7
  111. data/lib/ibex/codegen/report.rb +25 -13
  112. data/lib/ibex/codegen/ruby.rb +28 -64
  113. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  114. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  115. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  116. data/lib/ibex/configuration/explanation.rb +421 -0
  117. data/lib/ibex/configuration/inspector.rb +232 -0
  118. data/lib/ibex/configuration.rb +580 -0
  119. data/lib/ibex/coverage/collector.rb +21 -11
  120. data/lib/ibex/coverage/event_stream.rb +13 -7
  121. data/lib/ibex/coverage/report.rb +26 -18
  122. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  123. data/lib/ibex/delta_reducer.rb +99 -0
  124. data/lib/ibex/diff.rb +140 -0
  125. data/lib/ibex/equiv/machine.rb +135 -0
  126. data/lib/ibex/equiv.rb +373 -0
  127. data/lib/ibex/fix.rb +557 -0
  128. data/lib/ibex/frontend/ast.rb +22 -2
  129. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  130. data/lib/ibex/frontend/diagnostic.rb +1 -1
  131. data/lib/ibex/frontend/formatter.rb +72 -26
  132. data/lib/ibex/frontend/generated_parser.rb +147 -117
  133. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  134. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  135. data/lib/ibex/frontend/generation.rb +1 -1
  136. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  137. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  138. data/lib/ibex/frontend/regenerator.rb +1 -0
  139. data/lib/ibex/frontend/resolution.rb +2 -1
  140. data/lib/ibex/frontend/resolver.rb +1 -1
  141. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  142. data/lib/ibex/frontend/source_cursor.rb +2 -2
  143. data/lib/ibex/frontend/source_span.rb +9 -1
  144. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  145. data/lib/ibex/frontend/token_adapter.rb +10 -0
  146. data/lib/ibex/frontend.rb +1 -0
  147. data/lib/ibex/fuzz.rb +219 -0
  148. data/lib/ibex/generation_input.rb +1 -1
  149. data/lib/ibex/generation_manifest.rb +36 -25
  150. data/lib/ibex/generation_transaction.rb +1 -1
  151. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  152. data/lib/ibex/generation_transaction_validation.rb +2 -2
  153. data/lib/ibex/grammar_tests.rb +1 -1
  154. data/lib/ibex/ir/automaton_ir.rb +61 -19
  155. data/lib/ibex/ir/grammar_ir.rb +76 -45
  156. data/lib/ibex/ir/lexer_ir.rb +5 -5
  157. data/lib/ibex/ir/parser_contract.rb +135 -0
  158. data/lib/ibex/ir/serialize.rb +203 -76
  159. data/lib/ibex/ir/validator/automaton.rb +64 -34
  160. data/lib/ibex/ir/validator/base.rb +51 -33
  161. data/lib/ibex/ir/validator/grammar.rb +113 -83
  162. data/lib/ibex/ir/validator/lexer.rb +2 -2
  163. data/lib/ibex/ir/validator.rb +2 -1
  164. data/lib/ibex/ir.rb +16 -3
  165. data/lib/ibex/lalr/build_metrics.rb +50 -2
  166. data/lib/ibex/lalr/builder.rb +191 -56
  167. data/lib/ibex/lalr/conflict_search.rb +15 -4
  168. data/lib/ibex/lalr/counterexample.rb +19 -14
  169. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  170. data/lib/ibex/lalr/goto_follows.rb +229 -0
  171. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  172. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  173. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  174. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  175. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  176. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  177. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  178. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  179. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  180. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  181. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  182. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  183. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  184. data/lib/ibex/lalr.rb +52 -1
  185. data/lib/ibex/location.rb +3 -3
  186. data/lib/ibex/lsp/document_handlers.rb +9 -7
  187. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  188. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  189. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  190. data/lib/ibex/lsp/position_codec.rb +6 -2
  191. data/lib/ibex/lsp/request_handlers.rb +3 -2
  192. data/lib/ibex/lsp/request_support.rb +14 -7
  193. data/lib/ibex/lsp/server.rb +13 -11
  194. data/lib/ibex/lsp/symbol_index.rb +13 -13
  195. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  196. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  197. data/lib/ibex/lsp/transport.rb +13 -3
  198. data/lib/ibex/lsp/workspace.rb +5 -4
  199. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  200. data/lib/ibex/lsp.rb +1 -0
  201. data/lib/ibex/messages/en.yml +28 -0
  202. data/lib/ibex/messages/ja.yml +28 -0
  203. data/lib/ibex/messages.rb +68 -0
  204. data/lib/ibex/metrics.rb +175 -0
  205. data/lib/ibex/normalize/declarations.rb +2 -0
  206. data/lib/ibex/normalize/diagnostics.rb +63 -38
  207. data/lib/ibex/normalize/expander.rb +5 -4
  208. data/lib/ibex/normalize/expression.rb +8 -6
  209. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  210. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  211. data/lib/ibex/normalize/lexer.rb +3 -3
  212. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  213. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  214. data/lib/ibex/normalize/parameters.rb +31 -4
  215. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  216. data/lib/ibex/normalize.rb +10 -20
  217. data/lib/ibex/racc_migration/report.rb +6 -3
  218. data/lib/ibex/rake_task.rb +1 -1
  219. data/lib/ibex/samples.rb +43 -13
  220. data/lib/ibex/table_artifact/builder.rb +266 -0
  221. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  222. data/lib/ibex/table_artifact/document.rb +39 -0
  223. data/lib/ibex/table_artifact/executor.rb +187 -0
  224. data/lib/ibex/table_artifact/serializer.rb +57 -0
  225. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  226. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  227. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  228. data/lib/ibex/table_artifact/validator.rb +253 -0
  229. data/lib/ibex/table_artifact.rb +88 -0
  230. data/lib/ibex/table_simulation/result.rb +6 -2
  231. data/lib/ibex/table_simulation/step.rb +3 -1
  232. data/lib/ibex/tables.rb +14 -0
  233. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  234. data/lib/ibex/verification_report/builder.rb +159 -0
  235. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  236. data/lib/ibex/verification_report/logical_path.rb +68 -0
  237. data/lib/ibex/verification_report/validator.rb +329 -0
  238. data/lib/ibex/verification_report.rb +69 -0
  239. data/lib/ibex/verify/action_correspondence.rb +138 -0
  240. data/lib/ibex/verify/language_witness.rb +295 -0
  241. data/lib/ibex/verify/reference_collection.rb +190 -0
  242. data/lib/ibex/verify/result.rb +73 -0
  243. data/lib/ibex/verify/verifier.rb +598 -0
  244. data/lib/ibex/verify.rb +15 -0
  245. data/lib/ibex/version.rb +1 -1
  246. data/lib/ibex/watch/runner.rb +10 -1
  247. data/lib/ibex/watch/source_snapshot.rb +13 -8
  248. data/lib/ibex.rb +10 -0
  249. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  250. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  251. data/schema/bison-import-v1.schema.json +106 -0
  252. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  253. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  254. data/schema/construction-profile-v1.schema.json +779 -0
  255. data/schema/diff-v1.schema.json +41 -0
  256. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  257. data/schema/equiv-v1.schema.json +64 -0
  258. data/schema/error-ux-review-v1.schema.json +609 -0
  259. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  260. data/schema/error-ux-round2-v1.schema.json +519 -0
  261. data/schema/explain-v1.schema.json +63 -1
  262. data/schema/fix-v1.schema.json +64 -0
  263. data/schema/fix-v2.schema.json +66 -0
  264. data/schema/fix-v3.schema.json +101 -0
  265. data/schema/fuzz-regression-v1.schema.json +79 -0
  266. data/schema/fuzz-v1.schema.json +114 -0
  267. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  268. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  269. data/schema/grammar-ir.schema.json +271 -0
  270. data/schema/ielr-benchmark-v1.schema.json +85 -0
  271. data/schema/lexer-profile-v1.schema.json +491 -0
  272. data/schema/metrics-v1.schema.json +60 -0
  273. data/schema/reduce-v1.schema.json +22 -0
  274. data/schema/reduce-v2.schema.json +63 -0
  275. data/schema/table-artifact-v1.schema.json +377 -0
  276. data/schema/verification-report-v1.schema.json +222 -0
  277. data/schema/verify-v1.schema.json +42 -0
  278. data/sig/ibex/analysis/digraph.rbs +19 -0
  279. data/sig/ibex/bison_import/importer.rbs +140 -0
  280. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  281. data/sig/ibex/bison_import.rbs +95 -0
  282. data/sig/ibex/bounded_subprocess.rbs +76 -0
  283. data/sig/ibex/cli/ambiguity.rbs +6 -0
  284. data/sig/ibex/cli/analysis.rbs +43 -0
  285. data/sig/ibex/cli/bison_import.rbs +32 -0
  286. data/sig/ibex/cli/config.rbs +35 -0
  287. data/sig/ibex/cli/diagnostics.rbs +16 -3
  288. data/sig/ibex/cli/documentation.rbs +5 -1
  289. data/sig/ibex/cli/equiv.rbs +49 -0
  290. data/sig/ibex/cli/error_messages.rbs +6 -0
  291. data/sig/ibex/cli/explain.rbs +6 -0
  292. data/sig/ibex/cli/fix.rbs +53 -0
  293. data/sig/ibex/cli/formatting.rbs +5 -1
  294. data/sig/ibex/cli/fuzz.rbs +47 -0
  295. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  296. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  297. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  298. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  299. data/sig/ibex/cli/ir_tools.rbs +7 -19
  300. data/sig/ibex/cli/outputs.rbs +9 -3
  301. data/sig/ibex/cli/reduce.rbs +60 -0
  302. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  303. data/sig/ibex/cli/samples.rbs +8 -0
  304. data/sig/ibex/cli/verify.rbs +28 -0
  305. data/sig/ibex/cli/watch.rbs +2 -2
  306. data/sig/ibex/cli.rbs +79 -5
  307. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  308. data/sig/ibex/codegen/explain.rbs +45 -25
  309. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  310. data/sig/ibex/codegen/rbs.rbs +12 -10
  311. data/sig/ibex/codegen/report.rbs +12 -12
  312. data/sig/ibex/codegen/ruby.rbs +18 -15
  313. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  314. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  315. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  316. data/sig/ibex/configuration/explanation.rbs +195 -0
  317. data/sig/ibex/configuration/inspector.rbs +53 -0
  318. data/sig/ibex/configuration.rbs +242 -0
  319. data/sig/ibex/coverage/collector.rbs +16 -14
  320. data/sig/ibex/coverage/event_stream.rbs +12 -10
  321. data/sig/ibex/coverage/report.rbs +20 -18
  322. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  323. data/sig/ibex/delta_reducer.rbs +38 -0
  324. data/sig/ibex/diff.rbs +47 -0
  325. data/sig/ibex/equiv/machine.rbs +54 -0
  326. data/sig/ibex/equiv.rbs +129 -0
  327. data/sig/ibex/fix.rbs +138 -0
  328. data/sig/ibex/frontend/ast.rbs +33 -7
  329. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  330. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  331. data/sig/ibex/frontend/formatter.rbs +38 -30
  332. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  333. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  334. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  335. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  336. data/sig/ibex/frontend/resolution.rbs +3 -2
  337. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  338. data/sig/ibex/frontend/source_span.rbs +5 -2
  339. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  340. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  341. data/sig/ibex/fuzz.rbs +71 -0
  342. data/sig/ibex/generation_input.rbs +2 -2
  343. data/sig/ibex/generation_manifest.rbs +35 -32
  344. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  345. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  346. data/sig/ibex/grammar_tests.rbs +2 -2
  347. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  348. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  349. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  350. data/sig/ibex/ir/parser_contract.rbs +69 -0
  351. data/sig/ibex/ir/serialize.rbs +63 -28
  352. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  353. data/sig/ibex/ir/validator/base.rbs +35 -31
  354. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  355. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  356. data/sig/ibex/ir.rbs +9 -3
  357. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  358. data/sig/ibex/lalr/builder.rbs +75 -24
  359. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  360. data/sig/ibex/lalr/counterexample.rbs +17 -14
  361. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  362. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  363. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  364. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  365. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  366. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  367. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  368. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  369. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  370. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  371. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  372. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  373. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  374. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  375. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  376. data/sig/ibex/lalr.rbs +11 -1
  377. data/sig/ibex/location.rbs +6 -6
  378. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  379. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  380. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  381. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  382. data/sig/ibex/lsp/position_codec.rbs +8 -4
  383. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  384. data/sig/ibex/lsp/request_support.rbs +8 -8
  385. data/sig/ibex/lsp/server.rbs +16 -16
  386. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  387. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  388. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  389. data/sig/ibex/lsp/transport.rbs +18 -6
  390. data/sig/ibex/lsp/workspace.rbs +3 -2
  391. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  392. data/sig/ibex/messages.rbs +26 -0
  393. data/sig/ibex/metrics.rbs +50 -0
  394. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  395. data/sig/ibex/normalize/expander.rbs +2 -2
  396. data/sig/ibex/normalize/expression.rbs +10 -8
  397. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  398. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  399. data/sig/ibex/normalize/lexer.rbs +4 -4
  400. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  401. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  402. data/sig/ibex/normalize/parameters.rbs +13 -8
  403. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  404. data/sig/ibex/normalize.rbs +11 -5
  405. data/sig/ibex/racc_migration/report.rbs +8 -6
  406. data/sig/ibex/rake_task.rbs +1 -1
  407. data/sig/ibex/samples.rbs +13 -4
  408. data/sig/ibex/table_artifact/builder.rbs +93 -0
  409. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  410. data/sig/ibex/table_artifact/document.rbs +27 -0
  411. data/sig/ibex/table_artifact/executor.rbs +66 -0
  412. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  413. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  414. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  415. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  416. data/sig/ibex/table_artifact/validator.rbs +66 -0
  417. data/sig/ibex/table_artifact.rbs +32 -0
  418. data/sig/ibex/table_simulation/result.rbs +8 -4
  419. data/sig/ibex/table_simulation/step.rbs +4 -2
  420. data/sig/ibex/tables.rbs +10 -9
  421. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  422. data/sig/ibex/verification_report/builder.rbs +53 -0
  423. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  424. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  425. data/sig/ibex/verification_report/validator.rbs +114 -0
  426. data/sig/ibex/verification_report.rbs +44 -0
  427. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  428. data/sig/ibex/verify/language_witness.rbs +112 -0
  429. data/sig/ibex/verify/reference_collection.rbs +63 -0
  430. data/sig/ibex/verify/result.rbs +52 -0
  431. data/sig/ibex/verify/verifier.rbs +170 -0
  432. data/sig/ibex/verify.rbs +6 -0
  433. data/sig/ibex/watch/runner.rbs +12 -2
  434. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  435. metadata +232 -12
  436. data/lib/ibex/ir/migration.rb +0 -120
  437. data/sig/ibex/ir/migration.rbs +0 -34
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "optparse"
5
+ require "shellwords"
6
+ require_relative "../bounded_subprocess"
7
+ require_relative "../delta_reducer"
8
+ require_relative "reduce_reporting"
9
+
10
+ module Ibex
11
+ # @rbs!
12
+ # type reduction_bounds = {
13
+ # max_trials: Integer,
14
+ # timeout_seconds: Integer,
15
+ # max_output_bytes: Integer,
16
+ # max_input_bytes: Integer
17
+ # }
18
+ # type reduction_budget_details = {
19
+ # kind: String,
20
+ # message: String,
21
+ # trials: Integer
22
+ # }
23
+ # type reduction_success_document = {
24
+ # ibex_report: String,
25
+ # schema_version: Integer,
26
+ # result: String,
27
+ # mode: Symbol,
28
+ # original_size: Integer,
29
+ # minimized_size: Integer,
30
+ # trials: Integer,
31
+ # complete: bool,
32
+ # minimized: Array[String | Integer],
33
+ # bounded: bool,
34
+ # bounds: reduction_bounds
35
+ # }
36
+ # type reduction_budget_document = {
37
+ # ibex_report: String,
38
+ # schema_version: Integer,
39
+ # result: String,
40
+ # mode: Symbol,
41
+ # bounded: bool,
42
+ # bounds: reduction_bounds,
43
+ # budget: reduction_budget_details
44
+ # }
45
+
46
+ # CLI entry point for generic bounded delta debugging.
47
+ module CLIReduce
48
+ include CLIReduceReporting
49
+
50
+ DEFAULT_MAX_INPUT_BYTES = 10 * 1024 * 1024 #: Integer
51
+
52
+ class ReductionBudgetExceeded < Ibex::Error
53
+ attr_reader :details #: reduction_budget_details
54
+
55
+ # @rbs (reduction_budget_details details) -> void
56
+ def initialize(details)
57
+ @details = details
58
+ super("(reduce):1:1: configured resource budget was exhausted")
59
+ end
60
+ end
61
+
62
+ # @rbs @reduction_mode: Symbol
63
+ # @rbs @reduction_bounds: reduction_bounds
64
+ # @rbs @reduction_trials: Integer
65
+ # @rbs @reduction_subprocess: BoundedSubprocess
66
+
67
+ # @rbs!
68
+ # private def print_help: (OptionParser) -> Integer
69
+ # private def input_path: (Array[String]) -> String
70
+
71
+ private
72
+
73
+ # @rbs (Array[String] arguments) -> Integer
74
+ def run_reduce_command(arguments)
75
+ parser = reduce_option_parser
76
+ remaining = parser.parse(arguments)
77
+ return print_help(parser) if @options[:help]
78
+
79
+ path = input_path(remaining)
80
+ configured_command = @options[:reduce_command]
81
+ raise OptionParser::MissingArgument, "--command" unless configured_command
82
+
83
+ command = Shellwords.split(configured_command)
84
+ raise OptionParser::InvalidArgument, "--command must not be empty" if command.empty?
85
+
86
+ prepare_reduction_run
87
+ source = bounded_reduction_source(path)
88
+ items = reduction_items(source, @reduction_mode)
89
+ reducer = DeltaReducer.new(max_trials: @reduction_bounds.fetch(:max_trials))
90
+ result = reducer.minimize(items) { |candidate| reduction_failure?(command, candidate, @reduction_mode) }
91
+ write_reduction_success(reduction_success_report(result))
92
+ result.complete ? 0 : 2
93
+ rescue ReductionBudgetExceeded => e
94
+ write_reduction_budget(reduction_budget_report(e.details))
95
+ 2
96
+ end
97
+
98
+ # @rbs () -> OptionParser
99
+ def reduce_option_parser
100
+ OptionParser.new do |options|
101
+ options.banner = "Usage: ibex reduce --command=COMMAND [options] input"
102
+ options.on("--command=COMMAND", "nonzero exit means the failure persists") do |value|
103
+ @options[:reduce_command] = value
104
+ end
105
+ options.on("--mode=MODE", %w[tokens lines bytes], "tokens, lines, or bytes") do |value|
106
+ @options[:reduce_mode] = value.to_sym
107
+ end
108
+ options.on("--max-trials=N", Integer, "subprocess trial budget (default 1000)") do |value|
109
+ @options[:reduce_max_trials] = positive_reduce_option!("max-trials", value)
110
+ end
111
+ options.on("--timeout=SECONDS", Integer, "checker timeout per trial (default 10)") do |value|
112
+ @options[:reduce_timeout] = positive_reduce_option!("timeout", value)
113
+ end
114
+ options.on("--max-output-bytes=N", Integer, "checker stdout/stderr byte budget") do |value|
115
+ @options[:reduce_max_output_bytes] = positive_reduce_option!("max-output-bytes", value)
116
+ end
117
+ options.on("--max-input-bytes=N", Integer, "input byte budget (default 10485760)") do |value|
118
+ @options[:reduce_max_input_bytes] = positive_reduce_option!("max-input-bytes", value)
119
+ end
120
+ options.on("--format=FORMAT", %w[json text], "json or text (default json)") do |value|
121
+ @options[:reduce_format] = value
122
+ end
123
+ options.on("--help", "show help") { @options[:help] = true }
124
+ end
125
+ end
126
+
127
+ # @rbs () -> void
128
+ def prepare_reduction_run
129
+ @reduction_mode = @options.fetch(:reduce_mode, :tokens)
130
+ @reduction_bounds = {
131
+ max_trials: @options.fetch(:reduce_max_trials, 1_000),
132
+ timeout_seconds: @options.fetch(:reduce_timeout, BoundedSubprocess::DEFAULT_TIMEOUT_SECONDS),
133
+ max_output_bytes: @options.fetch(
134
+ :reduce_max_output_bytes, BoundedSubprocess::DEFAULT_MAX_OUTPUT_BYTES
135
+ ),
136
+ max_input_bytes: @options.fetch(:reduce_max_input_bytes, DEFAULT_MAX_INPUT_BYTES)
137
+ }
138
+ @reduction_trials = 0
139
+ @reduction_subprocess = BoundedSubprocess.new(
140
+ timeout_seconds: @reduction_bounds.fetch(:timeout_seconds),
141
+ max_output_bytes: @reduction_bounds.fetch(:max_output_bytes)
142
+ )
143
+ end
144
+
145
+ # @rbs (String path) -> String
146
+ def bounded_reduction_source(path)
147
+ maximum = @reduction_bounds.fetch(:max_input_bytes)
148
+ source = File.binread(path, maximum + 1)
149
+ return source if source.bytesize <= maximum
150
+
151
+ raise ReductionBudgetExceeded.new(
152
+ kind: "input_bytes", message: "input exceeds #{maximum} bytes", trials: 0
153
+ )
154
+ end
155
+
156
+ # @rbs (String source, Symbol mode) -> Array[String | Integer]
157
+ def reduction_items(source, mode)
158
+ case mode
159
+ when :tokens
160
+ parsed = JSON.parse(source)
161
+ raise Ibex::Error, "(reduce):1:1: token input must be a JSON array" unless parsed.is_a?(Array)
162
+ raise Ibex::Error, "(reduce):1:1: every token must be a string" unless parsed.all?(String)
163
+
164
+ parsed
165
+ when :lines then source.lines
166
+ when :bytes then source.bytes
167
+ else raise Ibex::Error, "(reduce):1:1: unknown reduction mode #{mode.inspect}"
168
+ end
169
+ rescue JSON::ParserError => e
170
+ raise Ibex::Error, "(reduce):1:1: invalid token JSON: #{e.message}"
171
+ end
172
+
173
+ # @rbs (Array[String] command, Array[String | Integer] candidate, Symbol mode) -> bool
174
+ def reduction_failure?(command, candidate, mode)
175
+ input = case mode
176
+ when :tokens then JSON.generate(candidate)
177
+ when :lines then candidate.join
178
+ when :bytes then candidate.pack("C*")
179
+ else raise Ibex::Error, "(reduce):1:1: unknown reduction mode #{mode.inspect}"
180
+ end
181
+ @reduction_trials += 1
182
+ result = @reduction_subprocess.run(command, input: input)
183
+ if result.timed_out || result.output_limited
184
+ kind = result.timed_out ? "subprocess_timeout" : "subprocess_output"
185
+ message = result.timed_out ? "checker timed out" : "checker exceeded its output byte budget"
186
+ raise ReductionBudgetExceeded.new(kind: kind, message: message, trials: @reduction_trials)
187
+ end
188
+ unless result.status.exited?
189
+ raise Ibex::Error, "(reduce):1:1: checker terminated by signal #{result.status.termsig}"
190
+ end
191
+
192
+ !result.status.success?
193
+ end
194
+
195
+ # @rbs (String name, Integer value) -> Integer
196
+ def positive_reduce_option!(name, value)
197
+ return value if value.positive?
198
+
199
+ raise OptionParser::InvalidArgument, "--#{name} must be positive"
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Ibex
5
+ # Versioned machine and terminal reports for bounded delta reduction.
6
+ module CLIReduceReporting
7
+ # @rbs @reduction_mode: Symbol
8
+ # @rbs @reduction_bounds: reduction_bounds
9
+
10
+ private
11
+
12
+ # @rbs (DeltaReducer::Result result) -> reduction_success_document
13
+ def reduction_success_report(result)
14
+ items = result.items #: Array[String | Integer]
15
+ {
16
+ ibex_report: "reduce", schema_version: 2,
17
+ result: result.complete ? "minimized" : "incomplete",
18
+ mode: @reduction_mode, original_size: result.original_size,
19
+ minimized_size: items.length, trials: result.trials,
20
+ complete: result.complete, minimized: items, bounded: true,
21
+ bounds: @reduction_bounds
22
+ }
23
+ end
24
+
25
+ # @rbs (reduction_budget_details details) -> reduction_budget_document
26
+ def reduction_budget_report(details)
27
+ {
28
+ ibex_report: "reduce", schema_version: 2, result: "budget_exhausted",
29
+ mode: @reduction_mode || @options.fetch(:reduce_mode, :tokens),
30
+ bounded: true, bounds: @reduction_bounds || default_reduction_bounds,
31
+ budget: details
32
+ }
33
+ end
34
+
35
+ # @rbs () -> reduction_bounds
36
+ def default_reduction_bounds
37
+ {
38
+ max_trials: @options.fetch(:reduce_max_trials, 1_000),
39
+ timeout_seconds: @options.fetch(:reduce_timeout, BoundedSubprocess::DEFAULT_TIMEOUT_SECONDS),
40
+ max_output_bytes: @options.fetch(
41
+ :reduce_max_output_bytes, BoundedSubprocess::DEFAULT_MAX_OUTPUT_BYTES
42
+ ),
43
+ max_input_bytes: @options.fetch(:reduce_max_input_bytes, CLIReduce::DEFAULT_MAX_INPUT_BYTES)
44
+ }
45
+ end
46
+
47
+ # @rbs (reduction_success_document report) -> void
48
+ def write_reduction_success(report)
49
+ if @options.fetch(:reduce_format, "json") == "json"
50
+ @stdout.puts JSON.pretty_generate(report)
51
+ return
52
+ end
53
+
54
+ @stdout.puts("result=#{report[:result]}")
55
+ @stdout.puts("mode=#{report[:mode]} original_size=#{report[:original_size]} " \
56
+ "minimized_size=#{report[:minimized_size]} trials=#{report[:trials]}")
57
+ @stdout.puts("minimized=#{report[:minimized].inspect}")
58
+ end
59
+
60
+ # @rbs (reduction_budget_document report) -> void
61
+ def write_reduction_budget(report)
62
+ if @options.fetch(:reduce_format, "json") == "json"
63
+ @stdout.puts JSON.pretty_generate(report)
64
+ return
65
+ end
66
+
67
+ @stdout.puts("result=#{report[:result]}")
68
+ @stdout.puts("budget=#{report[:budget].inspect}")
69
+ end
70
+ end
71
+ end
@@ -13,6 +13,7 @@ module Ibex
13
13
  # private def handle_grammar_warnings: (IR::Grammar, String) -> void
14
14
  # private def warning_categories: (String) -> Array[Symbol]
15
15
  # private def normalize_grammar_path: (String) -> IR::Grammar
16
+ # private def set_configuration_option: (Symbol, Object?) -> void
16
17
 
17
18
  private
18
19
 
@@ -30,7 +31,9 @@ module Ibex
30
31
  seed: @options.fetch(:sample_seed, 0),
31
32
  max_tokens: @options.fetch(:sample_max_tokens, 32),
32
33
  max_depth: @options.fetch(:sample_max_depth, 16),
33
- max_expansions: @options.fetch(:sample_max_expansions, Samples::DEFAULT_MAX_EXPANSIONS)
34
+ max_expansions: @options.fetch(:sample_max_expansions, Samples::DEFAULT_MAX_EXPANSIONS),
35
+ strategy: @options.fetch(:sample_strategy, :random),
36
+ path_length: @options.fetch(:sample_path_length, 1)
34
37
  )
35
38
  generator.generate(count: @options.fetch(:sample_count, 5)).each do |sample|
36
39
  @stdout.puts(JSON.generate(sample))
@@ -42,32 +45,55 @@ module Ibex
42
45
  def samples_option_parser
43
46
  OptionParser.new do |options|
44
47
  options.banner = "Usage: ibex samples [options] grammarfile"
45
- options.on("--count=N", Integer, "number of samples (default 5)") do |value|
46
- @options[:sample_count] = positive_sample_option!("count", value)
47
- end
48
- options.on("--seed=N", Integer, "deterministic random seed (default 0)") do |value|
49
- @options[:sample_seed] = value
50
- end
51
- options.on("--max-tokens=N", Integer, "maximum tokens per sample (default 32)") do |value|
52
- @options[:sample_max_tokens] = positive_sample_option!("max-tokens", value)
53
- end
54
- options.on("--max-depth=N", Integer, "random expansion depth (default 16)") do |value|
55
- @options[:sample_max_depth] = positive_sample_option!("max-depth", value)
56
- end
57
- options.on("--max-expansions=N", Integer, "total expansion steps (default 100000)") do |value|
58
- @options[:sample_max_expansions] = positive_sample_option!("max-expansions", value)
59
- end
60
- options.on("--from=FORMAT", %w[grammar-ir automaton-ir], "read versioned IR JSON") do |value|
61
- @options[:from] = value
62
- end
63
- options.on("--mode=MODE", %w[default extended], "grammar mode") { |value| @options[:mode] = value.to_sym }
64
- options.on("--warnings=CATEGORIES", "all, error, all,error, or none") do |value|
65
- @options[:warnings] = warning_categories(value)
66
- end
48
+ add_sample_generation_options(options)
49
+ add_sample_input_options(options)
67
50
  options.on("--help", "show help") { @options[:help] = true }
68
51
  end
69
52
  end
70
53
 
54
+ # @rbs (OptionParser options) -> void
55
+ def add_sample_generation_options(options)
56
+ options.on("--count=N", Integer, "number of samples (default 5)") do |value|
57
+ @options[:sample_count] = positive_sample_option!("count", value)
58
+ end
59
+ options.on("--seed=N", Integer, "deterministic random seed (default 0)") do |value|
60
+ @options[:sample_seed] = value
61
+ end
62
+ options.on("--max-tokens=N", Integer, "maximum tokens per sample (default 32)") do |value|
63
+ @options[:sample_max_tokens] = positive_sample_option!("max-tokens", value)
64
+ end
65
+ options.on("--max-depth=N", Integer, "random expansion depth (default 16)") do |value|
66
+ @options[:sample_max_depth] = positive_sample_option!("max-depth", value)
67
+ end
68
+ options.on("--max-expansions=N", Integer, "total expansion steps (default 100000)") do |value|
69
+ @options[:sample_max_expansions] = positive_sample_option!("max-expansions", value)
70
+ end
71
+ options.on(
72
+ "--strategy=NAME", %w[random coverage],
73
+ "random or coverage-oriented production selection"
74
+ ) do |value|
75
+ @options[:sample_strategy] = value.to_sym
76
+ end
77
+ options.on("--path-length=N", Integer, "coverage path length: 1 or 2") do |value|
78
+ raise OptionParser::InvalidArgument, "--path-length must be 1 or 2" unless [1, 2].include?(value)
79
+
80
+ @options[:sample_path_length] = value
81
+ end
82
+ end
83
+
84
+ # @rbs (OptionParser options) -> void
85
+ def add_sample_input_options(options)
86
+ options.on("--from=FORMAT", %w[grammar-ir automaton-ir], "read current IR JSON") do |value|
87
+ @options[:from] = value
88
+ end
89
+ options.on("--mode=MODE", %w[default extended], "grammar mode") do |value|
90
+ set_configuration_option(:mode, value.to_sym)
91
+ end
92
+ options.on("--warnings=CATEGORIES", "all, error, all,error, or none") do |value|
93
+ @options[:warnings] = warning_categories(value)
94
+ end
95
+ end
96
+
71
97
  # @rbs (String path) -> IR::Grammar
72
98
  def grammar_for_samples(path)
73
99
  return normalize_grammar_path(path) unless @options[:from]
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ require "json"
5
+ require "optparse"
6
+ require_relative "../verify"
7
+ require_relative "../ir"
8
+
9
+ module Ibex
10
+ # CLI entry point for bounded, independent Automaton IR verification.
11
+ module CLIVerify
12
+ # @rbs!
13
+ # type verify_options = {
14
+ # paths: Array[String],
15
+ # strict: bool,
16
+ # max_states: Integer,
17
+ # max_items: Integer,
18
+ # ?grammar: String,
19
+ # format: String,
20
+ # ?help: String
21
+ # }
22
+
23
+ private
24
+
25
+ # @rbs (Array[String] arguments) -> Integer
26
+ def run_verify_command(arguments)
27
+ settings = verify_options(arguments)
28
+ if settings[:help]
29
+ @stdout.puts(settings.fetch(:help))
30
+ return 0
31
+ end
32
+ operands = settings.fetch(:paths)
33
+ raise Ibex::Error, "(verify):1:1: verify requires exactly one Automaton IR file" unless operands.length == 1
34
+
35
+ automaton = load_verify_automaton(operands.fetch(0))
36
+ verify_supplied_grammar!(automaton, settings[:grammar]) if settings[:grammar]
37
+ result = Verify::Verifier.new(
38
+ automaton,
39
+ strict: settings.fetch(:strict),
40
+ max_states: settings.fetch(:max_states),
41
+ max_items: settings.fetch(:max_items)
42
+ ).verify
43
+ write_verify_result(result, settings.fetch(:format))
44
+ result.valid? ? 0 : 1
45
+ rescue Verify::BudgetExceeded => e
46
+ violations = [] #: Array[Verify::Violation]
47
+ report = {
48
+ ibex_report: "verify", schema_version: 1, result: "budget_exhausted",
49
+ strict: settings&.fetch(:strict, false), bounds: e.bounds, violations: violations
50
+ }
51
+ @stdout.puts(JSON.pretty_generate(report))
52
+ 2
53
+ end
54
+
55
+ # @rbs (Array[String] arguments) -> verify_options
56
+ def verify_options(arguments)
57
+ settings = {
58
+ paths: [], strict: false, max_states: 100_000, max_items: 1_000_000, format: "json"
59
+ } #: verify_options
60
+ parser = OptionParser.new do |options|
61
+ options.banner = "Usage: ibex verify [options] AUTOMATON.json"
62
+ options.on("--strict", "include completeness and table-bisimulation checks") { settings[:strict] = true }
63
+ options.on("--grammar=GRAMMAR", "require an exact embedded Grammar IR match") do |value|
64
+ settings[:grammar] = value
65
+ end
66
+ options.on("--max-states=N", Integer, "maximum independently derived states") do |value|
67
+ settings[:max_states] = positive_verify_budget(value, "max-states")
68
+ end
69
+ options.on("--max-items=N", Integer, "maximum independently derived items") do |value|
70
+ settings[:max_items] = positive_verify_budget(value, "max-items")
71
+ end
72
+ options.on("--format=FORMAT", %w[json text], "json or text") { |value| settings[:format] = value }
73
+ options.on("--help", "show help") { settings[:help] = options.to_s }
74
+ end
75
+ settings[:paths] = parser.parse(arguments)
76
+ settings
77
+ end
78
+
79
+ # @rbs (String path) -> IR::Automaton
80
+ def load_verify_automaton(path)
81
+ value = IR::Validator.validate(File.binread(path))
82
+ return value if value.is_a?(IR::Automaton)
83
+
84
+ raise Ibex::Error, "#{path}:1:1: verify requires Automaton IR"
85
+ end
86
+
87
+ # @rbs (IR::Automaton automaton, String path) -> void
88
+ def verify_supplied_grammar!(automaton, path)
89
+ value = IR::Validator.validate(File.binread(path))
90
+ raise Ibex::Error, "#{path}:1:1: --grammar requires Grammar IR" unless value.is_a?(IR::Grammar)
91
+ return if IR::Serialize.dump(value) == IR::Serialize.dump(automaton.grammar)
92
+
93
+ raise Ibex::Error, "#{path}:1:1: Grammar IR does not match the automaton's embedded grammar"
94
+ end
95
+
96
+ # @rbs (Verify::Result result, String format) -> void
97
+ def write_verify_result(result, format)
98
+ if format == "json"
99
+ @stdout.puts(JSON.pretty_generate(result.to_h))
100
+ return
101
+ end
102
+
103
+ @stdout.puts("result=#{result.valid? ? 'valid' : 'invalid'} algorithm=#{result.algorithm}")
104
+ result.violations.each do |violation|
105
+ @stdout.puts("#{violation.id} #{violation.location}: #{violation.message}")
106
+ end
107
+ end
108
+
109
+ # @rbs (Integer value, String name) -> Integer
110
+ def positive_verify_budget(value, name)
111
+ return value if value.positive?
112
+
113
+ raise OptionParser::InvalidArgument, "--#{name} must be positive"
114
+ end
115
+ end
116
+ end
@@ -70,20 +70,21 @@ module Ibex
70
70
  @defer_generation_publication = false
71
71
  end
72
72
 
73
- # @rbs (Build build, Watch::SourceSnapshot snapshot, ^() -> bool continue) -> void
73
+ # @rbs (Watch::_BuildResult build, Watch::SourceSnapshot snapshot, ^() -> bool continue) -> void
74
74
  def publish_watch_generation(build, snapshot, continue)
75
+ typed_build = build #: Build
75
76
  stable = lambda do
76
- continue.call && build.source_records.all?(&:current?) &&
77
+ continue.call && typed_build.source_records.all?(&:current?) &&
77
78
  Watch::SourceSnapshot.new(snapshot.paths) == snapshot
78
79
  end
79
80
  GenerationTransaction.new(
80
- build.artifacts,
81
+ typed_build.artifacts,
81
82
  warning: ->(message) { @stderr.puts("ibex: warning: #{message}") },
82
83
  stability_check: stable,
83
- source_records: build.source_records,
84
+ source_records: typed_build.source_records,
84
85
  lock_sleeper: @watch_sleeper
85
86
  ).commit
86
- build.statuses.each { |message| report_status(message) }
87
+ typed_build.statuses.each { |message| report_status(message) }
87
88
  end
88
89
 
89
90
  # @rbs (String path) -> Array[String]