@@ -30,6 +30,7 @@ import {
3030 tryConvertSnippet ,
3131} from './conversion.ts' ;
3232import {
33+ ArrayExpression ,
3334 concretize ,
3435 type GenerationCtx ,
3536 numericLiteralToSnippet ,
@@ -503,21 +504,21 @@ ${this.ctx.pre}}`;
503504 const [ _ , calleeNode , argNodes ] = expression ;
504505 const callee = this . expression ( calleeNode ) ;
505506
506- if ( wgsl . isWgslStruct ( callee . value ) || wgsl . isWgslArray ( callee . value ) ) {
507- // Struct/array schema call.
507+ if ( wgsl . isWgslStruct ( callee . value ) ) {
508+ // Struct schema call.
508509 if ( argNodes . length > 1 ) {
509510 throw new WgslTypeError (
510- 'Array and struct schemas should always be called with at most 1 argument' ,
511+ 'Struct schemas should always be called with at most 1 argument' ,
511512 ) ;
512513 }
513514
514515 // No arguments `Struct()`, resolve struct name and return.
515516 if ( ! argNodes [ 0 ] ) {
516- // the schema becomes the data type
517+ // The schema becomes the data type.
517518 return snip (
518519 `${ this . ctx . resolve ( callee . value ) . value } ()` ,
519520 callee . value ,
520- // A new struct, so not a reference
521+ // A new struct, so not a reference.
521522 /* origin */ 'runtime' ,
522523 ) ;
523524 }
@@ -532,7 +533,54 @@ ${this.ctx.pre}}`;
532533 return snip (
533534 this . ctx . resolve ( arg . value , callee . value ) . value ,
534535 callee . value ,
535- // A new struct, so not a reference
536+ // A new struct, so not a reference.
537+ /* origin */ 'runtime' ,
538+ ) ;
539+ }
540+
541+ if ( wgsl . isWgslArray ( callee . value ) ) {
542+ // Array schema call.
543+ if ( argNodes . length > 1 ) {
544+ throw new WgslTypeError (
545+ 'Array schemas should always be called with at most 1 argument' ,
546+ ) ;
547+ }
548+
549+ // No arguments `array<...>()`, resolve array type and return.
550+ if ( ! argNodes [ 0 ] ) {
551+ // The schema becomes the data type.
552+ return snip (
553+ `${ this . ctx . resolve ( callee . value ) . value } ()` ,
554+ callee . value ,
555+ // A new array, so not a reference.
556+ /* origin */ 'runtime' ,
557+ ) ;
558+ }
559+
560+ const arg = this . typedExpression (
561+ argNodes [ 0 ] ,
562+ callee . value ,
563+ ) ;
564+
565+ // `d.arrayOf(...)([...])`.
566+ // We don't resolve the ArrayExpression object itself to
567+ // avoid reference checks (we're copying so it's fine)
568+ if ( arg . value instanceof ArrayExpression ) {
569+ return snip (
570+ stitch `${
571+ this . ctx . resolve ( callee . value ) . value
572+ } (${ arg . value . elements } )`,
573+ arg . dataType ,
574+ /* origin */ 'runtime' ,
575+ ) ;
576+ }
577+
578+ // `d.arrayOf(...)(otherArr)`.
579+ // We just let the argument resolve everything.
580+ return snip (
581+ this . ctx . resolve ( arg . value , callee . value ) . value ,
582+ callee . value ,
583+ // A new array, so not a reference.
536584 /* origin */ 'runtime' ,
537585 ) ;
538586 }
@@ -729,25 +777,9 @@ ${this.ctx.pre}}`;
729777 }
730778 } else {
731779 // The array is not typed, so we try to guess the types.
732- const valuesSnippets = valueNodes . map ( ( value ) => {
733- const snippet = this . expression ( value as tinyest . Expression ) ;
734- // We check if there are no references among the elements
735- if (
736- ( snippet . origin === 'argument' &&
737- ! wgsl . isNaturallyEphemeral ( snippet . dataType ) ) ||
738- ! isEphemeralSnippet ( snippet )
739- ) {
740- const snippetStr =
741- this . ctx . resolve ( snippet . value , snippet . dataType ) . value ;
742- const snippetType =
743- this . ctx . resolve ( concretize ( snippet . dataType as wgsl . BaseData ) )
744- . value ;
745- throw new WgslTypeError (
746- `'${ snippetStr } ' reference cannot be used in an array constructor.\n-----\nTry '${ snippetType } (${ snippetStr } )' or 'arrayOf(${ snippetType } , count)([...])' to copy the value instead.\n-----` ,
747- ) ;
748- }
749- return snippet ;
750- } ) ;
780+ const valuesSnippets = valueNodes . map ( ( value ) =>
781+ this . expression ( value as tinyest . Expression )
782+ ) ;
751783
752784 if ( valuesSnippets . length === 0 ) {
753785 throw new WgslTypeError (
@@ -766,13 +798,17 @@ ${this.ctx.pre}}`;
766798 elemType = concretize ( values [ 0 ] ?. dataType as wgsl . AnyWgslData ) ;
767799 }
768800
769- const arrayType = `array<${
770- this . ctx . resolve ( elemType ) . value
771- } , ${ values . length } >`;
801+ const arrayType = arrayOf (
802+ elemType as wgsl . AnyWgslData ,
803+ values . length ,
804+ ) ;
772805
773806 return snip (
774- stitch `${ arrayType } (${ values } )` ,
775- arrayOf ( elemType as wgsl . AnyWgslData , values . length ) ,
807+ new ArrayExpression (
808+ arrayType ,
809+ values ,
810+ ) ,
811+ arrayType ,
776812 /* origin */ 'runtime' ,
777813 ) ;
778814 }
0 commit comments