| 57 | * |
| 58 | * If the expression cannot be compiled, falls back to interpretation |
| 59 | * (success: false, run: applicableN1) unless `options.fallback` is false, |
| 60 | * in which case it throws. |
| 61 | * |
| 62 | * ## Real-only special functions (compile targets) |
| 63 | * |
| 64 | * The built-in targets implement most special functions (`Erf`, `Gamma`, |
| 65 | * `Zeta`, the Bessel/Airy family, …) with **real-only** library helpers |
| 66 | * (`_SYS.erf`, `scipy.special.erf`, GLSL `log2`, …). They accept a real scalar |
| 67 | * only. Elementary functions that *do* have a complex extension (`Sin`, `Exp`, |
| 68 | * `Sqrt`, `Power`, …) dispatch to a complex helper when an argument is |
| 69 | * complex-valued; the real-only special functions do not. A complex value |
| 70 | * must never reach a real helper (a compiled `Erf(z)` would return −1): under |
| 71 | * `mode: 'strict'` the compiler **fails closed** (D6) with the offending |
| 72 | * head; under `auto` (the default) and `complex` a MAYBE-complex operand (a |
| 73 | * `complex`-typed symbol, a promoted radical, a wide binding in complex mode) |
| 74 | * takes the D2/D6 runtime rule — the real helper runs when the value's |
| 75 | * imaginary part is exactly zero, `NaN` otherwise — and only a STATICALLY |
| 76 | * non-real operand (`Erf(2i)`) is the compile-time decline. The shader |
| 77 | * targets always fail closed. (`Real`/`Imaginary`/`Argument`/`Conjugate` are |
| 78 | * exempt: they consume a complex value by design.) |
| 79 | */ |
| 80 | export function compile<T extends string = 'javascript'>( |
| 81 | expr: Expression, |
| 82 | options: CompileExpressionOptions<T> & { realOnly: true } |
| 83 | ): CompilationResult<T, number>; |
| 84 | export function compile<T extends string = 'javascript'>( |
| 85 | expr: Expression, |
| 86 | options?: CompileExpressionOptions<T> |
| 87 | ): CompilationResult<T>; |
| 88 | export function compile<T extends string = 'javascript'>( |
| 89 | expr: Expression, |
| 90 | options?: CompileExpressionOptions<T> |
| 91 | ): CompilationResult<T> { |
| 92 | assertCompilationOptionsContract(options); |
| 93 | // The deprecated `complexPromotion: true` maps to `mode: 'complex'` — but |
| 94 | // only where the target OFFERS complex mode. The flag was documented as |
| 95 | // ignored on the shader targets ("they keep the real kernel |
| 96 | // unconditionally"), so a caller passing it globally must not see a shader |
| 97 | // compile that used to succeed decline with `unsupported-mode`; on such a |
| 98 | // target the alias is dropped and the target's default mode applies. |
| 99 | const deprecated = applyDeprecatedModeOptions(options); |
| 100 | options = deprecated.options; |
| 101 | const modeFromAlias = deprecated.modeFromAlias; |
| 102 | |
| 103 | // An option-contract violation, not a compilation failure: raised OUTSIDE |
| 104 | // the `try` so the interpreter fallback cannot swallow it. A direct custom |
| 105 | // target never gets CSE in Phase 1 (§4.2), so an EXPLICIT `cse: true` here |
| 106 | // is a request that cannot be honored — silently stamping it off would leave |
| 107 | // the caller believing CSE ran. |
| 108 | if (options?.target !== undefined && options.cse === true) |
| 109 | throw new Error( |
| 110 | 'CSE is not supported on direct custom targets in Phase 1; omit `cse` ' + |
| 111 | 'or use a registered target.' |
| 112 | ); |
| 113 | |
| 114 | try { |
| 115 | // Determine the target to use |
| 116 | if (options?.target) { |