@divmain/jdm-asm 0.2.0 → 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,507 +0,0 @@
|
|
|
1
|
-
import type { JDMNode } from '../parser';
|
|
2
|
-
import type { CompilationContext, AssemblyScriptCode, NoMatchBehavior } from '../types';
|
|
3
|
-
import { sanitizeId } from '../utils';
|
|
4
|
-
import { compileExpression } from './expression';
|
|
5
|
-
import { replaceDollarRefWithCode, compileExpressionWithInlineCode } from '../unary-transform';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Decision table content structure.
|
|
9
|
-
*/
|
|
10
|
-
interface DecisionTableContent {
|
|
11
|
-
rules: any[];
|
|
12
|
-
inputs: any[];
|
|
13
|
-
outputs: any[];
|
|
14
|
-
hitPolicy: 'first' | 'collect' | 'unique' | 'ruleOrder' | 'outputOrder' | 'priority';
|
|
15
|
-
/** Override the global no-match behavior for this table */
|
|
16
|
-
noMatchBehavior?: NoMatchBehavior;
|
|
17
|
-
/** Whether to pass through input values to output */
|
|
18
|
-
passThrough?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Compile a comparison expression for a decision table condition.
|
|
23
|
-
*
|
|
24
|
-
* In decision tables, expressions are evaluated in a "unary" context where
|
|
25
|
-
* the $ symbol is automatically bound to the input field's value.
|
|
26
|
-
*
|
|
27
|
-
* For example:
|
|
28
|
-
* - "> 100" becomes "$ > 100" with $ bound to the input field
|
|
29
|
-
* - "admin" becomes "$ == admin" (equality check)
|
|
30
|
-
* - "[1..10]" becomes "$ in [1..10]" (range check)
|
|
31
|
-
*
|
|
32
|
-
* The field parameter can be either:
|
|
33
|
-
* - A simple field name like "creditScore" → ctx.get("creditScore")
|
|
34
|
-
* - An expression like "date(order.createdAt)" → needs to be parsed and evaluated
|
|
35
|
-
*
|
|
36
|
-
* Since AssemblyScript doesn't support closures, we transform the AST
|
|
37
|
-
* to replace DollarRef nodes with the compiled field expression.
|
|
38
|
-
*
|
|
39
|
-
* @param expr - The raw expression string
|
|
40
|
-
* @param inputType - The type of the input field
|
|
41
|
-
* @param field - The field expression to compare against
|
|
42
|
-
* @param context - The compilation context
|
|
43
|
-
* @returns Compiled AssemblyScript code for the comparison
|
|
44
|
-
*/
|
|
45
|
-
function compileComparison(
|
|
46
|
-
expr: string,
|
|
47
|
-
inputType: string,
|
|
48
|
-
field: string | undefined,
|
|
49
|
-
context: CompilationContext,
|
|
50
|
-
): string {
|
|
51
|
-
// Handle empty expressions or unset values. Empty cells mean "any value matches" for
|
|
52
|
-
// that column. This is flexible (allows partial rule specification) but can be dangerous
|
|
53
|
-
// (typos become wildcards). Following DMN/JDM convention where blank = don't care.
|
|
54
|
-
if (!expr || expr === '' || expr === '-') {
|
|
55
|
-
return 'true';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
// When input field is "$", the cell contains a full boolean expression rather than a
|
|
60
|
-
// unary comparison:
|
|
61
|
-
// e.g., "age > 18 and tier == 'gold'"
|
|
62
|
-
// This allows complex conditions that span multiple input values in a single cell, useful
|
|
63
|
-
// for cross-column logic.
|
|
64
|
-
if (!field || field === '$') {
|
|
65
|
-
// Parse and compile the expression directly as a standard expression
|
|
66
|
-
const ast = context.parseExpression(expr);
|
|
67
|
-
const compiledExpr = compileExpression(ast, context);
|
|
68
|
-
return `${compiledExpr}.asBool()`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Parse the expression using unary parser for decision table cells
|
|
72
|
-
// This transforms expressions like "> 100" into AST representing "$ > 100"
|
|
73
|
-
const ast = context.parseUnaryExpression(expr);
|
|
74
|
-
|
|
75
|
-
// Compile the field expression to get the value to compare against
|
|
76
|
-
// The field can be a simple name like "creditScore" or an expression like "date(order.createdAt)"
|
|
77
|
-
const fieldAst = context.parseExpression(field);
|
|
78
|
-
const compiledField = compileExpression(fieldAst, context);
|
|
79
|
-
|
|
80
|
-
// Transform the AST to replace DollarRef nodes with the compiled field expression
|
|
81
|
-
// AssemblyScript doesn't support closures, so we can't create a function context
|
|
82
|
-
// where $ refers to the field value. Instead, we do direct AST substitution.
|
|
83
|
-
const transformedAst = replaceDollarRefWithCode(ast, compiledField);
|
|
84
|
-
|
|
85
|
-
// Compile the transformed AST to AssemblyScript code
|
|
86
|
-
const compiledExpr = compileExpressionWithInlineCode(transformedAst, context);
|
|
87
|
-
|
|
88
|
-
// Return the compiled expression wrapped in .asBool() for the condition
|
|
89
|
-
return `${compiledExpr}.asBool()`;
|
|
90
|
-
} catch (e) {
|
|
91
|
-
// If parsing fails, log the error and return false (no match)
|
|
92
|
-
// This prevents compilation failures from breaking the entire decision
|
|
93
|
-
throw new Error(
|
|
94
|
-
`Failed to compile decision table condition "${expr}" for field "${field}": ${e}`,
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Compile an output value for a decision table result.
|
|
101
|
-
*
|
|
102
|
-
* @param value - The raw value string
|
|
103
|
-
* @param outputType - The type of the output field
|
|
104
|
-
* @param field - The field name being set
|
|
105
|
-
* @param context - The compilation context
|
|
106
|
-
* @returns Compiled AssemblyScript code for the value
|
|
107
|
-
*/
|
|
108
|
-
function compileOutputValue(
|
|
109
|
-
value: string,
|
|
110
|
-
outputType: string,
|
|
111
|
-
field: string,
|
|
112
|
-
context: CompilationContext,
|
|
113
|
-
): string {
|
|
114
|
-
// Handle empty/unset values: in multi-output tables, rules may set some outputs but not others.
|
|
115
|
-
// Empty cells mean "this rule doesn't provide a value for this output field", allowing sparse tables.
|
|
116
|
-
if (!value || value === '-' || value === '') {
|
|
117
|
-
return '';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const normalizedType = (outputType || '').toLowerCase();
|
|
121
|
-
|
|
122
|
-
// Check if value is a quoted string literal ('value' or "value")
|
|
123
|
-
// In JDM format, string literals are often wrapped in single quotes
|
|
124
|
-
const isQuotedString =
|
|
125
|
-
(value.startsWith("'") && value.endsWith("'")) ||
|
|
126
|
-
(value.startsWith('"') && value.endsWith('"'));
|
|
127
|
-
|
|
128
|
-
// Strip outer quotes if present for string literal values
|
|
129
|
-
const unquotedValue = isQuotedString ? value.slice(1, -1) : value;
|
|
130
|
-
|
|
131
|
-
switch (normalizedType) {
|
|
132
|
-
case 'expression': {
|
|
133
|
-
// For expression type, parse and compile the value as an expression
|
|
134
|
-
// This allows output values to reference context variables or perform calculations
|
|
135
|
-
const ast = context.parseExpression(value);
|
|
136
|
-
return compileExpression(ast, context);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
case 'string':
|
|
140
|
-
case 'text':
|
|
141
|
-
// Input values may have quotes that need escaping for the generated AS code. Must escape
|
|
142
|
-
// both backslashes (for escape sequences) and double quotes (for string delimiters).
|
|
143
|
-
const escaped = unquotedValue.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
144
|
-
return 'Value.String("' + escaped + '")';
|
|
145
|
-
|
|
146
|
-
case 'number':
|
|
147
|
-
case 'integer':
|
|
148
|
-
case 'decimal':
|
|
149
|
-
case 'double':
|
|
150
|
-
return `Value.Float(${parseFloat(value)})`;
|
|
151
|
-
|
|
152
|
-
case 'boolean':
|
|
153
|
-
case 'bool':
|
|
154
|
-
return `Value.Bool(${value.toLowerCase() === 'true'})`;
|
|
155
|
-
|
|
156
|
-
default:
|
|
157
|
-
// For untyped values, infer type through a cascade:
|
|
158
|
-
// 1. Quoted strings → string literal
|
|
159
|
-
// 2. "true"/"false" → boolean
|
|
160
|
-
// 3. Numeric format → number
|
|
161
|
-
// 4. Otherwise → try parsing as expression, fallback to string literal
|
|
162
|
-
if (isQuotedString) {
|
|
163
|
-
// Value is a string literal - use the unquoted value
|
|
164
|
-
const defaultEscaped = unquotedValue.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
165
|
-
return 'Value.String("' + defaultEscaped + '")';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Check if it's a boolean
|
|
169
|
-
if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') {
|
|
170
|
-
return `Value.Bool(${value.toLowerCase() === 'true'})`;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Check if it's a number (use regex to handle trailing zeros like "0.10")
|
|
174
|
-
// The regex matches integer, decimal, and scientific notation formats
|
|
175
|
-
if (/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(value)) {
|
|
176
|
-
return `Value.Float(${parseFloat(value)})`;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// For unquoted non-literal values, treat as an expression
|
|
180
|
-
// This handles cases like "basicEligibility.reason" or "totalScore * 1.5"
|
|
181
|
-
try {
|
|
182
|
-
const ast = context.parseExpression(value);
|
|
183
|
-
return compileExpression(ast, context);
|
|
184
|
-
} catch (e) {
|
|
185
|
-
// Throw error instead of silently falling back to string literal
|
|
186
|
-
// This prevents type errors and typos from being silently converted to strings
|
|
187
|
-
throw new Error(
|
|
188
|
-
`Failed to compile output value "${value}" for field "${field}": ${e}. ` +
|
|
189
|
-
`If you intended a literal string, wrap it in quotes: '"${value}"' or "'${value}'"`,
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Extract string literals from compiled code and generate hoisted constants.
|
|
197
|
-
* This optimization avoids repeated string allocations in large decision tables.
|
|
198
|
-
*
|
|
199
|
-
* Hoisting string literals to module-level constants prevents repeated allocations
|
|
200
|
-
* that can exhaust WASM memory during table evaluation.
|
|
201
|
-
*
|
|
202
|
-
* @param code - The compiled code containing Value.String(...) calls
|
|
203
|
-
* @param nodeId - Unique identifier for this node (used in constant names)
|
|
204
|
-
* @returns Object with hoisted constants code and transformed code
|
|
205
|
-
*/
|
|
206
|
-
function hoistStringLiterals(code: string, nodeId: string): { constants: string; code: string } {
|
|
207
|
-
// Find all Value.String("...") patterns
|
|
208
|
-
const stringLiteralRegex = /Value\.String\("([^"\\]|\\.)*"\)/g;
|
|
209
|
-
const matches = code.match(stringLiteralRegex) || [];
|
|
210
|
-
|
|
211
|
-
// Count occurrences
|
|
212
|
-
const counts = new Map<string, number>();
|
|
213
|
-
for (const match of matches) {
|
|
214
|
-
counts.set(match, (counts.get(match) || 0) + 1);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Only hoist strings that appear more than once
|
|
218
|
-
const toHoist = new Map<string, string>();
|
|
219
|
-
let constIndex = 0;
|
|
220
|
-
for (const [literal, count] of counts) {
|
|
221
|
-
if (count > 1) {
|
|
222
|
-
// Extract the string content for naming
|
|
223
|
-
const constName = `__str_${sanitizeId(nodeId)}_${constIndex++}`;
|
|
224
|
-
toHoist.set(literal, constName);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// If nothing to hoist, return original
|
|
229
|
-
if (toHoist.size === 0) {
|
|
230
|
-
return { constants: '', code };
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Generate constant declarations
|
|
234
|
-
const constants = Array.from(toHoist.entries())
|
|
235
|
-
.map(([literal, constName]) => `const ${constName}: Value = ${literal};`)
|
|
236
|
-
.join('\n');
|
|
237
|
-
|
|
238
|
-
// Replace literals with constant references
|
|
239
|
-
let transformedCode = code;
|
|
240
|
-
for (const [literal, constName] of toHoist) {
|
|
241
|
-
// Need to escape regex special chars in the literal
|
|
242
|
-
const escapedLiteral = literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
243
|
-
transformedCode = transformedCode.replace(new RegExp(escapedLiteral, 'g'), constName);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return { constants, code: transformedCode };
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Compile a decision table node.
|
|
251
|
-
*
|
|
252
|
-
* Generates if/else chains for decision table evaluation, supporting:
|
|
253
|
-
* - FIRST hit policy: Returns the first matching rule's output
|
|
254
|
-
* - COLLECT hit policy: Aggregates all matching rules' outputs
|
|
255
|
-
* - UNIQUE hit policy: Returns output if exactly one rule matches
|
|
256
|
-
* - RULE ORDER hit policy: Returns all matching rules' outputs in rule order
|
|
257
|
-
* - OUTPUT ORDER hit policy: Returns all matching rules sorted by output priority
|
|
258
|
-
* - PRIORITY hit policy: Returns only the highest-priority matching rule
|
|
259
|
-
*
|
|
260
|
-
* For large decision tables (many rules with repeated string literals),
|
|
261
|
-
* string literals are hoisted to module-level constants to avoid
|
|
262
|
-
* repeated allocations that can exhaust memory.
|
|
263
|
-
*
|
|
264
|
-
* @param node - The JDM decision table node
|
|
265
|
-
* @param context - The compilation context
|
|
266
|
-
* @returns Generated AssemblyScript code
|
|
267
|
-
*/
|
|
268
|
-
export function compileDecisionTableNode(
|
|
269
|
-
node: JDMNode,
|
|
270
|
-
context: CompilationContext,
|
|
271
|
-
): AssemblyScriptCode {
|
|
272
|
-
const {
|
|
273
|
-
rules,
|
|
274
|
-
inputs,
|
|
275
|
-
outputs,
|
|
276
|
-
hitPolicy,
|
|
277
|
-
noMatchBehavior: tableNoMatchBehavior,
|
|
278
|
-
passThrough,
|
|
279
|
-
} = node.content as DecisionTableContent;
|
|
280
|
-
|
|
281
|
-
// Determine the effective no-match behavior (table-level overrides global)
|
|
282
|
-
const noMatchBehavior = tableNoMatchBehavior ??
|
|
283
|
-
context.options.noMatchBehavior ?? { type: 'returnNull' };
|
|
284
|
-
|
|
285
|
-
// Unique and priority need to evaluate all rules before making a decision
|
|
286
|
-
const isCollectAll =
|
|
287
|
-
hitPolicy === 'collect' ||
|
|
288
|
-
hitPolicy === 'unique' ||
|
|
289
|
-
hitPolicy === 'ruleOrder' ||
|
|
290
|
-
hitPolicy === 'outputOrder' ||
|
|
291
|
-
hitPolicy === 'priority';
|
|
292
|
-
|
|
293
|
-
// Generate the result declaration based on hit policy
|
|
294
|
-
let resultDeclaration: string;
|
|
295
|
-
if (isCollectAll) {
|
|
296
|
-
resultDeclaration = 'let results = new Array<Value>();';
|
|
297
|
-
} else {
|
|
298
|
-
resultDeclaration = '';
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Generate the rule evaluation branches
|
|
302
|
-
const ruleBranches = rules
|
|
303
|
-
.map((rule, idx) => {
|
|
304
|
-
// Compile all input conditions for this rule
|
|
305
|
-
const conditions = inputs
|
|
306
|
-
.map((input) => {
|
|
307
|
-
const expr = rule[input.id];
|
|
308
|
-
if (!expr || expr === '' || expr === '-') {
|
|
309
|
-
return 'true';
|
|
310
|
-
}
|
|
311
|
-
return compileComparison(expr, input.type, input.field, context);
|
|
312
|
-
})
|
|
313
|
-
.join(' && ');
|
|
314
|
-
|
|
315
|
-
// Compile all output values for this rule
|
|
316
|
-
const resultAssignments = outputs
|
|
317
|
-
.map((output) => {
|
|
318
|
-
const value = rule[output.id];
|
|
319
|
-
if (!value || value === '' || value === '-') {
|
|
320
|
-
return '';
|
|
321
|
-
}
|
|
322
|
-
const compiled = compileOutputValue(value, output.type, output.field, context);
|
|
323
|
-
return ` result.set("${output.field}", ${compiled});`;
|
|
324
|
-
})
|
|
325
|
-
.filter(Boolean)
|
|
326
|
-
.join('\n');
|
|
327
|
-
|
|
328
|
-
// Generate the conditional expression and action
|
|
329
|
-
if (isCollectAll) {
|
|
330
|
-
// For collect-mode hit policies, evaluate all rules independently
|
|
331
|
-
return `
|
|
332
|
-
if (${conditions || 'true'}) {
|
|
333
|
-
let result = new Map<string, Value>();
|
|
334
|
-
${resultAssignments}
|
|
335
|
-
results.push(Value.Object(result));
|
|
336
|
-
}`;
|
|
337
|
-
} else {
|
|
338
|
-
// For FIRST hit policy, use if/else if chain
|
|
339
|
-
const conditionalExpr =
|
|
340
|
-
idx === 0 ? `if (${conditions || 'true'})` : `else if (${conditions || 'true'})`;
|
|
341
|
-
return `${conditionalExpr} {
|
|
342
|
-
let result = new Map<string, Value>();
|
|
343
|
-
${resultAssignments}
|
|
344
|
-
return Value.Object(result);
|
|
345
|
-
}`;
|
|
346
|
-
}
|
|
347
|
-
})
|
|
348
|
-
.join(isCollectAll ? '\n' : '\n');
|
|
349
|
-
|
|
350
|
-
// Generate the no-match handler based on the effective behavior
|
|
351
|
-
function generateNoMatchHandler(): string {
|
|
352
|
-
const returnNull = 'return Value.Null();';
|
|
353
|
-
|
|
354
|
-
// We need to signal to the caller that no rules matched but the table has passThrough enabled,
|
|
355
|
-
// so it should return accumulated context. We can't directly access the outer context here, so
|
|
356
|
-
// we return a marker object that the caller detects and handles.
|
|
357
|
-
const returnPassthroughSignal = `let __pt = new Map<string, Value>();
|
|
358
|
-
__pt.set("__passthrough", Value.Bool(true));
|
|
359
|
-
return Value.Object(__pt);`;
|
|
360
|
-
|
|
361
|
-
if (noMatchBehavior.type === 'throwError') {
|
|
362
|
-
return `SetLastErrorWithMessage(RuntimeErrorCode.EVALUATION_ERROR, "Decision table \\"${node.name}\\" (id: ${node.id}): No matching rules found");\n ${returnNull}`;
|
|
363
|
-
} else if (noMatchBehavior.type === 'returnDefault') {
|
|
364
|
-
const defaultValue = noMatchBehavior.value;
|
|
365
|
-
|
|
366
|
-
// Generate the default value as a Value based on its JavaScript type
|
|
367
|
-
let defaultValueCode: string;
|
|
368
|
-
switch (typeof defaultValue) {
|
|
369
|
-
case 'string':
|
|
370
|
-
defaultValueCode = `Value.String("${String(defaultValue).replace(/"/g, '\\"')}")`;
|
|
371
|
-
break;
|
|
372
|
-
case 'number':
|
|
373
|
-
defaultValueCode = `Value.Float(${defaultValue})`;
|
|
374
|
-
break;
|
|
375
|
-
case 'boolean':
|
|
376
|
-
defaultValueCode = `Value.Bool(${defaultValue})`;
|
|
377
|
-
break;
|
|
378
|
-
default:
|
|
379
|
-
defaultValueCode = `Value.String("${String(defaultValue)}")`;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Assign the default value to each output field
|
|
383
|
-
const defaultAssignments = outputs
|
|
384
|
-
.map((output) => {
|
|
385
|
-
return ` result.set("${output.field}", ${defaultValueCode});`;
|
|
386
|
-
})
|
|
387
|
-
.join('\n');
|
|
388
|
-
|
|
389
|
-
const defaultAssignmentSingle =
|
|
390
|
-
outputs.length > 0
|
|
391
|
-
? ` let result = new Map<string, Value>();\n${defaultAssignments}\n return Value.Object(result);`
|
|
392
|
-
: returnNull;
|
|
393
|
-
|
|
394
|
-
if (isCollectAll) {
|
|
395
|
-
// For collect-mode policies, return array with default result
|
|
396
|
-
return ` let result = new Map<string, Value>();\n${defaultAssignments}\n return Value.Array([Value.Object(result)]);`;
|
|
397
|
-
} else {
|
|
398
|
-
return defaultAssignmentSingle;
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
// Default: returnNull
|
|
402
|
-
// But for FIRST hit policy with passThrough, signal to use accumulated context
|
|
403
|
-
if (passThrough && hitPolicy === 'first') {
|
|
404
|
-
return returnPassthroughSignal;
|
|
405
|
-
}
|
|
406
|
-
return returnNull;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// Generate the final return statement based on hit policy
|
|
411
|
-
// COLLECT-style policies return arrays directly (not wrapped in object)
|
|
412
|
-
// The node name keying is handled by codegen.ts when storing in context
|
|
413
|
-
let finalReturn: string;
|
|
414
|
-
if (hitPolicy === 'collect' || hitPolicy === 'ruleOrder') {
|
|
415
|
-
// For collect policies no-match handling
|
|
416
|
-
if (noMatchBehavior.type === 'throwError') {
|
|
417
|
-
finalReturn = `
|
|
418
|
-
if (results.length == 0) {
|
|
419
|
-
${generateNoMatchHandler()}
|
|
420
|
-
}
|
|
421
|
-
return Value.Array(results);`;
|
|
422
|
-
} else if (noMatchBehavior.type === 'returnDefault') {
|
|
423
|
-
finalReturn = `
|
|
424
|
-
if (results.length == 0) {
|
|
425
|
-
${generateNoMatchHandler()}
|
|
426
|
-
}
|
|
427
|
-
return Value.Array(results);`;
|
|
428
|
-
} else {
|
|
429
|
-
finalReturn = `return Value.Array(results);`;
|
|
430
|
-
}
|
|
431
|
-
} else if (hitPolicy === 'unique') {
|
|
432
|
-
finalReturn = `
|
|
433
|
-
// Validate exactly one match
|
|
434
|
-
if (results.length == 1) {
|
|
435
|
-
return results[0];
|
|
436
|
-
} else if (results.length == 0) {
|
|
437
|
-
${generateNoMatchHandler()}
|
|
438
|
-
} else {
|
|
439
|
-
// Multiple matches - this violates UNIQUE constraint
|
|
440
|
-
SetLastErrorWithMessage(RuntimeErrorCode.EVALUATION_ERROR, "Decision table \\"${node.name}\\" (id: ${node.id}): Multiple rules matched but UNIQUE hit policy requires exactly one match");
|
|
441
|
-
return Value.Null();
|
|
442
|
-
}`;
|
|
443
|
-
} else if (hitPolicy === 'outputOrder' || hitPolicy === 'priority') {
|
|
444
|
-
if (outputs.length === 0) {
|
|
445
|
-
throw new Error(`${hitPolicy.toUpperCase()} hit policy requires at least one output field`);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const primaryOutput = outputs[0];
|
|
449
|
-
finalReturn = `
|
|
450
|
-
// Sort by output value (descending priority), with rule order as tie-breaker
|
|
451
|
-
results.sort((a: Value, b: Value): i32 => {
|
|
452
|
-
let aOutput = a.asObject().get("${primaryOutput.field}");
|
|
453
|
-
let bOutput = b.asObject().get("${primaryOutput.field}");
|
|
454
|
-
|
|
455
|
-
// Compare the primary output values
|
|
456
|
-
let cmp = compareValues(aOutput, bOutput);
|
|
457
|
-
|
|
458
|
-
// If outputs are equal, maintain rule order (lower index = higher priority)
|
|
459
|
-
if (cmp == 0) {
|
|
460
|
-
return 1; // already in rule order, so keep it
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// Return results in descending order of output priority
|
|
464
|
-
// Higher output values come first
|
|
465
|
-
return cmp < 0 ? 1 : -1;
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
if (results.length == 0) {
|
|
469
|
-
${generateNoMatchHandler()}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
${
|
|
473
|
-
hitPolicy === 'priority'
|
|
474
|
-
? '// Return only the highest-priority result\n return results[0];'
|
|
475
|
-
: 'return Value.Array(results);'
|
|
476
|
-
}`;
|
|
477
|
-
} else {
|
|
478
|
-
// Default case - FIRST hit policy
|
|
479
|
-
finalReturn = `\n else {\n ${generateNoMatchHandler()}\n }`;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
const sanitizedId = sanitizeId(node.id);
|
|
483
|
-
|
|
484
|
-
// Build the raw function body
|
|
485
|
-
const rawFunctionBody = `
|
|
486
|
-
export function evaluateNode_${sanitizedId}(ctx: Context): Value {
|
|
487
|
-
${resultDeclaration}
|
|
488
|
-
|
|
489
|
-
${ruleBranches}
|
|
490
|
-
${finalReturn}
|
|
491
|
-
}
|
|
492
|
-
`;
|
|
493
|
-
|
|
494
|
-
// For large decision tables, hoist repeated string literals to module-level constants
|
|
495
|
-
// This prevents memory exhaustion from repeated Value.String() allocations
|
|
496
|
-
if (rules.length > 100) {
|
|
497
|
-
const { constants, code: optimizedBody } = hoistStringLiterals(rawFunctionBody, node.id);
|
|
498
|
-
if (constants) {
|
|
499
|
-
return `// Hoisted string constants for decision table "${node.name}" (${rules.length} rules)
|
|
500
|
-
${constants}
|
|
501
|
-
|
|
502
|
-
${optimizedBody}`;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
return rawFunctionBody;
|
|
507
|
-
}
|