ibex 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -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 +274 -0
  40. data/docs/development.md +196 -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 +1617 -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/impact.md +101 -0
  56. data/docs/ja/bison-import.md +51 -0
  57. data/docs/ja/stable-api.md +53 -0
  58. data/docs/lexer-construction-profile.md +109 -0
  59. data/docs/lexer-migration.md +5 -0
  60. data/docs/maturity.md +129 -0
  61. data/docs/project-site-strategy.md +54 -0
  62. data/docs/racc-migration-evidence.md +45 -0
  63. data/docs/racc-migration.md +11 -0
  64. data/docs/release-readiness.md +126 -68
  65. data/docs/repair-semantics.md +123 -0
  66. data/docs/runtime-abi-evolution.md +310 -0
  67. data/docs/stability.md +145 -34
  68. data/docs/status.md +43 -0
  69. data/docs/syntax-sessions.md +183 -0
  70. data/docs/table-artifact.md +125 -0
  71. data/docs/test-interactions.md +219 -0
  72. data/docs/verification-report.md +137 -0
  73. data/docs/verifier-trust-boundary.md +199 -0
  74. data/docs/workloads.md +132 -0
  75. data/lib/ibex/analysis/digraph.rb +128 -0
  76. data/lib/ibex/analysis/sets.rb +14 -0
  77. data/lib/ibex/analysis.rb +1 -0
  78. data/lib/ibex/bison_import/importer.rb +516 -0
  79. data/lib/ibex/bison_import/tokenizer.rb +260 -0
  80. data/lib/ibex/bison_import.rb +200 -0
  81. data/lib/ibex/bounded_subprocess.rb +171 -0
  82. data/lib/ibex/cli/ambiguity.rb +14 -5
  83. data/lib/ibex/cli/analysis.rb +134 -0
  84. data/lib/ibex/cli/bison_import.rb +121 -0
  85. data/lib/ibex/cli/config.rb +128 -0
  86. data/lib/ibex/cli/diagnostics.rb +31 -11
  87. data/lib/ibex/cli/documentation.rb +11 -8
  88. data/lib/ibex/cli/equiv.rb +169 -0
  89. data/lib/ibex/cli/error_messages.rb +11 -4
  90. data/lib/ibex/cli/explain.rb +14 -5
  91. data/lib/ibex/cli/fix.rb +203 -0
  92. data/lib/ibex/cli/formatting.rb +11 -10
  93. data/lib/ibex/cli/fuzz.rb +200 -0
  94. data/lib/ibex/cli/fuzz_regressions.rb +145 -0
  95. data/lib/ibex/cli/generation_artifacts.rb +53 -2
  96. data/lib/ibex/cli/generation_error_messages.rb +1 -1
  97. data/lib/ibex/cli/grammar_tests.rb +32 -14
  98. data/lib/ibex/cli/impact.rb +393 -0
  99. data/lib/ibex/cli/ir_tools.rb +5 -61
  100. data/lib/ibex/cli/outputs.rb +60 -33
  101. data/lib/ibex/cli/reduce.rb +202 -0
  102. data/lib/ibex/cli/reduce_reporting.rb +71 -0
  103. data/lib/ibex/cli/samples.rb +49 -23
  104. data/lib/ibex/cli/verify.rb +116 -0
  105. data/lib/ibex/cli/watch.rb +6 -5
  106. data/lib/ibex/cli.rb +362 -56
  107. data/lib/ibex/codegen/action_locations.rb +1 -1
  108. data/lib/ibex/codegen/action_method_source.rb +5 -6
  109. data/lib/ibex/codegen/action_source.rb +3 -2
  110. data/lib/ibex/codegen/ambiguity.rb +5 -4
  111. data/lib/ibex/codegen/explain.rb +123 -55
  112. data/lib/ibex/codegen/generated_action_abi.rb +10 -5
  113. data/lib/ibex/codegen/rbs.rb +15 -7
  114. data/lib/ibex/codegen/report.rb +25 -13
  115. data/lib/ibex/codegen/ruby.rb +28 -64
  116. data/lib/ibex/codegen/ruby_actions.rb +9 -6
  117. data/lib/ibex/codegen/ruby_syntax.rb +15 -9
  118. data/lib/ibex/configuration/analysis_grammar.rb +35 -0
  119. data/lib/ibex/configuration/explanation.rb +421 -0
  120. data/lib/ibex/configuration/inspector.rb +232 -0
  121. data/lib/ibex/configuration.rb +580 -0
  122. data/lib/ibex/coverage/collector.rb +21 -11
  123. data/lib/ibex/coverage/event_stream.rb +13 -7
  124. data/lib/ibex/coverage/report.rb +26 -18
  125. data/lib/ibex/coverage/runtime_event_validator.rb +30 -21
  126. data/lib/ibex/delta_reducer.rb +99 -0
  127. data/lib/ibex/diff.rb +141 -0
  128. data/lib/ibex/equiv/machine.rb +135 -0
  129. data/lib/ibex/equiv.rb +373 -0
  130. data/lib/ibex/fix.rb +557 -0
  131. data/lib/ibex/frontend/ast.rb +22 -2
  132. data/lib/ibex/frontend/bootstrap_parser.rb +6 -13
  133. data/lib/ibex/frontend/diagnostic.rb +1 -1
  134. data/lib/ibex/frontend/formatter.rb +72 -26
  135. data/lib/ibex/frontend/generated_parser.rb +147 -117
  136. data/lib/ibex/frontend/generated_parser_base.rb +7 -3
  137. data/lib/ibex/frontend/generated_parser_includes.rb +1 -11
  138. data/lib/ibex/frontend/generation.rb +1 -1
  139. data/lib/ibex/frontend/parser/declarations.rb +17 -2
  140. data/lib/ibex/frontend/parser_configuration_support.rb +56 -0
  141. data/lib/ibex/frontend/regenerator.rb +1 -0
  142. data/lib/ibex/frontend/resolution.rb +2 -1
  143. data/lib/ibex/frontend/resolver.rb +1 -1
  144. data/lib/ibex/frontend/rule_documentation.rb +2 -1
  145. data/lib/ibex/frontend/source_cursor.rb +2 -2
  146. data/lib/ibex/frontend/source_span.rb +9 -1
  147. data/lib/ibex/frontend/token_adapter/declaration_state.rb +38 -6
  148. data/lib/ibex/frontend/token_adapter.rb +10 -0
  149. data/lib/ibex/frontend.rb +1 -0
  150. data/lib/ibex/fuzz.rb +219 -0
  151. data/lib/ibex/generation_input.rb +1 -1
  152. data/lib/ibex/generation_manifest.rb +36 -25
  153. data/lib/ibex/generation_transaction.rb +1 -1
  154. data/lib/ibex/generation_transaction_recovery.rb +4 -4
  155. data/lib/ibex/generation_transaction_validation.rb +2 -2
  156. data/lib/ibex/grammar_tests.rb +1 -1
  157. data/lib/ibex/impact/action_impact.rb +148 -0
  158. data/lib/ibex/impact/automaton_impact.rb +57 -0
  159. data/lib/ibex/impact/coverage_impact.rb +53 -0
  160. data/lib/ibex/impact/graph.rb +132 -0
  161. data/lib/ibex/impact/propagation.rb +147 -0
  162. data/lib/ibex/impact/report.rb +273 -0
  163. data/lib/ibex/impact/seeds.rb +69 -0
  164. data/lib/ibex/impact/severity.rb +139 -0
  165. data/lib/ibex/impact.rb +16 -0
  166. data/lib/ibex/ir/automaton_ir.rb +61 -19
  167. data/lib/ibex/ir/grammar_ir.rb +76 -45
  168. data/lib/ibex/ir/lexer_ir.rb +5 -5
  169. data/lib/ibex/ir/parser_contract.rb +135 -0
  170. data/lib/ibex/ir/serialize.rb +203 -76
  171. data/lib/ibex/ir/validator/automaton.rb +64 -34
  172. data/lib/ibex/ir/validator/base.rb +51 -33
  173. data/lib/ibex/ir/validator/grammar.rb +113 -83
  174. data/lib/ibex/ir/validator/lexer.rb +2 -2
  175. data/lib/ibex/ir/validator.rb +2 -1
  176. data/lib/ibex/ir.rb +16 -3
  177. data/lib/ibex/lalr/build_metrics.rb +50 -2
  178. data/lib/ibex/lalr/builder.rb +191 -56
  179. data/lib/ibex/lalr/conflict_search.rb +15 -4
  180. data/lib/ibex/lalr/counterexample.rb +19 -14
  181. data/lib/ibex/lalr/direct_lookaheads.rb +110 -57
  182. data/lib/ibex/lalr/goto_follows.rb +229 -0
  183. data/lib/ibex/lalr/ielr/annotator.rb +214 -0
  184. data/lib/ibex/lalr/ielr/bits.rb +28 -0
  185. data/lib/ibex/lalr/ielr/inadequacy.rb +47 -0
  186. data/lib/ibex/lalr/ielr/item_lookaheads.rb +78 -0
  187. data/lib/ibex/lalr/ielr/pipeline.rb +75 -0
  188. data/lib/ibex/lalr/ielr/split_stability.rb +78 -0
  189. data/lib/ibex/lalr/ielr/split_state.rb +20 -0
  190. data/lib/ibex/lalr/ielr/state_splitter.rb +258 -0
  191. data/lib/ibex/lalr/ielr_partition.rb +22 -8
  192. data/lib/ibex/lalr/inadequacy_report.rb +50 -0
  193. data/lib/ibex/lalr/lookahead_propagation.rb +111 -0
  194. data/lib/ibex/lalr/lr0_collection.rb +121 -0
  195. data/lib/ibex/lalr/unreachable_states.rb +80 -0
  196. data/lib/ibex/lalr.rb +52 -1
  197. data/lib/ibex/location.rb +3 -3
  198. data/lib/ibex/lsp/document_handlers.rb +9 -7
  199. data/lib/ibex/lsp/initialization_handlers.rb +9 -7
  200. data/lib/ibex/lsp/navigation_handlers.rb +25 -11
  201. data/lib/ibex/lsp/parser_configuration_assistance.rb +149 -0
  202. data/lib/ibex/lsp/position_codec.rb +6 -2
  203. data/lib/ibex/lsp/request_handlers.rb +3 -2
  204. data/lib/ibex/lsp/request_support.rb +14 -7
  205. data/lib/ibex/lsp/server.rb +13 -11
  206. data/lib/ibex/lsp/symbol_index.rb +13 -13
  207. data/lib/ibex/lsp/symbol_index_builder.rb +30 -20
  208. data/lib/ibex/lsp/symbol_occurrence.rb +8 -2
  209. data/lib/ibex/lsp/transport.rb +13 -3
  210. data/lib/ibex/lsp/workspace.rb +5 -4
  211. data/lib/ibex/lsp/workspace_analyzer.rb +1 -1
  212. data/lib/ibex/lsp.rb +1 -0
  213. data/lib/ibex/messages/en.yml +28 -0
  214. data/lib/ibex/messages/ja.yml +28 -0
  215. data/lib/ibex/messages.rb +68 -0
  216. data/lib/ibex/metrics.rb +175 -0
  217. data/lib/ibex/normalize/declarations.rb +2 -0
  218. data/lib/ibex/normalize/diagnostics.rb +63 -38
  219. data/lib/ibex/normalize/expander.rb +5 -4
  220. data/lib/ibex/normalize/expression.rb +8 -6
  221. data/lib/ibex/normalize/grammar_builder.rb +26 -0
  222. data/lib/ibex/normalize/inline_expansion.rb +100 -49
  223. data/lib/ibex/normalize/lexer.rb +3 -3
  224. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +11 -10
  225. data/lib/ibex/normalize/parameter_lowering.rb +40 -23
  226. data/lib/ibex/normalize/parameters.rb +31 -4
  227. data/lib/ibex/normalize/parser_configuration.rb +70 -0
  228. data/lib/ibex/normalize.rb +10 -20
  229. data/lib/ibex/racc_migration/report.rb +6 -3
  230. data/lib/ibex/rake_task.rb +1 -1
  231. data/lib/ibex/samples.rb +43 -13
  232. data/lib/ibex/table_artifact/builder.rb +266 -0
  233. data/lib/ibex/table_artifact/cst_projection.rb +70 -0
  234. data/lib/ibex/table_artifact/document.rb +39 -0
  235. data/lib/ibex/table_artifact/executor.rb +187 -0
  236. data/lib/ibex/table_artifact/serializer.rb +57 -0
  237. data/lib/ibex/table_artifact/validator/metadata.rb +179 -0
  238. data/lib/ibex/table_artifact/validator/support.rb +86 -0
  239. data/lib/ibex/table_artifact/validator/tables.rb +238 -0
  240. data/lib/ibex/table_artifact/validator.rb +253 -0
  241. data/lib/ibex/table_artifact.rb +88 -0
  242. data/lib/ibex/table_simulation/result.rb +6 -2
  243. data/lib/ibex/table_simulation/step.rb +3 -1
  244. data/lib/ibex/tables.rb +14 -0
  245. data/lib/ibex/verifiable_generation_bundle.rb +86 -0
  246. data/lib/ibex/verification_report/builder.rb +159 -0
  247. data/lib/ibex/verification_report/canonical_ir.rb +123 -0
  248. data/lib/ibex/verification_report/logical_path.rb +68 -0
  249. data/lib/ibex/verification_report/validator.rb +329 -0
  250. data/lib/ibex/verification_report.rb +69 -0
  251. data/lib/ibex/verify/action_correspondence.rb +138 -0
  252. data/lib/ibex/verify/language_witness.rb +295 -0
  253. data/lib/ibex/verify/reference_collection.rb +190 -0
  254. data/lib/ibex/verify/result.rb +73 -0
  255. data/lib/ibex/verify/verifier.rb +598 -0
  256. data/lib/ibex/verify.rb +15 -0
  257. data/lib/ibex/version.rb +1 -1
  258. data/lib/ibex/watch/runner.rb +10 -1
  259. data/lib/ibex/watch/source_snapshot.rb +13 -8
  260. data/lib/ibex.rb +11 -0
  261. data/schema/{automaton-ir-v1.schema.json → automaton-ir-definitions.schema.json} +6 -6
  262. data/schema/{automaton-ir-v2.schema.json → automaton-ir.schema.json} +14 -7
  263. data/schema/bison-import-v1.schema.json +106 -0
  264. data/schema/conflict-explanation-review-v1.schema.json +196 -0
  265. data/schema/conflict-explanation-study-v1.schema.json +528 -0
  266. data/schema/construction-profile-v1.schema.json +779 -0
  267. data/schema/diff-v1.schema.json +41 -0
  268. data/schema/direct-ielr-decision-v1.schema.json +200 -0
  269. data/schema/equiv-v1.schema.json +64 -0
  270. data/schema/error-ux-review-v1.schema.json +609 -0
  271. data/schema/error-ux-round2-review-v1.schema.json +191 -0
  272. data/schema/error-ux-round2-v1.schema.json +519 -0
  273. data/schema/explain-v1.schema.json +63 -1
  274. data/schema/fix-v1.schema.json +64 -0
  275. data/schema/fix-v2.schema.json +66 -0
  276. data/schema/fix-v3.schema.json +101 -0
  277. data/schema/fuzz-regression-v1.schema.json +79 -0
  278. data/schema/fuzz-v1.schema.json +114 -0
  279. data/schema/{grammar-ir-v2.schema.json → grammar-ir-extensions.schema.json} +20 -65
  280. data/schema/{grammar-ir-v1.schema.json → grammar-ir-foundation.schema.json} +3 -3
  281. data/schema/grammar-ir.schema.json +271 -0
  282. data/schema/ielr-benchmark-v1.schema.json +85 -0
  283. data/schema/impact-v1.schema.json +208 -0
  284. data/schema/lexer-profile-v1.schema.json +491 -0
  285. data/schema/metrics-v1.schema.json +60 -0
  286. data/schema/reduce-v1.schema.json +22 -0
  287. data/schema/reduce-v2.schema.json +63 -0
  288. data/schema/table-artifact-v1.schema.json +377 -0
  289. data/schema/verification-report-v1.schema.json +222 -0
  290. data/schema/verify-v1.schema.json +42 -0
  291. data/sig/ibex/analysis/digraph.rbs +19 -0
  292. data/sig/ibex/analysis/sets.rbs +10 -0
  293. data/sig/ibex/bison_import/importer.rbs +140 -0
  294. data/sig/ibex/bison_import/tokenizer.rbs +91 -0
  295. data/sig/ibex/bison_import.rbs +95 -0
  296. data/sig/ibex/bounded_subprocess.rbs +76 -0
  297. data/sig/ibex/cli/ambiguity.rbs +6 -0
  298. data/sig/ibex/cli/analysis.rbs +43 -0
  299. data/sig/ibex/cli/bison_import.rbs +32 -0
  300. data/sig/ibex/cli/config.rbs +35 -0
  301. data/sig/ibex/cli/diagnostics.rbs +16 -3
  302. data/sig/ibex/cli/documentation.rbs +5 -1
  303. data/sig/ibex/cli/equiv.rbs +49 -0
  304. data/sig/ibex/cli/error_messages.rbs +6 -0
  305. data/sig/ibex/cli/explain.rbs +6 -0
  306. data/sig/ibex/cli/fix.rbs +53 -0
  307. data/sig/ibex/cli/formatting.rbs +5 -1
  308. data/sig/ibex/cli/fuzz.rbs +47 -0
  309. data/sig/ibex/cli/fuzz_regressions.rbs +40 -0
  310. data/sig/ibex/cli/generation_artifacts.rbs +21 -2
  311. data/sig/ibex/cli/generation_error_messages.rbs +2 -2
  312. data/sig/ibex/cli/grammar_tests.rbs +15 -3
  313. data/sig/ibex/cli/impact.rbs +95 -0
  314. data/sig/ibex/cli/ir_tools.rbs +7 -19
  315. data/sig/ibex/cli/outputs.rbs +9 -3
  316. data/sig/ibex/cli/reduce.rbs +60 -0
  317. data/sig/ibex/cli/reduce_reporting.rbs +27 -0
  318. data/sig/ibex/cli/samples.rbs +8 -0
  319. data/sig/ibex/cli/verify.rbs +28 -0
  320. data/sig/ibex/cli/watch.rbs +2 -2
  321. data/sig/ibex/cli.rbs +79 -5
  322. data/sig/ibex/codegen/action_method_source.rbs +4 -4
  323. data/sig/ibex/codegen/explain.rbs +45 -25
  324. data/sig/ibex/codegen/generated_action_abi.rbs +14 -10
  325. data/sig/ibex/codegen/rbs.rbs +12 -10
  326. data/sig/ibex/codegen/report.rbs +12 -12
  327. data/sig/ibex/codegen/ruby.rbs +18 -15
  328. data/sig/ibex/codegen/ruby_actions.rbs +6 -6
  329. data/sig/ibex/codegen/ruby_syntax.rbs +10 -8
  330. data/sig/ibex/configuration/analysis_grammar.rbs +13 -0
  331. data/sig/ibex/configuration/explanation.rbs +195 -0
  332. data/sig/ibex/configuration/inspector.rbs +53 -0
  333. data/sig/ibex/configuration.rbs +242 -0
  334. data/sig/ibex/coverage/collector.rbs +16 -14
  335. data/sig/ibex/coverage/event_stream.rbs +12 -10
  336. data/sig/ibex/coverage/report.rbs +20 -18
  337. data/sig/ibex/coverage/runtime_event_validator.rbs +38 -36
  338. data/sig/ibex/delta_reducer.rbs +38 -0
  339. data/sig/ibex/diff.rbs +47 -0
  340. data/sig/ibex/equiv/machine.rbs +54 -0
  341. data/sig/ibex/equiv.rbs +129 -0
  342. data/sig/ibex/fix.rbs +138 -0
  343. data/sig/ibex/frontend/ast.rbs +33 -7
  344. data/sig/ibex/frontend/bootstrap_parser.rbs +2 -0
  345. data/sig/ibex/frontend/diagnostic.rbs +2 -2
  346. data/sig/ibex/frontend/formatter.rbs +38 -30
  347. data/sig/ibex/frontend/generated_parser.rbs +87 -77
  348. data/sig/ibex/frontend/generated_parser_base.rbs +4 -2
  349. data/sig/ibex/frontend/parser/declarations.rbs +3 -0
  350. data/sig/ibex/frontend/parser_configuration_support.rbs +27 -0
  351. data/sig/ibex/frontend/resolution.rbs +3 -2
  352. data/sig/ibex/frontend/source_cursor.rbs +2 -2
  353. data/sig/ibex/frontend/source_span.rbs +5 -2
  354. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +13 -1
  355. data/sig/ibex/frontend/token_adapter.rbs +6 -0
  356. data/sig/ibex/fuzz.rbs +71 -0
  357. data/sig/ibex/generation_input.rbs +2 -2
  358. data/sig/ibex/generation_manifest.rbs +35 -32
  359. data/sig/ibex/generation_transaction_recovery.rbs +2 -2
  360. data/sig/ibex/generation_transaction_validation.rbs +2 -2
  361. data/sig/ibex/grammar_tests.rbs +2 -2
  362. data/sig/ibex/impact/action_impact.rbs +58 -0
  363. data/sig/ibex/impact/automaton_impact.rbs +37 -0
  364. data/sig/ibex/impact/coverage_impact.rbs +28 -0
  365. data/sig/ibex/impact/graph.rbs +67 -0
  366. data/sig/ibex/impact/propagation.rbs +56 -0
  367. data/sig/ibex/impact/report.rbs +107 -0
  368. data/sig/ibex/impact/seeds.rbs +36 -0
  369. data/sig/ibex/impact/severity.rbs +55 -0
  370. data/sig/ibex/impact.rbs +6 -0
  371. data/sig/ibex/ir/automaton_ir.rbs +30 -11
  372. data/sig/ibex/ir/grammar_ir.rbs +41 -27
  373. data/sig/ibex/ir/lexer_ir.rbs +8 -8
  374. data/sig/ibex/ir/parser_contract.rbs +69 -0
  375. data/sig/ibex/ir/serialize.rbs +63 -28
  376. data/sig/ibex/ir/validator/automaton.rbs +47 -44
  377. data/sig/ibex/ir/validator/base.rbs +35 -31
  378. data/sig/ibex/ir/validator/grammar.rbs +78 -67
  379. data/sig/ibex/ir/validator/lexer.rbs +4 -4
  380. data/sig/ibex/ir.rbs +9 -3
  381. data/sig/ibex/lalr/build_metrics.rbs +42 -2
  382. data/sig/ibex/lalr/builder.rbs +75 -24
  383. data/sig/ibex/lalr/conflict_search.rbs +5 -2
  384. data/sig/ibex/lalr/counterexample.rbs +17 -14
  385. data/sig/ibex/lalr/direct_lookaheads.rbs +35 -28
  386. data/sig/ibex/lalr/goto_follows.rbs +89 -0
  387. data/sig/ibex/lalr/ielr/annotator.rbs +67 -0
  388. data/sig/ibex/lalr/ielr/bits.rbs +14 -0
  389. data/sig/ibex/lalr/ielr/inadequacy.rbs +24 -0
  390. data/sig/ibex/lalr/ielr/item_lookaheads.rbs +35 -0
  391. data/sig/ibex/lalr/ielr/pipeline.rbs +17 -0
  392. data/sig/ibex/lalr/ielr/split_stability.rbs +27 -0
  393. data/sig/ibex/lalr/ielr/split_state.rbs +14 -0
  394. data/sig/ibex/lalr/ielr/state_splitter.rbs +76 -0
  395. data/sig/ibex/lalr/ielr_partition.rbs +17 -5
  396. data/sig/ibex/lalr/inadequacy_report.rbs +21 -0
  397. data/sig/ibex/lalr/lookahead_propagation.rbs +38 -0
  398. data/sig/ibex/lalr/lr0_collection.rbs +50 -0
  399. data/sig/ibex/lalr/unreachable_states.rbs +25 -0
  400. data/sig/ibex/lalr.rbs +11 -1
  401. data/sig/ibex/location.rbs +6 -6
  402. data/sig/ibex/lsp/document_handlers.rbs +8 -8
  403. data/sig/ibex/lsp/initialization_handlers.rbs +12 -12
  404. data/sig/ibex/lsp/navigation_handlers.rbs +15 -12
  405. data/sig/ibex/lsp/parser_configuration_assistance.rbs +49 -0
  406. data/sig/ibex/lsp/position_codec.rbs +8 -4
  407. data/sig/ibex/lsp/request_handlers.rbs +4 -4
  408. data/sig/ibex/lsp/request_support.rbs +8 -8
  409. data/sig/ibex/lsp/server.rbs +16 -16
  410. data/sig/ibex/lsp/symbol_index.rbs +20 -21
  411. data/sig/ibex/lsp/symbol_index_builder.rbs +9 -8
  412. data/sig/ibex/lsp/symbol_occurrence.rbs +11 -5
  413. data/sig/ibex/lsp/transport.rbs +18 -6
  414. data/sig/ibex/lsp/workspace.rbs +3 -2
  415. data/sig/ibex/lsp/workspace_analyzer.rbs +1 -1
  416. data/sig/ibex/messages.rbs +26 -0
  417. data/sig/ibex/metrics.rbs +50 -0
  418. data/sig/ibex/normalize/diagnostics.rbs +4 -4
  419. data/sig/ibex/normalize/expander.rbs +2 -2
  420. data/sig/ibex/normalize/expression.rbs +10 -8
  421. data/sig/ibex/normalize/grammar_builder.rbs +11 -0
  422. data/sig/ibex/normalize/inline_expansion.rbs +59 -50
  423. data/sig/ibex/normalize/lexer.rbs +4 -4
  424. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +15 -14
  425. data/sig/ibex/normalize/parameter_lowering.rbs +18 -18
  426. data/sig/ibex/normalize/parameters.rbs +13 -8
  427. data/sig/ibex/normalize/parser_configuration.rbs +23 -0
  428. data/sig/ibex/normalize.rbs +11 -5
  429. data/sig/ibex/racc_migration/report.rbs +8 -6
  430. data/sig/ibex/rake_task.rbs +1 -1
  431. data/sig/ibex/samples.rbs +13 -4
  432. data/sig/ibex/table_artifact/builder.rbs +93 -0
  433. data/sig/ibex/table_artifact/cst_projection.rbs +20 -0
  434. data/sig/ibex/table_artifact/document.rbs +27 -0
  435. data/sig/ibex/table_artifact/executor.rbs +66 -0
  436. data/sig/ibex/table_artifact/serializer.rbs +25 -0
  437. data/sig/ibex/table_artifact/validator/metadata.rbs +52 -0
  438. data/sig/ibex/table_artifact/validator/support.rbs +46 -0
  439. data/sig/ibex/table_artifact/validator/tables.rbs +63 -0
  440. data/sig/ibex/table_artifact/validator.rbs +66 -0
  441. data/sig/ibex/table_artifact.rbs +32 -0
  442. data/sig/ibex/table_simulation/result.rbs +8 -4
  443. data/sig/ibex/table_simulation/step.rbs +4 -2
  444. data/sig/ibex/tables.rbs +10 -9
  445. data/sig/ibex/verifiable_generation_bundle.rbs +24 -0
  446. data/sig/ibex/verification_report/builder.rbs +53 -0
  447. data/sig/ibex/verification_report/canonical_ir.rbs +41 -0
  448. data/sig/ibex/verification_report/logical_path.rbs +34 -0
  449. data/sig/ibex/verification_report/validator.rbs +114 -0
  450. data/sig/ibex/verification_report.rbs +44 -0
  451. data/sig/ibex/verify/action_correspondence.rbs +50 -0
  452. data/sig/ibex/verify/language_witness.rbs +112 -0
  453. data/sig/ibex/verify/reference_collection.rbs +63 -0
  454. data/sig/ibex/verify/result.rbs +52 -0
  455. data/sig/ibex/verify/verifier.rbs +170 -0
  456. data/sig/ibex/verify.rbs +6 -0
  457. data/sig/ibex/watch/runner.rbs +12 -2
  458. data/sig/ibex/watch/source_snapshot.rbs +13 -9
  459. metadata +254 -12
  460. data/lib/ibex/ir/migration.rb +0 -120
  461. data/sig/ibex/ir/migration.rbs +0 -34
@@ -3,33 +3,33 @@
3
3
  module Ibex
4
4
  module IR
5
5
  module Validator
6
- # Structural and referential validation for a versioned Automaton IR JSON object.
6
+ # Structural and referential validation for a current Automaton IR JSON object.
7
7
  # rubocop:disable Metrics/ClassLength -- inline type contracts accompany one cohesive document validator.
8
8
  class AutomatonDocument < Base
9
9
  ROOT_REQUIRED = %w[
10
- ibex_ir schema_version algorithm grammar_digest grammar states conflict_summary
10
+ ibex_ir schema_version algorithm entry_construction grammar_digest grammar states conflict_summary
11
11
  ].freeze #: Array[String]
12
- V2_ROOT_OPTIONAL = %w[entry_states].freeze #: Array[String]
12
+ ROOT_OPTIONAL = %w[entry_states].freeze #: Array[String]
13
13
  STATE_REQUIRED = %w[id items transitions actions gotos default_action conflicts].freeze #: Array[String]
14
14
  ACTION_TYPES = %w[shift reduce accept error].freeze #: Array[String]
15
15
  RESOLUTION_KINDS = %w[definition_order default_shift precedence associativity].freeze #: Array[String]
16
16
 
17
- # @rbs @data: Hash[String, untyped]
18
- # @rbs @states_by_id: Hash[Integer, Hash[String, untyped]]
17
+ # @rbs @data: json_object
18
+ # @rbs @states_by_id: Hash[Integer, json_object]
19
19
  # @rbs @grammar: GrammarDocument
20
20
  # @rbs @version: Integer
21
21
 
22
- # @rbs (Hash[String, untyped] data, ?version: Integer) -> void
22
+ # @rbs (json_object data, ?version: Integer) -> void
23
23
  def initialize(data, version: data.fetch("schema_version"))
24
24
  super()
25
25
  @data = data
26
26
  @version = version
27
- @states_by_id = {} #: Hash[Integer, Hash[String, untyped]]
27
+ @states_by_id = {} #: Hash[Integer, json_object]
28
28
  end
29
29
 
30
30
  # @rbs () -> self
31
31
  def validate
32
- record(@data, "$", ROOT_REQUIRED, @version >= 2 ? V2_ROOT_OPTIONAL : [])
32
+ record(@data, "$", ROOT_REQUIRED, ROOT_OPTIONAL)
33
33
  literal(@data["ibex_ir"], "$.ibex_ir", "automaton")
34
34
  literal(@data["schema_version"], "$.schema_version", @version)
35
35
  enum(@data["algorithm"], "$.algorithm", %w[slr lalr1 ielr1 lr1])
@@ -37,6 +37,7 @@ module Ibex
37
37
  grammar = object(@data["grammar"], "$.grammar")
38
38
  literal(grammar["schema_version"], "$.grammar.schema_version", @version)
39
39
  @grammar = GrammarDocument.new(grammar, path: "$.grammar", version: @version).validate
40
+ validate_construction_contract(grammar)
40
41
  validate_state_records
41
42
  validate_entry_states
42
43
  validate_state_contents
@@ -58,11 +59,31 @@ module Ibex
58
59
  expected = @data.dig("grammar", "starts") || [@data.dig("grammar", "start")]
59
60
  invalid("$.entry_states", "keys must equal grammar starts in order") unless entries.keys == expected
60
61
  entries.each do |name, state|
61
- nonnegative_integer(state, "$.entry_states.#{name}")
62
- invalid("$.entry_states.#{name}", "references missing state #{state}") unless @states_by_id[state]
62
+ state_id = nonnegative_integer(state, "$.entry_states.#{name}")
63
+ invalid("$.entry_states.#{name}", "references missing state #{state_id}") unless @states_by_id[state_id]
63
64
  end
64
65
  end
65
66
 
67
+ # @rbs (Hash[String, untyped] grammar) -> void
68
+ def validate_construction_contract(grammar)
69
+ entry_construction = enum(
70
+ @data["entry_construction"], "$.entry_construction", %w[shared isolated]
71
+ )
72
+ contract = grammar.fetch("parser_contract")
73
+ algorithm = contract.fetch("algorithm")
74
+ expected_algorithm = { "lalr" => "lalr1", "ielr" => "ielr1" }.fetch(
75
+ algorithm["value"], algorithm["value"]
76
+ )
77
+ if algorithm["explicit"] && @data["algorithm"] != expected_algorithm
78
+ invalid("$.algorithm", "must match the embedded parser contract")
79
+ end
80
+
81
+ entries = contract.fetch("entries")
82
+ return unless entries["explicit"] && entry_construction != entries["value"]
83
+
84
+ invalid("$.entry_construction", "must match the embedded parser contract")
85
+ end
86
+
66
87
  # @rbs () -> void
67
88
  def validate_digest
68
89
  digest = string(@data["grammar_digest"], "$.grammar_digest")
@@ -95,7 +116,7 @@ module Ibex
95
116
  end
96
117
  end
97
118
 
98
- # @rbs (untyped value, String path) -> void
119
+ # @rbs (json_value value, String path) -> void
99
120
  def validate_items(value, path)
100
121
  array(value, path).each_with_index do |item, index|
101
122
  item_path = "#{path}[#{index}]"
@@ -106,7 +127,7 @@ module Ibex
106
127
  end
107
128
  end
108
129
 
109
- # @rbs (Integer production_id, untyped dot_value, String path) -> void
130
+ # @rbs (Integer production_id, json_value dot_value, String path) -> void
110
131
  def validate_item_production(production_id, dot_value, path)
111
132
  dot = nonnegative_integer(dot_value, "#{path}.dot")
112
133
  if production_id == -1
@@ -115,10 +136,11 @@ module Ibex
115
136
  end
116
137
  production = @grammar.productions_by_id[production_id]
117
138
  invalid("#{path}.production", "references missing production id #{production_id}") unless production
118
- invalid("#{path}.dot", "exceeds production #{production_id} length") if dot > production["rhs"].length
139
+ rhs = array(production["rhs"], "#{path}.production.rhs")
140
+ invalid("#{path}.dot", "exceeds production #{production_id} length") if dot > rhs.length
119
141
  end
120
142
 
121
- # @rbs (untyped value, String path) -> void
143
+ # @rbs (json_value value, String path) -> void
122
144
  def validate_lookaheads(value, path)
123
145
  array(value, path).each_with_index do |name, index|
124
146
  name = string(name, "#{path}[#{index}]")
@@ -128,28 +150,28 @@ module Ibex
128
150
  end
129
151
  end
130
152
 
131
- # @rbs (untyped value, String path) -> void
153
+ # @rbs (json_value value, String path) -> void
132
154
  def validate_transitions(value, path)
133
155
  symbol_map(value, path) do |target, target_path, _symbol|
134
156
  validate_state_reference(target, target_path)
135
157
  end
136
158
  end
137
159
 
138
- # @rbs (untyped value, String path) -> void
160
+ # @rbs (json_value value, String path) -> void
139
161
  def validate_actions(value, path)
140
162
  symbol_map(value, path, kind: "terminal") do |action, action_path, _symbol|
141
163
  validate_parser_action(action, action_path)
142
164
  end
143
165
  end
144
166
 
145
- # @rbs (untyped value, String path) -> void
167
+ # @rbs (json_value value, String path) -> void
146
168
  def validate_gotos(value, path)
147
169
  symbol_map(value, path, kind: "nonterminal") do |target, target_path, _symbol|
148
170
  validate_state_reference(target, target_path)
149
171
  end
150
172
  end
151
173
 
152
- # @rbs (untyped value, String path, ?kind: String?) { (untyped, String, Hash[String, untyped]) -> void } -> void
174
+ # @rbs (json_value value, String path, ?kind: String?) { (json_value, String, json_object) -> void } -> void
153
175
  def symbol_map(value, path, kind: nil, &block)
154
176
  object(value, path).each do |name, item|
155
177
  item_path = child_path(path, name)
@@ -160,13 +182,13 @@ module Ibex
160
182
  end
161
183
  end
162
184
 
163
- # @rbs (untyped value, String path) -> void
185
+ # @rbs (json_value value, String path) -> void
164
186
  def validate_state_reference(value, path)
165
187
  id = nonnegative_integer(value, path)
166
188
  invalid(path, "references missing state id #{id}") unless @states_by_id.key?(id)
167
189
  end
168
190
 
169
- # @rbs (untyped value, String path, ?nullable: bool) -> void
191
+ # @rbs (json_value value, String path, ?nullable: bool) -> void
170
192
  def validate_parser_action(value, path, nullable: false)
171
193
  return if nullable && value.nil?
172
194
 
@@ -182,13 +204,13 @@ module Ibex
182
204
  validate_production_reference(action["production"], "#{path}.production") if type == "reduce"
183
205
  end
184
206
 
185
- # @rbs (untyped value, String path) -> void
207
+ # @rbs (json_value value, String path) -> void
186
208
  def validate_production_reference(value, path)
187
209
  id = nonnegative_integer(value, path)
188
210
  invalid(path, "references missing production id #{id}") unless @grammar.productions_by_id.key?(id)
189
211
  end
190
212
 
191
- # @rbs (untyped value, String path) -> void
213
+ # @rbs (json_value value, String path) -> void
192
214
  def validate_conflicts(value, path)
193
215
  array(value, path).each_with_index do |conflict, index|
194
216
  conflict_path = "#{path}[#{index}]"
@@ -203,7 +225,7 @@ module Ibex
203
225
  end
204
226
  end
205
227
 
206
- # @rbs (Hash[String, untyped] conflict, String path) -> void
228
+ # @rbs (json_object conflict, String path) -> void
207
229
  def validate_shift_reduce(conflict, path)
208
230
  record(conflict, path, %w[type symbol shift_to reduce resolution], %w[midrule_origins entries composite])
209
231
  validate_conflict_symbol(conflict["symbol"], "#{path}.symbol")
@@ -215,11 +237,13 @@ module Ibex
215
237
  validate_conflict_entries(conflict, path)
216
238
  end
217
239
 
218
- # @rbs (Hash[String, untyped] conflict, String path) -> void
240
+ # @rbs (json_object conflict, String path) -> void
219
241
  def validate_reduce_reduce(conflict, path)
220
242
  record(conflict, path, %w[type symbol reductions resolution], %w[midrule_origins entries composite])
221
243
  validate_conflict_symbol(conflict["symbol"], "#{path}.symbol")
222
- reductions = array(conflict["reductions"], "#{path}.reductions")
244
+ reductions = array(conflict["reductions"], "#{path}.reductions").map.with_index do |id, index|
245
+ nonnegative_integer(id, "#{path}.reductions[#{index}]")
246
+ end
223
247
  invalid("#{path}.reductions", "must contain at least two productions") if reductions.length < 2
224
248
  reductions.each_with_index do |id, index|
225
249
  validate_production_reference(id, "#{path}.reductions[#{index}]")
@@ -233,7 +257,7 @@ module Ibex
233
257
  validate_conflict_entries(conflict, path)
234
258
  end
235
259
 
236
- # @rbs (Hash[String, untyped] conflict, String path) -> void
260
+ # @rbs (json_object conflict, String path) -> void
237
261
  def validate_conflict_entries(conflict, path)
238
262
  if conflict.key?("entries")
239
263
  starts = @data.dig("grammar", "starts") || [@data.dig("grammar", "start")]
@@ -248,14 +272,14 @@ module Ibex
248
272
  boolean(conflict["composite"], "#{path}.composite") if conflict.key?("composite")
249
273
  end
250
274
 
251
- # @rbs (untyped value, String path) -> void
275
+ # @rbs (json_value value, String path) -> void
252
276
  def validate_midrule_origins(value, path)
253
277
  origins = array(value, path)
254
278
  invalid(path, "must not be empty") if origins.empty?
255
279
  origins.each_with_index { |origin, index| location(origin, "#{path}[#{index}]") }
256
280
  end
257
281
 
258
- # @rbs (untyped value, String path) -> void
282
+ # @rbs (json_value value, String path) -> void
259
283
  def validate_conflict_symbol(value, path)
260
284
  name = string(value, path)
261
285
  symbol = @grammar.symbols_by_name[name]
@@ -263,7 +287,7 @@ module Ibex
263
287
  invalid(path, "must reference a terminal") unless symbol["kind"] == "terminal"
264
288
  end
265
289
 
266
- # @rbs (untyped value, String path, ?reductions: Array[Integer]?) -> void
290
+ # @rbs (json_value value, String path, ?reductions: Array[Integer]?) -> void
267
291
  def validate_resolution(value, path, reductions: nil)
268
292
  resolution = record(value, path, %w[by chose], %w[associativity])
269
293
  enum(resolution["by"], "#{path}.by", RESOLUTION_KINDS)
@@ -298,9 +322,14 @@ module Ibex
298
322
  validate_expectation(summary, path)
299
323
  end
300
324
 
301
- # @rbs (Hash[String, untyped] summary, String path) -> void
325
+ # @rbs (json_object summary, String path) -> void
302
326
  def validate_conflict_counts(summary, path)
303
- conflicts = @states_by_id.values.flat_map { |state| state["conflicts"] }
327
+ conflicts = @states_by_id.values.flat_map do |state|
328
+ array(state["conflicts"], "$.states.conflicts").map do |conflict|
329
+ record = conflict #: json_object
330
+ record
331
+ end
332
+ end
304
333
  shift_reduce = conflicts.select { |conflict| conflict["type"] == "shift_reduce" }
305
334
  counts = {
306
335
  "sr" => shift_reduce.count { |conflict| conflict.dig("resolution", "by") == "default_shift" },
@@ -315,9 +344,10 @@ module Ibex
315
344
  end
316
345
  end
317
346
 
318
- # @rbs (Hash[String, untyped] summary, String path) -> void
347
+ # @rbs (json_object summary, String path) -> void
319
348
  def validate_expectation(summary, path)
320
- grammar_expect = @data.fetch("grammar").fetch("expect")
349
+ grammar = @data.fetch("grammar") #: json_object
350
+ grammar_expect = grammar.fetch("expect")
321
351
  unless summary["expected_sr"] == grammar_expect
322
352
  invalid("#{path}.expected_sr", "must equal embedded grammar expect #{grammar_expect}")
323
353
  end
@@ -326,7 +356,7 @@ module Ibex
326
356
  invalid("#{path}.expectation_met", "must be #{expected_met} for the recorded shift/reduce count")
327
357
  end
328
358
 
329
- grammar_expect_rr = @data.fetch("grammar")["expect_rr"]
359
+ grammar_expect_rr = grammar["expect_rr"]
330
360
  return if grammar_expect_rr.nil?
331
361
 
332
362
  unless summary["expected_rr"] == grammar_expect_rr
@@ -3,15 +3,19 @@
3
3
  module Ibex
4
4
  module IR
5
5
  module Validator
6
- # Shared JSON-shape checks for the two version-1 IR documents.
6
+ # @rbs!
7
+ # type json_value = String | Integer | Float | bool | nil | Array[json_value] | Hash[String, json_value]
8
+ # type json_object = Hash[String, json_value]
9
+
10
+ # Shared JSON-shape checks for current IR documents.
7
11
  class Base
8
12
  POSITION = "(ir):1:1"
9
13
 
10
14
  private
11
15
 
12
- # @rbs (untyped value, String path, Array[String] required, ?Array[String] optional) -> Hash[String, untyped]
16
+ # @rbs (json_value value, String path, Array[String] required, ?Array[String] optional) -> json_object
13
17
  def record(value, path, required, optional = [])
14
- object(value, path)
18
+ value = object(value, path)
15
19
  missing = required.reject { |key| value.key?(key) }
16
20
  invalid(path, "is missing required field #{missing.first.inspect}") unless missing.empty?
17
21
  unknown = value.keys - required - optional
@@ -19,97 +23,111 @@ module Ibex
19
23
  value
20
24
  end
21
25
 
22
- # @rbs (untyped value, String path) -> Hash[String, untyped]
26
+ # @rbs (json_value value, String path) -> json_object
23
27
  def object(value, path)
24
- invalid(path, "must be an object") unless value.is_a?(Hash)
25
- value
28
+ if value.is_a?(Hash)
29
+ object = value #: json_object
30
+ return object
31
+ end
32
+
33
+ invalid(path, "must be an object")
26
34
  end
27
35
 
28
- # @rbs (untyped value, String path) -> Array[untyped]
36
+ # @rbs (json_value value, String path) -> Array[json_value]
29
37
  def array(value, path)
30
- invalid(path, "must be an array") unless value.is_a?(Array)
31
- value
38
+ if value.is_a?(Array)
39
+ array = value #: Array[json_value]
40
+ return array
41
+ end
42
+
43
+ invalid(path, "must be an array")
32
44
  end
33
45
 
34
- # @rbs (untyped value, String path) -> String
46
+ # @rbs (json_value value, String path) -> String
35
47
  def string(value, path)
36
- invalid(path, "must be a string") unless value.is_a?(String)
37
- value
48
+ return value if value.is_a?(String)
49
+
50
+ invalid(path, "must be a string")
38
51
  end
39
52
 
40
- # @rbs (untyped value, String path) -> String
53
+ # @rbs (json_value value, String path) -> String
41
54
  def nonempty_string(value, path)
42
- string(value, path)
55
+ value = string(value, path)
43
56
  invalid(path, "must not be empty") if value.empty?
44
57
  value
45
58
  end
46
59
 
47
- # @rbs (untyped value, String path) -> Integer
60
+ # @rbs (json_value value, String path) -> Integer
48
61
  def integer(value, path)
49
- invalid(path, "must be an integer") unless value.is_a?(Integer)
50
- value
62
+ return value if value.is_a?(Integer)
63
+
64
+ invalid(path, "must be an integer")
51
65
  end
52
66
 
53
- # @rbs (untyped value, String path) -> Integer
67
+ # @rbs (json_value value, String path) -> Integer
54
68
  def nonnegative_integer(value, path)
55
- integer(value, path)
69
+ value = integer(value, path)
56
70
  invalid(path, "must be greater than or equal to 0") if value.negative?
57
71
  value
58
72
  end
59
73
 
60
- # @rbs (untyped value, String path) -> bool
74
+ # @rbs (json_value value, String path) -> bool
61
75
  def boolean(value, path)
62
- invalid(path, "must be a boolean") unless [true, false].include?(value)
63
- value
76
+ if [true, false].include?(value)
77
+ result = value #: bool
78
+ return result
79
+ end
80
+
81
+ invalid(path, "must be a boolean")
64
82
  end
65
83
 
66
- # @rbs (untyped value, String path, untyped expected) -> void
84
+ # @rbs (json_value value, String path, json_value expected) -> void
67
85
  def literal(value, path, expected)
68
86
  invalid(path, "must be #{expected.inspect}") unless value == expected
69
87
  end
70
88
 
71
- # @rbs (untyped value, String path, Array[String] values) -> String
89
+ # @rbs (json_value value, String path, Array[String] values) -> String
72
90
  def enum(value, path, values)
73
- string(value, path)
91
+ value = string(value, path)
74
92
  invalid(path, "must be one of #{values.join(', ')}") unless values.include?(value)
75
93
  value
76
94
  end
77
95
 
78
- # @rbs (untyped value, String path, ?nullable: bool) -> void
96
+ # @rbs (json_value value, String path, ?nullable: bool) -> void
79
97
  def location(value, path, nullable: true)
80
98
  return if nullable && value.nil?
81
99
 
82
- record(value, path, %w[file line column])
100
+ value = record(value, path, %w[file line column])
83
101
  string(value["file"], "#{path}.file")
84
102
  positive_integer(value["line"], "#{path}.line")
85
103
  positive_integer(value["column"], "#{path}.column")
86
104
  end
87
105
 
88
- # @rbs (untyped value, String path) -> Integer
106
+ # @rbs (json_value value, String path) -> Integer
89
107
  def positive_integer(value, path)
90
- integer(value, path)
108
+ value = integer(value, path)
91
109
  invalid(path, "must be greater than or equal to 1") unless value.positive?
92
110
  value
93
111
  end
94
112
 
95
- # @rbs (untyped value, String path) -> String?
113
+ # @rbs (json_value value, String path) -> String?
96
114
  def nullable_string(value, path)
97
115
  return nil if value.nil?
98
116
 
99
117
  string(value, path)
100
118
  end
101
119
 
102
- # @rbs (untyped value, String path) -> void
120
+ # @rbs (json_value value, String path) -> void
103
121
  def metadata(value, path)
104
122
  return if value.nil?
105
123
 
106
- string(value, path)
124
+ value = string(value, path)
107
125
  invalid(path, "must not be empty") if value.strip.empty?
108
126
  invalid(path, "must be a single line") if value.match?(/[\r\n]/)
109
127
  invalid(path, "must not contain control characters") if value.match?(/[[:cntrl:]]/)
110
128
  end
111
129
 
112
- # @rbs (Hash[String, untyped] value, String key, String path) -> untyped
130
+ # @rbs (json_object value, String key, String path) -> json_value
113
131
  def field(value, key, path)
114
132
  value.fetch(key) { invalid(path, "is missing required field #{key.inspect}") }
115
133
  end