ibex 0.1.0 → 0.2.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 (384) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +247 -104
  3. data/docs/architecture.md +322 -28
  4. data/docs/cst-migration.md +107 -0
  5. data/docs/cst.md +213 -0
  6. data/docs/development.md +129 -0
  7. data/docs/editor-setup.md +25 -0
  8. data/docs/error-ux.md +60 -0
  9. data/docs/grammar-reference.md +458 -18
  10. data/docs/lexer-migration.md +51 -0
  11. data/docs/racc-migration.md +34 -6
  12. data/docs/release-readiness.md +163 -0
  13. data/docs/stability.md +124 -0
  14. data/examples/README.md +60 -0
  15. data/examples/calculator.y +44 -0
  16. data/examples/csv.y +32 -0
  17. data/examples/ini.y +70 -0
  18. data/examples/json.y +48 -0
  19. data/examples/tiny_language.y +75 -0
  20. data/lib/ibex/analysis/sets.rb +5 -4
  21. data/lib/ibex/artifact_set.rb +63 -0
  22. data/lib/ibex/cli/ambiguity.rb +66 -0
  23. data/lib/ibex/cli/counterexample_options.rb +6 -2
  24. data/lib/ibex/cli/coverage.rb +173 -0
  25. data/lib/ibex/cli/debug.rb +106 -0
  26. data/lib/ibex/cli/diagnostics.rb +116 -0
  27. data/lib/ibex/cli/documentation.rb +67 -0
  28. data/lib/ibex/cli/error_messages.rb +177 -0
  29. data/lib/ibex/cli/explain.rb +76 -0
  30. data/lib/ibex/cli/formatting.rb +386 -0
  31. data/lib/ibex/cli/generation_artifacts.rb +138 -0
  32. data/lib/ibex/cli/generation_error_messages.rb +39 -0
  33. data/lib/ibex/cli/grammar_tests.rb +122 -0
  34. data/lib/ibex/cli/ir_tools.rb +184 -0
  35. data/lib/ibex/cli/lsp.rb +33 -0
  36. data/lib/ibex/cli/outputs.rb +91 -8
  37. data/lib/ibex/cli/racc_migration.rb +87 -0
  38. data/lib/ibex/cli/samples.rb +92 -0
  39. data/lib/ibex/cli/watch.rb +103 -0
  40. data/lib/ibex/cli.rb +506 -37
  41. data/lib/ibex/codegen/action_locations.rb +103 -0
  42. data/lib/ibex/codegen/action_method_source.rb +210 -0
  43. data/lib/ibex/codegen/action_source.rb +118 -0
  44. data/lib/ibex/codegen/ambiguity.rb +173 -0
  45. data/lib/ibex/codegen/cst_metadata.rb +171 -0
  46. data/lib/ibex/codegen/documentation.rb +170 -0
  47. data/lib/ibex/codegen/explain.rb +312 -0
  48. data/lib/ibex/codegen/generated_action_abi.rb +288 -0
  49. data/lib/ibex/codegen/html.rb +94 -10
  50. data/lib/ibex/codegen/mermaid.rb +43 -0
  51. data/lib/ibex/codegen/railroad.rb +197 -0
  52. data/lib/ibex/codegen/railroad_documentation.rb +59 -0
  53. data/lib/ibex/codegen/rbs.rb +323 -2
  54. data/lib/ibex/codegen/report.rb +46 -6
  55. data/lib/ibex/codegen/ruby.rb +334 -59
  56. data/lib/ibex/codegen/ruby_actions.rb +143 -0
  57. data/lib/ibex/codegen/ruby_ast.rb +121 -0
  58. data/lib/ibex/codegen/ruby_error_messages.rb +28 -0
  59. data/lib/ibex/codegen/ruby_lexer.rb +83 -0
  60. data/lib/ibex/codegen/ruby_syntax.rb +90 -0
  61. data/lib/ibex/codegen/ruby_table_metadata.rb +57 -0
  62. data/lib/ibex/codegen/ruby_value_printers.rb +56 -0
  63. data/lib/ibex/codegen/symbol_labels.rb +1 -1
  64. data/lib/ibex/coverage/collector.rb +188 -0
  65. data/lib/ibex/coverage/event_stream.rb +97 -0
  66. data/lib/ibex/coverage/report.rb +259 -0
  67. data/lib/ibex/coverage/runtime_event_validator.rb +160 -0
  68. data/lib/ibex/coverage.rb +13 -0
  69. data/lib/ibex/error_messages/parser.rb +159 -0
  70. data/lib/ibex/error_messages/parser_v2.rb +198 -0
  71. data/lib/ibex/error_messages/renderer.rb +65 -0
  72. data/lib/ibex/error_messages/sentence_search.rb +196 -0
  73. data/lib/ibex/error_messages/update.rb +169 -0
  74. data/lib/ibex/error_messages.rb +165 -0
  75. data/lib/ibex/frontend/ast.rb +145 -6
  76. data/lib/ibex/frontend/bootstrap_parser.rb +47 -4
  77. data/lib/ibex/frontend/diagnostic.rb +81 -0
  78. data/lib/ibex/frontend/diagnostic_recovery.rb +268 -0
  79. data/lib/ibex/frontend/dsl.rb +66 -7
  80. data/lib/ibex/frontend/formatter.rb +407 -0
  81. data/lib/ibex/frontend/generated_parser.rb +614 -190
  82. data/lib/ibex/frontend/generated_parser_base.rb +164 -30
  83. data/lib/ibex/frontend/generated_parser_includes.rb +61 -0
  84. data/lib/ibex/frontend/generated_parser_metadata.rb +61 -0
  85. data/lib/ibex/frontend/generated_parser_parameters.rb +60 -0
  86. data/lib/ibex/frontend/generation.rb +33 -0
  87. data/lib/ibex/frontend/lexer.rb +162 -10
  88. data/lib/ibex/frontend/lexer_recovery.rb +84 -0
  89. data/lib/ibex/frontend/parser/declarations.rb +247 -11
  90. data/lib/ibex/frontend/parser/parameters.rb +82 -0
  91. data/lib/ibex/frontend/parser/rules.rb +43 -6
  92. data/lib/ibex/frontend/parser.rb +182 -4
  93. data/lib/ibex/frontend/regenerator.rb +26 -1
  94. data/lib/ibex/frontend/resolution.rb +69 -0
  95. data/lib/ibex/frontend/resolver.rb +217 -0
  96. data/lib/ibex/frontend/rule_documentation.rb +103 -0
  97. data/lib/ibex/frontend/source_cursor.rb +132 -8
  98. data/lib/ibex/frontend/source_document.rb +229 -0
  99. data/lib/ibex/frontend/source_loader.rb +150 -0
  100. data/lib/ibex/frontend/source_span.rb +81 -0
  101. data/lib/ibex/frontend/token_adapter/declaration_document_state.rb +47 -0
  102. data/lib/ibex/frontend/token_adapter/declaration_lexer_state.rb +83 -0
  103. data/lib/ibex/frontend/token_adapter/declaration_state.rb +216 -26
  104. data/lib/ibex/frontend/token_adapter/delimiter_tracker.rb +8 -2
  105. data/lib/ibex/frontend/token_adapter/rule_state.rb +60 -2
  106. data/lib/ibex/frontend/token_adapter.rb +8 -3
  107. data/lib/ibex/frontend.rb +13 -2
  108. data/lib/ibex/generation_input.rb +57 -0
  109. data/lib/ibex/generation_manifest.rb +200 -0
  110. data/lib/ibex/generation_transaction.rb +261 -0
  111. data/lib/ibex/generation_transaction_recovery.rb +109 -0
  112. data/lib/ibex/generation_transaction_validation.rb +196 -0
  113. data/lib/ibex/grammar_tests.rb +206 -0
  114. data/lib/ibex/ir/automaton_ir.rb +38 -5
  115. data/lib/ibex/ir/grammar_ir.rb +137 -24
  116. data/lib/ibex/ir/lexer_ir.rb +76 -0
  117. data/lib/ibex/ir/migration.rb +120 -0
  118. data/lib/ibex/ir/serialize.rb +110 -19
  119. data/lib/ibex/ir/validator/automaton.rb +345 -0
  120. data/lib/ibex/ir/validator/base.rb +129 -0
  121. data/lib/ibex/ir/validator/grammar.rb +604 -0
  122. data/lib/ibex/ir/validator/lexer.rb +113 -0
  123. data/lib/ibex/ir/validator.rb +62 -0
  124. data/lib/ibex/ir.rb +57 -4
  125. data/lib/ibex/lalr/build_metrics.rb +23 -0
  126. data/lib/ibex/lalr/builder.rb +379 -52
  127. data/lib/ibex/lalr/conflict.rb +1 -0
  128. data/lib/ibex/lalr/conflict_search.rb +11 -5
  129. data/lib/ibex/lalr/counterexample.rb +20 -5
  130. data/lib/ibex/lalr/direct_lookaheads.rb +236 -0
  131. data/lib/ibex/lalr/ielr_partition.rb +152 -0
  132. data/lib/ibex/lalr/on_error_reductions.rb +74 -0
  133. data/lib/ibex/lalr.rb +7 -0
  134. data/lib/ibex/location.rb +129 -0
  135. data/lib/ibex/lsp/document_handlers.rb +66 -0
  136. data/lib/ibex/lsp/document_store.rb +264 -0
  137. data/lib/ibex/lsp/document_store_diagnostics.rb +44 -0
  138. data/lib/ibex/lsp/document_store_validation.rb +61 -0
  139. data/lib/ibex/lsp/initialization_handlers.rb +78 -0
  140. data/lib/ibex/lsp/navigation_handlers.rb +56 -0
  141. data/lib/ibex/lsp/position_codec.rb +109 -0
  142. data/lib/ibex/lsp/protocol_error.rb +33 -0
  143. data/lib/ibex/lsp/request_handlers.rb +45 -0
  144. data/lib/ibex/lsp/request_support.rb +87 -0
  145. data/lib/ibex/lsp/server.rb +146 -0
  146. data/lib/ibex/lsp/symbol_index.rb +241 -0
  147. data/lib/ibex/lsp/symbol_index_builder.rb +267 -0
  148. data/lib/ibex/lsp/symbol_index_precedence_references.rb +44 -0
  149. data/lib/ibex/lsp/symbol_index_source_queries.rb +61 -0
  150. data/lib/ibex/lsp/symbol_occurrence.rb +17 -0
  151. data/lib/ibex/lsp/transport.rb +118 -0
  152. data/lib/ibex/lsp/workspace.rb +127 -0
  153. data/lib/ibex/lsp/workspace_analyzer.rb +199 -0
  154. data/lib/ibex/lsp.rb +32 -0
  155. data/lib/ibex/normalize/declarations.rb +140 -7
  156. data/lib/ibex/normalize/diagnostics.rb +50 -5
  157. data/lib/ibex/normalize/expander.rb +59 -55
  158. data/lib/ibex/normalize/expression.rb +60 -39
  159. data/lib/ibex/normalize/inline_expansion.rb +414 -0
  160. data/lib/ibex/normalize/inline_validation.rb +174 -0
  161. data/lib/ibex/normalize/lexer.rb +131 -0
  162. data/lib/ibex/normalize/named_references.rb +60 -0
  163. data/lib/ibex/normalize/nodes.rb +46 -0
  164. data/lib/ibex/normalize/parameter_ebnf_lowering.rb +69 -0
  165. data/lib/ibex/normalize/parameter_lowering.rb +126 -0
  166. data/lib/ibex/normalize/parameter_substitution.rb +125 -0
  167. data/lib/ibex/normalize/parameter_validation.rb +140 -0
  168. data/lib/ibex/normalize/parameters.rb +199 -0
  169. data/lib/ibex/normalize/recovery_declarations.rb +84 -0
  170. data/lib/ibex/normalize.rb +179 -14
  171. data/lib/ibex/racc_migration/checker.rb +122 -0
  172. data/lib/ibex/racc_migration/harness.rb +177 -0
  173. data/lib/ibex/racc_migration/report.rb +94 -0
  174. data/lib/ibex/racc_migration.rb +12 -0
  175. data/lib/ibex/rake_task.rb +116 -0
  176. data/lib/ibex/samples.rb +186 -0
  177. data/lib/ibex/table_simulation/result.rb +51 -0
  178. data/lib/ibex/table_simulation/simulator.rb +253 -0
  179. data/lib/ibex/table_simulation/step.rb +60 -0
  180. data/lib/ibex/table_simulation/text.rb +31 -0
  181. data/lib/ibex/table_simulation.rb +13 -0
  182. data/lib/ibex/tables.rb +9 -70
  183. data/lib/ibex/version.rb +1 -1
  184. data/lib/ibex/watch/runner.rb +172 -0
  185. data/lib/ibex/watch/source_snapshot.rb +93 -0
  186. data/lib/ibex/watch.rb +11 -0
  187. data/lib/ibex.rb +25 -1
  188. data/schema/automaton-ir-v1.schema.json +401 -0
  189. data/schema/automaton-ir-v2.schema.json +58 -0
  190. data/schema/benchmark-v1.schema.json +212 -0
  191. data/schema/benchmark-v2.schema.json +61 -0
  192. data/schema/cst-v1.json +170 -0
  193. data/schema/error-ux-v1.schema.json +258 -0
  194. data/schema/explain-v1.schema.json +433 -0
  195. data/schema/frontend-diagnostics-v1.schema.json +154 -0
  196. data/schema/generation-manifest-v1.schema.json +115 -0
  197. data/schema/grammar-ir-v1.schema.json +426 -0
  198. data/schema/grammar-ir-v2.schema.json +779 -0
  199. data/schema/lexer-ir-v1.schema.json +215 -0
  200. data/schema/migration-check-v1.schema.json +60 -0
  201. data/schema/performance-comparison-v1.schema.json +395 -0
  202. data/schema/public-performance-comparison-v1.schema.json +506 -0
  203. data/schema/public-performance-profile-v1.schema.json +360 -0
  204. data/schema/runtime-coverage-v1.schema.json +86 -0
  205. data/schema/runtime-event-v1.schema.json +308 -0
  206. data/schema/table-simulation-v1.schema.json +70 -0
  207. data/sig/ibex/artifact_set.rbs +37 -0
  208. data/sig/ibex/cli/ambiguity.rbs +22 -0
  209. data/sig/ibex/cli/counterexample_options.rbs +2 -0
  210. data/sig/ibex/cli/coverage.rbs +53 -0
  211. data/sig/ibex/cli/debug.rbs +28 -0
  212. data/sig/ibex/cli/diagnostics.rbs +38 -0
  213. data/sig/ibex/cli/documentation.rbs +25 -0
  214. data/sig/ibex/cli/error_messages.rbs +57 -0
  215. data/sig/ibex/cli/explain.rbs +25 -0
  216. data/sig/ibex/cli/formatting.rbs +103 -0
  217. data/sig/ibex/cli/generation_artifacts.rbs +50 -0
  218. data/sig/ibex/cli/generation_error_messages.rbs +19 -0
  219. data/sig/ibex/cli/grammar_tests.rbs +36 -0
  220. data/sig/ibex/cli/ir_tools.rbs +51 -0
  221. data/sig/ibex/cli/lsp.rbs +14 -0
  222. data/sig/ibex/cli/outputs.rbs +17 -0
  223. data/sig/ibex/cli/racc_migration.rbs +30 -0
  224. data/sig/ibex/cli/samples.rbs +30 -0
  225. data/sig/ibex/cli/watch.rbs +43 -0
  226. data/sig/ibex/cli.rbs +104 -5
  227. data/sig/ibex/codegen/action_locations.rbs +45 -0
  228. data/sig/ibex/codegen/action_method_source.rbs +65 -0
  229. data/sig/ibex/codegen/action_source.rbs +50 -0
  230. data/sig/ibex/codegen/ambiguity.rbs +60 -0
  231. data/sig/ibex/codegen/cst_metadata.rbs +59 -0
  232. data/sig/ibex/codegen/documentation.rbs +50 -0
  233. data/sig/ibex/codegen/explain.rbs +85 -0
  234. data/sig/ibex/codegen/generated_action_abi.rbs +101 -0
  235. data/sig/ibex/codegen/html.rbs +18 -2
  236. data/sig/ibex/codegen/mermaid.rbs +16 -0
  237. data/sig/ibex/codegen/railroad.rbs +82 -0
  238. data/sig/ibex/codegen/railroad_documentation.rbs +31 -0
  239. data/sig/ibex/codegen/rbs.rbs +84 -4
  240. data/sig/ibex/codegen/report.rbs +8 -0
  241. data/sig/ibex/codegen/ruby.rbs +97 -23
  242. data/sig/ibex/codegen/ruby_actions.rbs +54 -0
  243. data/sig/ibex/codegen/ruby_ast.rbs +34 -0
  244. data/sig/ibex/codegen/ruby_error_messages.rbs +16 -0
  245. data/sig/ibex/codegen/ruby_lexer.rbs +25 -0
  246. data/sig/ibex/codegen/ruby_syntax.rbs +25 -0
  247. data/sig/ibex/codegen/ruby_table_metadata.rbs +26 -0
  248. data/sig/ibex/codegen/ruby_value_printers.rbs +28 -0
  249. data/sig/ibex/coverage/collector.rbs +76 -0
  250. data/sig/ibex/coverage/event_stream.rbs +42 -0
  251. data/sig/ibex/coverage/report.rbs +100 -0
  252. data/sig/ibex/coverage/runtime_event_validator.rbs +68 -0
  253. data/sig/ibex/coverage.rbs +7 -0
  254. data/sig/ibex/error_messages/parser.rbs +58 -0
  255. data/sig/ibex/error_messages/parser_v2.rbs +67 -0
  256. data/sig/ibex/error_messages/renderer.rbs +23 -0
  257. data/sig/ibex/error_messages/sentence_search.rbs +80 -0
  258. data/sig/ibex/error_messages/update.rbs +43 -0
  259. data/sig/ibex/error_messages.rbs +85 -0
  260. data/sig/ibex/frontend/ast.rbs +208 -19
  261. data/sig/ibex/frontend/bootstrap_parser.rbs +11 -0
  262. data/sig/ibex/frontend/diagnostic.rbs +53 -0
  263. data/sig/ibex/frontend/diagnostic_recovery.rbs +98 -0
  264. data/sig/ibex/frontend/dsl.rbs +33 -4
  265. data/sig/ibex/frontend/formatter.rbs +135 -0
  266. data/sig/ibex/frontend/generated_parser.rbs +218 -68
  267. data/sig/ibex/frontend/generated_parser_base.rbs +61 -10
  268. data/sig/ibex/frontend/generated_parser_includes.rbs +23 -0
  269. data/sig/ibex/frontend/generated_parser_metadata.rbs +23 -0
  270. data/sig/ibex/frontend/generated_parser_parameters.rbs +24 -0
  271. data/sig/ibex/frontend/generation.rbs +6 -0
  272. data/sig/ibex/frontend/lexer.rbs +49 -2
  273. data/sig/ibex/frontend/lexer_recovery.rbs +25 -0
  274. data/sig/ibex/frontend/parser/declarations.rbs +54 -0
  275. data/sig/ibex/frontend/parser/parameters.rbs +28 -0
  276. data/sig/ibex/frontend/parser/rules.rbs +3 -0
  277. data/sig/ibex/frontend/parser.rbs +66 -0
  278. data/sig/ibex/frontend/regenerator.rbs +11 -0
  279. data/sig/ibex/frontend/resolution.rbs +33 -0
  280. data/sig/ibex/frontend/resolver.rbs +91 -0
  281. data/sig/ibex/frontend/rule_documentation.rbs +42 -0
  282. data/sig/ibex/frontend/source_cursor.rbs +36 -3
  283. data/sig/ibex/frontend/source_document.rbs +119 -0
  284. data/sig/ibex/frontend/source_loader.rbs +66 -0
  285. data/sig/ibex/frontend/source_span.rbs +53 -0
  286. data/sig/ibex/frontend/token_adapter/declaration_document_state.rbs +21 -0
  287. data/sig/ibex/frontend/token_adapter/declaration_lexer_state.rbs +27 -0
  288. data/sig/ibex/frontend/token_adapter/declaration_state.rbs +73 -5
  289. data/sig/ibex/frontend/token_adapter/rule_state.rbs +20 -0
  290. data/sig/ibex/frontend/token_adapter.rbs +5 -2
  291. data/sig/ibex/frontend.rbs +1 -1
  292. data/sig/ibex/generation_input.rbs +37 -0
  293. data/sig/ibex/generation_manifest.rbs +67 -0
  294. data/sig/ibex/generation_transaction.rbs +82 -0
  295. data/sig/ibex/generation_transaction_recovery.rbs +36 -0
  296. data/sig/ibex/generation_transaction_validation.rbs +65 -0
  297. data/sig/ibex/grammar_tests.rbs +93 -0
  298. data/sig/ibex/ir/automaton_ir.rbs +8 -2
  299. data/sig/ibex/ir/grammar_ir.rbs +75 -15
  300. data/sig/ibex/ir/lexer_ir.rbs +57 -0
  301. data/sig/ibex/ir/migration.rbs +34 -0
  302. data/sig/ibex/ir/serialize.rbs +23 -6
  303. data/sig/ibex/ir/validator/automaton.rbs +109 -0
  304. data/sig/ibex/ir/validator/base.rbs +65 -0
  305. data/sig/ibex/ir/validator/grammar.rbs +184 -0
  306. data/sig/ibex/ir/validator/lexer.rbs +37 -0
  307. data/sig/ibex/ir/validator.rbs +16 -0
  308. data/sig/ibex/ir.rbs +38 -4
  309. data/sig/ibex/lalr/build_metrics.rbs +20 -0
  310. data/sig/ibex/lalr/builder.rbs +95 -15
  311. data/sig/ibex/lalr/conflict_search.rbs +7 -3
  312. data/sig/ibex/lalr/counterexample.rbs +5 -2
  313. data/sig/ibex/lalr/direct_lookaheads.rbs +86 -0
  314. data/sig/ibex/lalr/ielr_partition.rbs +59 -0
  315. data/sig/ibex/lalr/on_error_reductions.rbs +22 -0
  316. data/sig/ibex/lalr.rbs +6 -0
  317. data/sig/ibex/location.rbs +67 -0
  318. data/sig/ibex/lsp/document_handlers.rbs +24 -0
  319. data/sig/ibex/lsp/document_store.rbs +94 -0
  320. data/sig/ibex/lsp/document_store_diagnostics.rbs +20 -0
  321. data/sig/ibex/lsp/document_store_validation.rbs +26 -0
  322. data/sig/ibex/lsp/initialization_handlers.rbs +30 -0
  323. data/sig/ibex/lsp/navigation_handlers.rbs +30 -0
  324. data/sig/ibex/lsp/position_codec.rbs +40 -0
  325. data/sig/ibex/lsp/protocol_error.rbs +32 -0
  326. data/sig/ibex/lsp/request_handlers.rbs +26 -0
  327. data/sig/ibex/lsp/request_support.rbs +40 -0
  328. data/sig/ibex/lsp/server.rbs +55 -0
  329. data/sig/ibex/lsp/symbol_index.rbs +78 -0
  330. data/sig/ibex/lsp/symbol_index_builder.rbs +87 -0
  331. data/sig/ibex/lsp/symbol_index_precedence_references.rbs +18 -0
  332. data/sig/ibex/lsp/symbol_index_source_queries.rbs +26 -0
  333. data/sig/ibex/lsp/symbol_occurrence.rbs +25 -0
  334. data/sig/ibex/lsp/transport.rbs +35 -0
  335. data/sig/ibex/lsp/workspace.rbs +41 -0
  336. data/sig/ibex/lsp/workspace_analyzer.rbs +69 -0
  337. data/sig/ibex/lsp.rbs +7 -0
  338. data/sig/ibex/normalize/declarations.rbs +31 -0
  339. data/sig/ibex/normalize/diagnostics.rbs +9 -0
  340. data/sig/ibex/normalize/expander.rbs +20 -14
  341. data/sig/ibex/normalize/expression.rbs +10 -10
  342. data/sig/ibex/normalize/inline_expansion.rbs +120 -0
  343. data/sig/ibex/normalize/inline_validation.rbs +40 -0
  344. data/sig/ibex/normalize/lexer.rbs +37 -0
  345. data/sig/ibex/normalize/named_references.rbs +20 -0
  346. data/sig/ibex/normalize/nodes.rbs +14 -0
  347. data/sig/ibex/normalize/parameter_ebnf_lowering.rbs +32 -0
  348. data/sig/ibex/normalize/parameter_lowering.rbs +35 -0
  349. data/sig/ibex/normalize/parameter_substitution.rbs +42 -0
  350. data/sig/ibex/normalize/parameter_validation.rbs +44 -0
  351. data/sig/ibex/normalize/parameters.rbs +46 -0
  352. data/sig/ibex/normalize/recovery_declarations.rbs +24 -0
  353. data/sig/ibex/normalize.rbs +123 -18
  354. data/sig/ibex/racc_migration/checker.rbs +36 -0
  355. data/sig/ibex/racc_migration/harness.rbs +16 -0
  356. data/sig/ibex/racc_migration/report.rbs +53 -0
  357. data/sig/ibex/racc_migration.rbs +8 -0
  358. data/sig/ibex/rake_task.rbs +51 -0
  359. data/sig/ibex/samples.rbs +51 -0
  360. data/sig/ibex/table_simulation/result.rbs +32 -0
  361. data/sig/ibex/table_simulation/simulator.rbs +98 -0
  362. data/sig/ibex/table_simulation/step.rbs +40 -0
  363. data/sig/ibex/table_simulation/text.rbs +14 -0
  364. data/sig/ibex/table_simulation.rbs +7 -0
  365. data/sig/ibex/tables.rbs +0 -26
  366. data/sig/ibex/watch/runner.rbs +48 -0
  367. data/sig/ibex/watch/source_snapshot.rbs +42 -0
  368. data/sig/ibex/watch.rbs +7 -0
  369. data/sig/ibex.rbs +2 -0
  370. metadata +301 -16
  371. data/.rubocop.yml +0 -43
  372. data/CHANGELOG.md +0 -30
  373. data/Rakefile +0 -25
  374. data/Steepfile +0 -10
  375. data/docs/compat-notes.md +0 -37
  376. data/docs/lexer-coverage.md +0 -14
  377. data/docs/phase10-extensions.md +0 -27
  378. data/gemfiles/Gemfile +0 -7
  379. data/gemfiles/Gemfile.lock +0 -98
  380. data/lib/ibex/frontend/grammar.y +0 -156
  381. data/lib/ibex/runtime/parser.rb +0 -360
  382. data/lib/ibex/runtime.rb +0 -8
  383. data/sig/ibex/runtime/parser.rbs +0 -167
  384. data/sig/ibex/runtime.rbs +0 -6
@@ -0,0 +1,196 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../lalr/conflict_search_limits"
4
+
5
+ module Ibex
6
+ module ErrorMessages
7
+ # Finds deterministic shortest token sentences that reach each syntax
8
+ # error state without running semantic actions.
9
+ class SentenceSearch
10
+ DEFAULT_MAX_TOKENS = LALR::ConflictSearchLimits::DEFAULT_MAX_TOKENS #: Integer
11
+ DEFAULT_MAX_CONFIGURATIONS = LALR::ConflictSearchLimits::DEFAULT_MAX_CONFIGURATIONS #: Integer
12
+
13
+ Witness = Struct.new(
14
+ :entry, #: String
15
+ :tokens, #: Array[String]
16
+ :state, #: Integer
17
+ keyword_init: true
18
+ )
19
+
20
+ # @rbs @automaton: IR::Automaton
21
+ # @rbs @grammar: IR::Grammar
22
+ # @rbs @max_tokens: Integer
23
+ # @rbs @max_configurations: Integer
24
+ # @rbs @candidates: Array[IR::GrammarSymbol]
25
+ # @rbs @input_candidates: Array[IR::GrammarSymbol]
26
+ # @rbs @explored: Integer
27
+
28
+ # @rbs (IR::Automaton automaton, ?max_tokens: Integer, ?max_configurations: Integer) -> void
29
+ def initialize(automaton, max_tokens: DEFAULT_MAX_TOKENS,
30
+ max_configurations: DEFAULT_MAX_CONFIGURATIONS)
31
+ LALR::ConflictSearchLimits.validate!(
32
+ max_tokens: max_tokens, max_configurations: max_configurations
33
+ )
34
+ @automaton = automaton
35
+ @grammar = automaton.grammar
36
+ @max_tokens = max_tokens
37
+ @max_configurations = max_configurations
38
+ @candidates = grammar_terminals
39
+ @input_candidates = @candidates.reject { |symbol| symbol.id.zero? }
40
+ @explored = 0
41
+ end
42
+
43
+ # @rbs () -> Hash[Integer, Witness]
44
+ def all
45
+ targets = ErrorMessages.error_states(@automaton).to_h { |state| [state.id, true] }
46
+ witnesses = {} #: Hash[Integer, Witness]
47
+ @automaton.entry_states.each do |entry, initial_state|
48
+ search_entry(entry, initial_state, targets, witnesses)
49
+ break if witnesses.length == targets.length
50
+ end
51
+ witnesses.sort.to_h.freeze
52
+ end
53
+
54
+ # @rbs (Array[String] tokens, ?entry: String?) -> Integer?
55
+ def state_for(tokens, entry: nil)
56
+ return nil if tokens.empty?
57
+
58
+ start = entry || @grammar.start
59
+ initial = @automaton.entry_states[start]
60
+ return nil unless initial
61
+
62
+ states = [initial]
63
+ tokens.each_with_index do |name, index|
64
+ status, value = consume_sentence_token(states, name, index == tokens.length - 1)
65
+ return value if status == :error && value.is_a?(Integer)
66
+ return nil unless status == :continue && value.is_a?(Array)
67
+
68
+ states = value
69
+ end
70
+ nil
71
+ end
72
+
73
+ private
74
+
75
+ # @rbs (Array[Integer] states, String name, bool final) ->
76
+ # [Symbol, Array[Integer] | Integer | nil]
77
+ def consume_sentence_token(states, name, final)
78
+ symbol = sentence_symbol(name, final)
79
+ return [:invalid, nil] unless symbol
80
+
81
+ status, value = advance(states, symbol.id)
82
+ return [:error, value] if status == :error && final && value.is_a?(Integer)
83
+ return [:continue, value] if status == :shift && value.is_a?(Array)
84
+
85
+ [:invalid, nil]
86
+ end
87
+
88
+ # @rbs (String name, bool final) -> IR::GrammarSymbol?
89
+ def sentence_symbol(name, final)
90
+ symbol = @grammar.symbol(name)
91
+ return nil unless symbol&.terminal?
92
+ return nil if symbol.name == "error" || (symbol.id.zero? && !final)
93
+
94
+ symbol
95
+ end
96
+
97
+ # @rbs () -> Array[IR::GrammarSymbol]
98
+ def grammar_terminals
99
+ @grammar.terminals
100
+ .reject { |symbol| symbol.name == "error" }
101
+ .sort_by { |symbol| [symbol.id.zero? ? 1 : 0, symbol.name] }
102
+ end
103
+
104
+ # @rbs (String entry, Integer initial_state, Hash[Integer, bool] targets,
105
+ # Hash[Integer, Witness] witnesses) -> void
106
+ def search_entry(entry, initial_state, targets, witnesses)
107
+ queue = [[[initial_state], Array.new(0)]] #: Array[[Array[Integer], Array[String]]]
108
+ visited = { [initial_state] => true }
109
+ until queue.empty? || witnesses.length == targets.length
110
+ states, prefix = queue.shift
111
+ count_configuration!
112
+ collect_errors(entry, states, prefix, targets, witnesses)
113
+ enqueue_shifts(queue, visited, states, prefix) if prefix.length < @max_tokens - 1
114
+ end
115
+ end
116
+
117
+ # @rbs (String entry, Array[Integer] states, Array[String] prefix, Hash[Integer, bool] targets,
118
+ # Hash[Integer, Witness] witnesses) -> void
119
+ def collect_errors(entry, states, prefix, targets, witnesses)
120
+ @candidates.each do |symbol|
121
+ status, state = advance(states, symbol.id)
122
+ next unless status == :error && state.is_a?(Integer)
123
+
124
+ error_state = state #: Integer
125
+ next unless targets[error_state] && !witnesses[error_state]
126
+
127
+ witnesses[error_state] = Witness.new(
128
+ entry: entry, tokens: (prefix + [symbol.name]).freeze, state: error_state
129
+ ).freeze
130
+ end
131
+ end
132
+
133
+ # @rbs (Array[[Array[Integer], Array[String]]] queue, Hash[Array[Integer], bool] visited,
134
+ # Array[Integer] states, Array[String] prefix) -> void
135
+ def enqueue_shifts(queue, visited, states, prefix)
136
+ @input_candidates.each do |symbol|
137
+ status, shifted = advance(states, symbol.id)
138
+ next unless status == :shift && shifted.is_a?(Array)
139
+
140
+ shifted_states = shifted #: Array[Integer]
141
+ next if visited[shifted_states]
142
+
143
+ visited[shifted_states] = true
144
+ queue << [shifted_states, prefix + [symbol.name]]
145
+ end
146
+ end
147
+
148
+ # @rbs (Array[Integer] initial, Integer token_id) -> [Symbol, Array[Integer] | Integer | nil]
149
+ def advance(initial, token_id)
150
+ states = initial
151
+ visited = {} #: Hash[Array[Integer], bool]
152
+ loop do
153
+ return [:invalid, nil] if visited[states]
154
+
155
+ visited[states] = true
156
+ state = @automaton.states.fetch(states.last)
157
+ action = state.actions[token_id] || state.default_action
158
+ return [:error, state.id] if action.nil? || action[:type] == :error
159
+
160
+ case action[:type]
161
+ when :shift
162
+ shift = action #: IR::shift_action
163
+ return [:shift, (states + [shift[:state]]).freeze]
164
+ when :reduce
165
+ reduce = action #: IR::reduce_action
166
+ states = reduce_stack(states, reduce[:production])
167
+ return [:invalid, nil] unless states
168
+ when :accept
169
+ return [:accept, nil]
170
+ else
171
+ return [:invalid, nil]
172
+ end
173
+ end
174
+ end
175
+
176
+ # @rbs (Array[Integer] states, Integer production_id) -> Array[Integer]?
177
+ def reduce_stack(states, production_id)
178
+ production = @grammar.productions.fetch(production_id)
179
+ return nil if production.rhs.length >= states.length
180
+
181
+ remaining = states.take(states.length - production.rhs.length)
182
+ target = @automaton.states.fetch(remaining.last).gotos[production.lhs]
183
+ target && (remaining + [target]).freeze
184
+ end
185
+
186
+ # @rbs () -> void
187
+ def count_configuration!
188
+ @explored += 1
189
+ return if @explored <= @max_configurations
190
+
191
+ raise Ibex::Error,
192
+ "(messages):1:1: error-sentence search exceeded #{@max_configurations} configurations"
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "renderer"
4
+
5
+ module Ibex
6
+ module ErrorMessages
7
+ # @rbs (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer,
8
+ # ?max_configurations: Integer) -> String
9
+ def render(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS,
10
+ max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS)
11
+ update(
12
+ automaton, existing: existing, max_tokens: max_tokens, max_configurations: max_configurations
13
+ ).source
14
+ end
15
+ module_function :render
16
+
17
+ # @rbs (IR::Automaton automaton, ?existing: Document?, ?max_tokens: Integer,
18
+ # ?max_configurations: Integer) -> Update
19
+ def update(automaton, existing: nil, max_tokens: SentenceSearch::DEFAULT_MAX_TOKENS,
20
+ max_configurations: SentenceSearch::DEFAULT_MAX_CONFIGURATIONS)
21
+ document = existing || Document.new(entries: [])
22
+ search = SentenceSearch.new(
23
+ automaton, max_tokens: max_tokens, max_configurations: max_configurations
24
+ )
25
+ witnesses = search.all
26
+ classifications = { uncovered: [], unreachable: [], moved: [] } #: Hash[Symbol, Array[String]]
27
+ next_id = next_error_id(document)
28
+ entries, covered, next_id = update_existing_entries(
29
+ document, search, witnesses, classifications, next_id
30
+ )
31
+ add_uncovered_entries(entries, covered, witnesses, classifications[:uncovered], next_id)
32
+ entries.sort_by! { |entry| entry_sort_key(entry) }
33
+ Update.new(
34
+ source: render_entries(automaton, entries),
35
+ uncovered: classifications[:uncovered],
36
+ unreachable: classifications[:unreachable],
37
+ moved: classifications[:moved]
38
+ )
39
+ end
40
+ module_function :update
41
+
42
+ # @rbs (Array[Entry] entries, Hash[Integer, bool] covered,
43
+ # Hash[Integer, SentenceSearch::Witness] witnesses, Array[String] uncovered, Integer next_id) -> void
44
+ def add_uncovered_entries(entries, covered, witnesses, uncovered, next_id)
45
+ witnesses.each do |state, witness|
46
+ next if covered[state]
47
+
48
+ error_id = format_error_id(next_id)
49
+ next_id += 1
50
+ entries << Entry.new(
51
+ state: state, status: :active, message: nil, line: 1,
52
+ sentence: witness.tokens, error_id: error_id, entry: witness.entry
53
+ )
54
+ uncovered << "#{error_id} state #{state}: #{witness.tokens.join(' ')}"
55
+ end
56
+ end
57
+
58
+ # @rbs (Document document, SentenceSearch search, Hash[Integer, SentenceSearch::Witness] witnesses,
59
+ # Hash[Symbol, Array[String]] classifications, Integer next_id) ->
60
+ # [Array[Entry], Hash[Integer, bool], Integer]
61
+ def update_existing_entries(document, search, witnesses, classifications, next_id)
62
+ return migrate_legacy_entries(document, witnesses, classifications, next_id) if document.version == 1
63
+
64
+ entries = [] #: Array[Entry]
65
+ covered = {} #: Hash[Integer, bool]
66
+ document.entries.each do |entry|
67
+ if entry.sentence
68
+ next_id = update_sentence_entry(
69
+ entry, search, entries, covered, classifications, next_id
70
+ )
71
+ else
72
+ entries << with_error_id(entry, next_id)
73
+ next_id += 1 unless entry.error_id
74
+ end
75
+ end
76
+ [entries, covered, next_id]
77
+ end
78
+
79
+ # @rbs (Entry entry, SentenceSearch search, Array[Entry] entries, Hash[Integer, bool] covered,
80
+ # Hash[Symbol, Array[String]] classifications, Integer next_id) -> Integer
81
+ def update_sentence_entry(entry, search, entries, covered, classifications, next_id)
82
+ error_id = entry.error_id || format_error_id(next_id)
83
+ next_id += 1 unless entry.error_id
84
+ sentence = entry.sentence || raise(Ibex::Error, "missing error sentence")
85
+ state = search.state_for(sentence, entry: entry.entry)
86
+ unless state
87
+ entries << Entry.new(
88
+ state: entry.state, status: :unreachable, message: entry.message, line: entry.line,
89
+ sentence: sentence, error_id: error_id, entry: entry.entry
90
+ )
91
+ classifications[:unreachable] << "#{error_id}: #{sentence.join(' ')}"
92
+ return next_id
93
+ end
94
+
95
+ classifications[:moved] << "#{error_id}: state #{entry.state} -> #{state}" if entry.state && entry.state != state
96
+ covered[state] = true
97
+ entries << Entry.new(
98
+ state: state, status: :active, message: entry.message, line: entry.line,
99
+ sentence: sentence, error_id: error_id, entry: entry.entry
100
+ )
101
+ next_id
102
+ end
103
+
104
+ # @rbs (Document document, Hash[Integer, SentenceSearch::Witness] witnesses,
105
+ # Hash[Symbol, Array[String]] classifications, Integer next_id) ->
106
+ # [Array[Entry], Hash[Integer, bool], Integer]
107
+ def migrate_legacy_entries(document, witnesses, classifications, next_id)
108
+ by_state = document.entries.to_h { |entry| [entry.state, entry] }
109
+ entries = [] #: Array[Entry]
110
+ covered = {} #: Hash[Integer, bool]
111
+ witnesses.each do |state, witness|
112
+ previous = by_state.delete(state)
113
+ error_id = format_error_id(next_id)
114
+ next_id += 1
115
+ entries << Entry.new(
116
+ state: state, status: :active, message: previous&.message, line: previous&.line || 1,
117
+ sentence: witness.tokens, error_id: error_id, entry: witness.entry
118
+ )
119
+ covered[state] = true
120
+ classifications[:uncovered] << "#{error_id} state #{state}: #{witness.tokens.join(' ')}" unless previous
121
+ end
122
+ by_state.values.sort_by { |entry| entry.state || -1 }.each do |entry|
123
+ error_id = format_error_id(next_id)
124
+ next_id += 1
125
+ entries << Entry.new(
126
+ state: entry.state, status: :removed, message: entry.message, line: entry.line, error_id: error_id
127
+ )
128
+ classifications[:unreachable] << "#{error_id}: legacy state #{entry.state}"
129
+ end
130
+ [entries, covered, next_id]
131
+ end
132
+
133
+ # @rbs (Entry entry, Integer next_id) -> Entry
134
+ def with_error_id(entry, next_id)
135
+ Entry.new(
136
+ state: entry.state, status: entry.status, message: entry.message, line: entry.line,
137
+ sentence: entry.sentence, error_id: entry.error_id || format_error_id(next_id), entry: entry.entry
138
+ )
139
+ end
140
+
141
+ # @rbs (Document document) -> Integer
142
+ def next_error_id(document)
143
+ maximum = document.entries.filter_map do |entry|
144
+ match = entry.error_id&.match(/\AE([0-9]{4,})\z/)
145
+ match && Integer(match[1] || "0", 10)
146
+ end.max
147
+ (maximum || 0) + 1
148
+ end
149
+
150
+ # @rbs (Integer number) -> String
151
+ def format_error_id(number)
152
+ format("E%04d", number)
153
+ end
154
+
155
+ # @rbs (Entry entry) -> [Integer, Integer, String]
156
+ def entry_sort_key(entry)
157
+ rank = { active: 0, unreachable: 1, removed: 2 }.fetch(entry.status)
158
+ [rank, entry.state || (1 << 62), entry.error_id || ""]
159
+ end
160
+
161
+ module_function :add_uncovered_entries, :update_existing_entries, :update_sentence_entry, :migrate_legacy_entries,
162
+ :with_error_id, :next_error_id, :format_error_id, :entry_sort_key
163
+
164
+ class << self
165
+ private :add_uncovered_entries, :update_existing_entries, :update_sentence_entry, :migrate_legacy_entries,
166
+ :with_error_id, :next_error_id, :format_error_id, :entry_sort_key
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ require_relative "error"
5
+
6
+ module Ibex
7
+ # Parses, validates, and deterministically updates example-keyed syntax
8
+ # error messages.
9
+ module ErrorMessages
10
+ HEADER_V1 = "# ibex-messages v1"
11
+ HEADER = "# ibex-messages v2"
12
+
13
+ # One active or archived error-sentence entry with its source line.
14
+ class Entry
15
+ attr_reader :state #: Integer?
16
+ attr_reader :status #: :active | :unreachable | :removed
17
+ attr_reader :message #: String?
18
+ attr_reader :line #: Integer
19
+ attr_reader :sentence #: Array[String]?
20
+ attr_reader :error_id #: String?
21
+ attr_reader :entry #: String?
22
+
23
+ # @rbs (state: Integer?, status: :active | :unreachable | :removed, message: String?, line: Integer,
24
+ # ?sentence: Array[String]?, ?error_id: String?, ?entry: String?) -> void
25
+ def initialize(state:, status:, message:, line:, sentence: nil, error_id: nil, entry: nil)
26
+ @state = state
27
+ @status = status
28
+ @message = message&.freeze
29
+ @line = line
30
+ @sentence = sentence&.dup&.freeze
31
+ @error_id = error_id&.freeze
32
+ @entry = entry&.freeze
33
+ freeze
34
+ end
35
+ end
36
+
37
+ # Immutable parsed messages document.
38
+ class Document
39
+ attr_reader :version #: Integer
40
+ attr_reader :entries #: Array[Entry]
41
+
42
+ # @rbs (entries: Array[Entry], ?version: Integer) -> void
43
+ def initialize(entries:, version: 2)
44
+ @version = version
45
+ @entries = entries.freeze
46
+ freeze
47
+ end
48
+ end
49
+
50
+ # Deterministic update output and review classifications.
51
+ class Update
52
+ attr_reader :source #: String
53
+ attr_reader :uncovered #: Array[String]
54
+ attr_reader :unreachable #: Array[String]
55
+ attr_reader :moved #: Array[String]
56
+
57
+ # @rbs (source: String, uncovered: Array[String], unreachable: Array[String], moved: Array[String]) -> void
58
+ def initialize(source:, uncovered:, unreachable:, moved:)
59
+ @source = source.freeze
60
+ @uncovered = uncovered.freeze
61
+ @unreachable = unreachable.freeze
62
+ @moved = moved.freeze
63
+ freeze
64
+ end
65
+ end
66
+
67
+ require_relative "error_messages/parser"
68
+ require_relative "error_messages/sentence_search"
69
+
70
+ # @rbs (String source, file: String) -> Document
71
+ def parse(source, file:)
72
+ Parser.new(source, file: file).parse
73
+ end
74
+ module_function :parse
75
+
76
+ # @rbs (String path) -> Document
77
+ def load(path)
78
+ parse(File.binread(path), file: path)
79
+ end
80
+ module_function :load
81
+
82
+ # @rbs (IR::Automaton automaton) -> Array[IR::AutomatonState]
83
+ def error_states(automaton)
84
+ terminals = ordinary_terminals(automaton)
85
+ automaton.states.select do |state|
86
+ terminals.any? { |terminal| error_action?(state.actions[terminal.id] || state.default_action) }
87
+ end.sort_by(&:id)
88
+ end
89
+ module_function :error_states
90
+
91
+ # @rbs (Document document, IR::Automaton automaton, file: String) -> Hash[Integer, String]
92
+ def messages_for(document, automaton, file:)
93
+ records_for(document, automaton, file: file).transform_values { |record| record.fetch(:message) }.freeze
94
+ end
95
+ module_function :messages_for
96
+
97
+ # @rbs (Document document, IR::Automaton automaton, file: String) ->
98
+ # Hash[Integer, { id: String, message: String }]
99
+ def records_for(document, automaton, file:)
100
+ return legacy_records_for(document, automaton, file: file) if document.version == 1
101
+
102
+ search = SentenceSearch.new(automaton)
103
+ records = {} #: Hash[Integer, { id: String, message: String }]
104
+ document.entries.each do |entry|
105
+ next unless entry.status == :active && entry.message
106
+
107
+ sentence = entry.sentence || raise(Ibex::Error, "missing active error sentence")
108
+ state = search.state_for(sentence, entry: entry.entry)
109
+ unless state
110
+ fail_at(file, entry.line, 1,
111
+ "error sentence no longer reaches a syntax error; run `ibex errors --update`")
112
+ end
113
+ if records[state]
114
+ fail_at(file, entry.line, 1,
115
+ "multiple messages reach error state #{state}; run `ibex errors --update`")
116
+ end
117
+
118
+ error_id = entry.error_id || raise(Ibex::Error, "missing error id")
119
+ records[state] = { id: error_id, message: entry.message }
120
+ end
121
+ records.sort.to_h.freeze
122
+ end
123
+ module_function :records_for
124
+
125
+ # @rbs (Document document, IR::Automaton automaton, file: String) ->
126
+ # Hash[Integer, { id: String, message: String }]
127
+ def legacy_records_for(document, automaton, file:)
128
+ valid = error_states(automaton).to_h { |state| [state.id, true] }
129
+ records = {} #: Hash[Integer, { id: String, message: String }]
130
+ document.entries.each do |entry|
131
+ next if entry.status == :removed || !entry.message
132
+
133
+ state = entry.state || raise(Ibex::Error, "missing legacy error state")
134
+ unless valid[state]
135
+ fail_at(file, entry.line, 1,
136
+ "unknown error state #{state} for current automaton; run `ibex errors --update`")
137
+ end
138
+ records[state] = { id: format_error_id(state + 1), message: entry.message }
139
+ end
140
+ records.sort.to_h.freeze
141
+ end
142
+
143
+ # @rbs (IR::Automaton automaton) -> Array[IR::GrammarSymbol]
144
+ def ordinary_terminals(automaton)
145
+ automaton.grammar.terminals.reject { |terminal| terminal.name == "error" }
146
+ end
147
+
148
+ # @rbs (IR::parser_action? action) -> bool
149
+ def error_action?(action)
150
+ action.nil? || action[:type].to_sym == :error
151
+ end
152
+
153
+ # @rbs (String file, Integer line, Integer column, String message) -> bot
154
+ def fail_at(file, line, column, message)
155
+ raise Ibex::Error, "#{file}:#{line}:#{column}: #{message}"
156
+ end
157
+ module_function :legacy_records_for, :ordinary_terminals, :error_action?, :fail_at
158
+
159
+ class << self
160
+ private :legacy_records_for, :ordinary_terminals, :error_action?, :fail_at
161
+ end
162
+ end
163
+ end
164
+
165
+ require_relative "error_messages/update"