@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
package/src/compiler/runtime.ts
DELETED
|
@@ -1,452 +0,0 @@
|
|
|
1
|
-
// src/compiler/runtime.ts
|
|
2
|
-
// Runtime execution support for evaluating compiled JDM decisions
|
|
3
|
-
|
|
4
|
-
import type { CompilationResult } from './types';
|
|
5
|
-
import {
|
|
6
|
-
loadGeneratedMarshaling,
|
|
7
|
-
loadGeneratedValidation,
|
|
8
|
-
type MarshalFn,
|
|
9
|
-
type UnmarshalFn,
|
|
10
|
-
type ValidateFn,
|
|
11
|
-
} from './runtime-codegen';
|
|
12
|
-
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Memory Constants
|
|
15
|
-
// ============================================================================
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* WebAssembly page size in bytes (64KB).
|
|
19
|
-
* This is a fixed constant defined by the WebAssembly specification.
|
|
20
|
-
* Used to calculate memory requirements and convert between pages and bytes.
|
|
21
|
-
*/
|
|
22
|
-
const WASM_PAGE_SIZE_BYTES = 65536;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Default maximum memory pages for compiled decisions (256 pages = 16MB).
|
|
26
|
-
*
|
|
27
|
-
* This limit balances:
|
|
28
|
-
* 1. Allowing large decision tables with many rules
|
|
29
|
-
* 2. Preventing unbounded memory growth
|
|
30
|
-
* 3. Browser compatibility (most browsers support at least 32MB per WASM instance)
|
|
31
|
-
*
|
|
32
|
-
* Can be overridden via CompiledDecisionOptions.maximumMemoryPages.
|
|
33
|
-
*/
|
|
34
|
-
const DEFAULT_MAX_MEMORY_PAGES = 256;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Input buffer start offset in bytes (after null pointer trap).
|
|
38
|
-
*
|
|
39
|
-
* Must match INPUT_BUFFER_START in src/runtime/memory.ts (which equals
|
|
40
|
-
* NULL_POINTER_TRAP_SIZE = 4 bytes). This ensures correct memory layout
|
|
41
|
-
* coordination between JavaScript marshaling and WASM memory access.
|
|
42
|
-
*
|
|
43
|
-
* The first 4 bytes are reserved as a null pointer trap zone - accessing
|
|
44
|
-
* address 0 will read/write this trap zone, helping catch null pointer bugs.
|
|
45
|
-
*/
|
|
46
|
-
const INPUT_BUFFER_START_OFFSET = 4;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Error type for runtime evaluation errors.
|
|
50
|
-
*/
|
|
51
|
-
export class RuntimeError extends Error {
|
|
52
|
-
constructor(
|
|
53
|
-
message: string,
|
|
54
|
-
public readonly code: number = -1,
|
|
55
|
-
public readonly context?: Record<string, unknown>,
|
|
56
|
-
) {
|
|
57
|
-
super(message);
|
|
58
|
-
this.name = 'RuntimeError';
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Ensure WASM memory is large enough for the required size.
|
|
64
|
-
*
|
|
65
|
-
* This function checks if the current memory buffer is large enough
|
|
66
|
-
* and grows it by 64KB pages if needed.
|
|
67
|
-
*
|
|
68
|
-
* @param memory - The WebAssembly.Memory instance
|
|
69
|
-
* @param required - The required memory size in bytes
|
|
70
|
-
* @throws {RuntimeError} If memory cannot be grown (e.g., exceeds maximum)
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```typescript
|
|
74
|
-
* ensureMemory(memory, 131072); // Ensure at least 128KB is available
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export function ensureMemory(memory: WebAssembly.Memory, required: number): void {
|
|
78
|
-
const current = memory.buffer.byteLength;
|
|
79
|
-
if (required <= current) {
|
|
80
|
-
return; // Already have enough memory
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Calculate how many pages to grow
|
|
84
|
-
const pagesNeeded = Math.ceil((required - current) / WASM_PAGE_SIZE_BYTES);
|
|
85
|
-
|
|
86
|
-
// Attempt to grow memory
|
|
87
|
-
try {
|
|
88
|
-
const oldPages = memory.grow(pagesNeeded);
|
|
89
|
-
if (oldPages < 0) {
|
|
90
|
-
throw new RuntimeError(`Failed to grow memory by ${pagesNeeded} pages`, 5); // OUT_OF_MEMORY
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
// Re-throw RuntimeError as-is
|
|
94
|
-
if (error instanceof RuntimeError) {
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
throw new RuntimeError(
|
|
98
|
-
`Cannot grow WASM memory: required ${required} bytes, ` +
|
|
99
|
-
`current ${current} bytes, need ${pagesNeeded} more pages. ` +
|
|
100
|
-
(error instanceof Error ? error.message : String(error)),
|
|
101
|
-
5, // OUT_OF_MEMORY
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Re-export type definitions from runtime-codegen for backward compatibility
|
|
107
|
-
export type { MarshalFn, UnmarshalFn, ValidateFn } from './runtime-codegen';
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Options for creating a CompiledDecision instance.
|
|
111
|
-
*/
|
|
112
|
-
export interface CompiledDecisionOptions {
|
|
113
|
-
/** The compiled WASM binary */
|
|
114
|
-
wasm: Uint8Array;
|
|
115
|
-
/** Schema hash for validation */
|
|
116
|
-
schemaHash: bigint;
|
|
117
|
-
/** Function to marshal input to WASM memory */
|
|
118
|
-
marshal: MarshalFn;
|
|
119
|
-
/** Function to unmarshal output from WASM memory */
|
|
120
|
-
unmarshal: UnmarshalFn;
|
|
121
|
-
/** Function to validate input against schema */
|
|
122
|
-
validate?: ValidateFn;
|
|
123
|
-
/** Initial memory size in pages (default: 1 page = 64KB) */
|
|
124
|
-
initialMemoryPages?: number;
|
|
125
|
-
/** Maximum memory pages (default: DEFAULT_MAX_MEMORY_PAGES = 256 pages = 16MB) */
|
|
126
|
-
maximumMemoryPages?: number;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* A compiled JDM decision ready for evaluation.
|
|
131
|
-
*
|
|
132
|
-
* This class manages the lifecycle of evaluating a compiled decision:
|
|
133
|
-
* 1. Validates input against schema (fail fast with good error)
|
|
134
|
-
* 2. Marshals input to WASM memory
|
|
135
|
-
* 3. Resets heap for fresh evaluation
|
|
136
|
-
* 4. Runs evaluation
|
|
137
|
-
* 5. Checks for runtime errors (schema mismatch, etc.)
|
|
138
|
-
* 6. Unmarshals output from WASM memory
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* ```typescript
|
|
142
|
-
* const decision = new CompiledDecision({
|
|
143
|
-
* wasm: compilationResult.wasm,
|
|
144
|
-
* schemaHash: compilationResult.schemaHash,
|
|
145
|
-
* marshal: marshalInput,
|
|
146
|
-
* unmarshal: unmarshalOutput,
|
|
147
|
-
* validate: validateInput,
|
|
148
|
-
* });
|
|
149
|
-
*
|
|
150
|
-
* const output = await decision.evaluate({ age: 25, name: 'Alice' });
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
export class CompiledDecision {
|
|
154
|
-
private instance: WebAssembly.Instance | null = null;
|
|
155
|
-
private memory: WebAssembly.Memory | null = null;
|
|
156
|
-
private module: WebAssembly.Module;
|
|
157
|
-
private marshal: MarshalFn;
|
|
158
|
-
private unmarshal: UnmarshalFn;
|
|
159
|
-
private validate?: ValidateFn;
|
|
160
|
-
|
|
161
|
-
constructor(private options: CompiledDecisionOptions) {
|
|
162
|
-
// WebAssembly.Module requires an ArrayBuffer starting at offset 0, but Uint8Array may
|
|
163
|
-
// be a view into a larger buffer at a non-zero offset, which would cause Module
|
|
164
|
-
// construction to fail. Create a proper Uint8Array view that the Module constructor
|
|
165
|
-
// can safely access, ensuring we only pass the exact bytes of the WASM binary.
|
|
166
|
-
const buffer = new Uint8Array(
|
|
167
|
-
options.wasm.buffer,
|
|
168
|
-
options.wasm.byteOffset,
|
|
169
|
-
options.wasm.byteLength,
|
|
170
|
-
);
|
|
171
|
-
this.module = new WebAssembly.Module(buffer as unknown as ArrayBuffer);
|
|
172
|
-
|
|
173
|
-
this.marshal = options.marshal;
|
|
174
|
-
this.unmarshal = options.unmarshal;
|
|
175
|
-
this.validate = options.validate;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Initialize the WebAssembly instance.
|
|
180
|
-
* This is done lazily on first evaluation, or can be called explicitly.
|
|
181
|
-
*/
|
|
182
|
-
private async initialize(): Promise<void> {
|
|
183
|
-
if (this.instance !== null) {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Don't provide memory via import - let the WASM module use its own exported memory.
|
|
188
|
-
// AssemblyScript's incremental GC runtime requires specific memory initialization
|
|
189
|
-
// that only works correctly with the module's own memory.
|
|
190
|
-
this.instance = await WebAssembly.instantiate(this.module, {
|
|
191
|
-
env: {
|
|
192
|
-
abort: () => {
|
|
193
|
-
throw new RuntimeError('WASM abort called');
|
|
194
|
-
},
|
|
195
|
-
seed: () => {
|
|
196
|
-
return Date.now();
|
|
197
|
-
},
|
|
198
|
-
'Date.now': () => Date.now(),
|
|
199
|
-
},
|
|
200
|
-
// Empty index module provided for AssemblyScript compatibility
|
|
201
|
-
index: {},
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Get memory from the WASM module's exports
|
|
205
|
-
this.memory = this.instance.exports.memory as WebAssembly.Memory;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Evaluate the decision with the given input.
|
|
210
|
-
*
|
|
211
|
-
* @param input - The input data to evaluate
|
|
212
|
-
* @returns The output of the decision evaluation
|
|
213
|
-
* @throws {RuntimeError} If evaluation fails
|
|
214
|
-
* @throws {ValidationError} If input validation fails (if validate is provided)
|
|
215
|
-
*/
|
|
216
|
-
async evaluate<I = Record<string, unknown>, O = Record<string, unknown>>(input: I): Promise<O> {
|
|
217
|
-
await this.initialize();
|
|
218
|
-
|
|
219
|
-
if (!this.instance || !this.memory) {
|
|
220
|
-
throw new RuntimeError('WASM instance not initialized');
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Local references to avoid null checks in the hot path
|
|
224
|
-
const memory = this.memory;
|
|
225
|
-
const instance = this.instance;
|
|
226
|
-
|
|
227
|
-
// 1. Validate input against schema (fail fast with good error)
|
|
228
|
-
if (this.validate) {
|
|
229
|
-
try {
|
|
230
|
-
this.validate(input);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
if (error instanceof Error) {
|
|
233
|
-
throw new RuntimeError(`Input validation failed: ${error.message}`, 1, { input });
|
|
234
|
-
}
|
|
235
|
-
throw error;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Clear any stale error state from previous evaluations before starting new evaluation.
|
|
240
|
-
// This ensures each evaluation starts with a clean slate.
|
|
241
|
-
const clearLastErrorFn = instance.exports.clearLastError as () => void;
|
|
242
|
-
if (clearLastErrorFn) {
|
|
243
|
-
clearLastErrorFn();
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
// 2. Marshal input to WASM memory
|
|
248
|
-
const inputPtr: number = this.marshal(input as Record<string, unknown>, memory);
|
|
249
|
-
|
|
250
|
-
// Verify input pointer is valid
|
|
251
|
-
if (inputPtr < INPUT_BUFFER_START_OFFSET) {
|
|
252
|
-
throw new RuntimeError(
|
|
253
|
-
`Invalid input pointer: ${inputPtr} (must be >= ${INPUT_BUFFER_START_OFFSET})`,
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// 3. Reset heap for fresh evaluation
|
|
258
|
-
const resetHeapFn = instance.exports.resetHeap as () => void;
|
|
259
|
-
if (resetHeapFn) {
|
|
260
|
-
resetHeapFn();
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// 4. Run evaluation
|
|
264
|
-
const evaluateFn = instance.exports.evaluate as (ptr: number) => number;
|
|
265
|
-
if (!evaluateFn) {
|
|
266
|
-
throw new RuntimeError('evaluate function not exported from WASM module');
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const outputPtr: number = evaluateFn(inputPtr);
|
|
270
|
-
|
|
271
|
-
// 5. Check for runtime errors (schema mismatch, etc.)
|
|
272
|
-
const getLastErrorFn = instance.exports.getLastError as () => number;
|
|
273
|
-
if (getLastErrorFn) {
|
|
274
|
-
const errorCode = getLastErrorFn();
|
|
275
|
-
if (errorCode !== 0) {
|
|
276
|
-
throw new RuntimeError(this.getErrorMessage(errorCode), errorCode, { input, outputPtr });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Verify output pointer is valid
|
|
281
|
-
// Output pointer validity is verified during unmarshal - we only check it's within
|
|
282
|
-
// addressable memory here to avoid segfault.
|
|
283
|
-
if (outputPtr < memory.buffer.byteLength) {
|
|
284
|
-
// Output pointer should be within a reasonable range
|
|
285
|
-
// We'll verify the unmarshal works properly
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// 6. Unmarshal output from WASM memory
|
|
289
|
-
const output = this.unmarshal(outputPtr, memory);
|
|
290
|
-
|
|
291
|
-
return output as O;
|
|
292
|
-
} finally {
|
|
293
|
-
// Always clear error state after evaluation, even if an error was thrown.
|
|
294
|
-
// This prevents stale error state from affecting subsequent evaluations.
|
|
295
|
-
if (clearLastErrorFn) {
|
|
296
|
-
clearLastErrorFn();
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Get a human-readable error message for a given error code.
|
|
303
|
-
*
|
|
304
|
-
* @param errorCode - The error code from getLastError()
|
|
305
|
-
* @returns A human-readable error message
|
|
306
|
-
*/
|
|
307
|
-
private getErrorMessage(errorCode: number): string {
|
|
308
|
-
// Error codes duplicated from assembly/runtime/errors.ts because WASM cannot export
|
|
309
|
-
// enum metadata - these must stay synchronized.
|
|
310
|
-
// NONE = 0, SCHEMA_MISMATCH = 1, NULL_POINTER = 2, INVALID_ACCESS = 3, EVALUATION_ERROR = 4, OUT_OF_MEMORY = 5
|
|
311
|
-
const errorMessages: Record<number, string> = {
|
|
312
|
-
0: 'No error',
|
|
313
|
-
1: 'Schema mismatch: input data does not match expected schema',
|
|
314
|
-
2: 'Null pointer dereference',
|
|
315
|
-
3: 'Invalid memory access',
|
|
316
|
-
4: 'Evaluation error',
|
|
317
|
-
5: 'Out of memory',
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
return errorMessages[errorCode] ?? `Unknown error code: ${errorCode}`;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Get the current WebAssembly memory instance.
|
|
325
|
-
* This can be useful for debugging or direct memory inspection.
|
|
326
|
-
*
|
|
327
|
-
* @returns The WebAssembly.Memory instance (null if not initialized)
|
|
328
|
-
*/
|
|
329
|
-
getMemory(): WebAssembly.Memory | null {
|
|
330
|
-
return this.memory;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Get the current WebAssembly instance.
|
|
335
|
-
*
|
|
336
|
-
* @returns The WebAssembly.Instance instance (null if not initialized)
|
|
337
|
-
*/
|
|
338
|
-
getInstance(): WebAssembly.Instance | null {
|
|
339
|
-
return this.instance;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Dispose of this CompiledDecision instance.
|
|
344
|
-
* This clears the WebAssembly instance and allows garbage collection.
|
|
345
|
-
*/
|
|
346
|
-
dispose(): void {
|
|
347
|
-
this.instance = null;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Get memory usage statistics.
|
|
352
|
-
*
|
|
353
|
-
* @returns Object with memory usage information
|
|
354
|
-
*/
|
|
355
|
-
getMemoryStats(): { current: number; maximum: number; used: number } {
|
|
356
|
-
// Note: 'used' equals 'current' because WebAssembly.Memory doesn't expose actual heap
|
|
357
|
-
// usage - tracking used bytes requires instrumentation in AssemblyScript allocator.
|
|
358
|
-
const currentBytes = this.memory?.buffer.byteLength ?? 0;
|
|
359
|
-
return {
|
|
360
|
-
current: currentBytes,
|
|
361
|
-
maximum: (this.options.maximumMemoryPages ?? DEFAULT_MAX_MEMORY_PAGES) * WASM_PAGE_SIZE_BYTES,
|
|
362
|
-
used: currentBytes,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Get the input buffer pointer, ensuring sufficient memory is available.
|
|
368
|
-
*
|
|
369
|
-
* This method doesn't allocate new buffers on each call - it always returns the
|
|
370
|
-
* same INPUT_BUFFER_START_OFFSET constant after ensuring the memory can accommodate the
|
|
371
|
-
* required size. Single-allocation design chosen because: (1) heap is reset between
|
|
372
|
-
* evaluations so fragmentation isn't an issue, (2) simpler than maintaining a free
|
|
373
|
-
* list, (3) marshal code controls actual layout in WASM memory. All input data is
|
|
374
|
-
* marshaled into a single buffer starting at INPUT_BUFFER_START_OFFSET.
|
|
375
|
-
*
|
|
376
|
-
* @param required - The required memory size in bytes
|
|
377
|
-
* @returns The base pointer of the input buffer (always INPUT_BUFFER_START_OFFSET)
|
|
378
|
-
* @throws {RuntimeError} If memory cannot be grown to accommodate the required size
|
|
379
|
-
*
|
|
380
|
-
* @example
|
|
381
|
-
* ```typescript
|
|
382
|
-
* const ptr = decision.getInputBuffer(1024); // Ensure 1KB available
|
|
383
|
-
* ```
|
|
384
|
-
*/
|
|
385
|
-
getInputBuffer(required: number): number {
|
|
386
|
-
if (!this.memory) {
|
|
387
|
-
throw new RuntimeError('Memory not initialized - call evaluate() first', 5);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Ensure enough memory
|
|
391
|
-
try {
|
|
392
|
-
ensureMemory(this.memory, required);
|
|
393
|
-
} catch (error) {
|
|
394
|
-
throw new RuntimeError(
|
|
395
|
-
`Memory allocation failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
396
|
-
5, // OUT_OF_MEMORY error code
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// Single-allocation design: return the INPUT_BUFFER_START_OFFSET
|
|
401
|
-
return INPUT_BUFFER_START_OFFSET;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Create a CompiledDecision instance from a CompilationResult.
|
|
407
|
-
*
|
|
408
|
-
* This is a convenience function that creates the necessary marshal,
|
|
409
|
-
* unmarshal, and validation functions from the generated code.
|
|
410
|
-
*
|
|
411
|
-
* @param result - The compilation result
|
|
412
|
-
* @param validate - Optional validation function (defaults to generated validation code)
|
|
413
|
-
* @returns A CompiledDecision instance ready for evaluation
|
|
414
|
-
*
|
|
415
|
-
* @example
|
|
416
|
-
* ```typescript
|
|
417
|
-
* const result = await compile({
|
|
418
|
-
* jdm: myJdm,
|
|
419
|
-
* inputSchema: MyInputSchema,
|
|
420
|
-
* outputSchema: MyOutputSchema,
|
|
421
|
-
* });
|
|
422
|
-
*
|
|
423
|
-
* const decision = createCompiledDecision(result);
|
|
424
|
-
* const output = await decision.evaluate({ age: 25 });
|
|
425
|
-
* ```
|
|
426
|
-
*/
|
|
427
|
-
export async function createCompiledDecision(
|
|
428
|
-
result: CompilationResult,
|
|
429
|
-
validate?: ValidateFn,
|
|
430
|
-
): Promise<CompiledDecision> {
|
|
431
|
-
// Load the marshal and unmarshal functions from the generated code
|
|
432
|
-
const { marshal, unmarshal } = loadGeneratedMarshaling(result.marshalCode);
|
|
433
|
-
|
|
434
|
-
// Load or use provided validation function
|
|
435
|
-
const validator = validate ?? (await loadGeneratedValidation(result.validationCode));
|
|
436
|
-
|
|
437
|
-
return new CompiledDecision({
|
|
438
|
-
wasm: result.wasm,
|
|
439
|
-
schemaHash: result.schemaHash,
|
|
440
|
-
marshal,
|
|
441
|
-
unmarshal,
|
|
442
|
-
validate: validator,
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Re-export compile-time code generation functions for backward compatibility
|
|
447
|
-
export { loadGeneratedMarshaling, loadGeneratedValidation } from './runtime-codegen';
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Re-export types from dependencies
|
|
451
|
-
*/
|
|
452
|
-
export type { TSchema } from '@sinclair/typebox';
|
package/src/compiler/schema.ts
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { type TSchema, Kind } from '@sinclair/typebox';
|
|
2
|
-
import type { FlattenedLayout } from './types';
|
|
3
|
-
import { createHash } from 'crypto';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Schema field information for memory layout
|
|
7
|
-
*/
|
|
8
|
-
interface SchemaField {
|
|
9
|
-
schema: TSchema;
|
|
10
|
-
path: string;
|
|
11
|
-
flatName: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Flattens a TypeBox schema to a memory layout.
|
|
16
|
-
*
|
|
17
|
-
* This function processes a schema and produces a flattened representation
|
|
18
|
-
* that can be used for direct memory access in WebAssembly.
|
|
19
|
-
*
|
|
20
|
-
* Memory structure:
|
|
21
|
-
* ┌─────────────────────────────────────────────────────────────┐
|
|
22
|
-
* │ Fixed Fields (numbers, bools, enum indices) │
|
|
23
|
-
* │ customer_age: f64 (8 bytes) │
|
|
24
|
-
* │ customer_tier: i32 (4 bytes) - enum index │
|
|
25
|
-
* ├─────────────────────────────────────────────────────────────┤
|
|
26
|
-
* │ String/Array Pointers (offset, length pairs) │
|
|
27
|
-
* │ order_items_ptr: i32, order_items_len: i32 │
|
|
28
|
-
* ├─────────────────────────────────────────────────────────────┤
|
|
29
|
-
* │ Variable-length data (UTF-16 strings, array contents) │
|
|
30
|
-
* └─────────────────────────────────────────────────────────────┘
|
|
31
|
-
*
|
|
32
|
-
* @param schema - The TypeBox schema to flatten
|
|
33
|
-
* @param _prefix - Internal parameter for recursive flattening with dotted paths
|
|
34
|
-
* @returns The flattened memory layout
|
|
35
|
-
*/
|
|
36
|
-
export function flattenSchema(schema: TSchema): FlattenedLayout {
|
|
37
|
-
const layout: FlattenedLayout = {
|
|
38
|
-
fields: [],
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Collect all fields from the schema
|
|
42
|
-
const fields: SchemaField[] = collectFields(schema, '');
|
|
43
|
-
|
|
44
|
-
// Track current offset for field layout
|
|
45
|
-
let currentOffset = 0;
|
|
46
|
-
|
|
47
|
-
// Process fields: first pass - fixed types
|
|
48
|
-
for (const field of fields) {
|
|
49
|
-
const typeInfo = getFieldType(field.schema);
|
|
50
|
-
if (typeInfo.isFixed) {
|
|
51
|
-
layout.fields.push({
|
|
52
|
-
path: field.path,
|
|
53
|
-
flatName: field.flatName,
|
|
54
|
-
type: typeInfo.asType,
|
|
55
|
-
offset: currentOffset,
|
|
56
|
-
size: typeInfo.size,
|
|
57
|
-
});
|
|
58
|
-
currentOffset += typeInfo.size;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Second pass - variable types (strings, arrays)
|
|
63
|
-
// These get pointers (2 x i32 = 8 bytes each for offset + length)
|
|
64
|
-
for (const field of fields) {
|
|
65
|
-
const typeInfo = getFieldType(field.schema);
|
|
66
|
-
if (!typeInfo.isFixed) {
|
|
67
|
-
layout.fields.push({
|
|
68
|
-
path: field.path,
|
|
69
|
-
flatName: field.flatName,
|
|
70
|
-
type: typeInfo.asType,
|
|
71
|
-
offset: currentOffset,
|
|
72
|
-
size: -1, // Variable length
|
|
73
|
-
});
|
|
74
|
-
currentOffset += 8; // 4 bytes offset + 4 bytes length
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return layout;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Collect all fields from a schema recursively
|
|
83
|
-
*/
|
|
84
|
-
function collectFields(schema: TSchema, path: string): SchemaField[] {
|
|
85
|
-
const fields: SchemaField[] = [];
|
|
86
|
-
|
|
87
|
-
const kind = (schema as any)[Kind];
|
|
88
|
-
|
|
89
|
-
if (kind === 'Object') {
|
|
90
|
-
const properties = (schema as any).properties || {};
|
|
91
|
-
for (const [name, fieldSchema] of Object.entries(properties)) {
|
|
92
|
-
const fieldPath = path ? `${path}.${name}` : name;
|
|
93
|
-
const flatName = path ? `${path}_${name}` : name;
|
|
94
|
-
|
|
95
|
-
const nestedFields = collectFields(fieldSchema as TSchema, fieldPath);
|
|
96
|
-
if (nestedFields.length > 0) {
|
|
97
|
-
fields.push(...nestedFields);
|
|
98
|
-
} else {
|
|
99
|
-
fields.push({
|
|
100
|
-
schema: fieldSchema as TSchema,
|
|
101
|
-
path: fieldPath,
|
|
102
|
-
flatName,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// For non-objects, return empty array (handled by parent)
|
|
109
|
-
return fields;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Get type information for a schema field
|
|
114
|
-
*/
|
|
115
|
-
function getFieldType(schema: TSchema): {
|
|
116
|
-
isFixed: boolean;
|
|
117
|
-
asType: 'f64' | 'i32' | 'i64' | 'bool' | 'string' | 'array';
|
|
118
|
-
size: number;
|
|
119
|
-
} {
|
|
120
|
-
const kind = (schema as any)[Kind];
|
|
121
|
-
|
|
122
|
-
switch (kind) {
|
|
123
|
-
case 'Number':
|
|
124
|
-
return { isFixed: true, asType: 'f64', size: 8 };
|
|
125
|
-
|
|
126
|
-
case 'Integer':
|
|
127
|
-
return { isFixed: true, asType: 'i32', size: 4 };
|
|
128
|
-
|
|
129
|
-
case 'Boolean':
|
|
130
|
-
// Booleans stored as i32 (4 bytes) to ensure natural alignment and match AssemblyScript's
|
|
131
|
-
// bool representation
|
|
132
|
-
return { isFixed: true, asType: 'bool', size: 4 };
|
|
133
|
-
|
|
134
|
-
case 'String':
|
|
135
|
-
return { isFixed: false, asType: 'string', size: -1 };
|
|
136
|
-
|
|
137
|
-
case 'Array':
|
|
138
|
-
return { isFixed: false, asType: 'array', size: -1 };
|
|
139
|
-
|
|
140
|
-
case 'Literal':
|
|
141
|
-
// Literals are stored as i32 indices (for boolean-like or enum-like)
|
|
142
|
-
return { isFixed: true, asType: 'i32', size: 4 };
|
|
143
|
-
|
|
144
|
-
case 'Union':
|
|
145
|
-
// First, handle unions of Literal types (enum-like) as i32 indices for efficiency
|
|
146
|
-
const anyOf = (schema as any).anyOf;
|
|
147
|
-
if (Array.isArray(anyOf) && anyOf.length > 0) {
|
|
148
|
-
const firstKind = (anyOf[0] as any)[Kind];
|
|
149
|
-
if (firstKind === 'Literal') {
|
|
150
|
-
return { isFixed: true, asType: 'i32', size: 4 };
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Default to string for heterogeneous unions - can represent multiple incompatible types
|
|
154
|
-
// (e.g., string | number | object)
|
|
155
|
-
return { isFixed: false, asType: 'string', size: -1 };
|
|
156
|
-
|
|
157
|
-
default:
|
|
158
|
-
// Default to string for unknown types
|
|
159
|
-
return { isFixed: false, asType: 'string', size: -1 };
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Compute a hash of the input and output schemas for runtime validation.
|
|
165
|
-
*
|
|
166
|
-
* This hash is embedded in the compiled WASM module and can be used to
|
|
167
|
-
* verify that the runtime data matches the expected schema.
|
|
168
|
-
*
|
|
169
|
-
* Uses SHA256 to create a canonical hash, then takes the first 8 bytes as u64.
|
|
170
|
-
*
|
|
171
|
-
* @param inputSchema - The input schema
|
|
172
|
-
* @param outputSchema - The output schema
|
|
173
|
-
* @returns A 64-bit hash value
|
|
174
|
-
*/
|
|
175
|
-
export function computeSchemaHash(inputSchema: TSchema, outputSchema: TSchema): bigint {
|
|
176
|
-
// Create canonical representation with sorted keys
|
|
177
|
-
const canonical = JSON.stringify(
|
|
178
|
-
{
|
|
179
|
-
input: canonicalizeSchema(inputSchema),
|
|
180
|
-
output: canonicalizeSchema(outputSchema),
|
|
181
|
-
},
|
|
182
|
-
null,
|
|
183
|
-
2,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
// Compute SHA256 hash
|
|
187
|
-
const hash = createHash('sha256').update(canonical).digest();
|
|
188
|
-
|
|
189
|
-
// Take first 8 bytes as u64 (little-endian)
|
|
190
|
-
return hash.readBigUInt64LE(0);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Convert a schema to a canonical form for hashing by sorting keys and normalizing structure
|
|
195
|
-
*/
|
|
196
|
-
function canonicalizeSchema(schema: TSchema): unknown {
|
|
197
|
-
const kind = (schema as any)[Kind];
|
|
198
|
-
|
|
199
|
-
if (kind === 'Object') {
|
|
200
|
-
const properties = (schema as any).properties || {};
|
|
201
|
-
const canonical: Record<string, unknown> = {};
|
|
202
|
-
const keys = Object.keys(properties).sort();
|
|
203
|
-
|
|
204
|
-
for (const key of keys) {
|
|
205
|
-
canonical[key] = canonicalizeSchema(properties[key]);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
type: 'object',
|
|
210
|
-
properties: canonical,
|
|
211
|
-
required: ((schema as any).required || []).sort(),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (kind === 'Array') {
|
|
216
|
-
return {
|
|
217
|
-
type: 'array',
|
|
218
|
-
items: canonicalizeSchema((schema as any).items),
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (kind === 'Enum') {
|
|
223
|
-
return {
|
|
224
|
-
type: 'enum',
|
|
225
|
-
values: ((schema as any).anyOf || []).map((val: TSchema) => (val as any).const).sort(),
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (kind === 'Literal') {
|
|
230
|
-
return {
|
|
231
|
-
type: 'literal',
|
|
232
|
-
value: (schema as any).const,
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// For primitive types, return a simple representation
|
|
237
|
-
const primitiveTypes: Record<string, string> = {
|
|
238
|
-
Number: 'number',
|
|
239
|
-
Integer: 'integer',
|
|
240
|
-
String: 'string',
|
|
241
|
-
Boolean: 'boolean',
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
return primitiveTypes[kind] || kind;
|
|
245
|
-
}
|