expressir 2.4.29-arm-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 (426) hide show
  1. checksums.yaml +7 -0
  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 +19 -0
  9. data/.github/workflows/release.yml +37 -0
  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 +55 -0
  15. data/.hound.yml +3 -0
  16. data/.rspec +2 -0
  17. data/.rubocop.yml +18 -0
  18. data/.rubocop_todo.yml +297 -0
  19. data/CHANGELOG.md +159 -0
  20. data/Gemfile +18 -0
  21. data/README.adoc +2783 -0
  22. data/Rakefile +41 -0
  23. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  24. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  25. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  26. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  27. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  28. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  29. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  30. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  31. data/TODO.bugs/09-parser-split.md +53 -0
  32. data/TODO.bugs/10-to-s-override.md +42 -0
  33. data/TODO.bugs/11-parser-class-variables.md +39 -0
  34. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  35. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  36. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  37. data/TODO.bugs/15-expression-children-macro.md +27 -0
  38. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  39. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  40. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  41. data/TODO.bugs/19-format-methods-public.md +22 -0
  42. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  43. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  44. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  45. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  46. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  47. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  48. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  49. data/TODO.bugs/27-package-build-god-method.md +19 -0
  50. data/TODO.bugs/28-package-god-class.md +30 -0
  51. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  52. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  53. data/TODO.bugs/README.md +43 -0
  54. data/TODO.max-perf/01-restore-ci-green.md +36 -0
  55. data/TODO.max-perf/02-streaming-parse-path.md +31 -0
  56. data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
  57. data/TODO.max-perf/04-benchmark-harness.md +28 -0
  58. data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
  59. data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
  60. data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
  61. data/TODO.max-perf/08-builder-build-perf.md +45 -0
  62. data/TODO.max-perf/09-grammar-cold-start.md +25 -0
  63. data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
  64. data/TODO.max-perf/11-ci-green-closeout.md +25 -0
  65. data/TODO.max-perf/12-require-boot-profile.md +25 -0
  66. data/TODO.max-perf/13-key-conversion-specs.md +26 -0
  67. data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
  68. data/TODO.parity-ee/00-overview.md +76 -0
  69. data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
  70. data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
  71. data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
  72. data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
  73. data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
  74. data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
  75. data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
  76. data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
  77. data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
  78. data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
  79. data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
  80. data/TODO.parity-ee/12-full-check-catalog.md +67 -0
  81. data/TODO.parity-ee/13-population-p21.md +54 -0
  82. data/TODO.parity-ee/14-shtolo-completion.md +44 -0
  83. data/TODO.parity-ee/15-part28-xml.md +51 -0
  84. data/TODO.parity-ee/16-compare-patch.md +48 -0
  85. data/TODO.parity-ee/17-official-tests.md +42 -0
  86. data/TODO.parity-ee/18-mim-mapping.md +47 -0
  87. data/TODO.parity-ee/19-architecture.md +97 -0
  88. data/TODO.parity-ee/parity-matrix.md +108 -0
  89. data/TODO.refpath-v2/00-overview.md +64 -0
  90. data/TODO.suma-improvements/00-overview.md +23 -0
  91. data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
  92. data/TODO.suma-improvements/02-suma-e2e.md +39 -0
  93. data/TODO.suma-improvements/03-item-graph.md +22 -0
  94. data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
  95. data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
  96. data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
  97. data/TODO.suma-improvements/07-part28-xml.md +15 -0
  98. data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
  99. data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
  100. data/TODO.suma-improvements/10-expressdoc.md +8 -0
  101. data/benchmark/srl_benchmark.rb +458 -0
  102. data/benchmark/srl_native_benchmark.rb +146 -0
  103. data/benchmark/srl_ruby_benchmark.rb +132 -0
  104. data/bin/console +11 -0
  105. data/bin/rspec +30 -0
  106. data/bin/setup +8 -0
  107. data/docs/Gemfile +12 -0
  108. data/docs/_config.yml +141 -0
  109. data/docs/_guides/changes/changes-format.adoc +778 -0
  110. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  111. data/docs/_guides/changes/index.adoc +396 -0
  112. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  113. data/docs/_guides/changes/validating-changes.adoc +681 -0
  114. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  115. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  116. data/docs/_guides/cli/format-schemas.adoc +547 -0
  117. data/docs/_guides/cli/index.adoc +8 -0
  118. data/docs/_guides/cli/managing-changes.adoc +927 -0
  119. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  120. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  121. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  122. data/docs/_guides/index.adoc +165 -0
  123. data/docs/_guides/ler/creating-packages.adoc +664 -0
  124. data/docs/_guides/ler/index.adoc +305 -0
  125. data/docs/_guides/ler/loading-packages.adoc +707 -0
  126. data/docs/_guides/ler/package-formats.adoc +748 -0
  127. data/docs/_guides/ler/querying-packages.adoc +826 -0
  128. data/docs/_guides/ler/step-packages.adoc +385 -0
  129. data/docs/_guides/ler/validating-packages.adoc +750 -0
  130. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  131. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  132. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  133. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  134. data/docs/_guides/liquid/index.adoc +468 -0
  135. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  136. data/docs/_guides/manifests/index.adoc +307 -0
  137. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  138. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  139. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  140. data/docs/_guides/ruby-api/index.adoc +257 -0
  141. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  142. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  143. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  144. data/docs/_pages/data-model.adoc +665 -0
  145. data/docs/_pages/express-language.adoc +506 -0
  146. data/docs/_pages/getting-started.adoc +414 -0
  147. data/docs/_pages/index.adoc +116 -0
  148. data/docs/_pages/introduction.adoc +256 -0
  149. data/docs/_pages/ler-packages.adoc +837 -0
  150. data/docs/_pages/parsers.adoc +709 -0
  151. data/docs/_pages/schema-manifests.adoc +431 -0
  152. data/docs/_references/index.adoc +228 -0
  153. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  154. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  155. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  156. data/docs/_tutorials/index.adoc +231 -0
  157. data/docs/_tutorials/liquid-templates.adoc +806 -0
  158. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  159. data/docs/_tutorials/querying-schemas.adoc +751 -0
  160. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  161. data/docs/index.adoc +242 -0
  162. data/docs/lychee.toml +90 -0
  163. data/examples/demo_ler_usage.sh +86 -0
  164. data/examples/ler/README.md +111 -0
  165. data/examples/ler/simple_example.ler +0 -0
  166. data/examples/ler/simple_schema.exp +33 -0
  167. data/examples/ler_build.rb +75 -0
  168. data/examples/ler_cli.rb +79 -0
  169. data/examples/ler_demo_complete.rb +276 -0
  170. data/examples/ler_query.rb +91 -0
  171. data/examples/ler_query_examples.rb +305 -0
  172. data/examples/ler_stats.rb +81 -0
  173. data/examples/phase3_demo.rb +159 -0
  174. data/examples/query_demo_simple.rb +131 -0
  175. data/exe/expressir +11 -0
  176. data/exe/expressir-format +14 -0
  177. data/exe/expressir-format-test +82 -0
  178. data/expressir.gemspec +61 -0
  179. data/lib/expressir/3.2/expressir_core.so +0 -0
  180. data/lib/expressir/3.3/expressir_core.so +0 -0
  181. data/lib/expressir/3.4/expressir_core.so +0 -0
  182. data/lib/expressir/4.0/expressir_core.so +0 -0
  183. data/lib/expressir/benchmark.rb +310 -0
  184. data/lib/expressir/changes/item_change.rb +20 -0
  185. data/lib/expressir/changes/mapping_change.rb +16 -0
  186. data/lib/expressir/changes/schema_change.rb +85 -0
  187. data/lib/expressir/changes/version_change.rb +26 -0
  188. data/lib/expressir/changes.rb +9 -0
  189. data/lib/expressir/cli.rb +148 -0
  190. data/lib/expressir/commands/base.rb +25 -0
  191. data/lib/expressir/commands/benchmark.rb +59 -0
  192. data/lib/expressir/commands/benchmark_cache.rb +80 -0
  193. data/lib/expressir/commands/changes.rb +34 -0
  194. data/lib/expressir/commands/changes_import_eengine.rb +146 -0
  195. data/lib/expressir/commands/changes_validate.rb +63 -0
  196. data/lib/expressir/commands/check.rb +56 -0
  197. data/lib/expressir/commands/clean.rb +20 -0
  198. data/lib/expressir/commands/coverage.rb +458 -0
  199. data/lib/expressir/commands/expand.rb +26 -0
  200. data/lib/expressir/commands/file_violations.rb +70 -0
  201. data/lib/expressir/commands/fix.rb +33 -0
  202. data/lib/expressir/commands/flatten.rb +29 -0
  203. data/lib/expressir/commands/format.rb +43 -0
  204. data/lib/expressir/commands/manifest.rb +420 -0
  205. data/lib/expressir/commands/mapping_validate.rb +68 -0
  206. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  207. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  208. data/lib/expressir/commands/package.rb +1222 -0
  209. data/lib/expressir/commands/parity_inputs.rb +160 -0
  210. data/lib/expressir/commands/validate.rb +106 -0
  211. data/lib/expressir/commands/validate_ascii.rb +94 -0
  212. data/lib/expressir/commands/validate_load.rb +91 -0
  213. data/lib/expressir/commands/version.rb +9 -0
  214. data/lib/expressir/commands/xsd.rb +23 -0
  215. data/lib/expressir/commands.rb +30 -0
  216. data/lib/expressir/config.rb +60 -0
  217. data/lib/expressir/coverage.rb +510 -0
  218. data/lib/expressir/eengine/arm_compare_report.rb +23 -0
  219. data/lib/expressir/eengine/changes_section.rb +16 -0
  220. data/lib/expressir/eengine/compare_report.rb +69 -0
  221. data/lib/expressir/eengine/mim_compare_report.rb +23 -0
  222. data/lib/expressir/eengine/modified_object.rb +21 -0
  223. data/lib/expressir/eengine.rb +9 -0
  224. data/lib/expressir/errors.rb +113 -0
  225. data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
  226. data/lib/expressir/express/adoc_source_formatter.rb +12 -0
  227. data/lib/expressir/express/ast_key_converter.rb +114 -0
  228. data/lib/expressir/express/builder.rb +277 -0
  229. data/lib/expressir/express/builder_context.rb +22 -0
  230. data/lib/expressir/express/builder_registry.rb +397 -0
  231. data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
  232. data/lib/expressir/express/builders/built_in_builder.rb +75 -0
  233. data/lib/expressir/express/builders/constant_builder.rb +108 -0
  234. data/lib/expressir/express/builders/declaration_builder.rb +20 -0
  235. data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
  236. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  237. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  238. data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
  239. data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
  240. data/lib/expressir/express/builders/expression_builder.rb +416 -0
  241. data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
  242. data/lib/expressir/express/builders/helpers.rb +148 -0
  243. data/lib/expressir/express/builders/interface_builder.rb +151 -0
  244. data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
  245. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
  246. data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
  247. data/lib/expressir/express/builders/literal_builder.rb +93 -0
  248. data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
  249. data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
  250. data/lib/expressir/express/builders/reference_builder.rb +18 -0
  251. data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
  252. data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
  253. data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
  254. data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
  255. data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
  256. data/lib/expressir/express/builders/statement_builder.rb +243 -0
  257. data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
  258. data/lib/expressir/express/builders/syntax_builder.rb +30 -0
  259. data/lib/expressir/express/builders/type_builder.rb +238 -0
  260. data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
  261. data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
  262. data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
  263. data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
  264. data/lib/expressir/express/builders.rb +55 -0
  265. data/lib/expressir/express/cache.rb +76 -0
  266. data/lib/expressir/express/checker.rb +812 -0
  267. data/lib/expressir/express/concatenator.rb +79 -0
  268. data/lib/expressir/express/core.rb +95 -0
  269. data/lib/expressir/express/error.rb +124 -0
  270. data/lib/expressir/express/formatter.rb +149 -0
  271. data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
  272. data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
  273. data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
  274. data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
  275. data/lib/expressir/express/formatters/references_formatter.rb +53 -0
  276. data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
  277. data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
  278. data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
  279. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
  280. data/lib/expressir/express/formatters.rb +22 -0
  281. data/lib/expressir/express/grammar/parser.rb +712 -0
  282. data/lib/expressir/express/grammar.rb +11 -0
  283. data/lib/expressir/express/hyperlink_formatter.rb +35 -0
  284. data/lib/expressir/express/interface_dot.rb +105 -0
  285. data/lib/expressir/express/lazy_repository.rb +211 -0
  286. data/lib/expressir/express/line_map.rb +48 -0
  287. data/lib/expressir/express/listing.rb +174 -0
  288. data/lib/expressir/express/model_traversal.rb +42 -0
  289. data/lib/expressir/express/model_visitor.rb +25 -0
  290. data/lib/expressir/express/node_position_index.rb +342 -0
  291. data/lib/expressir/express/parallel_files.rb +229 -0
  292. data/lib/expressir/express/parser.rb +523 -0
  293. data/lib/expressir/express/pretty_formatter.rb +586 -0
  294. data/lib/expressir/express/pretty_gate.rb +61 -0
  295. data/lib/expressir/express/refs_overlay.rb +47 -0
  296. data/lib/expressir/express/remark_attacher.rb +1098 -0
  297. data/lib/expressir/express/remark_overlay.rb +86 -0
  298. data/lib/expressir/express/remark_scanner.rb +245 -0
  299. data/lib/expressir/express/resolve_references_model_visitor.rb +29 -0
  300. data/lib/expressir/express/schema_block_scanner.rb +137 -0
  301. data/lib/expressir/express/schema_head_formatter.rb +22 -0
  302. data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
  303. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  304. data/lib/expressir/express/scope_resolver.rb +223 -0
  305. data/lib/expressir/express/self_schema_reference.rb +126 -0
  306. data/lib/expressir/express/shtolo.rb +679 -0
  307. data/lib/expressir/express/smrl_xml.rb +125 -0
  308. data/lib/expressir/express/source_formatter.rb +15 -0
  309. data/lib/expressir/express/streaming_builder.rb +435 -0
  310. data/lib/expressir/express/xsd.rb +259 -0
  311. data/lib/expressir/express.rb +53 -0
  312. data/lib/expressir/liquid.rb +1 -0
  313. data/lib/expressir/manifest/resolver.rb +210 -0
  314. data/lib/expressir/manifest/validator.rb +192 -0
  315. data/lib/expressir/manifest.rb +6 -0
  316. data/lib/expressir/mapping/refpath.rb +857 -0
  317. data/lib/expressir/mapping.rb +253 -0
  318. data/lib/expressir/model/cache.rb +18 -0
  319. data/lib/expressir/model/concerns.rb +42 -0
  320. data/lib/expressir/model/data_types/aggregate.rb +26 -0
  321. data/lib/expressir/model/data_types/array.rb +25 -0
  322. data/lib/expressir/model/data_types/bag.rb +21 -0
  323. data/lib/expressir/model/data_types/binary.rb +19 -0
  324. data/lib/expressir/model/data_types/boolean.rb +15 -0
  325. data/lib/expressir/model/data_types/enumeration.rb +21 -0
  326. data/lib/expressir/model/data_types/enumeration_item.rb +24 -0
  327. data/lib/expressir/model/data_types/generic.rb +24 -0
  328. data/lib/expressir/model/data_types/generic_entity.rb +24 -0
  329. data/lib/expressir/model/data_types/integer.rb +15 -0
  330. data/lib/expressir/model/data_types/list.rb +23 -0
  331. data/lib/expressir/model/data_types/logical.rb +15 -0
  332. data/lib/expressir/model/data_types/number.rb +15 -0
  333. data/lib/expressir/model/data_types/real.rb +17 -0
  334. data/lib/expressir/model/data_types/select.rb +23 -0
  335. data/lib/expressir/model/data_types/set.rb +21 -0
  336. data/lib/expressir/model/data_types/string.rb +19 -0
  337. data/lib/expressir/model/data_types.rb +25 -0
  338. data/lib/expressir/model/declarations/attribute.rb +38 -0
  339. data/lib/expressir/model/declarations/constant.rb +28 -0
  340. data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
  341. data/lib/expressir/model/declarations/entity.rb +62 -0
  342. data/lib/expressir/model/declarations/function.rb +59 -0
  343. data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
  344. data/lib/expressir/model/declarations/interface.rb +37 -0
  345. data/lib/expressir/model/declarations/interface_item.rb +21 -0
  346. data/lib/expressir/model/declarations/interfaced_item.rb +33 -0
  347. data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
  348. data/lib/expressir/model/declarations/parameter.rb +28 -0
  349. data/lib/expressir/model/declarations/procedure.rb +57 -0
  350. data/lib/expressir/model/declarations/remark_item.rb +21 -0
  351. data/lib/expressir/model/declarations/rule.rb +66 -0
  352. data/lib/expressir/model/declarations/schema.rb +215 -0
  353. data/lib/expressir/model/declarations/schema_version.rb +19 -0
  354. data/lib/expressir/model/declarations/schema_version_item.rb +19 -0
  355. data/lib/expressir/model/declarations/subtype_constraint.rb +32 -0
  356. data/lib/expressir/model/declarations/type.rb +45 -0
  357. data/lib/expressir/model/declarations/unique_rule.rb +26 -0
  358. data/lib/expressir/model/declarations/variable.rb +28 -0
  359. data/lib/expressir/model/declarations/where_rule.rb +26 -0
  360. data/lib/expressir/model/declarations.rb +31 -0
  361. data/lib/expressir/model/dependency_resolver.rb +268 -0
  362. data/lib/expressir/model/exp_file.rb +42 -0
  363. data/lib/expressir/model/expressions/aggregate_initializer.rb +18 -0
  364. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +20 -0
  365. data/lib/expressir/model/expressions/binary_expression.rb +59 -0
  366. data/lib/expressir/model/expressions/entity_constructor.rb +20 -0
  367. data/lib/expressir/model/expressions/function_call.rb +20 -0
  368. data/lib/expressir/model/expressions/interval.rb +29 -0
  369. data/lib/expressir/model/expressions/query_expression.rb +31 -0
  370. data/lib/expressir/model/expressions/unary_expression.rb +25 -0
  371. data/lib/expressir/model/expressions.rb +18 -0
  372. data/lib/expressir/model/identifier.rb +26 -0
  373. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  374. data/lib/expressir/model/indexes/item_graph.rb +185 -0
  375. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  376. data/lib/expressir/model/indexes/type_index.rb +149 -0
  377. data/lib/expressir/model/indexes.rb +12 -0
  378. data/lib/expressir/model/interface_validator.rb +384 -0
  379. data/lib/expressir/model/literals/binary.rb +17 -0
  380. data/lib/expressir/model/literals/integer.rb +17 -0
  381. data/lib/expressir/model/literals/logical.rb +21 -0
  382. data/lib/expressir/model/literals/real.rb +17 -0
  383. data/lib/expressir/model/literals/string.rb +20 -0
  384. data/lib/expressir/model/literals.rb +13 -0
  385. data/lib/expressir/model/model_element.rb +377 -0
  386. data/lib/expressir/model/references/attribute_reference.rb +19 -0
  387. data/lib/expressir/model/references/group_reference.rb +19 -0
  388. data/lib/expressir/model/references/index_reference.rb +23 -0
  389. data/lib/expressir/model/references/simple_reference.rb +21 -0
  390. data/lib/expressir/model/references.rb +12 -0
  391. data/lib/expressir/model/remark_format.rb +17 -0
  392. data/lib/expressir/model/remark_info.rb +92 -0
  393. data/lib/expressir/model/remark_placement.rb +42 -0
  394. data/lib/expressir/model/repository.rb +483 -0
  395. data/lib/expressir/model/repository_validator.rb +293 -0
  396. data/lib/expressir/model/search_engine.rb +551 -0
  397. data/lib/expressir/model/statements/alias.rb +31 -0
  398. data/lib/expressir/model/statements/assignment.rb +23 -0
  399. data/lib/expressir/model/statements/case.rb +42 -0
  400. data/lib/expressir/model/statements/case_action.rb +20 -0
  401. data/lib/expressir/model/statements/compound.rb +21 -0
  402. data/lib/expressir/model/statements/escape.rb +18 -0
  403. data/lib/expressir/model/statements/if.rb +26 -0
  404. data/lib/expressir/model/statements/null.rb +18 -0
  405. data/lib/expressir/model/statements/procedure_call.rb +22 -0
  406. data/lib/expressir/model/statements/repeat.rb +40 -0
  407. data/lib/expressir/model/statements/return.rb +20 -0
  408. data/lib/expressir/model/statements/skip.rb +18 -0
  409. data/lib/expressir/model/statements.rb +20 -0
  410. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +25 -0
  411. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +17 -0
  412. data/lib/expressir/model/supertype_expressions.rb +12 -0
  413. data/lib/expressir/model.rb +39 -0
  414. data/lib/expressir/package/builder.rb +231 -0
  415. data/lib/expressir/package/metadata.rb +79 -0
  416. data/lib/expressir/package/reader.rb +149 -0
  417. data/lib/expressir/package.rb +8 -0
  418. data/lib/expressir/schema_manifest.rb +159 -0
  419. data/lib/expressir/schema_manifest_entry.rb +15 -0
  420. data/lib/expressir/version.rb +8 -0
  421. data/lib/expressir.rb +94 -0
  422. data/lib/tasks/verify_remarks.rake +16 -0
  423. data/rakelib/native.rake +24 -0
  424. data/rakelib/oracle.rake +52 -0
  425. data/rakelib/verify_remarks.rake +16 -0
  426. metadata +692 -0
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "yaml"
4
+ require "tempfile"
5
+ require_relative "../lib/expressir/express/parser"
6
+ require_relative "../lib/expressir/express/formatter"
7
+ require_relative "../lib/expressir/express/schema_head_formatter"
8
+ require_relative "../lib/expressir/express/hyperlink_formatter"
9
+ require_relative "../lib/expressir/express/cache"
10
+
11
+ exp_files = [
12
+ # basic test
13
+ # '../iso-10303-stepmod/data/resources/action_schema/action_schema_annotated.exp',
14
+ # '../iso-10303-stepmod/data/resources/basic_attribute_schema/basic_attribute_schema_annotated.exp',
15
+ # '../iso-10303-stepmod/data/resources/support_resource_schema/support_resource_schema_annotated.exp',
16
+ # cyclic reference test
17
+ # '../iso-10303-stepmod/data/modules/analysis/mim_annotated.exp',
18
+ # '../iso-10303-stepmod/data/modules/analysis_product_relationships/mim_annotated.exp',
19
+ # cyclic reference test 2
20
+ # '../iso-10303-stepmod/data/resources/product_property_definition_schema/product_property_definition_schema_annotated.exp',
21
+ # '../iso-10303-stepmod/data/resources/product_property_representation_schema/product_property_representation_schema_annotated.exp',
22
+ # renamed reference test (36s)
23
+ # '../iso-10303-stepmod/ballots/ballots/ap210_wg12/express/resources/mathematical_functions_schema.exp',
24
+ # '../iso-10303-stepmod/data/resources/iso13584_expressions_schema/iso13584_expressions_schema.exp',
25
+ # annotated-express test (12s)
26
+ # see https://github.com/metanorma/annotated-express/blob/master/data/documents/resources/fundamentals_of_product_description_and_support/sections/04-schemas.adoc
27
+ "../iso-10303-stepmod/data/resources/action_schema/action_schema_annotated.exp",
28
+ "../iso-10303-stepmod/data/resources/application_context_schema/application_context_schema_annotated.exp",
29
+ "../iso-10303-stepmod/data/resources/approval_schema/approval_schema_annotated.exp",
30
+ "../iso-10303-stepmod/data/resources/basic_attribute_schema/basic_attribute_schema_annotated.exp",
31
+ "../iso-10303-stepmod/data/resources/certification_schema/certification_schema_annotated.exp",
32
+ "../iso-10303-stepmod/data/resources/contract_schema/contract_schema_annotated.exp",
33
+ "../iso-10303-stepmod/data/resources/date_time_schema/date_time_schema_annotated.exp",
34
+ "../iso-10303-stepmod/data/resources/document_schema/document_schema.exp",
35
+ "../iso-10303-stepmod/data/resources/effectivity_schema/effectivity_schema_annotated.exp",
36
+ "../iso-10303-stepmod/data/resources/experience_schema/experience_schema_annotated.exp",
37
+ "../iso-10303-stepmod/data/resources/external_reference_schema/external_reference_schema_annotated.exp",
38
+ "../iso-10303-stepmod/data/resources/group_schema/group_schema_annotated.exp",
39
+ "../iso-10303-stepmod/data/resources/language_schema/language_schema_annotated.exp",
40
+ "../iso-10303-stepmod/data/resources/location_schema/location_schema_annotated.exp",
41
+ "../iso-10303-stepmod/data/resources/management_resources_schema/management_resources_schema_annotated.exp",
42
+ "../iso-10303-stepmod/data/resources/measure_schema/measure_schema_annotated.exp",
43
+ "../iso-10303-stepmod/data/resources/person_organization_schema/person_organization_schema_annotated.exp",
44
+ "../iso-10303-stepmod/data/resources/process_property_schema/process_property_schema_annotated.exp",
45
+ "../iso-10303-stepmod/data/resources/product_definition_schema/product_definition_schema_annotated.exp",
46
+ "../iso-10303-stepmod/data/resources/product_property_definition_schema/product_property_definition_schema_annotated.exp",
47
+ "../iso-10303-stepmod/data/resources/product_property_representation_schema/product_property_representation_schema_annotated.exp",
48
+ "../iso-10303-stepmod/data/resources/qualifications_schema/qualifications_schema_annotated.exp",
49
+ "../iso-10303-stepmod/data/resources/security_classification_schema/security_classification_schema_annotated.exp",
50
+ "../iso-10303-stepmod/data/resources/support_resource_schema/support_resource_schema_annotated.exp",
51
+ # full test (6m18s + 8s = 6m26s)
52
+ # *`bundle exec ../stepmod-utils/exe/stepmod-find-express-files ../iso-10303-stepmod`.strip
53
+ # .split("\n").map{|file| File.exists?(file.sub(/\.exp$/, '_annotated.exp')) ? file.sub(/\.exp$/, '_annotated.exp') : file}
54
+ ]
55
+
56
+ start = Time.now
57
+ repository = Expressir::Express::Parser.from_files(exp_files)
58
+ puts "Parser.from_files time: #{(Time.now - start).round(2)}s"
59
+
60
+ temp_file = Tempfile.new
61
+ begin
62
+ start = Time.now
63
+ Expressir::Express::Cache.to_file(temp_file, repository)
64
+ puts "Cache.to_file time: #{(Time.now - start).round(2)}s"
65
+
66
+ start = Time.now
67
+ repository = Expressir::Express::Cache.from_file(temp_file)
68
+ puts "Cache.from_file time: #{(Time.now - start).round(2)}s"
69
+ ensure
70
+ temp_file.close
71
+ temp_file.unlink
72
+ end
73
+
74
+ start = Time.now
75
+ formatter = Class.new(Expressir::Express::Formatter) do
76
+ include Expressir::Express::SchemaHeadFormatter
77
+ include Expressir::Express::HyperlinkFormatter
78
+ end
79
+ repository.to_hash(formatter: formatter)
80
+ puts "Repository.to_hash time: #{(Time.now - start).round(2)}s"
81
+
82
+ # puts YAML.dump(result)
data/expressir.gemspec ADDED
@@ -0,0 +1,61 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "expressir/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "expressir"
7
+ spec.version = Expressir::Version::VERSION
8
+ spec.authors = ["Ribose Inc."]
9
+ spec.email = ["open.source@ribose.com"]
10
+
11
+ spec.summary = "EXPRESS parser and toolkit for Ruby"
12
+ spec.description = 'Expressir ("EXPRESS in Ruby") is a Ruby parser for EXPRESS and a set of tools for accessing EXPRESS data models.'
13
+
14
+ spec.homepage = "https://github.com/lutaml/expressir"
15
+ spec.license = "BSD-2-Clause"
16
+
17
+ spec.bindir = "exe"
18
+ spec.executables = %w[expressir]
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = spec.homepage
23
+ spec.metadata["changelog_uri"] = "https://github.com/lutaml/expressir/releases"
24
+ spec.metadata["rubygems_mfa_required"] = "true"
25
+
26
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
27
+ # Source gem builds on the ruby platform; declaring it keeps
28
+ # rake-compiler's `gem` task from rebuilding the extension for the
29
+ # host ruby during cross builds (rb-sys then sees a windows
30
+ # CARGO_BUILD_TARGET with linux headers and refuses).
31
+ spec.platform = Gem::Platform::RUBY
32
+
33
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
34
+ `git ls-files -z`.split("\x0").reject do |f|
35
+ f.match(%r{^(test|spec|features)/})
36
+ end
37
+ end
38
+
39
+ # Build the Rust core extension at install time. extconf.rb fails
40
+ # soft (dummy Makefile) wherever cargo is unavailable, so installs
41
+ # without a Rust toolchain fall back to the pure-Ruby parser.
42
+ spec.extensions = ["ext/expressir_core/extconf.rb"]
43
+ spec.add_dependency "rb_sys", "~> 0.9.130"
44
+
45
+ spec.add_dependency "base64"
46
+ spec.add_dependency "benchmark"
47
+ spec.add_dependency "benchmark-ips"
48
+ spec.add_dependency "csv"
49
+ spec.add_dependency "liquid"
50
+ spec.add_dependency "lutaml-model", "~> 0.8.76"
51
+ spec.add_dependency "moxml"
52
+ spec.add_dependency "nokogiri"
53
+ spec.add_dependency "paint"
54
+ spec.add_dependency "parsanol", "~> 1.3.9", ">= 1.3.9"
55
+ spec.add_dependency "ruby-progressbar", "~> 1.11"
56
+ spec.add_dependency "rubyzip"
57
+ spec.add_dependency "table_tennis"
58
+ spec.add_dependency "thor", "~> 1.0"
59
+ # Native YAML/JSON engine (lutaml-model opt-in by bundle contents)
60
+ spec.add_dependency "yeptris", "~> 0.6.1"
61
+ end
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,310 @@
1
+ module Expressir
2
+ module Benchmark
3
+ require "benchmark"
4
+ require "json"
5
+ require "csv"
6
+
7
+ class << self
8
+ # Measures the execution time of schema loading and optionally reports it
9
+ # @param file [String] File being processed
10
+ # @param options [Hash] Options for benchmarking
11
+ # @return The result of the block
12
+ def measure_file(file)
13
+ return yield unless Expressir.configuration.benchmark_enabled?
14
+
15
+ if Expressir.configuration.benchmark_ips?
16
+ require "benchmark/ips"
17
+
18
+ result = nil
19
+ ::Benchmark.ips do |x|
20
+ x.config(time: Expressir.configuration.benchmark_iterations,
21
+ warmup: Expressir.configuration.benchmark_warmup)
22
+
23
+ x.report("Loading #{file}") do
24
+ result = yield
25
+ end
26
+
27
+ if Expressir.configuration.benchmark_save?
28
+ x.save! "expressir_benchmark_#{File.basename(file)}"
29
+ end
30
+ end
31
+
32
+ # Calculate objects per second
33
+ if result.is_a?(Model::Repository)
34
+ objects_per_second = calculate_objects_per_second(result)
35
+ puts "Objects per second: #{objects_per_second}" if Expressir.configuration.benchmark_verbose?
36
+ end
37
+
38
+ else
39
+ # Standard benchmarking
40
+ result = nil
41
+ time = ::Benchmark.measure do
42
+ result = yield
43
+ end
44
+
45
+ if result.is_a?(Model::Repository)
46
+ objects_per_second = calculate_objects_per_second(result, time.real)
47
+ output_benchmark_result(file, time.real, objects_per_second)
48
+ else
49
+ output_benchmark_result(file, time.real)
50
+ end
51
+
52
+ end
53
+ result
54
+ end
55
+
56
+ # Benchmarks file collection processing
57
+ # @param files [Array<String>] List of files to process
58
+ # @return [Array] Results from processing files
59
+ def measure_collection(files)
60
+ unless Expressir.configuration.benchmark_enabled?
61
+ # Process each file individually even when benchmarking is disabled
62
+ results = []
63
+ files.each do |file|
64
+ file_results = yield(file)
65
+ results.concat(Array(file_results))
66
+ end
67
+ return results
68
+ end
69
+
70
+ results = []
71
+ total_time = ::Benchmark.measure do
72
+ files.each_with_index do |file, i|
73
+ if Expressir.configuration.benchmark_verbose?
74
+ puts "#{i + 1}/#{files.length} Processing #{file}"
75
+ end
76
+
77
+ file_results = measure_file(file) do
78
+ yield(file)
79
+ end
80
+
81
+ results.concat(Array(file_results))
82
+ end
83
+ end
84
+
85
+ output_collection_result(files.length, total_time.real, results)
86
+ results
87
+ end
88
+
89
+ # Measures reference resolution
90
+ # @return The result of the block
91
+ def measure_references
92
+ return yield unless Expressir.configuration.benchmark_enabled?
93
+
94
+ if Expressir.configuration.benchmark_ips?
95
+ require "benchmark/ips"
96
+
97
+ result = nil
98
+ ::Benchmark.ips do |x|
99
+ x.config(time: Expressir.configuration.benchmark_iterations,
100
+ warmup: Expressir.configuration.benchmark_warmup)
101
+
102
+ x.report("Reference resolution") do
103
+ result = yield
104
+ end
105
+ end
106
+
107
+ else
108
+ result = nil
109
+ time = ::Benchmark.measure do
110
+ result = yield
111
+ end
112
+
113
+ output_benchmark_result("Reference resolution", time.real)
114
+ end
115
+ result
116
+ end
117
+
118
+ # Benchmark with caching
119
+ # @param path [String] Path to the file
120
+ # @param cache_path [String] Path for the cache file
121
+ # @return [Hash] Results with timing information
122
+ def measure_with_cache(path, cache_path = nil)
123
+ return yield(path) unless Expressir.configuration.benchmark_enabled?
124
+
125
+ require "tempfile"
126
+ temp_file = nil
127
+
128
+ unless cache_path
129
+ temp_file = Tempfile.new(["expressir_cache", ".bin"])
130
+ cache_path = temp_file.path
131
+ end
132
+
133
+ results = {}
134
+
135
+ # Measure parsing time
136
+ parsing_time = ::Benchmark.measure do
137
+ results[:repository] = yield(path)
138
+ end
139
+ results[:parsing_time] = parsing_time.real
140
+
141
+ # Measure cache writing time
142
+ cache_write_time = ::Benchmark.measure do
143
+ Expressir::Express::Cache.to_file(cache_path, results[:repository])
144
+ end
145
+ results[:cache_write_time] = cache_write_time.real
146
+
147
+ # Measure cache reading time
148
+ cache_read_time = ::Benchmark.measure do
149
+ results[:cached_repository] =
150
+ Expressir::Express::Cache.from_file(cache_path)
151
+ end
152
+ results[:cache_read_time] = cache_read_time.real
153
+
154
+ # Output results
155
+ if Expressir.configuration.benchmark_verbose?
156
+ puts "Parsing time: #{results[:parsing_time].round(4)}s"
157
+ puts "Cache write time: #{results[:cache_write_time].round(4)}s"
158
+ puts "Cache read time: #{results[:cache_read_time].round(4)}s"
159
+
160
+ if results[:repository].is_a?(Model::Repository)
161
+ objects = count_objects(results[:repository])
162
+ puts "Total objects: #{objects}"
163
+ puts "Objects per second (parsing): #{(objects / results[:parsing_time]).round(2)}"
164
+ puts "Objects per second (reading): #{(objects / results[:cache_read_time]).round(2)}"
165
+ end
166
+ end
167
+
168
+ # Clean up temp file if we created one
169
+ if temp_file
170
+ temp_file.close
171
+ temp_file.unlink
172
+ end
173
+
174
+ results
175
+ end
176
+
177
+ private
178
+
179
+ # Calculate objects per second
180
+ # @param repository [Object] The repository object
181
+ # @param time [Float] The time taken in seconds
182
+ # @return [Float] Objects per second
183
+ def calculate_objects_per_second(repository, time = 1.0)
184
+ objects = count_objects(repository)
185
+ (objects / time).round(2)
186
+ end
187
+
188
+ # Count objects in a repository
189
+ # @param repository [Object] The repository object
190
+ # @return [Integer] Number of objects
191
+ def count_objects(repository)
192
+ return 0 unless repository.is_a?(Model::Repository)
193
+
194
+ count = repository.schemas.size
195
+
196
+ repository.schemas.each do |schema|
197
+ count += schema.entities.size if schema.entities
198
+ count += schema.types.size if schema.types
199
+ count += schema.functions.size if schema.functions
200
+ count += schema.rules.size if schema.rules
201
+ count += schema.procedures.size if schema.procedures
202
+ count += schema.constants.size if schema.constants
203
+
204
+ # Count attributes in entities
205
+ schema.entities&.each do |entity|
206
+ # Count explicit attributes
207
+ if entity.attributes
208
+ count += entity.attributes.size
209
+ end
210
+
211
+ # Count inheritance relationships
212
+ count += 1 if entity.subtype_of
213
+ end
214
+ end
215
+
216
+ count
217
+ end
218
+
219
+ # Output benchmark result in the appropriate format
220
+ # @param label [String] Label for the benchmark
221
+ # @param time [Float] Time in seconds
222
+ # @param objects_per_second [Float, nil] Objects per second metric (optional)
223
+ def output_benchmark_result(label, time, objects_per_second = nil)
224
+ time_rounded = time.round(4)
225
+
226
+ case Expressir.configuration.benchmark_format
227
+ when "json"
228
+ result = {
229
+ label: label,
230
+ time_seconds: time_rounded,
231
+ }
232
+ result[:objects_per_second] = objects_per_second if objects_per_second
233
+ puts JSON.generate(result)
234
+ when "csv"
235
+ headers = ["Label", "Time (s)"]
236
+ headers << "Objects/s" if objects_per_second
237
+
238
+ values = [label, time_rounded]
239
+ values << objects_per_second if objects_per_second
240
+
241
+ puts headers.join(",")
242
+ puts values.join(",")
243
+ else
244
+ # Default format
245
+ message = "#{label}: #{time_rounded}s"
246
+ message += " (#{objects_per_second} objects/s)" if objects_per_second
247
+ puts message if Expressir.configuration.benchmark_verbose?
248
+ end
249
+ end
250
+
251
+ # Output collection benchmark result
252
+ # @param count [Integer] Number of files processed
253
+ # @param total_time [Float] Total time in seconds
254
+ # @param results [Array] Array of results
255
+ def output_collection_result(count, total_time, results)
256
+ avg_time = total_time / count
257
+
258
+ # Get total object count if possible
259
+ total_objects = 0
260
+ schema_count = 0
261
+
262
+ # Try to count total objects and schemas
263
+ results.each do |result|
264
+ if result.is_a?(Model::Repository)
265
+ schema_count += result.schemas.size
266
+ total_objects += count_objects(result)
267
+ elsif result.is_a?(Array)
268
+ result.each do |r|
269
+ if r.is_a?(Model::Declarations::Schema)
270
+ schema_count += 1
271
+ total_objects += 1 # Count the schema itself
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ objects_per_second = (total_objects / total_time).round(2)
278
+
279
+ case Expressir.configuration.benchmark_format
280
+ when "json"
281
+ result = {
282
+ files_processed: count,
283
+ schemas_loaded: schema_count,
284
+ total_objects: total_objects,
285
+ total_time_seconds: total_time.round(4),
286
+ average_time_seconds: avg_time.round(4),
287
+ objects_per_second: objects_per_second,
288
+ }
289
+ puts JSON.generate(result)
290
+ when "csv"
291
+ headers = ["Files", "Schemas", "Objects", "Total Time (s)",
292
+ "Avg Time (s)", "Objects/s"]
293
+ values = [count, schema_count, total_objects, total_time.round(4),
294
+ avg_time.round(4), objects_per_second]
295
+
296
+ puts headers.join(",")
297
+ puts values.join(",")
298
+ else
299
+ # Default format
300
+ if Expressir.configuration.benchmark_verbose?
301
+ puts "\nProcessed #{count} files in #{total_time.round(4)}s"
302
+ puts "Loaded #{schema_count} schemas containing #{total_objects} objects"
303
+ puts "Average time per file: #{avg_time.round(4)}s"
304
+ puts "Performance: #{objects_per_second} objects/s"
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
310
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Changes
5
+ # Represents a single change to an EXPRESS construct
6
+ class ItemChange < Lutaml::Model::Serializable
7
+ attribute :type, :string
8
+ attribute :name, :string
9
+ attribute :description, :string, collection: true
10
+ attribute :interfaced_items, :string
11
+
12
+ yaml do
13
+ map "type", to: :type
14
+ map "name", to: :name
15
+ map "description", to: :description
16
+ map "interfaced_items", to: :interfaced_items
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Changes
5
+ # Represents a mapping change entry
6
+ class MappingChange < Lutaml::Model::Serializable
7
+ attribute :name, :string
8
+ attribute :description, :string
9
+
10
+ yaml do
11
+ map "name", to: :name
12
+ map "description", to: :description
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Changes
5
+ # Represents changes to an EXPRESS schema across multiple versions
6
+ class SchemaChange < Lutaml::Model::Serializable
7
+ attribute :schema, :string
8
+ attribute :versions, VersionChange, collection: true
9
+
10
+ yaml do
11
+ map "schema", to: :schema
12
+ map "versions", to: :versions
13
+ end
14
+
15
+ class << self
16
+ # Load a SchemaChange from a YAML file
17
+ #
18
+ # @param path [String] Path to the YAML file
19
+ # @return [SchemaChange] The loaded schema changes
20
+ def from_file(path)
21
+ content = File.read(path)
22
+ # Handle empty or minimal YAML files
23
+ # Skip leading comments and empty lines
24
+ lines = content.lines
25
+ yaml_start_index = lines.find_index do |line|
26
+ !line.strip.start_with?("#") && !line.strip.empty?
27
+ end
28
+
29
+ if yaml_start_index
30
+ content = lines[yaml_start_index..].join
31
+ end
32
+
33
+ return new if content.strip == "---" || content.strip.empty?
34
+
35
+ from_yaml(content)
36
+ end
37
+ end
38
+
39
+ # Add or update a change version in this schema
40
+ #
41
+ # @param version [String] Version number
42
+ # @param description [String] Description of changes
43
+ # @param changes [Hash] Hash with :additions, :modifications, :deletions
44
+ # @return [VersionChange] The added or updated version
45
+ def add_or_update_version(version, description, changes)
46
+ # Initialize versions array if nil
47
+ self.versions ||= []
48
+
49
+ # Find existing version with this version
50
+ existing_index = versions.find_index do |ed|
51
+ ed.version == version
52
+ end
53
+
54
+ # Create new version
55
+ version = VersionChange.new(
56
+ version: version,
57
+ description: description,
58
+ additions: changes[:additions] || [],
59
+ modifications: changes[:modifications] || [],
60
+ deletions: changes[:deletions] || [],
61
+ )
62
+
63
+ if existing_index
64
+ # Replace existing version with same version
65
+ versions[existing_index] = version
66
+ else
67
+ # Add new version
68
+ versions << version
69
+ end
70
+
71
+ version
72
+ end
73
+
74
+ # Save this SchemaChange to a YAML file
75
+ #
76
+ # @param path [String] Path where to save the file
77
+ # @return [Integer] Number of bytes written
78
+ def to_file(path)
79
+ # Add schema hint for editor support
80
+ content = "# yaml-language-server: $schema=https://www.expresslang.org/schemas/changes/v1/schema_changes.yaml\n#{to_yaml}"
81
+ File.write(path, content)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Changes
5
+ # Represents a version version of schema changes
6
+ class VersionChange < Lutaml::Model::Serializable
7
+ attribute :version, :integer
8
+ attribute :description, :string
9
+ attribute :additions, ItemChange, collection: true
10
+ attribute :modifications, ItemChange, collection: true
11
+ attribute :deletions, ItemChange, collection: true
12
+ attribute :mappings, MappingChange, collection: true
13
+ attribute :changes, MappingChange, collection: true
14
+
15
+ yaml do
16
+ map "version", to: :version
17
+ map "description", to: :description
18
+ map "additions", to: :additions
19
+ map "modifications", to: :modifications
20
+ map "deletions", to: :deletions
21
+ map "mappings", to: :mappings
22
+ map "changes", to: :changes
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ # lib/expressir/changes.rb
2
+ module Expressir
3
+ module Changes
4
+ autoload :SchemaChange, "#{__dir__}/changes/schema_change"
5
+ autoload :VersionChange, "#{__dir__}/changes/version_change"
6
+ autoload :ItemChange, "#{__dir__}/changes/item_change"
7
+ autoload :MappingChange, "#{__dir__}/changes/mapping_change"
8
+ end
9
+ end