@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.
- package/dist/index.js +2227 -29
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/.github/workflows/ci.yml +0 -53
- package/.oxfmtrc.json +0 -16
- package/.oxlintrc.json +0 -183
- package/AGENTS.md +0 -81
- package/asconfig.json +0 -23
- package/benchmarks/fixtures.ts +0 -111
- package/benchmarks/input-fixtures.ts +0 -80
- package/benchmarks/run.ts +0 -913
- package/benchmarks/worker-pool.ts +0 -223
- package/benchmarks/worker.ts +0 -374
- package/scripts/run-all-tests.ts +0 -220
- package/src/compiler/EXPRESSION_SUBSETS.md +0 -228
- package/src/compiler/asc-compiler.ts +0 -315
- package/src/compiler/ast-types.ts +0 -215
- package/src/compiler/build.ts +0 -56
- package/src/compiler/cache.ts +0 -414
- package/src/compiler/code-generators.ts +0 -211
- package/src/compiler/codegen/index.ts +0 -15
- package/src/compiler/codegen/js-marshal.ts +0 -999
- package/src/compiler/codegen/js-validation.ts +0 -243
- package/src/compiler/codegen.ts +0 -19
- package/src/compiler/compile-time-validation.ts +0 -507
- package/src/compiler/cst-visitor.ts +0 -434
- package/src/compiler/errors.ts +0 -227
- package/src/compiler/expression-parser.ts +0 -536
- package/src/compiler/graph.ts +0 -197
- package/src/compiler/index.ts +0 -199
- package/src/compiler/input-validation.ts +0 -33
- package/src/compiler/marshal-gen.ts +0 -21
- package/src/compiler/nodes/context-resolvers.ts +0 -197
- package/src/compiler/nodes/decision-table.ts +0 -507
- package/src/compiler/nodes/decision.ts +0 -292
- package/src/compiler/nodes/expression-compiler.ts +0 -526
- package/src/compiler/nodes/expression.ts +0 -425
- package/src/compiler/nodes/function.ts +0 -316
- package/src/compiler/nodes/input.ts +0 -60
- package/src/compiler/nodes/switch.ts +0 -547
- package/src/compiler/optimizer.ts +0 -948
- package/src/compiler/orchestrator.ts +0 -352
- package/src/compiler/parser.ts +0 -115
- package/src/compiler/result-selection.ts +0 -161
- package/src/compiler/runtime/index.ts +0 -26
- package/src/compiler/runtime-codegen.ts +0 -211
- package/src/compiler/runtime-validation-codegen.ts +0 -294
- package/src/compiler/runtime.ts +0 -452
- package/src/compiler/schema.ts +0 -245
- package/src/compiler/switch-branch-detection.ts +0 -92
- package/src/compiler/types.ts +0 -136
- package/src/compiler/unary-ast-transforms.ts +0 -148
- package/src/compiler/unary-parser.ts +0 -301
- package/src/compiler/unary-transform.ts +0 -161
- package/src/compiler/utils.ts +0 -27
- package/src/compiler/virtual-fs.ts +0 -90
- package/src/compiler/wasm-instantiate.ts +0 -127
- package/src/index.ts +0 -1
- package/src/runtime/arrays.ts +0 -579
- package/src/runtime/context.ts +0 -189
- package/src/runtime/expressions.ts +0 -1811
- package/src/runtime/index.ts +0 -8
- package/src/runtime/memory.ts +0 -607
- package/src/runtime/strings.ts +0 -260
- package/src/runtime/tables.ts +0 -96
- package/src/runtime/tsconfig.json +0 -4
- package/src/runtime/values.ts +0 -209
- package/test-data/README.md +0 -83
- package/test-data/decision-tables/basic/8k.json +0 -87992
- package/test-data/decision-tables/basic/affiliate-commission-calculator.json +0 -228
- package/test-data/decision-tables/basic/airline-loyalty-points-calculations.json +0 -285
- package/test-data/decision-tables/basic/airline-upgrade-eligibility.json +0 -466
- package/test-data/decision-tables/basic/auto-insurance-premium-calculator.json +0 -412
- package/test-data/decision-tables/basic/booking-personalization-system.json +0 -553
- package/test-data/decision-tables/basic/care-team-assignment-system.json +0 -585
- package/test-data/decision-tables/basic/claim-validation-system.json +0 -307
- package/test-data/decision-tables/basic/clinical-lab-result-interpreter.json +0 -433
- package/test-data/decision-tables/basic/clinical-treatment-protocol.json +0 -474
- package/test-data/decision-tables/basic/credit-limit-adjustment.json +0 -479
- package/test-data/decision-tables/basic/customer-eligibility-engine.json +0 -551
- package/test-data/decision-tables/basic/customer-lifetime-value.json +0 -200
- package/test-data/decision-tables/basic/customer-onboarding-kyc-verification.json +0 -611
- package/test-data/decision-tables/basic/customer-service-escalation.json +0 -191
- package/test-data/decision-tables/basic/decision-table-discounts.json +0 -168
- package/test-data/decision-tables/basic/decision-table-shipping.json +0 -398
- package/test-data/decision-tables/basic/delivery-route-optimizer.json +0 -271
- package/test-data/decision-tables/basic/device-compatibility-checker.json +0 -303
- package/test-data/decision-tables/basic/disaster-relief-fund-allocation.json +0 -296
- package/test-data/decision-tables/basic/dynamic-fx-rate-pricing-system.json +0 -237
- package/test-data/decision-tables/basic/dynamic-marketplace-comission-calculator.json +0 -242
- package/test-data/decision-tables/basic/dynamic-shipping-cost-calculator.json +0 -378
- package/test-data/decision-tables/basic/dynamic-tarrif-engine.json +0 -289
- package/test-data/decision-tables/basic/dynamic-ticket-pricing.json +0 -325
- package/test-data/decision-tables/basic/empty-column-with-space.json +0 -100
- package/test-data/decision-tables/basic/empty-column-without-space.json +0 -100
- package/test-data/decision-tables/basic/environment-compliance-assessment.json +0 -386
- package/test-data/decision-tables/basic/expression-table-map.json +0 -313
- package/test-data/decision-tables/basic/flash-sale-eligibility.json +0 -366
- package/test-data/decision-tables/basic/flight-dispatch-decision-system.json +0 -455
- package/test-data/decision-tables/basic/flight-rebooking-fee-calculator.json +0 -406
- package/test-data/decision-tables/basic/government-assistance.json +0 -299
- package/test-data/decision-tables/basic/grant-funding-distribution.json +0 -307
- package/test-data/decision-tables/basic/hazardous-materials-management-system.json +0 -414
- package/test-data/decision-tables/basic/immigration-eligibility-evaluator.json +0 -765
- package/test-data/decision-tables/basic/import-duties-calculator.json +0 -318
- package/test-data/decision-tables/basic/insurance-agent-commission.json +0 -228
- package/test-data/decision-tables/basic/insurance-coverage-calculator.json +0 -362
- package/test-data/decision-tables/basic/insurance-underwriting-risk.json +0 -321
- package/test-data/decision-tables/basic/international-roaming-policy-manager.json +0 -199
- package/test-data/decision-tables/basic/legacy-plan-management.json +0 -434
- package/test-data/decision-tables/basic/marketplace-listing-verification-system.json +0 -334
- package/test-data/decision-tables/basic/medication-dosage-calculator.json +0 -318
- package/test-data/decision-tables/basic/merch-bags.json +0 -171
- package/test-data/decision-tables/basic/municipal-permit-evaluation-system.json +0 -364
- package/test-data/decision-tables/basic/mvno-partner-enablement.json +0 -313
- package/test-data/decision-tables/basic/partner-revenue-sharing.json +0 -244
- package/test-data/decision-tables/basic/payment-routing-and-fee-calculator.json +0 -475
- package/test-data/decision-tables/basic/policy-discount-calculator.json +0 -307
- package/test-data/decision-tables/basic/policy-eligibility-analyzer.json +0 -299
- package/test-data/decision-tables/basic/product-listing-scoring.json +0 -358
- package/test-data/decision-tables/basic/realtime-fraud-detection.json +0 -235
- package/test-data/decision-tables/basic/regional-compliance-manager.json +0 -278
- package/test-data/decision-tables/basic/returns-and-refund-policy.json +0 -366
- package/test-data/decision-tables/basic/returns-processing-system.json +0 -448
- package/test-data/decision-tables/basic/school-district-resource-allocation.json +0 -282
- package/test-data/decision-tables/basic/seat-map-optimization.json +0 -325
- package/test-data/decision-tables/basic/seller-fee-calculator.json +0 -307
- package/test-data/decision-tables/basic/service-level-agreement-enforcement.json +0 -575
- package/test-data/decision-tables/basic/smart-financial-product-matcher.json +0 -249
- package/test-data/decision-tables/basic/supply-chain-risk.json +0 -316
- package/test-data/decision-tables/basic/table-loop.json +0 -93
- package/test-data/decision-tables/basic/table.json +0 -76
- package/test-data/decision-tables/basic/traffic-violation-penalty-calculator.json +0 -436
- package/test-data/decision-tables/basic/transaction-compliance-classifier.json +0 -525
- package/test-data/decision-tables/basic/vehicle-claims-resolution.json +0 -310
- package/test-data/decision-tables/basic/warehouse-storage-location.json +0 -345
- package/test-data/decision-tables/hit-policy-collect/collect-multiple-matches.json +0 -127
- package/test-data/decision-tables/hit-policy-collect/collect-no-match.json +0 -95
- package/test-data/decision-tables/hit-policy-first/first-match.json +0 -103
- package/test-data/decision-tables/hit-policy-first/no-match.json +0 -95
- package/test-data/decision-tables/hit-policy-output-order/output-order-respected.json +0 -94
- package/test-data/decision-tables/hit-policy-output-order/string-output-order.json +0 -94
- package/test-data/decision-tables/hit-policy-priority/priority-respected.json +0 -86
- package/test-data/decision-tables/hit-policy-rule-order/rule-order-respected.json +0 -94
- package/test-data/decision-tables/hit-policy-unique/all-match-error.json +0 -89
- package/test-data/decision-tables/hit-policy-unique/multiple-match-error.json +0 -89
- package/test-data/decision-tables/hit-policy-unique/no-match.json +0 -88
- package/test-data/decision-tables/hit-policy-unique/unique-match.json +0 -99
- package/test-data/expressions/arithmetic/error-cyclic.json +0 -114
- package/test-data/expressions/arithmetic/error-missing-input.json +0 -54
- package/test-data/expressions/arithmetic/error-missing-output.json +0 -54
- package/test-data/expressions/arithmetic/expression-default.json +0 -93
- package/test-data/expressions/arithmetic/expression-fields.json +0 -94
- package/test-data/expressions/arithmetic/expression-loop.json +0 -94
- package/test-data/expressions/arithmetic/expression-passthrough.json +0 -108
- package/test-data/expressions/arithmetic/expression.json +0 -69
- package/test-data/expressions/arithmetic/nested-request.json +0 -125
- package/test-data/expressions/arithmetic/number-function.json +0 -58
- package/test-data/expressions/arithmetic/test-number-functions.json +0 -68
- package/test-data/expressions/functions/all.json +0 -149
- package/test-data/expressions/functions/avg.json +0 -89
- package/test-data/expressions/functions/filter.json +0 -109
- package/test-data/expressions/functions/flat.json +0 -167
- package/test-data/expressions/functions/map-strings.json +0 -65
- package/test-data/expressions/functions/map.json +0 -73
- package/test-data/expressions/functions/reduce.json +0 -49
- package/test-data/expressions/functions/some.json +0 -175
- package/test-data/expressions/functions/sort-strings.json +0 -97
- package/test-data/expressions/functions/sort.json +0 -97
- package/test-data/expressions/logical/logical-and.json +0 -116
- package/test-data/expressions/logical/logical-complex.json +0 -260
- package/test-data/expressions/logical/logical-not.json +0 -111
- package/test-data/expressions/logical/logical-or.json +0 -123
- package/test-data/expressions/string/string-comparison.json +0 -128
- package/test-data/expressions/string/string-concat.json +0 -106
- package/test-data/expressions/string/string-contains.json +0 -125
- package/test-data/expressions/string/string-endsWith.json +0 -113
- package/test-data/expressions/string/string-indexOf.json +0 -131
- package/test-data/expressions/string/string-join.json +0 -92
- package/test-data/expressions/string/string-lower.json +0 -94
- package/test-data/expressions/string/string-replace.json +0 -130
- package/test-data/expressions/string/string-split.json +0 -101
- package/test-data/expressions/string/string-startsWith.json +0 -113
- package/test-data/expressions/string/string-substring.json +0 -138
- package/test-data/expressions/string/string-trim.json +0 -100
- package/test-data/expressions/string/string-upper.json +0 -94
- package/test-data/other/custom.json +0 -51
- package/test-data/other/customer-input-schema.json +0 -34
- package/test-data/other/customer-output-schema.json +0 -34
- package/test-data/other/passthrough.json +0 -31
- package/test-data/sub-decisions/basic/$nodes-child.json +0 -31
- package/test-data/sub-decisions/basic/$nodes-parent.json +0 -49
- package/test-data/sub-decisions/basic/recursive-table1.json +0 -49
- package/test-data/sub-decisions/basic/recursive-table2.json +0 -49
- package/test-data/sub-decisions/complex-multi/approval-decision.json +0 -31
- package/test-data/sub-decisions/complex-multi/complex-dag.json +0 -175
- package/test-data/sub-decisions/complex-multi/credit-check.json +0 -31
- package/test-data/sub-decisions/complex-multi/customer-segmentation.json +0 -31
- package/test-data/sub-decisions/complex-multi/discount-eligibility.json +0 -31
- package/test-data/sub-decisions/complex-multi/eligibility-check.json +0 -31
- package/test-data/sub-decisions/complex-multi/final-offer.json +0 -31
- package/test-data/sub-decisions/complex-multi/income-verification.json +0 -31
- package/test-data/sub-decisions/complex-multi/linear-chain.json +0 -121
- package/test-data/sub-decisions/complex-multi/pricing-calculation.json +0 -31
- package/test-data/sub-decisions/complex-multi/product-eligibility.json +0 -31
- package/test-data/sub-decisions/complex-multi/risk-assessment.json +0 -31
- package/test-data/sub-decisions/complex-multi/shared-validation.json +0 -31
- package/test-data/sub-decisions/complex-multi/validation.json +0 -31
- package/test-data/sub-decisions/diamond/decision-a.json +0 -31
- package/test-data/sub-decisions/diamond/decision-b.json +0 -31
- package/test-data/sub-decisions/diamond/decision-c.json +0 -31
- package/test-data/sub-decisions/diamond/decision-shared.json +0 -31
- package/test-data/sub-decisions/diamond/diamond-pattern.json +0 -109
- package/test-data/sub-decisions/error-propagation/parent-calls-error.json +0 -44
- package/test-data/sub-decisions/error-propagation/sub-decision-with-error.json +0 -60
- package/test-data/switch-nodes/basic/account-dormancy-management.json +0 -245
- package/test-data/switch-nodes/basic/application-risk-assessment.json +0 -474
- package/test-data/switch-nodes/basic/cellular-data-rollover-system.json +0 -281
- package/test-data/switch-nodes/basic/clinical-pathway-selection.json +0 -454
- package/test-data/switch-nodes/basic/insurance-prior-authorization.json +0 -467
- package/test-data/switch-nodes/basic/last-mile-delivery-assignment.json +0 -373
- package/test-data/switch-nodes/basic/loan-approval.json +0 -469
- package/test-data/switch-nodes/basic/multi-switch.json +0 -498
- package/test-data/switch-nodes/basic/online-checkin-eligibility.json +0 -285
- package/test-data/switch-nodes/basic/order-consolidation-system.json +0 -493
- package/test-data/switch-nodes/basic/seller-approval-workflow.json +0 -383
- package/test-data/switch-nodes/basic/set-fee.json +0 -243
- package/test-data/switch-nodes/basic/shipping-carrier-selector.json +0 -379
- package/test-data/switch-nodes/basic/switch-node.json +0 -167
- package/test-data/switch-nodes/basic/switch-performance-2.json +0 -1307
- package/test-data/switch-nodes/basic/switch-performance.json +0 -691
- package/test-data/switch-nodes/basic/tax-exemption.json +0 -295
- package/test-data/switch-nodes/basic/warehouse-cross-docking.json +0 -313
- package/test-data/switch-nodes/default-cases/switch-with-default.json +0 -134
- package/test-data/zen-reference/$nodes-child.json +0 -69
- package/test-data/zen-reference/$nodes-parent.json +0 -34
- package/test-data/zen-reference/8k.json +0 -87992
- package/test-data/zen-reference/credit-analysis.json +0 -324
- package/test-data/zen-reference/custom.json +0 -51
- package/test-data/zen-reference/customer-input-schema.json +0 -34
- package/test-data/zen-reference/customer-output-schema.json +0 -34
- package/test-data/zen-reference/error-cyclic.json +0 -114
- package/test-data/zen-reference/error-missing-input.json +0 -54
- package/test-data/zen-reference/error-missing-output.json +0 -54
- package/test-data/zen-reference/expression.json +0 -69
- package/test-data/zen-reference/function-v2.json +0 -48
- package/test-data/zen-reference/function.json +0 -46
- package/test-data/zen-reference/graphs/account-dormancy-management.json +0 -245
- package/test-data/zen-reference/graphs/affiliate-commission-calculator.json +0 -228
- package/test-data/zen-reference/graphs/airline-loyalty-points-calculations.json +0 -285
- package/test-data/zen-reference/graphs/airline-upgrade-eligibility.json +0 -466
- package/test-data/zen-reference/graphs/aml.json +0 -537
- package/test-data/zen-reference/graphs/application-risk-assessment.json +0 -474
- package/test-data/zen-reference/graphs/auto-insurance-premium-calculator.json +0 -412
- package/test-data/zen-reference/graphs/booking-personalization-system.json +0 -553
- package/test-data/zen-reference/graphs/care-team-assignment-system.json +0 -585
- package/test-data/zen-reference/graphs/cellular-data-rollover-system.json +0 -281
- package/test-data/zen-reference/graphs/claim-validation-system.json +0 -307
- package/test-data/zen-reference/graphs/clinical-lab-result-interpreter.json +0 -433
- package/test-data/zen-reference/graphs/clinical-pathway-selection.json +0 -454
- package/test-data/zen-reference/graphs/clinical-treatment-protocol.json +0 -474
- package/test-data/zen-reference/graphs/company-analysis.json +0 -390
- package/test-data/zen-reference/graphs/credit-limit-adjustment.json +0 -479
- package/test-data/zen-reference/graphs/customer-eligibility-engine.json +0 -551
- package/test-data/zen-reference/graphs/customer-lifetime-value.json +0 -200
- package/test-data/zen-reference/graphs/customer-onboarding-kyc-verification.json +0 -611
- package/test-data/zen-reference/graphs/customer-service-escalation.json +0 -191
- package/test-data/zen-reference/graphs/decision-table-discounts.json +0 -168
- package/test-data/zen-reference/graphs/decision-table-shipping.json +0 -398
- package/test-data/zen-reference/graphs/delivery-route-optimizer.json +0 -271
- package/test-data/zen-reference/graphs/device-compatibility-checker.json +0 -303
- package/test-data/zen-reference/graphs/disaster-relief-fund-allocation.json +0 -296
- package/test-data/zen-reference/graphs/dynamic-fx-rate-pricing-system.json +0 -237
- package/test-data/zen-reference/graphs/dynamic-marketplace-comission-calculator.json +0 -242
- package/test-data/zen-reference/graphs/dynamic-shipping-cost-calculator.json +0 -378
- package/test-data/zen-reference/graphs/dynamic-tarrif-engine.json +0 -289
- package/test-data/zen-reference/graphs/dynamic-ticket-pricing.json +0 -325
- package/test-data/zen-reference/graphs/empty-column-with-space.json +0 -100
- package/test-data/zen-reference/graphs/empty-column-without-space.json +0 -100
- package/test-data/zen-reference/graphs/environment-compliance-assessment.json +0 -386
- package/test-data/zen-reference/graphs/expression-default.json +0 -93
- package/test-data/zen-reference/graphs/expression-fields.json +0 -94
- package/test-data/zen-reference/graphs/expression-loop.json +0 -94
- package/test-data/zen-reference/graphs/expression-passthrough.json +0 -108
- package/test-data/zen-reference/graphs/expression-table-map.json +0 -313
- package/test-data/zen-reference/graphs/flash-sale-eligibility.json +0 -366
- package/test-data/zen-reference/graphs/flight-dispatch-decision-system.json +0 -455
- package/test-data/zen-reference/graphs/flight-rebooking-fee-calculator.json +0 -406
- package/test-data/zen-reference/graphs/government-assistance.json +0 -299
- package/test-data/zen-reference/graphs/grant-funding-distribution.json +0 -307
- package/test-data/zen-reference/graphs/hazardous-materials-management-system.json +0 -414
- package/test-data/zen-reference/graphs/immigration-eligibility-evaluator.json +0 -765
- package/test-data/zen-reference/graphs/import-duties-calculator.json +0 -318
- package/test-data/zen-reference/graphs/insurance-agent-commission.json +0 -228
- package/test-data/zen-reference/graphs/insurance-breakdown.json +0 -421
- package/test-data/zen-reference/graphs/insurance-coverage-calculator.json +0 -362
- package/test-data/zen-reference/graphs/insurance-prior-authorization.json +0 -467
- package/test-data/zen-reference/graphs/insurance-underwriting-risk.json +0 -321
- package/test-data/zen-reference/graphs/international-roaming-policy-manager.json +0 -199
- package/test-data/zen-reference/graphs/last-mile-delivery-assignment.json +0 -373
- package/test-data/zen-reference/graphs/legacy-plan-management.json +0 -434
- package/test-data/zen-reference/graphs/loan-approval.json +0 -469
- package/test-data/zen-reference/graphs/marketplace-listing-verification-system.json +0 -334
- package/test-data/zen-reference/graphs/medication-dosage-calculator.json +0 -318
- package/test-data/zen-reference/graphs/merch-bags.json +0 -171
- package/test-data/zen-reference/graphs/multi-switch.json +0 -498
- package/test-data/zen-reference/graphs/municipal-permit-evaluation-system.json +0 -364
- package/test-data/zen-reference/graphs/mvno-partner-enablement.json +0 -313
- package/test-data/zen-reference/graphs/nested-request.json +0 -125
- package/test-data/zen-reference/graphs/online-checkin-eligibility.json +0 -285
- package/test-data/zen-reference/graphs/order-consolidation-system.json +0 -493
- package/test-data/zen-reference/graphs/partner-revenue-sharing.json +0 -244
- package/test-data/zen-reference/graphs/payment-routing-and-fee-calculator.json +0 -475
- package/test-data/zen-reference/graphs/policy-discount-calculator.json +0 -307
- package/test-data/zen-reference/graphs/policy-eligibility-analyzer.json +0 -299
- package/test-data/zen-reference/graphs/product-listing-scoring.json +0 -358
- package/test-data/zen-reference/graphs/realtime-fraud-detection.json +0 -235
- package/test-data/zen-reference/graphs/regional-compliance-manager.json +0 -278
- package/test-data/zen-reference/graphs/returns-and-refund-policy.json +0 -366
- package/test-data/zen-reference/graphs/returns-processing-system.json +0 -448
- package/test-data/zen-reference/graphs/school-district-resource-allocation.json +0 -282
- package/test-data/zen-reference/graphs/seat-map-optimization.json +0 -325
- package/test-data/zen-reference/graphs/seller-approval-workflow.json +0 -383
- package/test-data/zen-reference/graphs/seller-fee-calculator.json +0 -307
- package/test-data/zen-reference/graphs/service-level-agreement-enforcement.json +0 -575
- package/test-data/zen-reference/graphs/set-fee.json +0 -243
- package/test-data/zen-reference/graphs/shipping-carrier-selector.json +0 -379
- package/test-data/zen-reference/graphs/smart-financial-product-matcher.json +0 -249
- package/test-data/zen-reference/graphs/supply-chain-risk.json +0 -316
- package/test-data/zen-reference/graphs/table-loop.json +0 -93
- package/test-data/zen-reference/graphs/tax-exemption.json +0 -295
- package/test-data/zen-reference/graphs/traffic-violation-penalty-calculator.json +0 -436
- package/test-data/zen-reference/graphs/transaction-compliance-classifier.json +0 -525
- package/test-data/zen-reference/graphs/vehicle-claims-resolution.json +0 -310
- package/test-data/zen-reference/graphs/warehouse-cross-docking.json +0 -313
- package/test-data/zen-reference/graphs/warehouse-storage-location.json +0 -345
- package/test-data/zen-reference/http-function.json +0 -34
- package/test-data/zen-reference/infinite-function.json +0 -46
- package/test-data/zen-reference/js/imports.js +0 -25
- package/test-data/zen-reference/passthrough.json +0 -31
- package/test-data/zen-reference/recursive-table1.json +0 -49
- package/test-data/zen-reference/recursive-table2.json +0 -49
- package/test-data/zen-reference/sleep-function.json +0 -34
- package/test-data/zen-reference/switch-node.json +0 -167
- package/test-data/zen-reference/switch-performance-2.json +0 -1307
- package/test-data/zen-reference/switch-performance.json +0 -691
- package/test-data/zen-reference/table.json +0 -76
- package/tests/helpers/index.ts +0 -73
- package/tests/helpers/mock-context.ts +0 -231
- package/tests/helpers/round-trip.ts +0 -398
- package/tests/helpers/test-harness-comparison.ts +0 -325
- package/tests/helpers/test-harness-wasm.ts +0 -710
- package/tests/helpers/test-harness.ts +0 -28
- package/tests/helpers/wasm-test.ts +0 -659
- package/tests/integration/compilation-errors.test.ts +0 -864
- package/tests/integration/decision-tables.test.ts +0 -531
- package/tests/integration/edge-cases.test.ts +0 -787
- package/tests/integration/expressions.test.ts +0 -513
- package/tests/integration/function-node-integration.test.ts +0 -182
- package/tests/integration/sub-decisions.test.ts +0 -108
- package/tests/integration/switch-nodes.test.ts +0 -399
- package/tests/integration/unary-or-matching.test.ts +0 -53
- package/tests/integration/wasm-data-types.test.ts +0 -398
- package/tests/integration/wasm-errors.test.ts +0 -199
- package/tests/integration/wasm-execution.test.ts +0 -348
- package/tests/integration/wasm-memory.test.ts +0 -228
- package/tests/scripts/analyze-coverage.ts +0 -166
- package/tests/scripts/categorize-tests.ts +0 -396
- package/tests/scripts/coverage-analysis.ts +0 -836
- package/tests/unit/compiler/cache.test.ts +0 -238
- package/tests/unit/compiler/errors.test.ts +0 -316
- package/tests/unit/compiler/graph-scalability.test.ts +0 -510
- package/tests/unit/compiler/graph.test.ts +0 -878
- package/tests/unit/compiler/input-validation.test.ts +0 -447
- package/tests/unit/compiler/logical-and-parser.test.ts +0 -143
- package/tests/unit/compiler/logical-not-parser.test.ts +0 -107
- package/tests/unit/compiler/logical-or-parser.test.ts +0 -236
- package/tests/unit/compiler/marshal-gen/marshal-gen.test.ts +0 -97
- package/tests/unit/compiler/nodes/decision-table.test.ts +0 -103
- package/tests/unit/compiler/nodes/decision.test.ts +0 -182
- package/tests/unit/compiler/nodes/function-compile.test.ts +0 -204
- package/tests/unit/compiler/nodes/function.test.ts +0 -176
- package/tests/unit/compiler/nodes/input.test.ts +0 -30
- package/tests/unit/compiler/nodes/switch.test.ts +0 -127
- package/tests/unit/compiler/optimizer-cache.test.ts +0 -327
- package/tests/unit/compiler/optimizer-implementation.test.ts +0 -625
- package/tests/unit/compiler/parser.test.ts +0 -508
- package/tests/unit/compiler/runtime-error-cleanup.test.ts +0 -426
- package/tests/unit/compiler/runtime-validation.test.ts +0 -303
- package/tests/unit/compiler/runtime.test.ts +0 -221
- package/tests/unit/compiler/schema/schema.test.ts +0 -248
- package/tests/unit/compiler/unary-ast-transforms.test.ts +0 -245
- package/tsconfig.json +0 -27
- package/tsup.config.ts +0 -11
- package/vitest.config.ts +0 -12
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Switch branch detection algorithm for JDM decisions.
|
|
3
|
-
*
|
|
4
|
-
* This module identifies nodes that are exclusively reachable through switch node branches.
|
|
5
|
-
* These nodes are marked as "switchBranchTargets" and should be skipped during the main
|
|
6
|
-
* evaluation loop because the switch node evaluates them inline when taking a branch.
|
|
7
|
-
*
|
|
8
|
-
* WHY: Prevent double-evaluation - switch nodes evaluate branches inline, so downstream
|
|
9
|
-
* nodes must be skipped in the main evaluation loop to avoid executing them twice.
|
|
10
|
-
*
|
|
11
|
-
* OPTIMIZATION: Uses a single forward traversal through the graph to mark all nodes
|
|
12
|
-
* reachable from switch branches. This is O(n + m) instead of O(s × b × (n + m))
|
|
13
|
-
* where s = switches, b = branches, n = nodes, m = edges.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import type { JDMDecision, JDMEdge } from './parser';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Build an adjacency map for fast edge lookups.
|
|
20
|
-
* Maps each source node ID to an array of target node IDs.
|
|
21
|
-
*
|
|
22
|
-
* @param edges - All edges in the decision graph
|
|
23
|
-
* @returns Map from source node ID to array of target node IDs
|
|
24
|
-
*/
|
|
25
|
-
function buildAdjacencyMap(edges: JDMEdge[]): Map<string, string[]> {
|
|
26
|
-
const adjacencyMap = new Map<string, string[]>();
|
|
27
|
-
|
|
28
|
-
for (const edge of edges) {
|
|
29
|
-
const targets = adjacencyMap.get(edge.sourceId);
|
|
30
|
-
if (targets) {
|
|
31
|
-
targets.push(edge.targetId);
|
|
32
|
-
} else {
|
|
33
|
-
adjacencyMap.set(edge.sourceId, [edge.targetId]);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return adjacencyMap;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Find all nodes that are exclusively reachable through switch node branches.
|
|
42
|
-
*
|
|
43
|
-
* Optimized algorithm:
|
|
44
|
-
* 1. Build adjacency map once for O(1) edge lookups
|
|
45
|
-
* 2. Identify all direct targets of switch nodes
|
|
46
|
-
* 3. Use BFS with efficient queue operations to traverse from all switch targets
|
|
47
|
-
* 4. Marks all nodes reachable from switch branches in a single traversal
|
|
48
|
-
*
|
|
49
|
-
* Time complexity: O(n + m) where n = nodes, m = edges
|
|
50
|
-
* Space complexity: O(n + m) for adjacency map and visited set
|
|
51
|
-
*
|
|
52
|
-
* @param jdm - The parsed JDM decision
|
|
53
|
-
* @returns Set of node IDs that are switch branch targets
|
|
54
|
-
*/
|
|
55
|
-
export function findSwitchBranchTargets(jdm: JDMDecision): Set<string> {
|
|
56
|
-
// Build adjacency map once for O(1) lookups instead of O(m) filtering
|
|
57
|
-
const adjacencyMap = buildAdjacencyMap(jdm.edges);
|
|
58
|
-
|
|
59
|
-
// Find all direct targets of switch nodes
|
|
60
|
-
const switchNodes = jdm.nodes.filter((n) => n.type === 'switchNode');
|
|
61
|
-
const switchBranchTargets = new Set<string>();
|
|
62
|
-
|
|
63
|
-
// Collect all direct switch targets to start BFS from
|
|
64
|
-
const bfsQueue: string[] = [];
|
|
65
|
-
for (const switchNode of switchNodes) {
|
|
66
|
-
const targets = adjacencyMap.get(switchNode.id) || [];
|
|
67
|
-
for (const targetId of targets) {
|
|
68
|
-
if (!switchBranchTargets.has(targetId)) {
|
|
69
|
-
switchBranchTargets.add(targetId);
|
|
70
|
-
bfsQueue.push(targetId);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Single BFS traversal from all switch targets
|
|
76
|
-
// Use index-based iteration instead of shift() to avoid O(n) array operations
|
|
77
|
-
let queueIndex = 0;
|
|
78
|
-
while (queueIndex < bfsQueue.length) {
|
|
79
|
-
const currentId = bfsQueue[queueIndex++];
|
|
80
|
-
|
|
81
|
-
// Get all outgoing edges using O(1) map lookup
|
|
82
|
-
const targets = adjacencyMap.get(currentId) || [];
|
|
83
|
-
for (const targetId of targets) {
|
|
84
|
-
if (!switchBranchTargets.has(targetId)) {
|
|
85
|
-
switchBranchTargets.add(targetId);
|
|
86
|
-
bfsQueue.push(targetId);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return switchBranchTargets;
|
|
92
|
-
}
|
package/src/compiler/types.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type { TSchema } from '@sinclair/typebox';
|
|
2
|
-
import type { JDMDecision } from './parser';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* No-match behavior options for decision tables and switch nodes.
|
|
6
|
-
*
|
|
7
|
-
* This is a discriminated union to ensure type safety:
|
|
8
|
-
* - returnNull and throwError don't require additional data
|
|
9
|
-
* - returnDefault requires a value at type level
|
|
10
|
-
*/
|
|
11
|
-
export type NoMatchBehavior =
|
|
12
|
-
| { type: 'returnNull' }
|
|
13
|
-
| { type: 'throwError' }
|
|
14
|
-
| { type: 'returnDefault'; value: unknown };
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Context passed through compilation phases.
|
|
18
|
-
*/
|
|
19
|
-
export interface CompilationContext {
|
|
20
|
-
/** The parsed JDM */
|
|
21
|
-
jdm: JDMDecision;
|
|
22
|
-
|
|
23
|
-
/** Input schema (TypeBox) */
|
|
24
|
-
inputSchema: TSchema;
|
|
25
|
-
|
|
26
|
-
/** Output schema (TypeBox) */
|
|
27
|
-
outputSchema: TSchema;
|
|
28
|
-
|
|
29
|
-
/** Flattened input memory layout */
|
|
30
|
-
inputLayout: FlattenedLayout;
|
|
31
|
-
|
|
32
|
-
/** Flattened output memory layout */
|
|
33
|
-
outputLayout: FlattenedLayout;
|
|
34
|
-
|
|
35
|
-
/** Schema hash for runtime validation */
|
|
36
|
-
schemaHash: bigint;
|
|
37
|
-
|
|
38
|
-
/** Compiler options */
|
|
39
|
-
options: CompilerOptions;
|
|
40
|
-
|
|
41
|
-
/** Parse an expression string to AST */
|
|
42
|
-
parseExpression(expr: string): any;
|
|
43
|
-
|
|
44
|
-
/** Parse an expression in unary mode */
|
|
45
|
-
parseUnaryExpression(expr: string): any;
|
|
46
|
-
|
|
47
|
-
/** Get unique identifier for generated code */
|
|
48
|
-
getUniqueId(prefix: string): string;
|
|
49
|
-
|
|
50
|
-
/** Loader function to load sub-decision JDM files by reference key */
|
|
51
|
-
loadDecision(key: string): JDMDecision;
|
|
52
|
-
|
|
53
|
-
/** Cache of compiled sub-decisions (key -> compiled code) */
|
|
54
|
-
compiledSubDecisions: Map<string, AssemblyScriptCode>;
|
|
55
|
-
|
|
56
|
-
/** Track the current decision path for cycle detection */
|
|
57
|
-
decisionPath: string[];
|
|
58
|
-
|
|
59
|
-
/** Generated helper functions for higher-order operations */
|
|
60
|
-
helperFunctions: Map<string, string>;
|
|
61
|
-
|
|
62
|
-
/** Function node sources for JavaScript bridge (node ID -> JavaScript source code) */
|
|
63
|
-
functionSources?: Map<string, string>;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Flattened schema layout for direct memory access.
|
|
68
|
-
*/
|
|
69
|
-
export interface FlattenedLayout {
|
|
70
|
-
fields: Array<{
|
|
71
|
-
path: string; // e.g., "customer.age"
|
|
72
|
-
flatName: string; // e.g., "customer_age"
|
|
73
|
-
type: 'f64' | 'i32' | 'i64' | 'bool' | 'string' | 'array';
|
|
74
|
-
offset: number; // Byte offset in struct
|
|
75
|
-
size: number; // Bytes (fixed types) or -1 (variable)
|
|
76
|
-
}>;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Compiler options.
|
|
81
|
-
*/
|
|
82
|
-
export interface CompilerOptions {
|
|
83
|
-
optimize?: boolean;
|
|
84
|
-
debug?: boolean;
|
|
85
|
-
validate?: boolean;
|
|
86
|
-
/** How to handle cases where no rules match in decision tables/switches */
|
|
87
|
-
noMatchBehavior?: NoMatchBehavior;
|
|
88
|
-
/** Optional loader function to load sub-decision JDM files */
|
|
89
|
-
loadDecision?: (key: string) => JDMDecision;
|
|
90
|
-
/** Optional testDataRoot path for default loader to search */
|
|
91
|
-
testDataRoot?: string;
|
|
92
|
-
/**
|
|
93
|
-
* Optional path to write debug AssemblyScript files on compilation failure.
|
|
94
|
-
*
|
|
95
|
-
* When compilation fails, the generated AssemblyScript code is written to disk
|
|
96
|
-
* to aid debugging. This option controls where these files are written:
|
|
97
|
-
*
|
|
98
|
-
* - `undefined` (default): No debug files are written
|
|
99
|
-
* - `string`: Files are written to a secure temporary directory under this path
|
|
100
|
-
* - Environment variable `JDM_ASM_DEBUG_OUTPUT`: Falls back to this path if option not set
|
|
101
|
-
*
|
|
102
|
-
* **Filesystem Side Effects:**
|
|
103
|
-
* - Creates temporary directories with random names (e.g., `jdm-asm-debug-XXXXXX`)
|
|
104
|
-
* - Writes `.ts` files with 0o600 permissions (owner read/write only)
|
|
105
|
-
* - Files are NOT automatically cleaned up and may accumulate
|
|
106
|
-
*
|
|
107
|
-
* **Security:**
|
|
108
|
-
* - Uses `fs.mkdtempSync()` to create secure temporary directories
|
|
109
|
-
* - Files are created with restricted permissions (0o600)
|
|
110
|
-
* - Temporary directories have random names to prevent conflicts
|
|
111
|
-
*/
|
|
112
|
-
debugOutputPath?: string;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Result of compilation.
|
|
117
|
-
*/
|
|
118
|
-
export interface CompilationResult {
|
|
119
|
-
/** Compiled WASM binary */
|
|
120
|
-
wasm: Uint8Array;
|
|
121
|
-
/** Schema hash for runtime validation */
|
|
122
|
-
schemaHash: bigint;
|
|
123
|
-
/** Generated marshaling code (JS) */
|
|
124
|
-
marshalCode: string;
|
|
125
|
-
/** Generated validation code (JS) */
|
|
126
|
-
validationCode: string;
|
|
127
|
-
/** WAT text format (if debug enabled) */
|
|
128
|
-
wat?: string;
|
|
129
|
-
/** Generated AssemblyScript source (if debug enabled) */
|
|
130
|
-
assemblyScript?: string;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Alias for generated AssemblyScript code strings.
|
|
135
|
-
*/
|
|
136
|
-
export type AssemblyScriptCode = string;
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unary AST transformation utilities.
|
|
3
|
-
*
|
|
4
|
-
* This module provides AST-level transformations specific to unary (decision table)
|
|
5
|
-
* context. These transformations are applied AFTER parsing to convert a standard AST
|
|
6
|
-
* into an AST that reflects the semantic meaning in unary context.
|
|
7
|
-
*
|
|
8
|
-
* Key transformations:
|
|
9
|
-
* - Bare identifiers → string literals (for implicit string matching)
|
|
10
|
-
* - Comparison without LHS → $ comparison (e.g., "> 100" → "$ > 100")
|
|
11
|
-
* - Multiple comma-separated values → OR chain
|
|
12
|
-
*
|
|
13
|
-
* This separates SEMANTIC transformations from SYNTACTIC parsing, keeping
|
|
14
|
-
* the parser focused solely on syntax-to-AST conversion.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import type { ExpressionAST, BinaryOperator, BinaryOp } from './ast-types';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Convert a bare Identifier node to a StringLiteral node.
|
|
21
|
-
*
|
|
22
|
-
* In decision table cells, unquoted words like "premium" are semantic values to match against,
|
|
23
|
-
* not variable references. This prevents errors when authors write intuitive cell values without
|
|
24
|
-
* quotes. This is a key DMN/JDM usability feature.
|
|
25
|
-
*
|
|
26
|
-
* This handles the common JDM/DMN convention where cell values like:
|
|
27
|
-
* - premium means match the string "premium" (identifier → string)
|
|
28
|
-
* - "premium" means match the string "premium" (already a string)
|
|
29
|
-
*
|
|
30
|
-
* We only convert top-level Identifiers. More complex expressions (member access,
|
|
31
|
-
* function calls, etc.) are left as-is since they likely involve actual variables.
|
|
32
|
-
*
|
|
33
|
-
* @param ast - The AST node that may be an Identifier
|
|
34
|
-
* @returns The AST node, with Identifier converted to StringLiteral if applicable
|
|
35
|
-
*/
|
|
36
|
-
export function convertIdentifierToStringLiteral(ast: ExpressionAST): ExpressionAST {
|
|
37
|
-
if (ast.type === 'Identifier') {
|
|
38
|
-
return { type: 'StringLiteral', value: (ast as { type: 'Identifier'; name: string }).name };
|
|
39
|
-
}
|
|
40
|
-
return ast;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Wrap an AST value in a comparison with DollarRef (the implicit cell input).
|
|
45
|
-
*
|
|
46
|
-
* In unary context, expressions like "> 100" implicitly compare against the input value.
|
|
47
|
-
* This function creates the full comparison AST: "$ <op> <value>".
|
|
48
|
-
*
|
|
49
|
-
* @param ast - The right-hand side value AST
|
|
50
|
-
* @param op - The comparison operator
|
|
51
|
-
* @returns A BinaryOp AST with DollarRef on the left
|
|
52
|
-
*/
|
|
53
|
-
export function wrapWithDollarComparison(ast: ExpressionAST, op: BinaryOperator): BinaryOp {
|
|
54
|
-
return {
|
|
55
|
-
type: 'BinaryOp',
|
|
56
|
-
op,
|
|
57
|
-
left: { type: 'DollarRef' },
|
|
58
|
-
right: ast,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Create an equality comparison with implicit identifier-to-string conversion.
|
|
64
|
-
*
|
|
65
|
-
* This is the default transformation for unary values - they become equality
|
|
66
|
-
* comparisons against the input value ($). For equality/inequality comparisons,
|
|
67
|
-
* bare identifiers are converted to string literals.
|
|
68
|
-
*
|
|
69
|
-
* @param ast - The value to compare against
|
|
70
|
-
* @param op - The equality operator (== or !=)
|
|
71
|
-
* @returns A BinaryOp AST representing the equality comparison
|
|
72
|
-
*/
|
|
73
|
-
export function createEqualityComparison(ast: ExpressionAST, op: '==' | '!='): BinaryOp {
|
|
74
|
-
const value = convertIdentifierToStringLiteral(ast);
|
|
75
|
-
return wrapWithDollarComparison(value, op);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Create an interval membership check.
|
|
80
|
-
*
|
|
81
|
-
* In unary context, interval notation like "[1..10]" becomes "$ in [1..10]".
|
|
82
|
-
*
|
|
83
|
-
* @param intervalAst - The interval AST node
|
|
84
|
-
* @returns A BinaryOp AST representing the membership check
|
|
85
|
-
*/
|
|
86
|
-
export function createIntervalCheck(intervalAst: ExpressionAST): BinaryOp {
|
|
87
|
-
return wrapWithDollarComparison(intervalAst, 'in');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Create an array membership check.
|
|
92
|
-
*
|
|
93
|
-
* In unary context, array literals like "['gold', 'platinum']" become
|
|
94
|
-
* "$ in ['gold', 'platinum']".
|
|
95
|
-
*
|
|
96
|
-
* @param arrayAst - The array literal AST node
|
|
97
|
-
* @returns A BinaryOp AST representing the membership check
|
|
98
|
-
*/
|
|
99
|
-
export function createArrayMembershipCheck(arrayAst: ExpressionAST): BinaryOp {
|
|
100
|
-
return wrapWithDollarComparison(arrayAst, 'in');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Combine multiple expression ASTs into an OR chain.
|
|
105
|
-
*
|
|
106
|
-
* In unary context, comma-separated values represent OR semantics.
|
|
107
|
-
* For example, "a, b, c" becomes "$ == 'a' or $ == 'b' or $ == 'c'".
|
|
108
|
-
*
|
|
109
|
-
* @param exprs - Array of expression ASTs to combine
|
|
110
|
-
* @returns A single AST representing the OR of all expressions
|
|
111
|
-
*/
|
|
112
|
-
export function combineWithOr(exprs: ExpressionAST[]): ExpressionAST {
|
|
113
|
-
if (exprs.length === 0) {
|
|
114
|
-
return { type: 'BooleanLiteral', value: true };
|
|
115
|
-
}
|
|
116
|
-
if (exprs.length === 1) {
|
|
117
|
-
return exprs[0];
|
|
118
|
-
}
|
|
119
|
-
return exprs.reduce((acc, expr) => ({
|
|
120
|
-
type: 'BinaryOp',
|
|
121
|
-
op: 'or',
|
|
122
|
-
left: acc,
|
|
123
|
-
right: expr,
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Combine multiple expression ASTs into an AND chain.
|
|
129
|
-
*
|
|
130
|
-
* Used for compound unary expressions like ">= 13 and < 15".
|
|
131
|
-
*
|
|
132
|
-
* @param exprs - Array of expression ASTs to combine
|
|
133
|
-
* @returns A single AST representing the AND of all expressions
|
|
134
|
-
*/
|
|
135
|
-
export function combineWithAnd(exprs: ExpressionAST[]): ExpressionAST {
|
|
136
|
-
if (exprs.length === 0) {
|
|
137
|
-
return { type: 'BooleanLiteral', value: true };
|
|
138
|
-
}
|
|
139
|
-
if (exprs.length === 1) {
|
|
140
|
-
return exprs[0];
|
|
141
|
-
}
|
|
142
|
-
return exprs.reduce((acc, expr) => ({
|
|
143
|
-
type: 'BinaryOp',
|
|
144
|
-
op: 'and',
|
|
145
|
-
left: acc,
|
|
146
|
-
right: expr,
|
|
147
|
-
}));
|
|
148
|
-
}
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unary expression parser for decision table cells.
|
|
3
|
-
*
|
|
4
|
-
* This module provides parsing for unary mode expressions, which are used in
|
|
5
|
-
* decision table cells. The parser is responsible for SYNTACTIC analysis only -
|
|
6
|
-
* converting text to AST nodes. Semantic transformations (like converting
|
|
7
|
-
* identifiers to string literals) are handled by the unary-ast-transforms module.
|
|
8
|
-
*
|
|
9
|
-
* Separation of Concerns:
|
|
10
|
-
* - This module: Tokenization, lexing, parsing (text → AST)
|
|
11
|
-
* - unary-ast-transforms: Semantic transformations (AST → transformed AST)
|
|
12
|
-
* - unary-transform: Dollar reference substitution for compilation (AST → compiled AST)
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { parser, lexer } from './expression-parser';
|
|
16
|
-
import { type ExpressionAST, type BinaryOperator } from './ast-types';
|
|
17
|
-
import { cstToAst } from './cst-visitor';
|
|
18
|
-
import { CompilationError, ErrorCode, type SourceLocation } from './errors';
|
|
19
|
-
import {
|
|
20
|
-
wrapWithDollarComparison,
|
|
21
|
-
createEqualityComparison,
|
|
22
|
-
createIntervalCheck,
|
|
23
|
-
createArrayMembershipCheck,
|
|
24
|
-
combineWithOr,
|
|
25
|
-
combineWithAnd,
|
|
26
|
-
} from './unary-ast-transforms';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Parse an expression in unary mode (for decision table cells).
|
|
30
|
-
*
|
|
31
|
-
* In DMN/JDM convention, decision table cells contain concise expressions that implicitly
|
|
32
|
-
* compare against the input column value ($). This allows table authors to write "premium"
|
|
33
|
-
* instead of "$ == 'premium'" or "> 100" instead of "$ > 100", making tables more readable.
|
|
34
|
-
*
|
|
35
|
-
* Unary mode transformations:
|
|
36
|
-
* - "admin" -> $ == "admin"
|
|
37
|
-
* - > 100 -> $ > 100
|
|
38
|
-
* - [1..10] -> $ in [1..10]
|
|
39
|
-
* - "a", "b", "c" -> $ == "a" or $ == "b" or $ == "c"
|
|
40
|
-
* - $ > 100 -> $ > 100 (explicit $ disables transformations)
|
|
41
|
-
*
|
|
42
|
-
* @param input - The unary expression to parse
|
|
43
|
-
* @returns The AST node
|
|
44
|
-
*/
|
|
45
|
-
export function parseUnaryExpression(input: string): ExpressionAST {
|
|
46
|
-
const trimmed = input.trim();
|
|
47
|
-
|
|
48
|
-
// Empty cell = always matches
|
|
49
|
-
if (trimmed === '' || trimmed === '-') {
|
|
50
|
-
return { type: 'BooleanLiteral', value: true };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Check if expression uses explicit $ - if so, parse as standard expression
|
|
54
|
-
if (trimmed.includes('$')) {
|
|
55
|
-
return parseStandardExpression(trimmed);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Check for comma-separated values (OR semantics)
|
|
59
|
-
// But only if it's not an array literal
|
|
60
|
-
if (trimmed.includes(',') && !isArrayLiteral(trimmed)) {
|
|
61
|
-
const parts = splitByComma(trimmed);
|
|
62
|
-
const comparisons = parts.map((part) => transformUnaryPart(part.trim()));
|
|
63
|
-
return combineWithOr(comparisons);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Check for compound expressions with 'and' or 'or' that need implicit $ expansion
|
|
67
|
-
// e.g., ">= 13 and < 15" should become "$ >= 13 and $ < 15"
|
|
68
|
-
const compoundResult = parseCompoundUnary(trimmed);
|
|
69
|
-
if (compoundResult) {
|
|
70
|
-
return compoundResult;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return transformUnaryPart(trimmed);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Parse a single unary part and apply semantic transformations.
|
|
78
|
-
*
|
|
79
|
-
* This function performs both parsing and transformation in a single step:
|
|
80
|
-
* 1. Parse the input using the standard expression parser
|
|
81
|
-
* 2. Apply unary-context semantic transformations (AST operations)
|
|
82
|
-
*
|
|
83
|
-
* @param input - The unary part to parse
|
|
84
|
-
* @returns The transformed AST node
|
|
85
|
-
*/
|
|
86
|
-
function transformUnaryPart(input: string): ExpressionAST {
|
|
87
|
-
// Check for comparison operator at start
|
|
88
|
-
const comparisonMatch = input.match(/^(==|!=|<=|>=|<|>)\s*(.+)$/);
|
|
89
|
-
if (comparisonMatch) {
|
|
90
|
-
const [, op, valueExpr] = comparisonMatch;
|
|
91
|
-
const value = parseStandardExpression(valueExpr);
|
|
92
|
-
// For equality/inequality comparisons, convert bare identifiers to strings
|
|
93
|
-
if (op === '==' || op === '!=') {
|
|
94
|
-
return createEqualityComparison(value, op as '==' | '!=');
|
|
95
|
-
}
|
|
96
|
-
return wrapWithDollarComparison(value, op as BinaryOperator);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check for interval notation
|
|
100
|
-
if (input.match(/^[[].+\.\..*[\])]$/)) {
|
|
101
|
-
const intervalAst = parseStandardExpression(input);
|
|
102
|
-
return createIntervalCheck(intervalAst);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check for array literal - use 'in' for membership
|
|
106
|
-
// e.g., "['gold', 'platinum']" should become "$ in ['gold', 'platinum']"
|
|
107
|
-
if (isArrayLiteral(input)) {
|
|
108
|
-
const arrayAst = parseStandardExpression(input);
|
|
109
|
-
return createArrayMembershipCheck(arrayAst);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Default: equality comparison
|
|
113
|
-
// Convert bare identifiers to string literals for implicit equality
|
|
114
|
-
const value = parseStandardExpression(input);
|
|
115
|
-
return createEqualityComparison(value, '==');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Parse compound unary expressions that use 'and' or 'or' with implicit $
|
|
120
|
-
* Examples:
|
|
121
|
-
* - ">= 13 and < 15" -> "$ >= 13 and $ < 15"
|
|
122
|
-
* - "> 0 or == null" -> "$ > 0 or $ == null"
|
|
123
|
-
*
|
|
124
|
-
* @param input - The expression to parse
|
|
125
|
-
* @returns The AST if compound, null otherwise
|
|
126
|
-
*/
|
|
127
|
-
function parseCompoundUnary(input: string): ExpressionAST | null {
|
|
128
|
-
// Match patterns like: <op1> <val1> and/or <op2> <val2>
|
|
129
|
-
// We need to split by ' and ' or ' or ' while preserving quotes and brackets
|
|
130
|
-
const andParts = splitByLogicalOp(input, 'and');
|
|
131
|
-
if (andParts.length > 1) {
|
|
132
|
-
const comparisons = andParts.map((part) => transformUnaryPart(part.trim()));
|
|
133
|
-
return combineWithAnd(comparisons);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const orParts = splitByLogicalOp(input, 'or');
|
|
137
|
-
if (orParts.length > 1) {
|
|
138
|
-
const comparisons = orParts.map((part) => transformUnaryPart(part.trim()));
|
|
139
|
-
return combineWithOr(comparisons);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Split input by a logical operator (' and ' or ' or '), respecting quotes and brackets.
|
|
147
|
-
*
|
|
148
|
-
* This is a parsing helper that performs tokenization while respecting nested structures.
|
|
149
|
-
*/
|
|
150
|
-
function splitByLogicalOp(input: string, op: 'and' | 'or'): string[] {
|
|
151
|
-
const pattern = ` ${op} `;
|
|
152
|
-
const parts: string[] = [];
|
|
153
|
-
let current = '';
|
|
154
|
-
let depth = 0;
|
|
155
|
-
let inString = false;
|
|
156
|
-
let stringChar = '';
|
|
157
|
-
let i = 0;
|
|
158
|
-
|
|
159
|
-
while (i < input.length) {
|
|
160
|
-
const char = input[i];
|
|
161
|
-
|
|
162
|
-
if (inString) {
|
|
163
|
-
current += char;
|
|
164
|
-
if (char === stringChar && input[i - 1] !== '\\') {
|
|
165
|
-
inString = false;
|
|
166
|
-
}
|
|
167
|
-
i++;
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (char === '"' || char === "'") {
|
|
172
|
-
inString = true;
|
|
173
|
-
stringChar = char;
|
|
174
|
-
current += char;
|
|
175
|
-
i++;
|
|
176
|
-
} else if (char === '[' || char === '(' || char === '{') {
|
|
177
|
-
depth++;
|
|
178
|
-
current += char;
|
|
179
|
-
i++;
|
|
180
|
-
} else if (char === ']' || char === ')' || char === '}') {
|
|
181
|
-
depth--;
|
|
182
|
-
current += char;
|
|
183
|
-
i++;
|
|
184
|
-
} else if (depth === 0 && input.substring(i, i + pattern.length).toLowerCase() === pattern) {
|
|
185
|
-
parts.push(current);
|
|
186
|
-
current = '';
|
|
187
|
-
i += pattern.length;
|
|
188
|
-
} else {
|
|
189
|
-
current += char;
|
|
190
|
-
i++;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (current) {
|
|
195
|
-
parts.push(current);
|
|
196
|
-
}
|
|
197
|
-
return parts;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Check if a string represents an array literal (not an interval).
|
|
202
|
-
*
|
|
203
|
-
* Arrays and intervals both use bracket syntax but have different semantics.
|
|
204
|
-
* Arrays check membership ($ in [1,2,3]), intervals check ranges ($ in [1..10]).
|
|
205
|
-
* Must detect .. to parse correctly.
|
|
206
|
-
*/
|
|
207
|
-
function isArrayLiteral(input: string): boolean {
|
|
208
|
-
return input.startsWith('[') && input.endsWith(']') && !input.includes('..');
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Smart split by comma that respects brackets and strings.
|
|
213
|
-
*
|
|
214
|
-
* This is a parsing helper for tokenizing comma-separated unary values
|
|
215
|
-
* while respecting nested structures.
|
|
216
|
-
*
|
|
217
|
-
* Examples:
|
|
218
|
-
* - "a, b, c" -> ["a", "b", "c"]
|
|
219
|
-
* - "[1, 2], [3, 4]" -> ["[1, 2]", "[3, 4]"]
|
|
220
|
-
* - '"a, b", "c, d"' -> ['"a, b"', '"c, d"']
|
|
221
|
-
*/
|
|
222
|
-
function splitByComma(input: string): string[] {
|
|
223
|
-
const parts: string[] = [];
|
|
224
|
-
let current = '';
|
|
225
|
-
let depth = 0;
|
|
226
|
-
let inString = false;
|
|
227
|
-
let stringChar = '';
|
|
228
|
-
|
|
229
|
-
for (let i = 0; i < input.length; i++) {
|
|
230
|
-
const char = input[i];
|
|
231
|
-
|
|
232
|
-
if (inString) {
|
|
233
|
-
current += char;
|
|
234
|
-
// Check if string ends (and handle escaped quotes)
|
|
235
|
-
if (char === stringChar && input[i - 1] !== '\\') {
|
|
236
|
-
inString = false;
|
|
237
|
-
}
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (char === '"' || char === "'") {
|
|
242
|
-
inString = true;
|
|
243
|
-
stringChar = char;
|
|
244
|
-
current += char;
|
|
245
|
-
} else if (char === '[' || char === '(') {
|
|
246
|
-
depth++;
|
|
247
|
-
current += char;
|
|
248
|
-
} else if (char === ']' || char === ')') {
|
|
249
|
-
depth--;
|
|
250
|
-
current += char;
|
|
251
|
-
} else if (char === ',' && depth === 0) {
|
|
252
|
-
parts.push(current);
|
|
253
|
-
current = '';
|
|
254
|
-
} else {
|
|
255
|
-
current += char;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (current) {
|
|
260
|
-
parts.push(current);
|
|
261
|
-
}
|
|
262
|
-
return parts;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Parse a standard (non-unary) expression.
|
|
267
|
-
*
|
|
268
|
-
* This is the core parsing function that converts an expression string to an AST.
|
|
269
|
-
* It uses the Chevrotain lexer and parser defined in expression-parser.ts,
|
|
270
|
-
* then converts the CST to AST using cst-visitor.ts.
|
|
271
|
-
*
|
|
272
|
-
* @param input - The expression string to parse
|
|
273
|
-
* @param location - Optional source location for error reporting
|
|
274
|
-
* @returns The AST node
|
|
275
|
-
*/
|
|
276
|
-
export function parseStandardExpression(input: string, location?: SourceLocation): ExpressionAST {
|
|
277
|
-
const lexingResult = lexer.tokenize(input);
|
|
278
|
-
|
|
279
|
-
if (lexingResult.errors.length > 0) {
|
|
280
|
-
throw new CompilationError(
|
|
281
|
-
`Lexer error: ${lexingResult.errors.map((e: any) => e.message).join(', ')}`,
|
|
282
|
-
ErrorCode.PARSE_ERROR,
|
|
283
|
-
location,
|
|
284
|
-
{ expression: input },
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
parser.input = lexingResult.tokens;
|
|
289
|
-
const cst = parser.expression();
|
|
290
|
-
|
|
291
|
-
if (parser.errors.length > 0) {
|
|
292
|
-
throw new CompilationError(
|
|
293
|
-
`Parse error: ${parser.errors.map((e: any) => e.message).join(', ')}`,
|
|
294
|
-
ErrorCode.PARSE_ERROR,
|
|
295
|
-
location,
|
|
296
|
-
{ expression: input },
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return cstToAst(cst);
|
|
301
|
-
}
|