@@ -26,7 +26,7 @@ import { safeStringify } from '../shared/stringify.ts';
2626import { $internal } from '../shared/symbols.ts' ;
2727import { pow } from '../std/numeric.ts' ;
2828import { add , div , mul , neg , sub } from '../std/operators.ts' ;
29- import type { FnArgsConversionHint } from '../types.ts' ;
29+ import { type FnArgsConversionHint , isKnownAtComptime } from '../types.ts' ;
3030import {
3131 convertStructValues ,
3232 convertToCommonType ,
@@ -50,6 +50,8 @@ const { NodeTypeCatalog: NODE } = tinyest;
5050const parenthesizedOps = [
5151 '==' ,
5252 '!=' ,
53+ '===' ,
54+ '!==' ,
5355 '<' ,
5456 '<=' ,
5557 '>' ,
@@ -68,7 +70,48 @@ const parenthesizedOps = [
6870 '||' ,
6971] ;
7072
71- const binaryLogicalOps = [ '&&' , '||' , '==' , '!=' , '<' , '<=' , '>' , '>=' ] ;
73+ const binaryLogicalOps = [
74+ '&&' ,
75+ '||' ,
76+ '==' ,
77+ '!=' ,
78+ '===' ,
79+ '!==' ,
80+ '<' ,
81+ '<=' ,
82+ '>' ,
83+ '>=' ,
84+ ] ;
85+
86+ const OP_MAP = {
87+ //
88+ // binary
89+ //
90+ '===' : '==' ,
91+ '!==' : '!=' ,
92+ get '>>>' ( ) : never {
93+ throw new Error ( 'The `>>>` operator is unsupported in TypeGPU functions.' ) ;
94+ } ,
95+ get in ( ) : never {
96+ throw new Error ( 'The `in` operator is unsupported in TypeGPU functions.' ) ;
97+ } ,
98+ get instanceof ( ) : never {
99+ throw new Error (
100+ 'The `instanceof` operator is unsupported in TypeGPU functions.' ,
101+ ) ;
102+ } ,
103+ get '|>' ( ) : never {
104+ throw new Error ( 'The `|>` operator is unsupported in TypeGPU functions.' ) ;
105+ } ,
106+ //
107+ // logical
108+ //
109+ '||' : '||' ,
110+ '&&' : '&&' ,
111+ get '??' ( ) : never {
112+ throw new Error ( 'The `??` operator is unsupported in TypeGPU functions.' ) ;
113+ } ,
114+ } as Record < string , string > ;
72115
73116type Operator =
74117 | tinyest . BinaryOperator
@@ -250,8 +293,24 @@ ${this.ctx.pre}}`;
250293 ) ;
251294 }
252295
296+ if ( op === '==' ) {
297+ throw new Error ( 'Please use the === operator instead of ==' ) ;
298+ }
299+
300+ if (
301+ op === '===' && isKnownAtComptime ( lhsExpr ) && isKnownAtComptime ( rhsExpr )
302+ ) {
303+ return snip (
304+ lhsExpr . value === rhsExpr . value ,
305+ bool ,
306+ /* ref */ 'constant' ,
307+ ) ;
308+ }
309+
253310 if ( lhsExpr . dataType . type === 'unknown' ) {
254- throw new WgslTypeError ( `Left-hand side of '${ op } ' is of unknown type` ) ;
311+ throw new WgslTypeError (
312+ `Left-hand side of '${ op } ' is of unknown type` ,
313+ ) ;
255314 }
256315
257316 if ( rhsExpr . dataType . type === 'unknown' ) {
@@ -315,8 +374,8 @@ ${this.ctx.pre}}`;
315374
316375 return snip (
317376 parenthesizedOps . includes ( op )
318- ? `(${ lhsStr } ${ op } ${ rhsStr } )`
319- : `${ lhsStr } ${ op } ${ rhsStr } ` ,
377+ ? `(${ lhsStr } ${ OP_MAP [ op ] ?? op } ${ rhsStr } )`
378+ : `${ lhsStr } ${ OP_MAP [ op ] ?? op } ${ rhsStr } ` ,
320379 type ,
321380 // Result of an operation, so not a reference to anything
322381 /* ref */ 'runtime' ,
@@ -670,7 +729,7 @@ ${this.ctx.pre}}`;
670729 }
671730
672731 if ( expression [ 0 ] === NODE . stringLiteral ) {
673- return snip ( expression [ 1 ] , UnknownData , /* ref */ 'runtime ' ) ; // arbitrary ref
732+ return snip ( expression [ 1 ] , UnknownData , /* origin */ 'constant ' ) ;
674733 }
675734
676735 if ( expression [ 0 ] === NODE . preUpdate ) {
0 commit comments