Skip to content

Commit d89b53d

Browse files
committed
fix: ArrayExpression - immediate index access
1 parent 08fb40f commit d89b53d

2 files changed

Lines changed: 101 additions & 2 deletions

File tree

packages/typegpu/src/tgsl/accessIndex.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from '../data/wgslTypes.ts';
1414
import { isKnownAtComptime } from '../types.ts';
1515
import { accessProp } from './accessProp.ts';
16-
import { coerceToSnippet } from './generationHelpers.ts';
16+
import { ArrayExpression, coerceToSnippet } from './generationHelpers.ts';
1717

1818
const indexableTypeToResult = {
1919
mat2x2f: vec2f,
@@ -54,6 +54,10 @@ export function accessIndex(target: Snippet, indexArg: Snippet | number): Snippe
5454
origin = 'runtime';
5555
}
5656

57+
if (target.value instanceof ArrayExpression && isKnownAtComptime(index)) {
58+
return target.value.elements[index.value as number];
59+
}
60+
5761
return snip(
5862
isKnownAtComptime(target) && isKnownAtComptime(index)
5963
? // oxlint-disable-next-line typescript/no-explicit-any -- it's fine, it's there

packages/typegpu/tests/array.test.ts

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { attest } from '@ark/attest';
22
import { BufferReader, BufferWriter } from 'typed-binary';
3-
import { describe, expect, expectTypeOf, it } from 'vitest';
3+
import { describe, expect, expectTypeOf } from 'vitest';
44
import { readData, writeData } from '../src/data/dataIO.ts';
55
import { d, tgpu } from '../src/index.js';
66
import { namespace } from '../src/core/resolve/namespace.ts';
77
import { resolve } from '../src/resolutionCtx.ts';
88
import type { Infer } from '../src/shared/repr.ts';
99
import { arrayLength } from '../src/std/array.ts';
10+
import { it } from 'typegpu-testing-utility';
1011

1112
describe('array', () => {
1213
it('produces a visually pleasant type', () => {
@@ -443,6 +444,100 @@ describe('array', () => {
443444
}"
444445
`);
445446
});
447+
448+
it('array expressions can be indexed into with a comptime-known index', () => {
449+
function foo() {
450+
'use gpu';
451+
const i = 2;
452+
const a = [i, 2][0];
453+
const b = [i, 2][1];
454+
}
455+
456+
expect(tgpu.resolve([foo])).toMatchInlineSnapshot(`
457+
"fn foo() {
458+
const i = 2;
459+
const a = i;
460+
const b = 2i;
461+
}"
462+
`);
463+
});
464+
465+
it('array expressions can be indexed into with a runtime-known index', () => {
466+
function foo() {
467+
'use gpu';
468+
const i = 0;
469+
const a = [1, 2][i];
470+
}
471+
472+
expect(tgpu.resolve([foo])).toMatchInlineSnapshot(`
473+
"fn foo() {
474+
const i = 0;
475+
let a = array<i32, 2>(1, 2)[i];
476+
}"
477+
`);
478+
});
479+
480+
it('allows picking among references using comptime-known indices', () => {
481+
function foo() {
482+
'use gpu';
483+
const x = d.vec3f(1, 2, 3);
484+
// `const y = [x, d.vec3f()]` would throw, but since
485+
// we're never constructing the array, it's equivalent
486+
// to writing `const y = x;`
487+
const y = [x, d.vec3f()][0];
488+
return y;
489+
}
490+
491+
expect(tgpu.resolve([foo])).toMatchInlineSnapshot(`
492+
"fn foo() -> vec3f {
493+
var x = vec3f(1, 2, 3);
494+
let y = (&x);
495+
return (*y);
496+
}"
497+
`);
498+
});
499+
500+
it('resolves array expression elements when accessed with comptime-known index', () => {
501+
let n = 0;
502+
const next = tgpu.comptime(() => n++);
503+
504+
function foo() {
505+
'use gpu';
506+
const a = [next(), next()][0];
507+
const b = [next(), next()][1];
508+
}
509+
510+
expect(tgpu.resolve([foo])).toMatchInlineSnapshot(`
511+
"fn foo() {
512+
const a = 0;
513+
const b = 3;
514+
}"
515+
`);
516+
});
517+
518+
it('prunes definitions in array expressions accessed with comptime-known index', ({ root }) => {
519+
const u1 = root.createUniform(d.u32, 1);
520+
const u2 = root.createUniform(d.u32, 2);
521+
const u3 = root.createUniform(d.u32, 3);
522+
const u4 = root.createUniform(d.u32, 4);
523+
524+
function foo() {
525+
'use gpu';
526+
const a = [u1.$, u2.$][0];
527+
const b = [u3.$, u4.$][1];
528+
}
529+
530+
expect(tgpu.resolve([foo])).toMatchInlineSnapshot(`
531+
"@group(0) @binding(0) var<uniform> u1: u32;
532+
533+
@group(0) @binding(1) var<uniform> u4: u32;
534+
535+
fn foo() {
536+
let a = u1;
537+
let b = u4;
538+
}"
539+
`);
540+
});
446541
});
447542

448543
describe('array.length', () => {

0 commit comments

Comments
 (0)