expressir 1.2.11-aarch64-linux → 2.4.29-aarch64-linux

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 (467) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config.toml +3 -0
  3. data/.github/scripts/test_installed_gem.rb +34 -0
  4. data/.github/workflows/codeql.yml +35 -0
  5. data/.github/workflows/docs.yml +99 -0
  6. data/.github/workflows/links.yml +100 -0
  7. data/.github/workflows/native-gems.yml +201 -0
  8. data/.github/workflows/rake.yml +10 -296
  9. data/.github/workflows/release.yml +26 -114
  10. data/.github/workflows/rust-ext.yml +41 -0
  11. data/.github/workflows/stress.yml +36 -0
  12. data/.github/workflows/validate_schemas.yml +48 -0
  13. data/.github/workflows/verify_remarks.yml +33 -0
  14. data/.gitignore +33 -1
  15. data/.rubocop.yml +11 -11
  16. data/.rubocop_todo.yml +297 -0
  17. data/CHANGELOG.md +159 -0
  18. data/Gemfile +15 -1
  19. data/README.adoc +2675 -47
  20. data/Rakefile +34 -10
  21. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  22. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  23. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  24. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  25. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  26. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  27. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  28. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  29. data/TODO.bugs/09-parser-split.md +53 -0
  30. data/TODO.bugs/10-to-s-override.md +42 -0
  31. data/TODO.bugs/11-parser-class-variables.md +39 -0
  32. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  33. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  34. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  35. data/TODO.bugs/15-expression-children-macro.md +27 -0
  36. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  37. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  38. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  39. data/TODO.bugs/19-format-methods-public.md +22 -0
  40. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  41. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  42. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  43. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  44. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  45. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  46. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  47. data/TODO.bugs/27-package-build-god-method.md +19 -0
  48. data/TODO.bugs/28-package-god-class.md +30 -0
  49. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  50. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  51. data/TODO.bugs/README.md +43 -0
  52. data/TODO.max-perf/01-restore-ci-green.md +36 -0
  53. data/TODO.max-perf/02-streaming-parse-path.md +31 -0
  54. data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
  55. data/TODO.max-perf/04-benchmark-harness.md +28 -0
  56. data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
  57. data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
  58. data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
  59. data/TODO.max-perf/08-builder-build-perf.md +45 -0
  60. data/TODO.max-perf/09-grammar-cold-start.md +25 -0
  61. data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
  62. data/TODO.max-perf/11-ci-green-closeout.md +25 -0
  63. data/TODO.max-perf/12-require-boot-profile.md +25 -0
  64. data/TODO.max-perf/13-key-conversion-specs.md +26 -0
  65. data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
  66. data/TODO.parity-ee/00-overview.md +76 -0
  67. data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
  68. data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
  69. data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
  70. data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
  71. data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
  72. data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
  73. data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
  74. data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
  75. data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
  76. data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
  77. data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
  78. data/TODO.parity-ee/12-full-check-catalog.md +67 -0
  79. data/TODO.parity-ee/13-population-p21.md +54 -0
  80. data/TODO.parity-ee/14-shtolo-completion.md +44 -0
  81. data/TODO.parity-ee/15-part28-xml.md +51 -0
  82. data/TODO.parity-ee/16-compare-patch.md +48 -0
  83. data/TODO.parity-ee/17-official-tests.md +42 -0
  84. data/TODO.parity-ee/18-mim-mapping.md +47 -0
  85. data/TODO.parity-ee/19-architecture.md +97 -0
  86. data/TODO.parity-ee/parity-matrix.md +108 -0
  87. data/TODO.refpath-v2/00-overview.md +64 -0
  88. data/TODO.suma-improvements/00-overview.md +23 -0
  89. data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
  90. data/TODO.suma-improvements/02-suma-e2e.md +39 -0
  91. data/TODO.suma-improvements/03-item-graph.md +22 -0
  92. data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
  93. data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
  94. data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
  95. data/TODO.suma-improvements/07-part28-xml.md +15 -0
  96. data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
  97. data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
  98. data/TODO.suma-improvements/10-expressdoc.md +8 -0
  99. data/benchmark/srl_benchmark.rb +458 -0
  100. data/benchmark/srl_native_benchmark.rb +146 -0
  101. data/benchmark/srl_ruby_benchmark.rb +132 -0
  102. data/bin/rspec +2 -1
  103. data/docs/Gemfile +12 -0
  104. data/docs/_config.yml +141 -0
  105. data/docs/_guides/changes/changes-format.adoc +778 -0
  106. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  107. data/docs/_guides/changes/index.adoc +396 -0
  108. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  109. data/docs/_guides/changes/validating-changes.adoc +681 -0
  110. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  111. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  112. data/docs/_guides/cli/format-schemas.adoc +547 -0
  113. data/docs/_guides/cli/index.adoc +8 -0
  114. data/docs/_guides/cli/managing-changes.adoc +927 -0
  115. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  116. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  117. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  118. data/docs/_guides/index.adoc +165 -0
  119. data/docs/_guides/ler/creating-packages.adoc +664 -0
  120. data/docs/_guides/ler/index.adoc +305 -0
  121. data/docs/_guides/ler/loading-packages.adoc +707 -0
  122. data/docs/_guides/ler/package-formats.adoc +748 -0
  123. data/docs/_guides/ler/querying-packages.adoc +826 -0
  124. data/docs/_guides/ler/step-packages.adoc +385 -0
  125. data/docs/_guides/ler/validating-packages.adoc +750 -0
  126. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  127. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  128. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  129. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  130. data/docs/_guides/liquid/index.adoc +468 -0
  131. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  132. data/docs/_guides/manifests/index.adoc +307 -0
  133. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  134. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  135. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  136. data/docs/_guides/ruby-api/index.adoc +257 -0
  137. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  138. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  139. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  140. data/docs/_pages/data-model.adoc +665 -0
  141. data/docs/_pages/express-language.adoc +506 -0
  142. data/docs/_pages/getting-started.adoc +414 -0
  143. data/docs/_pages/index.adoc +116 -0
  144. data/docs/_pages/introduction.adoc +256 -0
  145. data/docs/_pages/ler-packages.adoc +837 -0
  146. data/docs/_pages/parsers.adoc +709 -0
  147. data/docs/_pages/schema-manifests.adoc +431 -0
  148. data/docs/_references/index.adoc +228 -0
  149. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  150. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  151. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  152. data/docs/_tutorials/index.adoc +231 -0
  153. data/docs/_tutorials/liquid-templates.adoc +806 -0
  154. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  155. data/docs/_tutorials/querying-schemas.adoc +751 -0
  156. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  157. data/docs/index.adoc +242 -0
  158. data/docs/lychee.toml +90 -0
  159. data/examples/demo_ler_usage.sh +86 -0
  160. data/examples/ler/README.md +111 -0
  161. data/examples/ler/simple_example.ler +0 -0
  162. data/examples/ler/simple_schema.exp +33 -0
  163. data/examples/ler_build.rb +75 -0
  164. data/examples/ler_cli.rb +79 -0
  165. data/examples/ler_demo_complete.rb +276 -0
  166. data/examples/ler_query.rb +91 -0
  167. data/examples/ler_query_examples.rb +305 -0
  168. data/examples/ler_stats.rb +81 -0
  169. data/examples/phase3_demo.rb +159 -0
  170. data/examples/query_demo_simple.rb +131 -0
  171. data/exe/expressir +6 -17
  172. data/exe/expressir-format +14 -0
  173. data/exe/{format-test → expressir-format-test} +8 -7
  174. data/expressir.gemspec +50 -37
  175. data/lib/expressir/3.2/expressir_core.so +0 -0
  176. data/lib/expressir/3.3/expressir_core.so +0 -0
  177. data/lib/expressir/3.4/expressir_core.so +0 -0
  178. data/lib/expressir/4.0/expressir_core.so +0 -0
  179. data/lib/expressir/benchmark.rb +310 -0
  180. data/lib/expressir/changes/item_change.rb +20 -0
  181. data/lib/expressir/changes/mapping_change.rb +16 -0
  182. data/lib/expressir/changes/schema_change.rb +85 -0
  183. data/lib/expressir/changes/version_change.rb +26 -0
  184. data/lib/expressir/changes.rb +9 -0
  185. data/lib/expressir/cli.rb +138 -11
  186. data/lib/expressir/commands/base.rb +25 -0
  187. data/lib/expressir/commands/benchmark.rb +59 -0
  188. data/lib/expressir/commands/benchmark_cache.rb +80 -0
  189. data/lib/expressir/commands/changes.rb +34 -0
  190. data/lib/expressir/commands/changes_import_eengine.rb +146 -0
  191. data/lib/expressir/commands/changes_validate.rb +63 -0
  192. data/lib/expressir/commands/check.rb +56 -0
  193. data/lib/expressir/commands/clean.rb +20 -0
  194. data/lib/expressir/commands/coverage.rb +458 -0
  195. data/lib/expressir/commands/expand.rb +26 -0
  196. data/lib/expressir/commands/file_violations.rb +70 -0
  197. data/lib/expressir/commands/fix.rb +33 -0
  198. data/lib/expressir/commands/flatten.rb +29 -0
  199. data/lib/expressir/commands/format.rb +43 -0
  200. data/lib/expressir/commands/manifest.rb +420 -0
  201. data/lib/expressir/commands/mapping_validate.rb +68 -0
  202. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  203. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  204. data/lib/expressir/commands/package.rb +1222 -0
  205. data/lib/expressir/commands/parity_inputs.rb +160 -0
  206. data/lib/expressir/commands/validate.rb +106 -0
  207. data/lib/expressir/commands/validate_ascii.rb +94 -0
  208. data/lib/expressir/commands/validate_load.rb +91 -0
  209. data/lib/expressir/commands/version.rb +9 -0
  210. data/lib/expressir/commands/xsd.rb +23 -0
  211. data/lib/expressir/commands.rb +30 -0
  212. data/lib/expressir/config.rb +40 -3
  213. data/lib/expressir/coverage.rb +510 -0
  214. data/lib/expressir/eengine/arm_compare_report.rb +23 -0
  215. data/lib/expressir/eengine/changes_section.rb +16 -0
  216. data/lib/expressir/eengine/compare_report.rb +69 -0
  217. data/lib/expressir/eengine/mim_compare_report.rb +23 -0
  218. data/lib/expressir/eengine/modified_object.rb +21 -0
  219. data/lib/expressir/eengine.rb +9 -0
  220. data/lib/expressir/errors.rb +113 -0
  221. data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
  222. data/lib/expressir/express/adoc_source_formatter.rb +12 -0
  223. data/lib/expressir/express/ast_key_converter.rb +114 -0
  224. data/lib/expressir/express/builder.rb +277 -0
  225. data/lib/expressir/express/builder_context.rb +22 -0
  226. data/lib/expressir/express/builder_registry.rb +397 -0
  227. data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
  228. data/lib/expressir/express/builders/built_in_builder.rb +75 -0
  229. data/lib/expressir/express/builders/constant_builder.rb +108 -0
  230. data/lib/expressir/express/builders/declaration_builder.rb +20 -0
  231. data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
  232. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  233. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  234. data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
  235. data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
  236. data/lib/expressir/express/builders/expression_builder.rb +416 -0
  237. data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
  238. data/lib/expressir/express/builders/helpers.rb +148 -0
  239. data/lib/expressir/express/builders/interface_builder.rb +151 -0
  240. data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
  241. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
  242. data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
  243. data/lib/expressir/express/builders/literal_builder.rb +93 -0
  244. data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
  245. data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
  246. data/lib/expressir/express/builders/reference_builder.rb +18 -0
  247. data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
  248. data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
  249. data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
  250. data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
  251. data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
  252. data/lib/expressir/express/builders/statement_builder.rb +243 -0
  253. data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
  254. data/lib/expressir/express/builders/syntax_builder.rb +30 -0
  255. data/lib/expressir/express/builders/type_builder.rb +238 -0
  256. data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
  257. data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
  258. data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
  259. data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
  260. data/lib/expressir/express/builders.rb +55 -0
  261. data/lib/expressir/express/cache.rb +43 -18
  262. data/lib/expressir/express/checker.rb +812 -0
  263. data/lib/expressir/express/concatenator.rb +79 -0
  264. data/lib/expressir/express/core.rb +95 -0
  265. data/lib/expressir/express/error.rb +124 -0
  266. data/lib/expressir/express/formatter.rb +89 -1548
  267. data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
  268. data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
  269. data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
  270. data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
  271. data/lib/expressir/express/formatters/references_formatter.rb +53 -0
  272. data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
  273. data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
  274. data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
  275. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
  276. data/lib/expressir/express/formatters.rb +22 -0
  277. data/lib/expressir/express/grammar/parser.rb +712 -0
  278. data/lib/expressir/express/grammar.rb +11 -0
  279. data/lib/expressir/express/hyperlink_formatter.rb +4 -5
  280. data/lib/expressir/express/interface_dot.rb +105 -0
  281. data/lib/expressir/express/lazy_repository.rb +211 -0
  282. data/lib/expressir/express/line_map.rb +48 -0
  283. data/lib/expressir/express/listing.rb +174 -0
  284. data/lib/expressir/express/model_traversal.rb +42 -0
  285. data/lib/expressir/express/model_visitor.rb +11 -10
  286. data/lib/expressir/express/node_position_index.rb +342 -0
  287. data/lib/expressir/express/parallel_files.rb +229 -0
  288. data/lib/expressir/express/parser.rb +501 -62
  289. data/lib/expressir/express/pretty_formatter.rb +586 -0
  290. data/lib/expressir/express/pretty_gate.rb +61 -0
  291. data/lib/expressir/express/refs_overlay.rb +47 -0
  292. data/lib/expressir/express/remark_attacher.rb +1098 -0
  293. data/lib/expressir/express/remark_overlay.rb +86 -0
  294. data/lib/expressir/express/remark_scanner.rb +245 -0
  295. data/lib/expressir/express/resolve_references_model_visitor.rb +7 -9
  296. data/lib/expressir/express/schema_block_scanner.rb +137 -0
  297. data/lib/expressir/express/schema_head_formatter.rb +4 -5
  298. data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
  299. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  300. data/lib/expressir/express/scope_resolver.rb +223 -0
  301. data/lib/expressir/express/self_schema_reference.rb +126 -0
  302. data/lib/expressir/express/shtolo.rb +679 -0
  303. data/lib/expressir/express/smrl_xml.rb +125 -0
  304. data/lib/expressir/express/source_formatter.rb +15 -0
  305. data/lib/expressir/express/streaming_builder.rb +435 -0
  306. data/lib/expressir/express/xsd.rb +259 -0
  307. data/lib/expressir/express.rb +53 -0
  308. data/lib/expressir/liquid.rb +1 -0
  309. data/lib/expressir/manifest/resolver.rb +210 -0
  310. data/lib/expressir/manifest/validator.rb +192 -0
  311. data/lib/expressir/manifest.rb +6 -0
  312. data/lib/expressir/mapping/refpath.rb +857 -0
  313. data/lib/expressir/mapping.rb +253 -0
  314. data/lib/expressir/model/cache.rb +10 -9
  315. data/lib/expressir/model/concerns.rb +42 -0
  316. data/lib/expressir/model/data_types/aggregate.rb +8 -13
  317. data/lib/expressir/model/data_types/array.rb +15 -21
  318. data/lib/expressir/model/data_types/bag.rb +11 -15
  319. data/lib/expressir/model/data_types/binary.rb +9 -12
  320. data/lib/expressir/model/data_types/boolean.rb +7 -2
  321. data/lib/expressir/model/data_types/enumeration.rb +11 -15
  322. data/lib/expressir/model/data_types/enumeration_item.rb +5 -7
  323. data/lib/expressir/model/data_types/generic.rb +6 -8
  324. data/lib/expressir/model/data_types/generic_entity.rb +11 -13
  325. data/lib/expressir/model/data_types/integer.rb +7 -2
  326. data/lib/expressir/model/data_types/list.rb +13 -18
  327. data/lib/expressir/model/data_types/logical.rb +7 -2
  328. data/lib/expressir/model/data_types/number.rb +7 -2
  329. data/lib/expressir/model/data_types/real.rb +7 -9
  330. data/lib/expressir/model/data_types/select.rb +13 -18
  331. data/lib/expressir/model/data_types/set.rb +11 -15
  332. data/lib/expressir/model/data_types/string.rb +9 -12
  333. data/lib/expressir/model/data_types.rb +25 -0
  334. data/lib/expressir/model/declarations/attribute.rb +19 -28
  335. data/lib/expressir/model/declarations/constant.rb +10 -16
  336. data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
  337. data/lib/expressir/model/declarations/entity.rb +39 -30
  338. data/lib/expressir/model/declarations/function.rb +32 -40
  339. data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
  340. data/lib/expressir/model/declarations/interface.rb +25 -16
  341. data/lib/expressir/model/declarations/interface_item.rb +9 -11
  342. data/lib/expressir/model/declarations/interfaced_item.rb +15 -19
  343. data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
  344. data/lib/expressir/model/declarations/parameter.rb +10 -16
  345. data/lib/expressir/model/declarations/procedure.rb +30 -37
  346. data/lib/expressir/model/declarations/remark_item.rb +11 -11
  347. data/lib/expressir/model/declarations/rule.rb +38 -43
  348. data/lib/expressir/model/declarations/schema.rb +162 -64
  349. data/lib/expressir/model/declarations/schema_version.rb +8 -11
  350. data/lib/expressir/model/declarations/schema_version_item.rb +8 -11
  351. data/lib/expressir/model/declarations/subtype_constraint.rb +14 -22
  352. data/lib/expressir/model/declarations/type.rb +18 -18
  353. data/lib/expressir/model/declarations/unique_rule.rb +8 -13
  354. data/lib/expressir/model/declarations/variable.rb +10 -16
  355. data/lib/expressir/model/declarations/where_rule.rb +8 -13
  356. data/lib/expressir/model/declarations.rb +31 -0
  357. data/lib/expressir/model/dependency_resolver.rb +268 -0
  358. data/lib/expressir/model/exp_file.rb +42 -0
  359. data/lib/expressir/model/expressions/aggregate_initializer.rb +8 -9
  360. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +10 -12
  361. data/lib/expressir/model/expressions/binary_expression.rb +42 -36
  362. data/lib/expressir/model/expressions/entity_constructor.rb +10 -12
  363. data/lib/expressir/model/expressions/function_call.rb +10 -12
  364. data/lib/expressir/model/expressions/interval.rb +18 -23
  365. data/lib/expressir/model/expressions/query_expression.rb +11 -15
  366. data/lib/expressir/model/expressions/unary_expression.rb +13 -15
  367. data/lib/expressir/model/expressions.rb +18 -0
  368. data/lib/expressir/model/identifier.rb +18 -26
  369. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  370. data/lib/expressir/model/indexes/item_graph.rb +185 -0
  371. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  372. data/lib/expressir/model/indexes/type_index.rb +149 -0
  373. data/lib/expressir/model/indexes.rb +12 -0
  374. data/lib/expressir/model/interface_validator.rb +384 -0
  375. data/lib/expressir/model/literals/binary.rb +7 -9
  376. data/lib/expressir/model/literals/integer.rb +7 -9
  377. data/lib/expressir/model/literals/logical.rb +10 -12
  378. data/lib/expressir/model/literals/real.rb +7 -9
  379. data/lib/expressir/model/literals/string.rb +10 -12
  380. data/lib/expressir/model/literals.rb +13 -0
  381. data/lib/expressir/model/model_element.rb +286 -117
  382. data/lib/expressir/model/references/attribute_reference.rb +9 -12
  383. data/lib/expressir/model/references/group_reference.rb +9 -12
  384. data/lib/expressir/model/references/index_reference.rb +11 -15
  385. data/lib/expressir/model/references/simple_reference.rb +11 -14
  386. data/lib/expressir/model/references.rb +12 -0
  387. data/lib/expressir/model/remark_format.rb +17 -0
  388. data/lib/expressir/model/remark_info.rb +92 -0
  389. data/lib/expressir/model/remark_placement.rb +42 -0
  390. data/lib/expressir/model/repository.rb +472 -12
  391. data/lib/expressir/model/repository_validator.rb +293 -0
  392. data/lib/expressir/model/search_engine.rb +551 -0
  393. data/lib/expressir/model/statements/alias.rb +12 -16
  394. data/lib/expressir/model/statements/assignment.rb +12 -11
  395. data/lib/expressir/model/statements/case.rb +31 -14
  396. data/lib/expressir/model/statements/case_action.rb +9 -11
  397. data/lib/expressir/model/statements/compound.rb +10 -8
  398. data/lib/expressir/model/statements/escape.rb +10 -2
  399. data/lib/expressir/model/statements/if.rb +15 -14
  400. data/lib/expressir/model/statements/null.rb +10 -2
  401. data/lib/expressir/model/statements/procedure_call.rb +11 -11
  402. data/lib/expressir/model/statements/repeat.rb +21 -28
  403. data/lib/expressir/model/statements/return.rb +9 -8
  404. data/lib/expressir/model/statements/skip.rb +10 -2
  405. data/lib/expressir/model/statements.rb +20 -0
  406. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +13 -17
  407. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +7 -9
  408. data/lib/expressir/model/supertype_expressions.rb +12 -0
  409. data/lib/expressir/model.rb +38 -78
  410. data/lib/expressir/package/builder.rb +231 -0
  411. data/lib/expressir/package/metadata.rb +79 -0
  412. data/lib/expressir/package/reader.rb +149 -0
  413. data/lib/expressir/package.rb +8 -0
  414. data/lib/expressir/schema_manifest.rb +159 -0
  415. data/lib/expressir/schema_manifest_entry.rb +15 -0
  416. data/lib/expressir/version.rb +6 -1
  417. data/lib/expressir.rb +79 -9
  418. data/lib/tasks/verify_remarks.rake +16 -0
  419. data/rakelib/native.rake +24 -0
  420. data/rakelib/oracle.rake +52 -0
  421. data/rakelib/verify_remarks.rake +16 -0
  422. metadata +431 -129
  423. data/.cross_rubies +0 -20
  424. data/.gitmodules +0 -6
  425. data/.yardopts +0 -11
  426. data/docs/development.md +0 -90
  427. data/exe/format +0 -18
  428. data/exe/generate-parser +0 -51
  429. data/lib/expressir/cli/ui.rb +0 -36
  430. data/lib/expressir/express/2.7/express_parser.so +0 -0
  431. data/lib/expressir/express/3.0/express_parser.so +0 -0
  432. data/lib/expressir/express/3.1/express_parser.so +0 -0
  433. data/lib/expressir/express/3.2/express_parser.so +0 -0
  434. data/lib/expressir/express/visitor.rb +0 -2588
  435. data/lib/expressir/model/data_type.rb +0 -9
  436. data/lib/expressir/model/declaration.rb +0 -9
  437. data/lib/expressir/model/expression.rb +0 -9
  438. data/lib/expressir/model/literal.rb +0 -9
  439. data/lib/expressir/model/reference.rb +0 -9
  440. data/lib/expressir/model/statement.rb +0 -9
  441. data/lib/expressir/model/supertype_expression.rb +0 -9
  442. data/rakelib/antlr4-native.rake +0 -161
  443. data/rakelib/cross-ruby.rake +0 -368
  444. data/spec/acceptance/version_spec.rb +0 -27
  445. data/spec/expressir/express/cache_spec.rb +0 -89
  446. data/spec/expressir/express/formatter_spec.rb +0 -173
  447. data/spec/expressir/express/parser_spec.rb +0 -141
  448. data/spec/expressir/model/model_element_spec.rb +0 -318
  449. data/spec/spec_helper.rb +0 -24
  450. data/spec/support/console_helper.rb +0 -29
  451. data/spec/syntax/multiple.exp +0 -23
  452. data/spec/syntax/multiple.yaml +0 -198
  453. data/spec/syntax/multiple_formatted.exp +0 -71
  454. data/spec/syntax/multiple_hyperlink_formatted.exp +0 -71
  455. data/spec/syntax/multiple_schema_head_hyperlink_formatted.exp +0 -13
  456. data/spec/syntax/remark.exp +0 -193
  457. data/spec/syntax/remark.yaml +0 -471
  458. data/spec/syntax/remark_formatted.exp +0 -228
  459. data/spec/syntax/single.exp +0 -4
  460. data/spec/syntax/single.yaml +0 -18
  461. data/spec/syntax/single_formatted.exp +0 -10
  462. data/spec/syntax/single_formatted.yaml +0 -36
  463. data/spec/syntax/syntax.exp +0 -333
  464. data/spec/syntax/syntax.yaml +0 -3509
  465. data/spec/syntax/syntax_formatted.exp +0 -902
  466. data/spec/syntax/syntax_hyperlink_formatted.exp +0 -902
  467. data/spec/syntax/syntax_schema_head_formatted.exp +0 -18
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds data type nodes (enumeration, select, array, bag, list, set, etc.).
7
+ class TypeBuilder
8
+ include ::Expressir::Express::Builders::Helpers
9
+
10
+ def build_boolean_type(_ast_data)
11
+ Expressir::Model::DataTypes::Boolean.new
12
+ end
13
+
14
+ def build_integer_type(_ast_data)
15
+ Expressir::Model::DataTypes::Integer.new
16
+ end
17
+
18
+ def build_logical_type(_ast_data)
19
+ Expressir::Model::DataTypes::Logical.new
20
+ end
21
+
22
+ def build_number_type(_ast_data)
23
+ Expressir::Model::DataTypes::Number.new
24
+ end
25
+
26
+ # String type
27
+ def build_string_type(ast_data)
28
+ width = Builder.build_optional(ast_data[:width_spec]&.dig(:width))
29
+ fixed = !ast_data[:width_spec]&.dig(:t_fixed).nil?
30
+ kwargs = { width: width }
31
+ kwargs[:fixed] = fixed if fixed
32
+ Expressir::Model::DataTypes::String.new(**kwargs)
33
+ end
34
+
35
+ # Binary type
36
+ def build_binary_type(ast_data)
37
+ width = Builder.build_optional(ast_data[:width_spec]&.dig(:width))
38
+ fixed = !ast_data[:width_spec]&.dig(:t_fixed).nil?
39
+ kwargs = { width: width }
40
+ kwargs[:fixed] = fixed if fixed
41
+ Expressir::Model::DataTypes::Binary.new(**kwargs)
42
+ end
43
+
44
+ # Real type
45
+ def build_real_type(ast_data)
46
+ precision = Builder.build_optional(ast_data[:precision_spec])
47
+ if precision
48
+ Expressir::Model::DataTypes::Real.new(precision: precision)
49
+ else
50
+ Expressir::Model::DataTypes::Real.new
51
+ end
52
+ end
53
+
54
+ # Aggregate type (AGGREGATE OF type)
55
+ def build_aggregate_type(ast_data)
56
+ base_type = Builder.build_optional(ast_data[:parameter_type])
57
+ Expressir::Model::DataTypes::Aggregate.new(base_type: base_type)
58
+ end
59
+
60
+ # Aggregation types
61
+ def build_array_type(ast_data)
62
+ build_aggregation_type(ast_data, Expressir::Model::DataTypes::Array)
63
+ end
64
+
65
+ def build_bag_type(ast_data)
66
+ build_aggregation_type(ast_data, Expressir::Model::DataTypes::Bag)
67
+ end
68
+
69
+ def build_list_type(ast_data)
70
+ build_aggregation_type(ast_data, Expressir::Model::DataTypes::List)
71
+ end
72
+
73
+ def build_set_type(ast_data)
74
+ build_aggregation_type(ast_data, Expressir::Model::DataTypes::Set)
75
+ end
76
+
77
+ def build_general_set_type(ast_data)
78
+ build_general_aggregation_type(ast_data, Expressir::Model::DataTypes::Set)
79
+ end
80
+
81
+ def build_general_list_type(ast_data)
82
+ build_general_aggregation_type(ast_data, Expressir::Model::DataTypes::List)
83
+ end
84
+
85
+ def build_general_bag_type(ast_data)
86
+ build_general_aggregation_type(ast_data, Expressir::Model::DataTypes::Bag)
87
+ end
88
+
89
+ def build_general_array_type(ast_data)
90
+ build_general_aggregation_type(ast_data, Expressir::Model::DataTypes::Array)
91
+ end
92
+
93
+ def build_aggregation_type(ast_data, type_class)
94
+ bound_spec = ast_data[:bound_spec] || {}
95
+ bound1 = Builder.build_optional(bound_spec[:bound1])
96
+ bound2 = Builder.build_optional(bound_spec[:bound2])
97
+ optional = !ast_data[:t_optional].nil?
98
+ unique = !ast_data[:t_unique].nil?
99
+ base_type = Builder.build_optional(ast_data[:instantiable_type])
100
+
101
+ type_class.new(
102
+ bound1: bound1,
103
+ bound2: bound2,
104
+ optional: optional,
105
+ unique: unique,
106
+ base_type: base_type,
107
+ )
108
+ end
109
+
110
+ # General aggregation types (used in parameter types)
111
+ # These use parameter_type instead of instantiable_type
112
+ def build_general_aggregation_type(ast_data, type_class)
113
+ bound_spec = ast_data[:bound_spec] || {}
114
+ bound1 = Builder.build_optional(bound_spec[:bound1])
115
+ bound2 = Builder.build_optional(bound_spec[:bound2])
116
+ base_type = Builder.build_optional(ast_data[:parameter_type])
117
+ # Element modifiers are legal on general aggregations too
118
+ # (attributes and parameters); dropping them silently changed
119
+ # element constraints (GH-338). ARRAY carries both flags,
120
+ # LIST only UNIQUE, per the model.
121
+ optional = !ast_data[:t_optional].nil? if type_class.method_defined?(:optional)
122
+ unique = !ast_data[:t_unique].nil? if type_class.method_defined?(:unique)
123
+
124
+ type_class.new(
125
+ bound1: bound1,
126
+ bound2: bound2,
127
+ optional: optional,
128
+ unique: unique,
129
+ base_type: base_type,
130
+ )
131
+ end
132
+
133
+ # Enumeration type
134
+ def build_enumeration_type(ast_data)
135
+ extensible = !ast_data[:t_extensible].nil?
136
+ items = []
137
+ based_on = nil
138
+
139
+ if ast_data[:enumeration_items].is_a?(Hash)
140
+ items_data = ast_data[:enumeration_items][:list_of_enumeration_item] ||
141
+ ast_data[:enumeration_items][:enumeration_item]
142
+ if items_data
143
+ items_data = items_data[:enumeration_item] if items_data.is_a?(Hash) && items_data[:enumeration_item]
144
+ items_data = [items_data] unless items_data.is_a?(Array)
145
+ items = items_data.filter_map do |item|
146
+ actual_item = item.is_a?(Hash) ? (item[:enumeration_item] || item) : item
147
+ Builder.build({ enumeration_item: actual_item })
148
+ end
149
+ end
150
+ elsif ast_data[:enumeration_extension].is_a?(Hash)
151
+ # Wrap type_ref data so the correct handler is called
152
+ type_ref_data = ast_data[:enumeration_extension][:type_ref]
153
+ based_on = Builder.build({ type_ref: type_ref_data }) if type_ref_data
154
+
155
+ if ast_data[:enumeration_extension][:enumeration_items].is_a?(Hash)
156
+ items_data = ast_data[:enumeration_extension][:enumeration_items][:list_of_enumeration_item] ||
157
+ ast_data[:enumeration_extension][:enumeration_items][:enumeration_item]
158
+ if items_data
159
+ items_data = items_data[:enumeration_item] if items_data.is_a?(Hash) && items_data[:enumeration_item]
160
+ items_data = [items_data] unless items_data.is_a?(Array)
161
+ items = items_data.filter_map do |item|
162
+ actual_item = item.is_a?(Hash) ? (item[:enumeration_item] || item) : item
163
+ Builder.build({ enumeration_item: actual_item })
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ kwargs = { based_on: based_on, items: items }
170
+ kwargs[:extensible] = extensible if extensible
171
+ Expressir::Model::DataTypes::Enumeration.new(**kwargs)
172
+ end
173
+
174
+ # Enumeration item
175
+ def build_enumeration_item(ast_data)
176
+ id = nil
177
+ if ast_data.is_a?(Hash)
178
+ if ast_data[:enumeration_id]
179
+ enum_id_data = ast_data[:enumeration_id]
180
+ id = if enum_id_data.is_a?(Hash)
181
+ extract_text(enum_id_data[:str]) || extract_text(enum_id_data[:simple_id]&.dig(:str))
182
+ else
183
+ enum_id_data.to_s
184
+ end
185
+ elsif ast_data[:simple_id]
186
+ id = extract_text(ast_data[:simple_id]&.dig(:str)) || extract_text(ast_data[:str])
187
+ elsif ast_data[:str]
188
+ id = extract_text(ast_data[:str])
189
+ end
190
+ elsif ast_data.is_a?(String)
191
+ id = ast_data
192
+ end
193
+ Expressir::Model::DataTypes::EnumerationItem.new(id: id)
194
+ end
195
+
196
+ # Select type
197
+ def build_select_type(ast_data)
198
+ extensible = !ast_data[:t_extensible].nil?
199
+ generic_entity = !ast_data[:t_generic_entity].nil?
200
+ items = []
201
+ based_on = nil
202
+
203
+ if ast_data[:select_list].is_a?(Hash)
204
+ named_types = ast_data[:select_list][:list_of_named_types]
205
+ items = Builder.build_children(named_types) if named_types
206
+ elsif ast_data[:select_extension].is_a?(Hash)
207
+ # Wrap type_ref data so the correct handler is called
208
+ if ast_data[:select_extension][:type_ref]
209
+ based_on = Builder.build({ type_ref: ast_data[:select_extension][:type_ref] })
210
+ end
211
+ if ast_data[:select_extension][:select_list].is_a?(Hash)
212
+ named_types = ast_data[:select_extension][:select_list][:list_of_named_types]
213
+ items = Builder.build_children(named_types) if named_types
214
+ end
215
+ end
216
+
217
+ kwargs = { based_on: based_on, items: items.compact }
218
+ kwargs[:extensible] = extensible if extensible
219
+ kwargs[:generic_entity] = generic_entity if generic_entity
220
+ Expressir::Model::DataTypes::Select.new(**kwargs)
221
+ end
222
+
223
+ # Type wrappers - choice types that dispatch to inner type
224
+ def build_type_wrapper(ast_data)
225
+ return nil unless ast_data.is_a?(Hash)
226
+
227
+ ast_data.each do |k, v|
228
+ next unless v
229
+
230
+ result = Builder.build({ k => v })
231
+ return result if result
232
+ end
233
+ nil
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds type_decl nodes.
7
+ class TypeDeclBuilder
8
+ def call(ast_data)
9
+ id = Builder.build_optional(ast_data[:type_id])
10
+ underlying_type = Builder.build_optional(ast_data[:underlying_type])
11
+ where_rules = if ast_data[:where_clause]
12
+ Builder.build({ where_clause: ast_data[:where_clause] })
13
+ else
14
+ []
15
+ end
16
+
17
+ Expressir::Model::Declarations::Type.new(
18
+ id: id,
19
+ underlying_type: underlying_type,
20
+ where_rules: [where_rules].flatten,
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds unique_clause nodes.
7
+ class UniqueClauseBuilder
8
+ def call(ast_data)
9
+ rules_data = ast_data[:list_of_unique_rule] || ast_data[:unique_rule]
10
+ return [] unless rules_data
11
+
12
+ rules_data = [rules_data] if rules_data.is_a?(Hash)
13
+ Builder.ensure_array(rules_data).filter_map do |rule|
14
+ Builder.build({ unique_rule: rule })
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds unique_rule nodes.
7
+ class UniqueRuleBuilder
8
+ def call(ast_data)
9
+ inner_data = ast_data[:unique_rule] || ast_data
10
+
11
+ id = Builder.build_optional(inner_data[:rule_label_id])
12
+
13
+ if inner_data[:list_of_referenced_attribute]
14
+ attrs_data = inner_data[:list_of_referenced_attribute]
15
+ if attrs_data.is_a?(Hash)
16
+ ref_attrs = attrs_data[:referenced_attribute]
17
+ ref_attrs = [ref_attrs] unless ref_attrs.is_a?(Array)
18
+ attributes = ref_attrs.filter_map do |attr|
19
+ Builder.build({ referenced_attribute: attr })
20
+ end
21
+ else
22
+ attributes = Builder.build_children(attrs_data)
23
+ end
24
+ else
25
+ attributes = Builder.build_children(inner_data[:referenced_attribute])
26
+ end
27
+
28
+ attributes = attributes.compact
29
+
30
+ # The grammar's separator repetition can yield a phantom rule
31
+ # fragment (no label, no referenced attributes) between real
32
+ # rules; drop it so clean never emits a bare ";" (GH-340).
33
+ return nil if id.nil? && attributes.empty?
34
+
35
+ Expressir::Model::Declarations::UniqueRule.new(id: id,
36
+ attributes: attributes)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds where_clause nodes.
7
+ class WhereClauseBuilder
8
+ def call(ast_data)
9
+ rules_data = ast_data[:list_of_domain_rule] || ast_data[:domain_rule]
10
+ return [] unless rules_data
11
+
12
+ rules_data = [rules_data] if rules_data.is_a?(Hash)
13
+ Builder.ensure_array(rules_data).filter_map do |rule|
14
+ Builder.build({ domain_rule: rule })
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Builder loader - requires all builder classes.
4
+ # This file has NO CODE, only requires.
5
+ # Each builder class registers itself with Builder.register.
6
+
7
+ # Ensure Expressir module and autoloads are set up first
8
+ module Expressir
9
+ module Express
10
+ module Builders
11
+ autoload :Helpers, "#{__dir__}/builders/helpers"
12
+
13
+ autoload :TokenBuilder, "#{__dir__}/builders/token_builder"
14
+ autoload :SimpleIdBuilder, "#{__dir__}/builders/simple_id_builder"
15
+ autoload :SyntaxBuilder, "#{__dir__}/builders/syntax_builder"
16
+ autoload :SchemaVersionBuilder,
17
+ "#{__dir__}/builders/schema_version_builder"
18
+ autoload :DeclarationBuilder, "#{__dir__}/builders/declaration_builder"
19
+ autoload :SchemaBodyDeclBuilder,
20
+ "#{__dir__}/builders/schema_body_decl_builder"
21
+ autoload :SchemaDeclBuilder, "#{__dir__}/builders/schema_decl_builder"
22
+ autoload :EntityDeclBuilder, "#{__dir__}/builders/entity_decl_builder"
23
+ autoload :ExplicitAttrBuilder, "#{__dir__}/builders/explicit_attr_builder"
24
+ autoload :AttributeDeclBuilder,
25
+ "#{__dir__}/builders/attribute_decl_builder"
26
+ autoload :DeriveClauseBuilder, "#{__dir__}/builders/derive_clause_builder"
27
+ autoload :DerivedAttrBuilder, "#{__dir__}/builders/derived_attr_builder"
28
+ autoload :InverseClauseBuilder,
29
+ "#{__dir__}/builders/inverse_clause_builder"
30
+ autoload :InverseAttrBuilder, "#{__dir__}/builders/inverse_attr_builder"
31
+ autoload :InverseAttrTypeBuilder,
32
+ "#{__dir__}/builders/inverse_attr_type_builder"
33
+ autoload :UniqueClauseBuilder, "#{__dir__}/builders/unique_clause_builder"
34
+ autoload :UniqueRuleBuilder, "#{__dir__}/builders/unique_rule_builder"
35
+ autoload :WhereClauseBuilder, "#{__dir__}/builders/where_clause_builder"
36
+ autoload :DomainRuleBuilder, "#{__dir__}/builders/domain_rule_builder"
37
+ autoload :ReferenceBuilder, "#{__dir__}/builders/reference_builder"
38
+ autoload :LiteralBuilder, "#{__dir__}/builders/literal_builder"
39
+ autoload :TypeDeclBuilder, "#{__dir__}/builders/type_decl_builder"
40
+ autoload :TypeBuilder, "#{__dir__}/builders/type_builder"
41
+ autoload :ExpressionBuilder, "#{__dir__}/builders/expression_builder"
42
+ autoload :StatementBuilder, "#{__dir__}/builders/statement_builder"
43
+ autoload :FunctionDeclBuilder, "#{__dir__}/builders/function_decl_builder"
44
+ autoload :ProcedureDeclBuilder,
45
+ "#{__dir__}/builders/procedure_decl_builder"
46
+ autoload :RuleDeclBuilder, "#{__dir__}/builders/rule_decl_builder"
47
+ autoload :SubtypeConstraintBuilder,
48
+ "#{__dir__}/builders/subtype_constraint_builder"
49
+ autoload :InterfaceBuilder, "#{__dir__}/builders/interface_builder"
50
+ autoload :ConstantBuilder, "#{__dir__}/builders/constant_builder"
51
+ autoload :QualifierBuilder, "#{__dir__}/builders/qualifier_builder"
52
+ autoload :BuiltInBuilder, "#{__dir__}/builders/built_in_builder"
53
+ end
54
+ end
55
+ end
@@ -1,29 +1,36 @@
1
- require 'yaml'
2
- require 'zlib'
3
- require 'expressir/model'
1
+ require "digest"
2
+ require "zlib"
4
3
 
5
4
  module Expressir
6
5
  module Express
7
6
  class Cache
7
+ # Format: magic + SHA-256 (raw, 32 bytes) + Zlib-deflated Marshal.dump
8
+ # of Model::Cache. The digest detects corruption; a corrupted cache is
9
+ # disposable — callers drop the file and regenerate. Marshal is only
10
+ # safe for trusted, locally generated cache files.
11
+ MAGIC = "EXPRC1".freeze
12
+
13
+ DIGEST_BYTES = Digest::SHA256.digest("").bytesize
14
+
8
15
  # Save Express model into a cache file
9
16
  # @param file [String] cache file path
10
17
  # @param content [Model::ModelElement] Express model
11
18
  # @param root_path [String] Express repository root path, to be stripped from Express file paths to create a portable cache file
12
19
  # @param test_overwrite_version [String] don't use, only for tests
13
20
  # @return [nil]
14
- def self.to_file(file, content, root_path: nil, test_overwrite_version: nil)
15
- version = test_overwrite_version || VERSION
21
+ def self.to_file(file, content, root_path: nil,
22
+ test_overwrite_version: nil)
23
+ version = test_overwrite_version || Expressir::Version::VERSION
16
24
 
17
25
  cache = Model::Cache.new(
18
26
  version: version,
19
- content: content
27
+ content: content,
28
+ root_path: root_path,
20
29
  )
21
30
 
22
- hash = cache.to_hash(root_path: root_path)
23
- yaml = YAML.dump(hash)
24
- yaml_compressed = Zlib::Deflate.deflate(yaml)
31
+ data = Zlib::Deflate.deflate(Marshal.dump(cache), 1)
32
+ File.binwrite(file, "#{MAGIC}#{Digest::SHA256.digest(data)}#{data}")
25
33
 
26
- File.binwrite(file, yaml_compressed)
27
34
  nil
28
35
  end
29
36
 
@@ -32,20 +39,38 @@ module Expressir
32
39
  # @param root_path [String] Express repository root path, to be prepended to Express file paths if loading a portable cache file
33
40
  # @param test_overwrite_version [String] don't use, only for tests
34
41
  # @return [Model::ModelElement] Express model
42
+ # @raise [Error::CacheCorruptedError] if the file is not a valid cache file or its digest does not match
43
+ # @raise [Error::CacheVersionMismatchError] if the cache was written by another Expressir version
35
44
  def self.from_file(file, root_path: nil, test_overwrite_version: nil)
36
- version = test_overwrite_version || VERSION
45
+ version = test_overwrite_version || Expressir::Version::VERSION
37
46
 
38
- yaml_compressed = File.binread(file)
39
- yaml = Zlib::Inflate.inflate(yaml_compressed)
40
- hash = YAML.load(yaml)
41
- cache = Model::ModelElement.from_hash(hash, root_path: root_path)
47
+ raw = File.binread(file)
48
+ data = Zlib::Inflate.inflate(validated_data(raw))
49
+ cache = Marshal.load(data) # rubocop:disable Security/MarshalLoad
42
50
 
43
51
  if cache.version != version
44
- raise Error.new("Cache version mismatch, cache version is #{cache.version}, Expressir version is #{version}")
52
+ raise Error::CacheVersionMismatchError.new(cache.version, version)
53
+ end
54
+
55
+ cache
56
+ rescue TypeError, ArgumentError, RangeError
57
+ raise Error::CacheCorruptedError
58
+ end
59
+
60
+ def self.validated_data(raw)
61
+ header = MAGIC.bytesize + DIGEST_BYTES
62
+ unless raw.bytesize > header && raw.start_with?(MAGIC)
63
+ raise Error::CacheCorruptedError
64
+ end
65
+
66
+ digest = raw.byteslice(MAGIC.bytesize, DIGEST_BYTES)
67
+ data = raw.byteslice(header, raw.bytesize - header)
68
+ unless Digest::SHA256.digest(data) == digest
69
+ raise Error::CacheCorruptedError
45
70
  end
46
71
 
47
- cache.content
72
+ data
48
73
  end
49
74
  end
50
75
  end
51
- end
76
+ end