@divmain/jdm-asm 0.2.1 → 0.2.3

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 (395) hide show
  1. package/dist/index.js +2227 -29
  2. package/dist/index.js.map +1 -1
  3. package/package.json +8 -2
  4. package/.github/workflows/ci.yml +0 -53
  5. package/.oxfmtrc.json +0 -16
  6. package/.oxlintrc.json +0 -183
  7. package/AGENTS.md +0 -81
  8. package/asconfig.json +0 -23
  9. package/benchmarks/fixtures.ts +0 -111
  10. package/benchmarks/input-fixtures.ts +0 -80
  11. package/benchmarks/run.ts +0 -913
  12. package/benchmarks/worker-pool.ts +0 -223
  13. package/benchmarks/worker.ts +0 -374
  14. package/scripts/run-all-tests.ts +0 -220
  15. package/src/compiler/EXPRESSION_SUBSETS.md +0 -228
  16. package/src/compiler/asc-compiler.ts +0 -315
  17. package/src/compiler/ast-types.ts +0 -215
  18. package/src/compiler/build.ts +0 -56
  19. package/src/compiler/cache.ts +0 -414
  20. package/src/compiler/code-generators.ts +0 -211
  21. package/src/compiler/codegen/index.ts +0 -15
  22. package/src/compiler/codegen/js-marshal.ts +0 -999
  23. package/src/compiler/codegen/js-validation.ts +0 -243
  24. package/src/compiler/codegen.ts +0 -19
  25. package/src/compiler/compile-time-validation.ts +0 -507
  26. package/src/compiler/cst-visitor.ts +0 -434
  27. package/src/compiler/errors.ts +0 -227
  28. package/src/compiler/expression-parser.ts +0 -536
  29. package/src/compiler/graph.ts +0 -197
  30. package/src/compiler/index.ts +0 -199
  31. package/src/compiler/input-validation.ts +0 -33
  32. package/src/compiler/marshal-gen.ts +0 -21
  33. package/src/compiler/nodes/context-resolvers.ts +0 -197
  34. package/src/compiler/nodes/decision-table.ts +0 -507
  35. package/src/compiler/nodes/decision.ts +0 -292
  36. package/src/compiler/nodes/expression-compiler.ts +0 -526
  37. package/src/compiler/nodes/expression.ts +0 -425
  38. package/src/compiler/nodes/function.ts +0 -316
  39. package/src/compiler/nodes/input.ts +0 -60
  40. package/src/compiler/nodes/switch.ts +0 -547
  41. package/src/compiler/optimizer.ts +0 -948
  42. package/src/compiler/orchestrator.ts +0 -352
  43. package/src/compiler/parser.ts +0 -115
  44. package/src/compiler/result-selection.ts +0 -161
  45. package/src/compiler/runtime/index.ts +0 -26
  46. package/src/compiler/runtime-codegen.ts +0 -211
  47. package/src/compiler/runtime-validation-codegen.ts +0 -294
  48. package/src/compiler/runtime.ts +0 -452
  49. package/src/compiler/schema.ts +0 -245
  50. package/src/compiler/switch-branch-detection.ts +0 -92
  51. package/src/compiler/types.ts +0 -136
  52. package/src/compiler/unary-ast-transforms.ts +0 -148
  53. package/src/compiler/unary-parser.ts +0 -301
  54. package/src/compiler/unary-transform.ts +0 -161
  55. package/src/compiler/utils.ts +0 -27
  56. package/src/compiler/virtual-fs.ts +0 -90
  57. package/src/compiler/wasm-instantiate.ts +0 -127
  58. package/src/index.ts +0 -1
  59. package/src/runtime/arrays.ts +0 -579
  60. package/src/runtime/context.ts +0 -189
  61. package/src/runtime/expressions.ts +0 -1811
  62. package/src/runtime/index.ts +0 -8
  63. package/src/runtime/memory.ts +0 -607
  64. package/src/runtime/strings.ts +0 -260
  65. package/src/runtime/tables.ts +0 -96
  66. package/src/runtime/tsconfig.json +0 -4
  67. package/src/runtime/values.ts +0 -209
  68. package/test-data/README.md +0 -83
  69. package/test-data/decision-tables/basic/8k.json +0 -87992
  70. package/test-data/decision-tables/basic/affiliate-commission-calculator.json +0 -228
  71. package/test-data/decision-tables/basic/airline-loyalty-points-calculations.json +0 -285
  72. package/test-data/decision-tables/basic/airline-upgrade-eligibility.json +0 -466
  73. package/test-data/decision-tables/basic/auto-insurance-premium-calculator.json +0 -412
  74. package/test-data/decision-tables/basic/booking-personalization-system.json +0 -553
  75. package/test-data/decision-tables/basic/care-team-assignment-system.json +0 -585
  76. package/test-data/decision-tables/basic/claim-validation-system.json +0 -307
  77. package/test-data/decision-tables/basic/clinical-lab-result-interpreter.json +0 -433
  78. package/test-data/decision-tables/basic/clinical-treatment-protocol.json +0 -474
  79. package/test-data/decision-tables/basic/credit-limit-adjustment.json +0 -479
  80. package/test-data/decision-tables/basic/customer-eligibility-engine.json +0 -551
  81. package/test-data/decision-tables/basic/customer-lifetime-value.json +0 -200
  82. package/test-data/decision-tables/basic/customer-onboarding-kyc-verification.json +0 -611
  83. package/test-data/decision-tables/basic/customer-service-escalation.json +0 -191
  84. package/test-data/decision-tables/basic/decision-table-discounts.json +0 -168
  85. package/test-data/decision-tables/basic/decision-table-shipping.json +0 -398
  86. package/test-data/decision-tables/basic/delivery-route-optimizer.json +0 -271
  87. package/test-data/decision-tables/basic/device-compatibility-checker.json +0 -303
  88. package/test-data/decision-tables/basic/disaster-relief-fund-allocation.json +0 -296
  89. package/test-data/decision-tables/basic/dynamic-fx-rate-pricing-system.json +0 -237
  90. package/test-data/decision-tables/basic/dynamic-marketplace-comission-calculator.json +0 -242
  91. package/test-data/decision-tables/basic/dynamic-shipping-cost-calculator.json +0 -378
  92. package/test-data/decision-tables/basic/dynamic-tarrif-engine.json +0 -289
  93. package/test-data/decision-tables/basic/dynamic-ticket-pricing.json +0 -325
  94. package/test-data/decision-tables/basic/empty-column-with-space.json +0 -100
  95. package/test-data/decision-tables/basic/empty-column-without-space.json +0 -100
  96. package/test-data/decision-tables/basic/environment-compliance-assessment.json +0 -386
  97. package/test-data/decision-tables/basic/expression-table-map.json +0 -313
  98. package/test-data/decision-tables/basic/flash-sale-eligibility.json +0 -366
  99. package/test-data/decision-tables/basic/flight-dispatch-decision-system.json +0 -455
  100. package/test-data/decision-tables/basic/flight-rebooking-fee-calculator.json +0 -406
  101. package/test-data/decision-tables/basic/government-assistance.json +0 -299
  102. package/test-data/decision-tables/basic/grant-funding-distribution.json +0 -307
  103. package/test-data/decision-tables/basic/hazardous-materials-management-system.json +0 -414
  104. package/test-data/decision-tables/basic/immigration-eligibility-evaluator.json +0 -765
  105. package/test-data/decision-tables/basic/import-duties-calculator.json +0 -318
  106. package/test-data/decision-tables/basic/insurance-agent-commission.json +0 -228
  107. package/test-data/decision-tables/basic/insurance-coverage-calculator.json +0 -362
  108. package/test-data/decision-tables/basic/insurance-underwriting-risk.json +0 -321
  109. package/test-data/decision-tables/basic/international-roaming-policy-manager.json +0 -199
  110. package/test-data/decision-tables/basic/legacy-plan-management.json +0 -434
  111. package/test-data/decision-tables/basic/marketplace-listing-verification-system.json +0 -334
  112. package/test-data/decision-tables/basic/medication-dosage-calculator.json +0 -318
  113. package/test-data/decision-tables/basic/merch-bags.json +0 -171
  114. package/test-data/decision-tables/basic/municipal-permit-evaluation-system.json +0 -364
  115. package/test-data/decision-tables/basic/mvno-partner-enablement.json +0 -313
  116. package/test-data/decision-tables/basic/partner-revenue-sharing.json +0 -244
  117. package/test-data/decision-tables/basic/payment-routing-and-fee-calculator.json +0 -475
  118. package/test-data/decision-tables/basic/policy-discount-calculator.json +0 -307
  119. package/test-data/decision-tables/basic/policy-eligibility-analyzer.json +0 -299
  120. package/test-data/decision-tables/basic/product-listing-scoring.json +0 -358
  121. package/test-data/decision-tables/basic/realtime-fraud-detection.json +0 -235
  122. package/test-data/decision-tables/basic/regional-compliance-manager.json +0 -278
  123. package/test-data/decision-tables/basic/returns-and-refund-policy.json +0 -366
  124. package/test-data/decision-tables/basic/returns-processing-system.json +0 -448
  125. package/test-data/decision-tables/basic/school-district-resource-allocation.json +0 -282
  126. package/test-data/decision-tables/basic/seat-map-optimization.json +0 -325
  127. package/test-data/decision-tables/basic/seller-fee-calculator.json +0 -307
  128. package/test-data/decision-tables/basic/service-level-agreement-enforcement.json +0 -575
  129. package/test-data/decision-tables/basic/smart-financial-product-matcher.json +0 -249
  130. package/test-data/decision-tables/basic/supply-chain-risk.json +0 -316
  131. package/test-data/decision-tables/basic/table-loop.json +0 -93
  132. package/test-data/decision-tables/basic/table.json +0 -76
  133. package/test-data/decision-tables/basic/traffic-violation-penalty-calculator.json +0 -436
  134. package/test-data/decision-tables/basic/transaction-compliance-classifier.json +0 -525
  135. package/test-data/decision-tables/basic/vehicle-claims-resolution.json +0 -310
  136. package/test-data/decision-tables/basic/warehouse-storage-location.json +0 -345
  137. package/test-data/decision-tables/hit-policy-collect/collect-multiple-matches.json +0 -127
  138. package/test-data/decision-tables/hit-policy-collect/collect-no-match.json +0 -95
  139. package/test-data/decision-tables/hit-policy-first/first-match.json +0 -103
  140. package/test-data/decision-tables/hit-policy-first/no-match.json +0 -95
  141. package/test-data/decision-tables/hit-policy-output-order/output-order-respected.json +0 -94
  142. package/test-data/decision-tables/hit-policy-output-order/string-output-order.json +0 -94
  143. package/test-data/decision-tables/hit-policy-priority/priority-respected.json +0 -86
  144. package/test-data/decision-tables/hit-policy-rule-order/rule-order-respected.json +0 -94
  145. package/test-data/decision-tables/hit-policy-unique/all-match-error.json +0 -89
  146. package/test-data/decision-tables/hit-policy-unique/multiple-match-error.json +0 -89
  147. package/test-data/decision-tables/hit-policy-unique/no-match.json +0 -88
  148. package/test-data/decision-tables/hit-policy-unique/unique-match.json +0 -99
  149. package/test-data/expressions/arithmetic/error-cyclic.json +0 -114
  150. package/test-data/expressions/arithmetic/error-missing-input.json +0 -54
  151. package/test-data/expressions/arithmetic/error-missing-output.json +0 -54
  152. package/test-data/expressions/arithmetic/expression-default.json +0 -93
  153. package/test-data/expressions/arithmetic/expression-fields.json +0 -94
  154. package/test-data/expressions/arithmetic/expression-loop.json +0 -94
  155. package/test-data/expressions/arithmetic/expression-passthrough.json +0 -108
  156. package/test-data/expressions/arithmetic/expression.json +0 -69
  157. package/test-data/expressions/arithmetic/nested-request.json +0 -125
  158. package/test-data/expressions/arithmetic/number-function.json +0 -58
  159. package/test-data/expressions/arithmetic/test-number-functions.json +0 -68
  160. package/test-data/expressions/functions/all.json +0 -149
  161. package/test-data/expressions/functions/avg.json +0 -89
  162. package/test-data/expressions/functions/filter.json +0 -109
  163. package/test-data/expressions/functions/flat.json +0 -167
  164. package/test-data/expressions/functions/map-strings.json +0 -65
  165. package/test-data/expressions/functions/map.json +0 -73
  166. package/test-data/expressions/functions/reduce.json +0 -49
  167. package/test-data/expressions/functions/some.json +0 -175
  168. package/test-data/expressions/functions/sort-strings.json +0 -97
  169. package/test-data/expressions/functions/sort.json +0 -97
  170. package/test-data/expressions/logical/logical-and.json +0 -116
  171. package/test-data/expressions/logical/logical-complex.json +0 -260
  172. package/test-data/expressions/logical/logical-not.json +0 -111
  173. package/test-data/expressions/logical/logical-or.json +0 -123
  174. package/test-data/expressions/string/string-comparison.json +0 -128
  175. package/test-data/expressions/string/string-concat.json +0 -106
  176. package/test-data/expressions/string/string-contains.json +0 -125
  177. package/test-data/expressions/string/string-endsWith.json +0 -113
  178. package/test-data/expressions/string/string-indexOf.json +0 -131
  179. package/test-data/expressions/string/string-join.json +0 -92
  180. package/test-data/expressions/string/string-lower.json +0 -94
  181. package/test-data/expressions/string/string-replace.json +0 -130
  182. package/test-data/expressions/string/string-split.json +0 -101
  183. package/test-data/expressions/string/string-startsWith.json +0 -113
  184. package/test-data/expressions/string/string-substring.json +0 -138
  185. package/test-data/expressions/string/string-trim.json +0 -100
  186. package/test-data/expressions/string/string-upper.json +0 -94
  187. package/test-data/other/custom.json +0 -51
  188. package/test-data/other/customer-input-schema.json +0 -34
  189. package/test-data/other/customer-output-schema.json +0 -34
  190. package/test-data/other/passthrough.json +0 -31
  191. package/test-data/sub-decisions/basic/$nodes-child.json +0 -31
  192. package/test-data/sub-decisions/basic/$nodes-parent.json +0 -49
  193. package/test-data/sub-decisions/basic/recursive-table1.json +0 -49
  194. package/test-data/sub-decisions/basic/recursive-table2.json +0 -49
  195. package/test-data/sub-decisions/complex-multi/approval-decision.json +0 -31
  196. package/test-data/sub-decisions/complex-multi/complex-dag.json +0 -175
  197. package/test-data/sub-decisions/complex-multi/credit-check.json +0 -31
  198. package/test-data/sub-decisions/complex-multi/customer-segmentation.json +0 -31
  199. package/test-data/sub-decisions/complex-multi/discount-eligibility.json +0 -31
  200. package/test-data/sub-decisions/complex-multi/eligibility-check.json +0 -31
  201. package/test-data/sub-decisions/complex-multi/final-offer.json +0 -31
  202. package/test-data/sub-decisions/complex-multi/income-verification.json +0 -31
  203. package/test-data/sub-decisions/complex-multi/linear-chain.json +0 -121
  204. package/test-data/sub-decisions/complex-multi/pricing-calculation.json +0 -31
  205. package/test-data/sub-decisions/complex-multi/product-eligibility.json +0 -31
  206. package/test-data/sub-decisions/complex-multi/risk-assessment.json +0 -31
  207. package/test-data/sub-decisions/complex-multi/shared-validation.json +0 -31
  208. package/test-data/sub-decisions/complex-multi/validation.json +0 -31
  209. package/test-data/sub-decisions/diamond/decision-a.json +0 -31
  210. package/test-data/sub-decisions/diamond/decision-b.json +0 -31
  211. package/test-data/sub-decisions/diamond/decision-c.json +0 -31
  212. package/test-data/sub-decisions/diamond/decision-shared.json +0 -31
  213. package/test-data/sub-decisions/diamond/diamond-pattern.json +0 -109
  214. package/test-data/sub-decisions/error-propagation/parent-calls-error.json +0 -44
  215. package/test-data/sub-decisions/error-propagation/sub-decision-with-error.json +0 -60
  216. package/test-data/switch-nodes/basic/account-dormancy-management.json +0 -245
  217. package/test-data/switch-nodes/basic/application-risk-assessment.json +0 -474
  218. package/test-data/switch-nodes/basic/cellular-data-rollover-system.json +0 -281
  219. package/test-data/switch-nodes/basic/clinical-pathway-selection.json +0 -454
  220. package/test-data/switch-nodes/basic/insurance-prior-authorization.json +0 -467
  221. package/test-data/switch-nodes/basic/last-mile-delivery-assignment.json +0 -373
  222. package/test-data/switch-nodes/basic/loan-approval.json +0 -469
  223. package/test-data/switch-nodes/basic/multi-switch.json +0 -498
  224. package/test-data/switch-nodes/basic/online-checkin-eligibility.json +0 -285
  225. package/test-data/switch-nodes/basic/order-consolidation-system.json +0 -493
  226. package/test-data/switch-nodes/basic/seller-approval-workflow.json +0 -383
  227. package/test-data/switch-nodes/basic/set-fee.json +0 -243
  228. package/test-data/switch-nodes/basic/shipping-carrier-selector.json +0 -379
  229. package/test-data/switch-nodes/basic/switch-node.json +0 -167
  230. package/test-data/switch-nodes/basic/switch-performance-2.json +0 -1307
  231. package/test-data/switch-nodes/basic/switch-performance.json +0 -691
  232. package/test-data/switch-nodes/basic/tax-exemption.json +0 -295
  233. package/test-data/switch-nodes/basic/warehouse-cross-docking.json +0 -313
  234. package/test-data/switch-nodes/default-cases/switch-with-default.json +0 -134
  235. package/test-data/zen-reference/$nodes-child.json +0 -69
  236. package/test-data/zen-reference/$nodes-parent.json +0 -34
  237. package/test-data/zen-reference/8k.json +0 -87992
  238. package/test-data/zen-reference/credit-analysis.json +0 -324
  239. package/test-data/zen-reference/custom.json +0 -51
  240. package/test-data/zen-reference/customer-input-schema.json +0 -34
  241. package/test-data/zen-reference/customer-output-schema.json +0 -34
  242. package/test-data/zen-reference/error-cyclic.json +0 -114
  243. package/test-data/zen-reference/error-missing-input.json +0 -54
  244. package/test-data/zen-reference/error-missing-output.json +0 -54
  245. package/test-data/zen-reference/expression.json +0 -69
  246. package/test-data/zen-reference/function-v2.json +0 -48
  247. package/test-data/zen-reference/function.json +0 -46
  248. package/test-data/zen-reference/graphs/account-dormancy-management.json +0 -245
  249. package/test-data/zen-reference/graphs/affiliate-commission-calculator.json +0 -228
  250. package/test-data/zen-reference/graphs/airline-loyalty-points-calculations.json +0 -285
  251. package/test-data/zen-reference/graphs/airline-upgrade-eligibility.json +0 -466
  252. package/test-data/zen-reference/graphs/aml.json +0 -537
  253. package/test-data/zen-reference/graphs/application-risk-assessment.json +0 -474
  254. package/test-data/zen-reference/graphs/auto-insurance-premium-calculator.json +0 -412
  255. package/test-data/zen-reference/graphs/booking-personalization-system.json +0 -553
  256. package/test-data/zen-reference/graphs/care-team-assignment-system.json +0 -585
  257. package/test-data/zen-reference/graphs/cellular-data-rollover-system.json +0 -281
  258. package/test-data/zen-reference/graphs/claim-validation-system.json +0 -307
  259. package/test-data/zen-reference/graphs/clinical-lab-result-interpreter.json +0 -433
  260. package/test-data/zen-reference/graphs/clinical-pathway-selection.json +0 -454
  261. package/test-data/zen-reference/graphs/clinical-treatment-protocol.json +0 -474
  262. package/test-data/zen-reference/graphs/company-analysis.json +0 -390
  263. package/test-data/zen-reference/graphs/credit-limit-adjustment.json +0 -479
  264. package/test-data/zen-reference/graphs/customer-eligibility-engine.json +0 -551
  265. package/test-data/zen-reference/graphs/customer-lifetime-value.json +0 -200
  266. package/test-data/zen-reference/graphs/customer-onboarding-kyc-verification.json +0 -611
  267. package/test-data/zen-reference/graphs/customer-service-escalation.json +0 -191
  268. package/test-data/zen-reference/graphs/decision-table-discounts.json +0 -168
  269. package/test-data/zen-reference/graphs/decision-table-shipping.json +0 -398
  270. package/test-data/zen-reference/graphs/delivery-route-optimizer.json +0 -271
  271. package/test-data/zen-reference/graphs/device-compatibility-checker.json +0 -303
  272. package/test-data/zen-reference/graphs/disaster-relief-fund-allocation.json +0 -296
  273. package/test-data/zen-reference/graphs/dynamic-fx-rate-pricing-system.json +0 -237
  274. package/test-data/zen-reference/graphs/dynamic-marketplace-comission-calculator.json +0 -242
  275. package/test-data/zen-reference/graphs/dynamic-shipping-cost-calculator.json +0 -378
  276. package/test-data/zen-reference/graphs/dynamic-tarrif-engine.json +0 -289
  277. package/test-data/zen-reference/graphs/dynamic-ticket-pricing.json +0 -325
  278. package/test-data/zen-reference/graphs/empty-column-with-space.json +0 -100
  279. package/test-data/zen-reference/graphs/empty-column-without-space.json +0 -100
  280. package/test-data/zen-reference/graphs/environment-compliance-assessment.json +0 -386
  281. package/test-data/zen-reference/graphs/expression-default.json +0 -93
  282. package/test-data/zen-reference/graphs/expression-fields.json +0 -94
  283. package/test-data/zen-reference/graphs/expression-loop.json +0 -94
  284. package/test-data/zen-reference/graphs/expression-passthrough.json +0 -108
  285. package/test-data/zen-reference/graphs/expression-table-map.json +0 -313
  286. package/test-data/zen-reference/graphs/flash-sale-eligibility.json +0 -366
  287. package/test-data/zen-reference/graphs/flight-dispatch-decision-system.json +0 -455
  288. package/test-data/zen-reference/graphs/flight-rebooking-fee-calculator.json +0 -406
  289. package/test-data/zen-reference/graphs/government-assistance.json +0 -299
  290. package/test-data/zen-reference/graphs/grant-funding-distribution.json +0 -307
  291. package/test-data/zen-reference/graphs/hazardous-materials-management-system.json +0 -414
  292. package/test-data/zen-reference/graphs/immigration-eligibility-evaluator.json +0 -765
  293. package/test-data/zen-reference/graphs/import-duties-calculator.json +0 -318
  294. package/test-data/zen-reference/graphs/insurance-agent-commission.json +0 -228
  295. package/test-data/zen-reference/graphs/insurance-breakdown.json +0 -421
  296. package/test-data/zen-reference/graphs/insurance-coverage-calculator.json +0 -362
  297. package/test-data/zen-reference/graphs/insurance-prior-authorization.json +0 -467
  298. package/test-data/zen-reference/graphs/insurance-underwriting-risk.json +0 -321
  299. package/test-data/zen-reference/graphs/international-roaming-policy-manager.json +0 -199
  300. package/test-data/zen-reference/graphs/last-mile-delivery-assignment.json +0 -373
  301. package/test-data/zen-reference/graphs/legacy-plan-management.json +0 -434
  302. package/test-data/zen-reference/graphs/loan-approval.json +0 -469
  303. package/test-data/zen-reference/graphs/marketplace-listing-verification-system.json +0 -334
  304. package/test-data/zen-reference/graphs/medication-dosage-calculator.json +0 -318
  305. package/test-data/zen-reference/graphs/merch-bags.json +0 -171
  306. package/test-data/zen-reference/graphs/multi-switch.json +0 -498
  307. package/test-data/zen-reference/graphs/municipal-permit-evaluation-system.json +0 -364
  308. package/test-data/zen-reference/graphs/mvno-partner-enablement.json +0 -313
  309. package/test-data/zen-reference/graphs/nested-request.json +0 -125
  310. package/test-data/zen-reference/graphs/online-checkin-eligibility.json +0 -285
  311. package/test-data/zen-reference/graphs/order-consolidation-system.json +0 -493
  312. package/test-data/zen-reference/graphs/partner-revenue-sharing.json +0 -244
  313. package/test-data/zen-reference/graphs/payment-routing-and-fee-calculator.json +0 -475
  314. package/test-data/zen-reference/graphs/policy-discount-calculator.json +0 -307
  315. package/test-data/zen-reference/graphs/policy-eligibility-analyzer.json +0 -299
  316. package/test-data/zen-reference/graphs/product-listing-scoring.json +0 -358
  317. package/test-data/zen-reference/graphs/realtime-fraud-detection.json +0 -235
  318. package/test-data/zen-reference/graphs/regional-compliance-manager.json +0 -278
  319. package/test-data/zen-reference/graphs/returns-and-refund-policy.json +0 -366
  320. package/test-data/zen-reference/graphs/returns-processing-system.json +0 -448
  321. package/test-data/zen-reference/graphs/school-district-resource-allocation.json +0 -282
  322. package/test-data/zen-reference/graphs/seat-map-optimization.json +0 -325
  323. package/test-data/zen-reference/graphs/seller-approval-workflow.json +0 -383
  324. package/test-data/zen-reference/graphs/seller-fee-calculator.json +0 -307
  325. package/test-data/zen-reference/graphs/service-level-agreement-enforcement.json +0 -575
  326. package/test-data/zen-reference/graphs/set-fee.json +0 -243
  327. package/test-data/zen-reference/graphs/shipping-carrier-selector.json +0 -379
  328. package/test-data/zen-reference/graphs/smart-financial-product-matcher.json +0 -249
  329. package/test-data/zen-reference/graphs/supply-chain-risk.json +0 -316
  330. package/test-data/zen-reference/graphs/table-loop.json +0 -93
  331. package/test-data/zen-reference/graphs/tax-exemption.json +0 -295
  332. package/test-data/zen-reference/graphs/traffic-violation-penalty-calculator.json +0 -436
  333. package/test-data/zen-reference/graphs/transaction-compliance-classifier.json +0 -525
  334. package/test-data/zen-reference/graphs/vehicle-claims-resolution.json +0 -310
  335. package/test-data/zen-reference/graphs/warehouse-cross-docking.json +0 -313
  336. package/test-data/zen-reference/graphs/warehouse-storage-location.json +0 -345
  337. package/test-data/zen-reference/http-function.json +0 -34
  338. package/test-data/zen-reference/infinite-function.json +0 -46
  339. package/test-data/zen-reference/js/imports.js +0 -25
  340. package/test-data/zen-reference/passthrough.json +0 -31
  341. package/test-data/zen-reference/recursive-table1.json +0 -49
  342. package/test-data/zen-reference/recursive-table2.json +0 -49
  343. package/test-data/zen-reference/sleep-function.json +0 -34
  344. package/test-data/zen-reference/switch-node.json +0 -167
  345. package/test-data/zen-reference/switch-performance-2.json +0 -1307
  346. package/test-data/zen-reference/switch-performance.json +0 -691
  347. package/test-data/zen-reference/table.json +0 -76
  348. package/tests/helpers/index.ts +0 -73
  349. package/tests/helpers/mock-context.ts +0 -231
  350. package/tests/helpers/round-trip.ts +0 -398
  351. package/tests/helpers/test-harness-comparison.ts +0 -325
  352. package/tests/helpers/test-harness-wasm.ts +0 -710
  353. package/tests/helpers/test-harness.ts +0 -28
  354. package/tests/helpers/wasm-test.ts +0 -659
  355. package/tests/integration/compilation-errors.test.ts +0 -864
  356. package/tests/integration/decision-tables.test.ts +0 -531
  357. package/tests/integration/edge-cases.test.ts +0 -787
  358. package/tests/integration/expressions.test.ts +0 -513
  359. package/tests/integration/function-node-integration.test.ts +0 -182
  360. package/tests/integration/sub-decisions.test.ts +0 -108
  361. package/tests/integration/switch-nodes.test.ts +0 -399
  362. package/tests/integration/unary-or-matching.test.ts +0 -53
  363. package/tests/integration/wasm-data-types.test.ts +0 -398
  364. package/tests/integration/wasm-errors.test.ts +0 -199
  365. package/tests/integration/wasm-execution.test.ts +0 -348
  366. package/tests/integration/wasm-memory.test.ts +0 -228
  367. package/tests/scripts/analyze-coverage.ts +0 -166
  368. package/tests/scripts/categorize-tests.ts +0 -396
  369. package/tests/scripts/coverage-analysis.ts +0 -836
  370. package/tests/unit/compiler/cache.test.ts +0 -238
  371. package/tests/unit/compiler/errors.test.ts +0 -316
  372. package/tests/unit/compiler/graph-scalability.test.ts +0 -510
  373. package/tests/unit/compiler/graph.test.ts +0 -878
  374. package/tests/unit/compiler/input-validation.test.ts +0 -447
  375. package/tests/unit/compiler/logical-and-parser.test.ts +0 -143
  376. package/tests/unit/compiler/logical-not-parser.test.ts +0 -107
  377. package/tests/unit/compiler/logical-or-parser.test.ts +0 -236
  378. package/tests/unit/compiler/marshal-gen/marshal-gen.test.ts +0 -97
  379. package/tests/unit/compiler/nodes/decision-table.test.ts +0 -103
  380. package/tests/unit/compiler/nodes/decision.test.ts +0 -182
  381. package/tests/unit/compiler/nodes/function-compile.test.ts +0 -204
  382. package/tests/unit/compiler/nodes/function.test.ts +0 -176
  383. package/tests/unit/compiler/nodes/input.test.ts +0 -30
  384. package/tests/unit/compiler/nodes/switch.test.ts +0 -127
  385. package/tests/unit/compiler/optimizer-cache.test.ts +0 -327
  386. package/tests/unit/compiler/optimizer-implementation.test.ts +0 -625
  387. package/tests/unit/compiler/parser.test.ts +0 -508
  388. package/tests/unit/compiler/runtime-error-cleanup.test.ts +0 -426
  389. package/tests/unit/compiler/runtime-validation.test.ts +0 -303
  390. package/tests/unit/compiler/runtime.test.ts +0 -221
  391. package/tests/unit/compiler/schema/schema.test.ts +0 -248
  392. package/tests/unit/compiler/unary-ast-transforms.test.ts +0 -245
  393. package/tsconfig.json +0 -27
  394. package/tsup.config.ts +0 -11
  395. package/vitest.config.ts +0 -12
@@ -1,948 +0,0 @@
1
- /**
2
- * Optimization Pipeline for JDM to WebAssembly Compilation
3
- *
4
- * This module defines the interface for optimization passes and the runner
5
- * that applies them sequentially to transform the compiled AST into an
6
- * optimized form before code generation.
7
- */
8
-
9
- import { type JDMDecision, type JDMNode, NodeType } from './parser';
10
- import {
11
- type ExpressionAST,
12
- type NumberLiteral,
13
- type StringLiteral,
14
- type BooleanLiteral,
15
- isNumberLiteral,
16
- isStringLiteral,
17
- isBooleanLiteral,
18
- isNullLiteral,
19
- isBinaryOp,
20
- isUnaryOp,
21
- isTernaryOp,
22
- } from './ast-types';
23
- import { parseStandardExpression, parseUnaryExpression } from './unary-parser';
24
-
25
- /**
26
- * Cache for parsed expression ASTs.
27
- * Maps expression strings to their parsed AST nodes to avoid redundant parsing.
28
- */
29
- type ExpressionCache = Map<string, ExpressionAST>;
30
-
31
- /**
32
- * Compiled AST - the intermediate representation after parsing.
33
- *
34
- * JDMDecision structure is simple enough for in-place transformation, avoiding the
35
- * complexity and memory overhead of building a separate intermediate representation.
36
- */
37
- export type CompiledAST = JDMDecision;
38
-
39
- /**
40
- * Interface for an optimization pass.
41
- *
42
- * Each optimization pass receives the compiled AST and returns a
43
- * potentially modified/optimized AST.
44
- */
45
- export interface OptimizationPass {
46
- /** Human-readable name of the optimization pass */
47
- name: string;
48
-
49
- /**
50
- * Run the optimization pass on the given AST.
51
- *
52
- * @param ast - The compiled AST to optimize
53
- * @returns The optimized AST
54
- */
55
- run(ast: CompiledAST): CompiledAST;
56
- }
57
-
58
- /**
59
- * Ordered list of optimization passes.
60
- *
61
- * Passes have dependencies - one pass may create opportunities for the next. For example,
62
- * constant folding might convert "if (2 > 3)" to "if (false)", then dead code elimination
63
- * removes the unreachable branch. Running DCE before folding would miss this optimization.
64
- */
65
- export const optimizer: OptimizationPass[] = [
66
- { name: 'Constant Folding', run: constantFolding },
67
- { name: 'Dead Code Elimination', run: deadCodeElimination },
68
- { name: 'Expression Inlining', run: expressionInlining },
69
- { name: 'Table Indexing', run: tableIndexing },
70
- ];
71
-
72
- /**
73
- * Run all optimization passes sequentially on the given AST.
74
- *
75
- * @param ast - The compiled AST to optimize
76
- * @returns The fully optimized AST
77
- */
78
- export function runOptimizations(ast: CompiledAST): CompiledAST {
79
- let optimized = ast;
80
-
81
- for (const pass of optimizer) {
82
- optimized = pass.run(optimized);
83
- }
84
-
85
- return optimized;
86
- }
87
-
88
- // ============================================================================
89
- // Expression Cache Utilities
90
- // ============================================================================
91
-
92
- /**
93
- * Get the expression cache for a node, creating it if it doesn't exist.
94
- */
95
- function getExpressionCache(node: JDMNode): ExpressionCache {
96
- if (!node.parsedContent) {
97
- node.parsedContent = {};
98
- }
99
- if (!node.parsedContent._cachedExprs) {
100
- node.parsedContent._cachedExprs = new Map<string, ExpressionAST>();
101
- }
102
- return node.parsedContent._cachedExprs as ExpressionCache;
103
- }
104
-
105
- /**
106
- * Parse an expression with caching.
107
- * Checks the cache first, and only parses if not found.
108
- */
109
- function cachedParseUnary(node: JDMNode, expr: string): ExpressionAST {
110
- const cache = getExpressionCache(node);
111
- const cached = cache.get(expr);
112
- if (cached) {
113
- return cached;
114
- }
115
- const parsed = parseUnaryExpression(expr);
116
- cache.set(expr, parsed);
117
- return parsed;
118
- }
119
-
120
- /**
121
- * Parse a standard expression with caching.
122
- * Checks the cache first, and only parses if not found.
123
- */
124
- function cachedParseStandard(node: JDMNode, expr: string): ExpressionAST {
125
- const cache = getExpressionCache(node);
126
- const cached = cache.get(expr);
127
- if (cached) {
128
- return cached;
129
- }
130
- const parsed = parseStandardExpression(expr);
131
- cache.set(expr, parsed);
132
- return parsed;
133
- }
134
-
135
- /**
136
- * Clear the expression cache for a node.
137
- * Should be called when the node's expressions are modified.
138
- */
139
- function clearExpressionCache(node: JDMNode): void {
140
- if (node.parsedContent && node.parsedContent._cachedExprs) {
141
- node.parsedContent._cachedExprs.clear();
142
- }
143
- }
144
-
145
- // Export individual optimization passes for testing
146
- export { constantFolding, deadCodeElimination, expressionInlining, tableIndexing };
147
-
148
- // Export cache utilities for testing
149
- export { getExpressionCache, clearExpressionCache };
150
-
151
- // ============================================================================
152
- // Constant Folding
153
- // ============================================================================
154
-
155
- /**
156
- * Fold constant expressions at compile time.
157
- *
158
- * This pass traverses expression ASTs and evaluates them at compile time
159
- * when possible. Examples:
160
- * - Replace (2 + 3) with 5
161
- * - Replace true and false with false
162
- * - Replace "hello" + " world" with "hello world"
163
- *
164
- * @param ast - The compiled AST to optimize
165
- * @returns The AST with folded constants
166
- */
167
- function constantFolding(ast: CompiledAST): CompiledAST {
168
- // Create a deep copy to avoid mutating the original
169
- const optimized = JSON.parse(JSON.stringify(ast)) as JDMDecision;
170
-
171
- // Apply constant folding to each node's expression content
172
- optimized.nodes = optimized.nodes.map((node: JDMNode) => foldNodeExpressions(node));
173
-
174
- return optimized;
175
- }
176
-
177
- /**
178
- * Apply constant folding to expressions within a node.
179
- */
180
- function foldNodeExpressions(node: JDMNode): JDMNode {
181
- if (!node.content) {
182
- return node;
183
- }
184
-
185
- const content = node.content;
186
-
187
- // Handle decision table nodes
188
- if (node.type === NodeType.DECISION_TABLE) {
189
- return foldDecisionTableExpressions(node, content);
190
- }
191
-
192
- // Handle switch nodes
193
- if (node.type === NodeType.SWITCH) {
194
- return foldSwitchExpressions(node, content);
195
- }
196
-
197
- // Handle expression nodes
198
- if (node.type === NodeType.EXPRESSION) {
199
- return foldExpressionNode(node, content);
200
- }
201
-
202
- return node;
203
- }
204
-
205
- /**
206
- * Fold expressions in a decision table node.
207
- */
208
- function foldDecisionTableExpressions(node: JDMNode, content: Record<string, unknown>): JDMNode {
209
- const { rules, inputs } = content as { rules: any[]; inputs: any[] };
210
- let modified = false;
211
-
212
- // Update each rule's input conditions with folded expressions
213
- const foldedRules = rules.map((rule: Record<string, unknown>) => {
214
- const foldedRule = { ...rule };
215
-
216
- for (const input of inputs) {
217
- const expr = rule[input.id] as string | undefined;
218
- if (!expr || expr === '' || expr === '-') {
219
- continue;
220
- }
221
-
222
- // Parse the expression in unary mode (using cache)
223
- try {
224
- const ast = cachedParseUnary(node, expr);
225
- const folded = foldExpression(ast);
226
-
227
- // If folding succeeded, update the expression string
228
- if (folded !== null && isLiteral(folded)) {
229
- const newExpr = literalToExprString(folded);
230
- if (newExpr !== expr) {
231
- foldedRule[input.id] = newExpr;
232
- modified = true;
233
- }
234
- }
235
- } catch {
236
- // If expression can't be parsed or folded, keep original
237
- }
238
- }
239
-
240
- return foldedRule;
241
- });
242
-
243
- // Clear cache if expressions were modified
244
- if (modified) {
245
- clearExpressionCache(node);
246
- }
247
-
248
- return {
249
- ...node,
250
- content: {
251
- ...content,
252
- rules: foldedRules,
253
- },
254
- };
255
- }
256
-
257
- /**
258
- * Fold expressions in a switch node.
259
- */
260
- function foldSwitchExpressions(node: JDMNode, content: any): JDMNode {
261
- const { conditions } = content;
262
- let modified = false;
263
-
264
- const foldedConditions = conditions.map((condition: any) => {
265
- const expr = condition.expression;
266
- if (!expr || expr === '') {
267
- return condition;
268
- }
269
-
270
- try {
271
- const ast = cachedParseStandard(node, expr);
272
- const folded = foldExpression(ast);
273
-
274
- if (folded !== null && isLiteral(folded)) {
275
- const newExpr = literalToExprString(folded);
276
- if (newExpr !== expr) {
277
- modified = true;
278
- return {
279
- ...condition,
280
- expression: newExpr,
281
- };
282
- }
283
- }
284
- } catch {
285
- // If expression can't be parsed or folded, keep original
286
- }
287
-
288
- return condition;
289
- });
290
-
291
- // Clear cache if expressions were modified
292
- if (modified) {
293
- clearExpressionCache(node);
294
- }
295
-
296
- return {
297
- ...node,
298
- content: {
299
- ...content,
300
- conditions: foldedConditions,
301
- },
302
- };
303
- }
304
-
305
- /**
306
- * Fold expressions in an expression node.
307
- */
308
- function foldExpressionNode(node: JDMNode, content: any): JDMNode {
309
- const expr = content.expression;
310
- if (!expr) {
311
- return node;
312
- }
313
-
314
- try {
315
- const ast = cachedParseStandard(node, expr);
316
- const folded = foldExpression(ast);
317
-
318
- if (folded !== null && isLiteral(folded)) {
319
- const newExpr = literalToExprString(folded);
320
- if (newExpr !== expr) {
321
- // Clear cache since we're modifying the expression
322
- clearExpressionCache(node);
323
- return {
324
- ...node,
325
- content: {
326
- ...content,
327
- expression: newExpr,
328
- },
329
- };
330
- }
331
- }
332
- } catch {
333
- // If expression can't be parsed or folded, keep original
334
- }
335
-
336
- return node;
337
- }
338
-
339
- /**
340
- * Recursively fold an expression AST.
341
- * Returns the folded AST node, or null if folding is not possible.
342
- */
343
- function foldExpression(expr: ExpressionAST): ExpressionAST | null {
344
- if (isLiteralExpr(expr)) {
345
- return expr;
346
- }
347
-
348
- if (isBinaryOp(expr)) {
349
- const leftFolded = foldExpression(expr.left);
350
- const rightFolded = foldExpression(expr.right);
351
-
352
- // If both sides are literals, try to evaluate at compilation time
353
- if (leftFolded && rightFolded && isLiteral(leftFolded) && isLiteral(rightFolded)) {
354
- const result = evaluateConstantBinaryOp(expr.op, leftFolded, rightFolded);
355
- if (result !== null) {
356
- return result;
357
- }
358
- }
359
-
360
- return {
361
- ...expr,
362
- left: leftFolded || expr.left,
363
- right: rightFolded || expr.right,
364
- };
365
- }
366
-
367
- if (isUnaryOp(expr)) {
368
- const operandFolded = foldExpression(expr.operand);
369
-
370
- if (operandFolded && isLiteral(operandFolded)) {
371
- const result = evaluateConstantUnaryOp(expr.op, operandFolded);
372
- if (result !== null) {
373
- return result;
374
- }
375
- }
376
-
377
- return {
378
- ...expr,
379
- operand: operandFolded || expr.operand,
380
- };
381
- }
382
-
383
- if (isTernaryOp(expr)) {
384
- const conditionFolded = foldExpression(expr.condition);
385
- const consequentFolded = foldExpression(expr.consequent);
386
- const alternateFolded = foldExpression(expr.alternate);
387
-
388
- if (conditionFolded && isLiteral(conditionFolded) && isBooleanLiteral(conditionFolded)) {
389
- return conditionFolded.value
390
- ? consequentFolded || expr.consequent
391
- : alternateFolded || expr.alternate;
392
- }
393
-
394
- return {
395
- ...expr,
396
- condition: conditionFolded || expr.condition,
397
- consequent: consequentFolded || expr.consequent,
398
- alternate: alternateFolded || expr.alternate,
399
- };
400
- }
401
-
402
- // Can't fold other expression types (identifiers, function calls, etc.)
403
- return null;
404
- }
405
-
406
- /**
407
- * Check if an expression is a literal value.
408
- */
409
- function isLiteralExpr(expr: ExpressionAST): boolean {
410
- return (
411
- isNumberLiteral(expr) || isStringLiteral(expr) || isBooleanLiteral(expr) || isNullLiteral(expr)
412
- );
413
- }
414
-
415
- /**
416
- * Check if a node is a literal.
417
- */
418
- function isLiteral(
419
- node: ExpressionAST | null,
420
- ): node is NumberLiteral | StringLiteral | BooleanLiteral {
421
- return node !== null && isLiteralExpr(node);
422
- }
423
-
424
- /**
425
- * Evaluate a binary operation with constant operands.
426
- */
427
- function evaluateConstantBinaryOp(
428
- op: string,
429
- left: NumberLiteral | StringLiteral | BooleanLiteral,
430
- right: NumberLiteral | StringLiteral | BooleanLiteral,
431
- ): ExpressionAST | null {
432
- // Numeric operations
433
- if (isNumberLiteral(left) && isNumberLiteral(right)) {
434
- switch (op) {
435
- case '+':
436
- return { type: 'NumberLiteral', value: left.value + right.value };
437
- case '-':
438
- return { type: 'NumberLiteral', value: left.value - right.value };
439
- case '*':
440
- return { type: 'NumberLiteral', value: left.value * right.value };
441
- case '/':
442
- return { type: 'NumberLiteral', value: left.value / right.value };
443
- case '%':
444
- return { type: 'NumberLiteral', value: left.value % right.value };
445
- case '^':
446
- return { type: 'NumberLiteral', value: Math.pow(left.value, right.value) };
447
- case '<':
448
- return { type: 'BooleanLiteral', value: left.value < right.value };
449
- case '>':
450
- return { type: 'BooleanLiteral', value: left.value > right.value };
451
- case '<=':
452
- return { type: 'BooleanLiteral', value: left.value <= right.value };
453
- case '>=':
454
- return { type: 'BooleanLiteral', value: left.value >= right.value };
455
- case '==':
456
- return { type: 'BooleanLiteral', value: left.value === right.value };
457
- case '!=':
458
- return { type: 'BooleanLiteral', value: left.value !== right.value };
459
- }
460
- }
461
-
462
- // String operations
463
- if (isStringLiteral(left) && isStringLiteral(right)) {
464
- switch (op) {
465
- case '+':
466
- return { type: 'StringLiteral', value: left.value + right.value };
467
- case '==':
468
- return { type: 'BooleanLiteral', value: left.value === right.value };
469
- case '!=':
470
- return { type: 'BooleanLiteral', value: left.value !== right.value };
471
- }
472
- }
473
-
474
- // Boolean operations
475
- if (isBooleanLiteral(left) && isBooleanLiteral(right)) {
476
- switch (op) {
477
- case 'and':
478
- return { type: 'BooleanLiteral', value: left.value && right.value };
479
- case 'or':
480
- return { type: 'BooleanLiteral', value: left.value || right.value };
481
- case '==':
482
- return { type: 'BooleanLiteral', value: left.value === right.value };
483
- case '!=':
484
- return { type: 'BooleanLiteral', value: left.value !== right.value };
485
- }
486
- }
487
-
488
- return null;
489
- }
490
-
491
- /**
492
- * Evaluate a unary operation with a constant operand.
493
- */
494
- function evaluateConstantUnaryOp(
495
- op: string,
496
- operand: NumberLiteral | StringLiteral | BooleanLiteral,
497
- ): ExpressionAST | null {
498
- if (op === 'not' && isBooleanLiteral(operand)) {
499
- return { type: 'BooleanLiteral', value: !operand.value };
500
- }
501
-
502
- if (op === '-' && isNumberLiteral(operand)) {
503
- return { type: 'NumberLiteral', value: -operand.value };
504
- }
505
-
506
- return null;
507
- }
508
-
509
- /**
510
- * Convert a literal AST node to its string representation.
511
- */
512
- function literalToExprString(node: NumberLiteral | StringLiteral | BooleanLiteral): string {
513
- switch (node.type) {
514
- case 'NumberLiteral':
515
- return String(node.value);
516
- case 'StringLiteral':
517
- return `"${node.value}"`;
518
- case 'BooleanLiteral':
519
- return String(node.value);
520
- }
521
- }
522
-
523
- // ============================================================================
524
- // Dead Code Elimination
525
- // ============================================================================
526
-
527
- /**
528
- * Remove unreachable code.
529
- *
530
- * This pass identifies and removes branches that can never be reached.
531
- * Examples:
532
- * - Remove if branches with constant false conditions
533
- * - Remove decision table rows with always-false conditions
534
- * - Remove decision table rows that can never match after previous rows
535
- *
536
- * @param ast - The compiled AST to optimize
537
- * @returns The AST with dead code removed
538
- */
539
- function deadCodeElimination(ast: CompiledAST): CompiledAST {
540
- const optimized = JSON.parse(JSON.stringify(ast)) as JDMDecision;
541
-
542
- optimized.nodes = optimized.nodes.map((node: JDMNode) => eliminateDeadCodeInNode(node));
543
-
544
- return optimized;
545
- }
546
-
547
- /**
548
- * Apply dead code elimination to a node.
549
- */
550
- function eliminateDeadCodeInNode(node: JDMNode): JDMNode {
551
- if (!node.content) {
552
- return node;
553
- }
554
-
555
- const content = node.content;
556
-
557
- if (node.type === NodeType.DECISION_TABLE) {
558
- return eliminateDeadCodeInDecisionTable(node, content);
559
- }
560
-
561
- if (node.type === NodeType.SWITCH) {
562
- return eliminateDeadCodeInSwitch(node, content);
563
- }
564
-
565
- return node;
566
- }
567
-
568
- /**
569
- * Check if a unary expression is always false.
570
- * In unary mode, "false" is equivalent to "$ == false".
571
- */
572
- function isUnaryAlwaysFalse(expr: ExpressionAST): boolean {
573
- if (isBinaryOp(expr) && expr.op === '==') {
574
- const leftIsDollar = expr.left.type === 'DollarRef';
575
- const rightIsFalse = isBooleanLiteral(expr.right) && !expr.right.value;
576
- return leftIsDollar && rightIsFalse;
577
- }
578
-
579
- if (isBinaryOp(expr) && expr.op === '!=') {
580
- const leftIsDollar = expr.left.type === 'DollarRef';
581
- const rightIsTrue = isBooleanLiteral(expr.right) && expr.right.value;
582
- return leftIsDollar && rightIsTrue;
583
- }
584
-
585
- return false;
586
- }
587
-
588
- /**
589
- * Eliminate dead code in decision table nodes.
590
- */
591
- function eliminateDeadCodeInSwitch(node: JDMNode, content: any): JDMNode {
592
- const { conditions } = content;
593
-
594
- // Filter out conditions that are always false
595
- const liveConditions = conditions.filter((condition: any) => {
596
- const expr = condition.expression;
597
- if (!expr || expr === '') {
598
- return true;
599
- }
600
-
601
- try {
602
- const parsed = cachedParseStandard(node, expr);
603
-
604
- if (isBooleanLiteral(parsed) && !parsed.value) {
605
- return false;
606
- }
607
- } catch {}
608
-
609
- return true;
610
- });
611
-
612
- return {
613
- ...node,
614
- content: {
615
- ...content,
616
- conditions: liveConditions,
617
- },
618
- };
619
- }
620
-
621
- /**
622
- * Eliminate dead code in decision table nodes.
623
- */
624
- function eliminateDeadCodeInDecisionTable(node: JDMNode, content: any): JDMNode {
625
- const { rules, inputs } = content;
626
-
627
- // Filter out rules that have a non-trivial always-false condition
628
- const liveRules = rules.filter((rule: any) => {
629
- for (const input of inputs) {
630
- const expr = rule[input.id];
631
- if (!expr || expr === '' || expr === '-') {
632
- continue;
633
- }
634
-
635
- try {
636
- const parsed = cachedParseUnary(node, expr);
637
-
638
- // Check if this is a boolean literal (not common in unary mode, but possible)
639
- if (isBooleanLiteral(parsed) && !parsed.value) {
640
- return false;
641
- }
642
-
643
- // Check if this is a unary expression that's always false
644
- // e.g., "false" in a decision table cell is interpreted as "$ == false"
645
- if (isUnaryAlwaysFalse(parsed)) {
646
- return false;
647
- }
648
- } catch {
649
- // If we can't parse it, assume the rule is live
650
- }
651
- }
652
-
653
- return true;
654
- });
655
-
656
- return {
657
- ...node,
658
- content: {
659
- ...content,
660
- rules: liveRules,
661
- },
662
- };
663
- }
664
-
665
- // ============================================================================
666
- // Expression Inlining
667
- // ============================================================================
668
-
669
- /**
670
- * Inline small expressions.
671
- *
672
- * This pass replaces function calls with evaluated results for pure functions.
673
- * Examples:
674
- * - Inline small arithmetic operations in decision table cells
675
- * - Pre-evaluate expressions that don't depend on runtime values
676
- *
677
- * @param ast - The compiled AST to optimize
678
- * @returns The AST with inlined expressions
679
- */
680
- function expressionInlining(ast: CompiledAST): CompiledAST {
681
- // Create a deep copy to avoid mutating the original
682
- const optimized = JSON.parse(JSON.stringify(ast)) as JDMDecision;
683
-
684
- // Only functions without side effects can be safely evaluated at compile time. Arithmetic
685
- // (sum, max, min, abs, floor, ceil, round) and string functions (upper, lower, len) are
686
- // pure and deterministic, so their results with constant inputs are predictable.
687
- optimized.nodes = optimized.nodes.map((node: JDMNode) => inlineExpressionsInNode(node));
688
-
689
- return optimized;
690
- }
691
-
692
- /**
693
- * Apply expression inlining to a node.
694
- */
695
- function inlineExpressionsInNode(node: JDMNode): JDMNode {
696
- if (!node.content) {
697
- return node;
698
- }
699
-
700
- const content = node.content;
701
-
702
- // Handle decision table nodes
703
- if (node.type === NodeType.DECISION_TABLE && content && content.rules && content.inputs) {
704
- return inlineDecisionTableExpressions(node, content);
705
- }
706
-
707
- return node;
708
- }
709
-
710
- /**
711
- * Inline expressions in decision table nodes.
712
- */
713
- function inlineDecisionTableExpressions(node: JDMNode, content: any): JDMNode {
714
- const { rules, inputs } = content;
715
-
716
- const inlinedRules = rules.map((rule: any) => {
717
- const inlinedRule = { ...rule };
718
-
719
- for (const input of inputs) {
720
- const expr = rule[input.id];
721
- if (!expr || expr === '' || expr === '-') {
722
- continue;
723
- }
724
-
725
- const inlined = tryInlineExpression(expr);
726
- if (inlined !== expr) {
727
- inlinedRule[input.id] = inlined;
728
- }
729
- }
730
-
731
- return inlinedRule;
732
- });
733
-
734
- return {
735
- ...node,
736
- content: {
737
- ...content,
738
- rules: inlinedRules,
739
- },
740
- };
741
- }
742
-
743
- /**
744
- * Try to inline an expression by evaluating simple pure function calls.
745
- * Returns the inlined expression string, or the original if inlining is not possible.
746
- */
747
- function tryInlineExpression(expr: string): string {
748
- const trimmed = expr.trim();
749
-
750
- // Inline simple arithmetic operations wrapped in function notation
751
- // Examples: sum(2, 3) → 5, min(10, 5) → 5, abs(-5) → 5, upper("hello") → "HELLO"
752
-
753
- // Match sum(a, b, ...) pattern where all arguments are numeric literals
754
- const sumMatch = trimmed.match(/^sum\((.+)\)$/i);
755
- if (sumMatch) {
756
- const args = sumMatch[1].split(',').map((s: string) => s.trim());
757
- if (args.every((arg: string) => /^-?\d+\.?\d*$/.test(arg))) {
758
- const sum = args.reduce((acc: number, arg: string) => acc + parseFloat(arg), 0);
759
- return String(sum);
760
- }
761
- }
762
-
763
- // Match max(a, b) pattern where both arguments are numeric literals
764
- const maxMatch = trimmed.match(/^max\((.+),(.+)\)$/i);
765
- if (maxMatch) {
766
- const [_, arg1, arg2] = maxMatch;
767
- const num1 = parseFloat(arg1.trim());
768
- const num2 = parseFloat(arg2.trim());
769
- if (!isNaN(num1) && !isNaN(num2)) {
770
- return String(Math.max(num1, num2));
771
- }
772
- }
773
-
774
- // Match min(a, b) pattern where both arguments are numeric literals
775
- const minMatch = trimmed.match(/^min\((.+),(.+)\)$/i);
776
- if (minMatch) {
777
- const [_, arg1, arg2] = minMatch;
778
- const num1 = parseFloat(arg1.trim());
779
- const num2 = parseFloat(arg2.trim());
780
- if (!isNaN(num1) && !isNaN(num2)) {
781
- return String(Math.min(num1, num2));
782
- }
783
- }
784
-
785
- // Match abs(a) pattern where argument is a numeric literal
786
- const absMatch = trimmed.match(/^abs\((.+)\)$/i);
787
- if (absMatch) {
788
- const val = parseFloat(absMatch[1].trim());
789
- if (!isNaN(val)) {
790
- return String(Math.abs(val));
791
- }
792
- }
793
-
794
- // Match floor(a) pattern where argument is a numeric literal
795
- const floorMatch = trimmed.match(/^floor\((.+)\)$/i);
796
- if (floorMatch) {
797
- const val = parseFloat(floorMatch[1].trim());
798
- if (!isNaN(val)) {
799
- return String(Math.floor(val));
800
- }
801
- }
802
-
803
- // Match ceil(a) pattern where argument is a numeric literal
804
- const ceilMatch = trimmed.match(/^ceil\((.+)\)$/i);
805
- if (ceilMatch) {
806
- const val = parseFloat(ceilMatch[1].trim());
807
- if (!isNaN(val)) {
808
- return String(Math.ceil(val));
809
- }
810
- }
811
-
812
- // Match round(a) pattern where argument is a numeric literal
813
- const roundMatch = trimmed.match(/^round\((.+)\)$/i);
814
- if (roundMatch) {
815
- const val = parseFloat(roundMatch[1].trim());
816
- if (!isNaN(val)) {
817
- return String(Math.round(val));
818
- }
819
- }
820
-
821
- // Match upper("string") pattern for constant string literals
822
- const upperMatch = trimmed.match(/^upper\("(.+)"\)$/i);
823
- if (upperMatch) {
824
- return `"${upperMatch[1].toUpperCase()}"`;
825
- }
826
-
827
- // Match lower("string") pattern for constant string literals
828
- const lowerMatch = trimmed.match(/^lower\("(.+)"\)$/i);
829
- if (lowerMatch) {
830
- return `"${lowerMatch[1].toLowerCase()}"`;
831
- }
832
-
833
- // Match len("string") pattern for constant string literals
834
- const lenMatch = trimmed.match(/^len\("(.*)"\)$/i);
835
- if (lenMatch) {
836
- return String(lenMatch[1].length);
837
- }
838
-
839
- // Match len(123) pattern for numeric literals (counting digits excluding sign)
840
- const lenNumMatch = trimmed.match(/^len\(-?\d+\.?\d*\)$/i);
841
- if (lenNumMatch) {
842
- const numStr = trimmed.match(/^len\((.+)\)$/i)![1].trim();
843
- // Count digits ignoring sign and decimal point
844
- const digitCount = numStr.replace(/^-/, '').replace('.', '').length;
845
- return String(digitCount);
846
- }
847
-
848
- return expr;
849
- }
850
-
851
- // ============================================================================
852
- // Table Indexing
853
- // ============================================================================
854
-
855
- /**
856
- * Build index structures for efficient table lookup.
857
- *
858
- * This pass transforms linear search structures into more efficient alternatives.
859
- * Examples:
860
- * - Convert decision table rows with equality checks to index-based lookup
861
- * - Mark tables that are good candidates for switch statement generation
862
- *
863
- * Table indexing converts O(n) linear search to O(1) hash lookup when all rules check
864
- * equality on a single column with unique values - this is common in lookup tables
865
- * (e.g., pricing tiers by customer type) and can improve evaluation time by 10-100x
866
- * for large tables.
867
- *
868
- * @param ast - The compiled AST to optimize
869
- * @returns The AST with optimized table lookups
870
- */
871
- function tableIndexing(ast: CompiledAST): CompiledAST {
872
- const optimized = JSON.parse(JSON.stringify(ast)) as JDMDecision;
873
-
874
- optimized.nodes = optimized.nodes.map((node: JDMNode) => indexTableInNode(node));
875
-
876
- return optimized;
877
- }
878
-
879
- /**
880
- * Apply table indexing to a node.
881
- */
882
- function indexTableInNode(node: JDMNode): JDMNode {
883
- if (!node.content) {
884
- return node;
885
- }
886
-
887
- const content = node.content;
888
-
889
- if (node.type === NodeType.DECISION_TABLE) {
890
- return indexDecisionTable(node, content);
891
- }
892
-
893
- return node;
894
- }
895
-
896
- /**
897
- * Index decision table for efficient lookup.
898
- *
899
- * This pass analyzes the decision table to identify patterns that can be
900
- * optimized, such as equality checks on a single column that could be
901
- * converted to a switch statement or hash map.
902
- */
903
- function indexDecisionTable(node: JDMNode, content: any): JDMNode {
904
- const { rules, inputs } = content;
905
-
906
- // Analyze each input column to find indexing opportunities
907
- const indexedInputs = inputs.map((input: any) => {
908
- const inputValues = rules.map((rule: any) => {
909
- const expr = rule[input.id];
910
- if (!expr || expr === '' || expr === '-') {
911
- return null;
912
- }
913
- return expr.trim();
914
- });
915
-
916
- // Check if this column is a good candidate for indexing:
917
- // - All values are string or number literals
918
- // - No intervals or complex expressions
919
- // - No duplicate values
920
- const allLiterals = inputValues.every((val: string | null) => {
921
- if (!val) {
922
- return true;
923
- }
924
- return /^(["'])(?:(?=(\\?))\2.)*?\1$|^-?\d+\.?\d*$/.test(val);
925
- });
926
-
927
- const uniqueValues = new Set(inputValues.filter((v: string | null) => v !== null));
928
- const hasDuplicates =
929
- uniqueValues.size < inputValues.filter((v: string | null) => v !== null).length;
930
-
931
- return {
932
- ...input,
933
- // Hash-based lookup becomes beneficial with ~10+ unique values, but overhead matters
934
- // for small tables. 50 is a practical limit where indexing provides clear wins without
935
- // excessive memory for the lookup structure.
936
- _indexable: allLiterals && !hasDuplicates && uniqueValues.size > 0 && uniqueValues.size < 50,
937
- _uniqueValues: Array.from(uniqueValues),
938
- };
939
- });
940
-
941
- return {
942
- ...node,
943
- content: {
944
- ...content,
945
- inputs: indexedInputs,
946
- },
947
- };
948
- }