@@ -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
@@ -248,8 +291,24 @@ ${this.ctx.pre}}`;
248291 ) ;
249292 }
250293
294+ if ( op === '==' ) {
295+ throw new Error ( 'Please use the === operator instead of ==' ) ;
296+ }
297+
298+ if (
299+ op === '===' && isKnownAtComptime ( lhsExpr ) && isKnownAtComptime ( rhsExpr )
300+ ) {
301+ return snip (
302+ lhsExpr . value === rhsExpr . value ,
303+ bool ,
304+ /* ref */ 'constant' ,
305+ ) ;
306+ }
307+
251308 if ( lhsExpr . dataType . type === 'unknown' ) {
252- throw new WgslTypeError ( `Left-hand side of '${ op } ' is of unknown type` ) ;
309+ throw new WgslTypeError (
310+ `Left-hand side of '${ op } ' is of unknown type` ,
311+ ) ;
253312 }
254313
255314 if ( rhsExpr . dataType . type === 'unknown' ) {
@@ -302,8 +361,8 @@ ${this.ctx.pre}}`;
302361
303362 return snip (
304363 parenthesizedOps . includes ( op )
305- ? `(${ lhsStr } ${ op } ${ rhsStr } )`
306- : `${ lhsStr } ${ op } ${ rhsStr } ` ,
364+ ? `(${ lhsStr } ${ OP_MAP [ op ] ?? op } ${ rhsStr } )`
365+ : `${ lhsStr } ${ OP_MAP [ op ] ?? op } ${ rhsStr } ` ,
307366 type ,
308367 // Result of an operation, so not a reference to anything
309368 /* ref */ 'runtime' ,
@@ -657,7 +716,7 @@ ${this.ctx.pre}}`;
657716 }
658717
659718 if ( expression [ 0 ] === NODE . stringLiteral ) {
660- return snip ( expression [ 1 ] , UnknownData , /* ref */ 'runtime ' ) ; // arbitrary ref
719+ return snip ( expression [ 1 ] , UnknownData , /* origin */ 'constant ' ) ;
661720 }
662721
663722 if ( expression [ 0 ] === NODE . preUpdate ) {
0 commit comments