(
expr: Expression,
options: CompilationOptions<Expression> = {}
)
| 3381 | } |
| 3382 | |
| 3383 | // A string KEY. Only a dictionary base takes one (and that base has already |
| 3384 | // declined above), so on a positional base it is the wrong index domain |
| 3385 | // outright — named separately from the type-based decline below, which |
| 3386 | // covers a symbol merely DECLARED `string`. |
| 3387 | if (isString(index)) |
| 3388 | decline( |
| 3389 | 'the index is a string key, and only a dictionary base takes one — a ' + |
| 3390 | 'positional shader access indexes by number' |
| 3391 | ); |
| 3392 | |
| 3393 | if (BaseCompiler.isComplexValued(index)) |
| 3394 | decline( |
| 3395 | 'the index is a complex value, which lowers to a `vec2(re, im)`; the ' + |
| 3396 | 'interpreter reads its real part, and a shader has no such reading ' + |
| 3397 | 'of a vector in an index position' |
| 3398 | ); |
| 3399 | |
| 3400 | // A CALLER-DECLARED name, whose declared shader type is the only reading of |
| 3401 | // it there is — asked ahead of the type-based readings below, which see the |
| 3402 | // undeclared engine symbol's type. |
| 3403 | const framedIndex = gpuAtFramedIndex(index); |
| 3404 | if (framedIndex !== undefined && 'decline' in framedIndex) |
| 3405 | decline(framedIndex.decline); |
| 3406 | |
| 3407 | // A literal real index resolves against N at compile time — zero runtime |
| 3408 | // cost, and `0` / out of range / non-integer / non-finite fold straight to |
| 3409 | // the NaN spelling. |
| 3410 | if (isNumber(index)) { |
| 3411 | const j = gpuAtSlot(index.re, n); |
| 3412 | if (j === null) { |
| 3413 | // The fold emits neither operand (the index is a literal, so pure). |
| 3414 | requirePureFold('base'); |
| 3415 | return gpuNaN(target); |
| 3416 | } |
| 3417 | if (isLiteralBase) requireLiteralBaseElements([j], 'access'); |
| 3418 | return gpuAtElement(base, j, n, compile); |
| 3419 | } |
| 3420 | |
| 3421 | // A collection-typed index that is NOT a literal list: there is no tier for |
| 3422 | // it (its entries are not readable at compile time). A STRING is excluded: |
| 3423 | // it matches `collection` in the lattice (its elements are its grapheme |
| 3424 | // clusters) but this target has no strings at all, so the honest diagnostic |
| 3425 | // is the "provably not a number" one below, which names the type — the |
| 3426 | // diagnostic a string index has always received. |
| 3427 | if (isSubtype(it, COLLECTION_SHAPE_TYPE) && !isSubtype(it, 'string')) { |
| 3428 | const k = BaseCompiler.aggregateComponentCount(index); |
| 3429 | // A NEGATIVE count is the type builder's encoding of an UNKNOWN extent |
| 3430 | // (`list<number^?>` → `dimensions: [-1]`), not a width — the same reading |
| 3431 | // the base side already takes. Without this it flowed on as a count and |
| 3432 | // described "a collection of -1 runtime-valued entries" in a |
| 3433 | // demand-gated text, when the shape is the PERMANENT no-static-count |
| 3434 | // decline (design § D4). |
| 3435 | if (k === undefined || k < 0) |
| 3436 | decline( |
| 3437 | `the index is a collection (type \`${index.type.toString()}\`) with ` + |
| 3438 | `no statically known length, so there is no static count to emit ` + |
| 3439 | `a result shape against` |
| 3440 | ); |
no test coverage detected