Skip to content

Commit 0f8fa0d

Browse files
committed
Merge branch 'test/incorporate-arkattest-for-checking-infer' of https://github.com/software-mansion/TypeGPU into test/incorporate-arkattest-for-checking-infer
2 parents e034494 + 650706c commit 0f8fa0d

File tree

12 files changed

+266
-77
lines changed

12 files changed

+266
-77
lines changed

packages/tgpu-jit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
"dependencies": {
5858
"acorn": "^8.14.1",
5959
"tinyest": "workspace:~0.1.0-alpha.7",
60-
"tinyest-for-wgsl": "workspace:~0.1.0-alpha.8"
60+
"tinyest-for-wgsl": "workspace:~0.1.0-alpha.9"
6161
}
6262
}

packages/tinyest-for-wgsl/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "tinyest-for-wgsl",
33
"private": true,
4-
"version": "0.1.0-alpha.8",
4+
"version": "0.1.0-alpha.9",
55
"description": "Transforms JavaScript into its 'tinyest' form, to be used in generating equivalent (or close to) WGSL code.",
66
"license": "MIT",
77
"type": "module",

packages/tinyest-for-wgsl/src/parsers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ export function extractFunctionParts(rootNode: JsNode): {
447447
params: {
448448
type: 'destructured-object',
449449
props: functionNode.params[0].properties.flatMap((prop) =>
450-
prop.type === 'Property' &&
450+
(prop.type === 'Property' || prop.type === 'ObjectProperty') &&
451451
prop.key.type === 'Identifier' &&
452452
prop.value.type === 'Identifier'
453453
? [{ prop: prop.key.name, alias: prop.value.name }]

packages/tinyest-for-wgsl/tests/parsers.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import babel from '@babel/parser';
22
import type { Node } from '@babel/types';
33
import * as acorn from 'acorn';
4+
import type { ArgNames } from 'tinyest';
45
import { describe, expect, it } from 'vitest';
56
import { transpileFn } from '../src/parsers.ts';
67

@@ -142,4 +143,31 @@ describe('transpileFn', () => {
142143
expect(externalNames).toEqual(['external']);
143144
}),
144145
);
146+
147+
it(
148+
'handles destructured args',
149+
dualTest((p) => {
150+
const { argNames, externalNames } = transpileFn(
151+
p(`({ pos, a: b }) => {
152+
const x = pos.x;
153+
}`),
154+
);
155+
156+
expect(argNames).toEqual({
157+
type: 'destructured-object',
158+
props: [
159+
{
160+
alias: 'pos',
161+
prop: 'pos',
162+
},
163+
{
164+
alias: 'b',
165+
prop: 'a',
166+
},
167+
],
168+
} satisfies ArgNames);
169+
170+
expect(externalNames).toEqual([]);
171+
}),
172+
);
145173
});

packages/typegpu/src/core/function/fnCore.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,12 @@ export function createFnCore(
175175

176176
const args: Snippet[] = Array.isArray(shell.argTypes)
177177
? ast.argNames.type === 'identifiers'
178-
? ast.argNames.names.map((name, idx) => ({
179-
value: name,
180-
dataType: (shell.argTypes as unknown[])[idx] as AnyWgslData,
178+
? shell.argTypes.map((arg, i) => ({
179+
value:
180+
(ast.argNames.type === 'identifiers'
181+
? ast.argNames.names[i]
182+
: undefined) ?? `arg_${i}`,
183+
dataType: arg as AnyWgslData,
181184
}))
182185
: []
183186
: Object.entries(shell.argTypes).map(([name, dataType]) => ({

packages/typegpu/src/core/function/tgpuComputeFn.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { stripTemplate } from './templateUtils.ts';
1717
type TgpuComputeFnShellHeader<
1818
ComputeIn extends Record<string, AnyComputeBuiltin>,
1919
> = {
20-
readonly argTypes: [AnyWgslStruct];
20+
readonly argTypes: [AnyWgslStruct] | [];
2121
readonly returnType: undefined;
2222
readonly workgroupSize: [number, number, number];
2323
readonly isEntry: true;
@@ -105,7 +105,10 @@ export function computeFn<
105105
workgroupSize: number[];
106106
}): TgpuComputeFnShell<ComputeIn> {
107107
const shell: TgpuComputeFnShellHeader<ComputeIn> = {
108-
argTypes: [createStructFromIO(options.in ?? {})],
108+
argTypes:
109+
options.in && Object.keys(options.in).length !== 0
110+
? [createStructFromIO(options.in)]
111+
: [],
109112
returnType: undefined,
110113
workgroupSize: [
111114
options.workgroupSize[0] ?? 1,

packages/typegpu/src/core/function/tgpuFragmentFn.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ type TgpuFragmentFnShellHeader<
5353
FragmentIn extends FragmentInConstrained,
5454
FragmentOut extends FragmentOutConstrained,
5555
> = {
56-
readonly argTypes: [AnyWgslStruct];
56+
readonly argTypes: [AnyWgslStruct] | [];
5757
readonly targets: FragmentOut;
5858
readonly returnType: FragmentOut;
5959
readonly isEntry: true;
@@ -149,9 +149,14 @@ export function fragmentFn<
149149
out: FragmentOut;
150150
}): TgpuFragmentFnShell<FragmentIn, FragmentOut> {
151151
const shell: TgpuFragmentFnShellHeader<FragmentIn, FragmentOut> = {
152-
argTypes: [createStructFromIO(options.in ?? {})],
152+
argTypes:
153+
options.in && Object.keys(options.in).length !== 0
154+
? [createStructFromIO(options.in)]
155+
: [],
153156
targets: options.out,
154-
returnType: createOutputType(options.out) as FragmentOut,
157+
returnType: (Object.keys(options.out).length !== 0
158+
? createOutputType(options.out)
159+
: undefined) as FragmentOut,
155160
isEntry: true,
156161
};
157162

packages/typegpu/src/core/function/tgpuVertexFn.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type TgpuVertexFnShellHeader<
2424
VertexIn extends IOLayout,
2525
VertexOut extends IOLayout,
2626
> = {
27-
readonly argTypes: [AnyWgslStruct];
27+
readonly argTypes: [AnyWgslStruct] | [];
2828
readonly returnType: VertexOut;
2929
readonly attributes: [VertexIn];
3030
readonly isEntry: true;
@@ -108,8 +108,13 @@ export function vertexFn<
108108
}): TgpuVertexFnShell<VertexIn, VertexOut> {
109109
const shell: TgpuVertexFnShellHeader<VertexIn, VertexOut> = {
110110
attributes: [options.in ?? ({} as VertexIn)],
111-
returnType: createOutputType(options.out) as unknown as VertexOut,
112-
argTypes: [createStructFromIO(options.in ?? {})],
111+
returnType: (Object.keys(options.out).length !== 0
112+
? createOutputType(options.out)
113+
: undefined) as unknown as VertexOut,
114+
argTypes:
115+
options.in && Object.keys(options.in).length !== 0
116+
? [createStructFromIO(options.in)]
117+
: [],
113118
isEntry: true,
114119
};
115120

packages/typegpu/tests/function.test.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,106 @@ describe('tgpu.fn', () => {
141141
});
142142
});
143143

144+
describe('tgpu.computeFn', () => {
145+
it('does not create In struct when the are no arguments', () => {
146+
const foo = tgpu['~unstable'].computeFn({ workgroupSize: [1] })(() => {
147+
const x = 2;
148+
});
149+
150+
expect(parseResolved({ foo })).not.toContain('struct');
151+
expect(foo.shell.argTypes).toEqual([]);
152+
});
153+
154+
it('does not create In struct when there is empty object for arguments', () => {
155+
const foo = tgpu['~unstable'].computeFn({ in: {}, workgroupSize: [1] })(
156+
() => {
157+
const x = 2;
158+
},
159+
);
160+
161+
expect(parseResolved({ foo })).not.toContain(parse('struct'));
162+
expect(foo.shell.argTypes).toEqual([]);
163+
});
164+
});
165+
166+
describe('tgpu.vertexFn', () => {
167+
it('does not create In struct when the are no arguments', () => {
168+
const foo = tgpu['~unstable'].vertexFn({
169+
out: { pos: d.builtin.position },
170+
})(() => ({
171+
pos: d.vec4f(),
172+
}));
173+
expect(parseResolved({ foo })).not.toContain(parse('struct foo_In'));
174+
expect(parseResolved({ foo })).toContain(parse('struct foo_Out'));
175+
expect(foo.shell.argTypes).toEqual([]);
176+
});
177+
178+
it('does not create In struct when there is empty object for arguments', () => {
179+
const foo = tgpu['~unstable'].vertexFn({
180+
in: {},
181+
out: { pos: d.builtin.position },
182+
})(() => {
183+
return {
184+
pos: d.vec4f(),
185+
};
186+
});
187+
expect(parseResolved({ foo })).not.toContain(parse('struct foo_In'));
188+
expect(parseResolved({ foo })).toContain(parse('struct foo_Out'));
189+
expect(foo.shell.argTypes).toEqual([]);
190+
});
191+
192+
it('does not create In struct when there is empty object for arguments', () => {
193+
const foo = tgpu['~unstable'].vertexFn({
194+
in: {},
195+
out: { pos: d.builtin.position },
196+
})(() => {
197+
return {
198+
pos: d.vec4f(),
199+
};
200+
});
201+
expect(parseResolved({ foo })).not.toContain(parse('struct foo_In'));
202+
expect(parseResolved({ foo })).toContain(parse('struct foo_Out'));
203+
expect(foo.shell.argTypes).toEqual([]);
204+
});
205+
206+
it('does not create Out struct when the are no output parameters', () => {
207+
const foo = tgpu['~unstable'].vertexFn({
208+
out: {},
209+
})(() => ({
210+
pos: d.vec4f(),
211+
}));
212+
expect(parseResolved({ foo })).not.toContain(parse('struct foo_Out'));
213+
});
214+
});
215+
216+
describe('tgpu.fragmentFn', () => {
217+
it('does not create In struct when the are no arguments', () => {
218+
const foo = tgpu['~unstable'].fragmentFn({
219+
out: d.vec4f,
220+
})(() => d.vec4f(0));
221+
222+
expect(parseResolved({ foo })).not.toContain(parse('struct'));
223+
expect(foo.shell.argTypes).toEqual([]);
224+
});
225+
226+
it('does not create In struct when there is empty object for arguments', () => {
227+
const foo = tgpu['~unstable'].fragmentFn({
228+
in: {},
229+
out: d.vec4f,
230+
})(() => d.vec4f(0));
231+
232+
expect(parseResolved({ foo })).not.toContain(parse('struct'));
233+
expect(foo.shell.argTypes).toEqual([]);
234+
});
235+
236+
it('does not create Out struct when the are no output parameters', () => {
237+
const foo = tgpu['~unstable'].fragmentFn({
238+
out: {},
239+
})(() => ({}));
240+
expect(parseResolved({ foo })).not.toContain(parse('struct foo_Out'));
241+
});
242+
});
243+
144244
describe('InferIO', () => {
145245
it('unwraps f32', () => {
146246
const layout = d.f32 satisfies IOLayout;

0 commit comments

Comments
 (0)