From 3c92a37588169850d143f7fe5f690b7e8204ec0e Mon Sep 17 00:00:00 2001 From: Caden Parker Date: Sun, 16 Nov 2025 13:38:36 -0800 Subject: [PATCH 1/9] TSL Transpiler: Support struct definitions --- examples/jsm/transpiler/AST.js | 29 ++++++++++++++++ examples/jsm/transpiler/GLSLDecoder.js | 47 +++++++++++++++++++++++++- examples/jsm/transpiler/TSLEncoder.js | 29 ++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index 7473a23e04b7e2..ce0dcb8dd9c7e6 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -629,3 +629,32 @@ export class SwitchCase extends ASTNode { } } + +// helper class for StructDefinition +export class StructMember { + + constructor( type, name ) { + + this.type = type; + this.name = name; + this.isStructMember = true; + + } + +} + +export class StructDefinition extends ASTNode { + + constructor( name, members = [] ) { + + super(); + + this.name = name; + this.members = members; + this.isStructDefinition = true; + + this.initialize(); + + } + +} \ No newline at end of file diff --git a/examples/jsm/transpiler/GLSLDecoder.js b/examples/jsm/transpiler/GLSLDecoder.js index 6661d818e5f03e..1e18c23d3071fd 100644 --- a/examples/jsm/transpiler/GLSLDecoder.js +++ b/examples/jsm/transpiler/GLSLDecoder.js @@ -1,4 +1,4 @@ -import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment } from './AST.js'; +import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment, StructMember, StructDefinition } from './AST.js'; import { isType } from './TranspilerUtils.js'; @@ -780,6 +780,47 @@ class GLSLDecoder { } + parseStructDefinition() { + + const tokens = this.readTokensUntil( ';' ); + + const structName = tokens[ 1 ].str; + + if (tokens[ 2 ].str !== '{' ) { + + throw new Error( 'Expected \'{\' after struct name ' ); + + } + + const structMembers = []; + for ( let i = 3; i < tokens.length - 2; i += 3 ) { + + const typeToken = tokens[ i ]; + const nameToken = tokens[ i + 1 ]; + + if (typeToken.type != 'literal' || nameToken.type != 'literal') { + throw new Error( 'Invalid struct declaration' ); + } + + if (tokens[ i + 2 ].str !== ';' ) { + throw new Error( 'Missing \';\' after struct member name' ); + } + + const member = new StructMember(typeToken.str, nameToken.str); + structMembers.push(member); + + } + + if (tokens[ tokens.length - 2 ].str !== '}' ) { + + throw new Error( 'Missing closing \'}\' for struct ' + structName ); + + } + + return new StructDefinition(structName, structMembers); + + } + parseReturn() { this.readToken(); // skip 'return' @@ -1079,6 +1120,10 @@ class GLSLDecoder { statement = this.parseVarying(); + } else if ( token.str === 'struct' ) { + + statement = this.parseStructDefinition(); + } else if ( isType( token.str ) ) { if ( this.getToken( 2 ).str === '(' ) { diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 3b44654007d385..944156409b8e8d 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -314,6 +314,10 @@ class TSLEncoder { code = this.emitVarying( node ); + } else if ( node.isStructDefinition ) { + + code = this.emitStructDefinition( node ); + } else if ( node.isTernary ) { code = this.emitTernary( node ); @@ -702,6 +706,31 @@ ${ this.tab }} )`; } + emitStructDefinition( node ) { + + const { name, members } = node; + + this.addImport( 'struct' ); + + let structString = `const ${ name } = struct({\n\n`; + + for ( let i = 0; i < members.length; i += 1 ) { + + const member = members[i]; + + structString += `${this.tab}\t${member.name}: '${member.type}'`; + + const delimiter = (i != members.length - 1) ? ',\n' : '\n'; + structString += delimiter; + + } + + structString += `\n${this.tab}}, \'${name}\' )`; + + return structString; + + } + emitOverloadingFunction( nodes ) { const { name } = nodes[ 0 ]; From 32943d48ddf8686f0d0924b3327a6a62040d7d8a Mon Sep 17 00:00:00 2001 From: Caden Parker Date: Sun, 16 Nov 2025 13:48:41 -0800 Subject: [PATCH 2/9] TSL Transpiler: Support constructors + struct return values --- examples/jsm/transpiler/AST.js | 4 +++- examples/jsm/transpiler/GLSLDecoder.js | 12 ++++++++---- examples/jsm/transpiler/TSLEncoder.js | 12 ++++++++++-- examples/jsm/transpiler/TranspilerUtils.js | 4 ++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index ce0dcb8dd9c7e6..d8a7e92f1c56c0 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -125,7 +125,7 @@ export class Program extends ASTNode { export class VariableDeclaration extends ASTNode { - constructor( type, name, value = null, next = null, immutable = false ) { + constructor( type, name, value = null, next = null, immutable = false, isUserDefinedStructType = false ) { super(); @@ -136,6 +136,8 @@ export class VariableDeclaration extends ASTNode { this.immutable = immutable; + this.isUserDefinedStructType = isUserDefinedStructType; + this.isVariableDeclaration = true; this.initialize(); diff --git a/examples/jsm/transpiler/GLSLDecoder.js b/examples/jsm/transpiler/GLSLDecoder.js index 1e18c23d3071fd..45f6c1ad1da623 100644 --- a/examples/jsm/transpiler/GLSLDecoder.js +++ b/examples/jsm/transpiler/GLSLDecoder.js @@ -1,6 +1,6 @@ import { Program, FunctionDeclaration, Switch, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform, Discard, SwitchCase, Continue, Break, While, Comment, StructMember, StructDefinition } from './AST.js'; -import { isType } from './TranspilerUtils.js'; +import { isBuiltinType } from './TranspilerUtils.js'; const unaryOperators = [ '+', '-', '~', '!', '++', '--' @@ -255,6 +255,7 @@ class GLSLDecoder { this.index = 0; this.tokenizer = null; this.keywords = []; + this.userDefinedStructTypes = new Set(); this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' ); @@ -708,6 +709,7 @@ class GLSLDecoder { if ( immutable ) index ++; type = type || tokens[ index ++ ].str; + const isUserDefinedStructType = this.userDefinedStructTypes.has(type); const name = tokens[ index ++ ].str; const token = tokens[ index ]; @@ -738,7 +740,7 @@ class GLSLDecoder { } - const variable = new VariableDeclaration( type, name, init, next, immutable ); + const variable = new VariableDeclaration( type, name, init, next, immutable, isUserDefinedStructType ); return variable; @@ -785,6 +787,7 @@ class GLSLDecoder { const tokens = this.readTokensUntil( ';' ); const structName = tokens[ 1 ].str; + this.userDefinedStructTypes.add(structName); if (tokens[ 2 ].str !== '{' ) { @@ -868,7 +871,8 @@ class GLSLDecoder { let initialization; - if ( initializationTokens[ 0 ] && isType( initializationTokens[ 0 ].str ) ) { + const firstToken = initializationTokens[ 0 ]; + if ( firstToken && ( isBuiltinType( firstToken.str ) || this.userDefinedStructTypes.has( firstToken.str ) ) ) { initialization = this.parseVariablesFromToken( initializationTokens ); @@ -1124,7 +1128,7 @@ class GLSLDecoder { statement = this.parseStructDefinition(); - } else if ( isType( token.str ) ) { + } else if ( isBuiltinType( token.str ) || this.userDefinedStructTypes.has( token.str ) ) { if ( this.getToken( 2 ).str === '(' ) { diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 944156409b8e8d..28f41657827d44 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -673,9 +673,17 @@ ${ this.tab }} )`; } else { - varStr += ` = property( '${ type }' )`; + if ( node.isUserDefinedStructType ) { - this.addImport( 'property' ); + varStr += ` = ${type}()`; + + } else { + + varStr += ` = property( '${ type }' )`; + + this.addImport( 'property' ); + + } } diff --git a/examples/jsm/transpiler/TranspilerUtils.js b/examples/jsm/transpiler/TranspilerUtils.js index d9e74a32504183..1774460838c918 100644 --- a/examples/jsm/transpiler/TranspilerUtils.js +++ b/examples/jsm/transpiler/TranspilerUtils.js @@ -10,9 +10,9 @@ export function isPrimitive( value ) { } -export function isType( str ) { +export function isBuiltinType( str ) { - return /void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234]/.test( str ); + return /^(void|bool|float|u?int|mat[234]|mat[234]x[234]|(u|i|b)?vec[234])$/.test( str ); } From 2237b07e29055ae1958c1614cf18bab75a6d613e Mon Sep 17 00:00:00 2001 From: Caden Parker Date: Thu, 20 Nov 2025 11:31:17 -0800 Subject: [PATCH 3/9] Address PR Feedback: Move struct definition lookup to Program class --- examples/jsm/transpiler/AST.js | 7 +++---- examples/jsm/transpiler/GLSLDecoder.js | 29 +++++++++++++++----------- examples/jsm/transpiler/TSLEncoder.js | 7 +++++-- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index d8a7e92f1c56c0..3799c32c26c2a4 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -109,11 +109,12 @@ export class Comment extends ASTNode { export class Program extends ASTNode { - constructor( body = [] ) { + constructor( body = [], userDefinedStructTypes = new Set() ) { super(); this.body = body; + this.userDefinedStructTypes = userDefinedStructTypes; this.isProgram = true; @@ -125,7 +126,7 @@ export class Program extends ASTNode { export class VariableDeclaration extends ASTNode { - constructor( type, name, value = null, next = null, immutable = false, isUserDefinedStructType = false ) { + constructor( type, name, value = null, next = null, immutable = false ) { super(); @@ -136,8 +137,6 @@ export class VariableDeclaration extends ASTNode { this.immutable = immutable; - this.isUserDefinedStructType = isUserDefinedStructType; - this.isVariableDeclaration = true; this.initialize(); diff --git a/examples/jsm/transpiler/GLSLDecoder.js b/examples/jsm/transpiler/GLSLDecoder.js index 45f6c1ad1da623..13a40fe1a8a4a2 100644 --- a/examples/jsm/transpiler/GLSLDecoder.js +++ b/examples/jsm/transpiler/GLSLDecoder.js @@ -255,7 +255,7 @@ class GLSLDecoder { this.index = 0; this.tokenizer = null; this.keywords = []; - this.userDefinedStructTypes = new Set(); + this.userDefinedStructTypes = new Map(); this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' ); @@ -709,7 +709,6 @@ class GLSLDecoder { if ( immutable ) index ++; type = type || tokens[ index ++ ].str; - const isUserDefinedStructType = this.userDefinedStructTypes.has(type); const name = tokens[ index ++ ].str; const token = tokens[ index ]; @@ -740,7 +739,7 @@ class GLSLDecoder { } - const variable = new VariableDeclaration( type, name, init, next, immutable, isUserDefinedStructType ); + const variable = new VariableDeclaration( type, name, init, next, immutable ); return variable; @@ -787,9 +786,8 @@ class GLSLDecoder { const tokens = this.readTokensUntil( ';' ); const structName = tokens[ 1 ].str; - this.userDefinedStructTypes.add(structName); - if (tokens[ 2 ].str !== '{' ) { + if ( tokens[ 2 ].str !== '{' ) { throw new Error( 'Expected \'{\' after struct name ' ); @@ -801,26 +799,33 @@ class GLSLDecoder { const typeToken = tokens[ i ]; const nameToken = tokens[ i + 1 ]; - if (typeToken.type != 'literal' || nameToken.type != 'literal') { + if ( typeToken.type != 'literal' || nameToken.type != 'literal' ) { + throw new Error( 'Invalid struct declaration' ); + } - if (tokens[ i + 2 ].str !== ';' ) { + if ( tokens[ i + 2 ].str !== ';' ) { + throw new Error( 'Missing \';\' after struct member name' ); + } - const member = new StructMember(typeToken.str, nameToken.str); - structMembers.push(member); + const member = new StructMember( typeToken.str, nameToken.str ); + structMembers.push( member ); } - if (tokens[ tokens.length - 2 ].str !== '}' ) { + if ( tokens[ tokens.length - 2 ].str !== '}' ) { throw new Error( 'Missing closing \'}\' for struct ' + structName ); } - return new StructDefinition(structName, structMembers); + const definition = new StructDefinition( structName, structMembers ); + this.userDefinedStructTypes.set( structName, definition ); + + return definition; } @@ -1208,7 +1213,7 @@ class GLSLDecoder { this.tokenizer = new Tokenizer( polyfill + source ).tokenize(); const body = this.parseBlock(); - const program = new Program( body ); + const program = new Program( body, this.userDefinedStructTypes ); return program; diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 28f41657827d44..7effaad2dec5ca 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -56,6 +56,7 @@ class TSLEncoder { this.imports = new Set(); this.global = new Set(); this.overloadings = new Map(); + this.userDefinedStructTypes = new Map(); this.iife = false; this.reference = false; @@ -673,9 +674,9 @@ ${ this.tab }} )`; } else { - if ( node.isUserDefinedStructType ) { + if ( this.userDefinedStructTypes.has( type ) ) { - varStr += ` = ${type}()`; + varStr += ` = ${ type }()`; } else { @@ -924,6 +925,8 @@ ${ this.tab }}`; } + this.userDefinedStructTypes = ast.userDefinedStructTypes; + for ( const statement of ast.body ) { code += this.emitExtraLine( statement, ast.body ); From 054e103c98071abf47682efd9d63bb1139b95770 Mon Sep 17 00:00:00 2001 From: Caden Parker Date: Thu, 20 Nov 2025 12:10:37 -0800 Subject: [PATCH 4/9] Emit struct definitions in WGSL --- examples/jsm/transpiler/AST.js | 4 ++-- examples/jsm/transpiler/TSLEncoder.js | 4 ++-- examples/jsm/transpiler/WGSLEncoder.js | 27 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index 3799c32c26c2a4..aae711ec68e01f 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -109,7 +109,7 @@ export class Comment extends ASTNode { export class Program extends ASTNode { - constructor( body = [], userDefinedStructTypes = new Set() ) { + constructor( body = [], userDefinedStructTypes = new Map() ) { super(); @@ -658,4 +658,4 @@ export class StructDefinition extends ASTNode { } -} \ No newline at end of file +} diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 7effaad2dec5ca..3102275d0d9dc0 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -725,11 +725,11 @@ ${ this.tab }} )`; for ( let i = 0; i < members.length; i += 1 ) { - const member = members[i]; + const member = members[ i ]; structString += `${this.tab}\t${member.name}: '${member.type}'`; - const delimiter = (i != members.length - 1) ? ',\n' : '\n'; + const delimiter = ( i != members.length - 1 ) ? ',\n' : '\n'; structString += delimiter; } diff --git a/examples/jsm/transpiler/WGSLEncoder.js b/examples/jsm/transpiler/WGSLEncoder.js index 3f588973a671ef..0588c36575491b 100644 --- a/examples/jsm/transpiler/WGSLEncoder.js +++ b/examples/jsm/transpiler/WGSLEncoder.js @@ -300,6 +300,10 @@ class WGSLEncoder { this.varyings.push( node ); return ''; // Defer emission to the header + } else if ( node.isStructDefinition ) { + + code = this.emitStructDefinition( node ); + } else if ( node.isTernary ) { const cond = this.emitExpression( node.cond ); @@ -584,6 +588,29 @@ class WGSLEncoder { } + emitStructDefinition( node ) { + + const { name, members } = node; + + let structString = `struct ${ name } {\n`; + + for ( let i = 0; i < members.length; i += 1 ) { + + const member = members[ i ]; + + structString += `${ this.tab }\t${ member.name }: ${ this.getWgslType( member.type ) }`; + + const delimiter = ( i != members.length - 1 ) ? ',\n' : '\n'; + structString += delimiter; + + } + + structString += this.tab + '}'; + + return structString; + + } + emitFunction( node ) { const name = node.name; From 9f0af8717783cdf833e1decadcfff4157761b6bf Mon Sep 17 00:00:00 2001 From: sunag Date: Thu, 20 Nov 2025 20:11:14 -0300 Subject: [PATCH 5/9] minor improvements --- examples/jsm/transpiler/AST.js | 18 ++++++++++++++++-- examples/jsm/transpiler/GLSLDecoder.js | 13 ++++++++----- examples/jsm/transpiler/TSLEncoder.js | 9 +++------ examples/jsm/transpiler/TranspilerUtils.js | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index aae711ec68e01f..393a91c1c31747 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -46,6 +46,20 @@ export class ASTNode { } + getProgram() { + + let current = this; + + while ( current.parent !== null ) { + + current = current.parent; + + } + + return current; + + } + getParent( parents = [] ) { if ( this.parent === null ) { @@ -109,12 +123,12 @@ export class Comment extends ASTNode { export class Program extends ASTNode { - constructor( body = [], userDefinedStructTypes = new Map() ) { + constructor( body = [] ) { super(); this.body = body; - this.userDefinedStructTypes = userDefinedStructTypes; + this.structTypes = new Map(); this.isProgram = true; diff --git a/examples/jsm/transpiler/GLSLDecoder.js b/examples/jsm/transpiler/GLSLDecoder.js index 13a40fe1a8a4a2..3055a465880c01 100644 --- a/examples/jsm/transpiler/GLSLDecoder.js +++ b/examples/jsm/transpiler/GLSLDecoder.js @@ -255,7 +255,7 @@ class GLSLDecoder { this.index = 0; this.tokenizer = null; this.keywords = []; - this.userDefinedStructTypes = new Map(); + this.structTypes = new Map(); this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' ); @@ -823,7 +823,7 @@ class GLSLDecoder { } const definition = new StructDefinition( structName, structMembers ); - this.userDefinedStructTypes.set( structName, definition ); + this.structTypes.set( structName, definition ); return definition; @@ -877,7 +877,8 @@ class GLSLDecoder { let initialization; const firstToken = initializationTokens[ 0 ]; - if ( firstToken && ( isBuiltinType( firstToken.str ) || this.userDefinedStructTypes.has( firstToken.str ) ) ) { + + if ( firstToken && ( isBuiltinType( firstToken.str ) || this.structTypes.has( firstToken.str ) ) ) { initialization = this.parseVariablesFromToken( initializationTokens ); @@ -1133,7 +1134,7 @@ class GLSLDecoder { statement = this.parseStructDefinition(); - } else if ( isBuiltinType( token.str ) || this.userDefinedStructTypes.has( token.str ) ) { + } else if ( isBuiltinType( token.str ) || this.structTypes.has( token.str ) ) { if ( this.getToken( 2 ).str === '(' ) { @@ -1213,7 +1214,9 @@ class GLSLDecoder { this.tokenizer = new Tokenizer( polyfill + source ).tokenize(); const body = this.parseBlock(); - const program = new Program( body, this.userDefinedStructTypes ); + + const program = new Program( body ); + program.structTypes = this.structTypes; return program; diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 3102275d0d9dc0..2c688ff3f082d6 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -56,7 +56,6 @@ class TSLEncoder { this.imports = new Set(); this.global = new Set(); this.overloadings = new Map(); - this.userDefinedStructTypes = new Map(); this.iife = false; this.reference = false; @@ -674,7 +673,7 @@ ${ this.tab }} )`; } else { - if ( this.userDefinedStructTypes.has( type ) ) { + if ( node.getProgram().structTypes.has( type ) ) { varStr += ` = ${ type }()`; @@ -721,7 +720,7 @@ ${ this.tab }} )`; this.addImport( 'struct' ); - let structString = `const ${ name } = struct({\n\n`; + let structString = `const ${ name } = struct( {\n`; for ( let i = 0; i < members.length; i += 1 ) { @@ -729,7 +728,7 @@ ${ this.tab }} )`; structString += `${this.tab}\t${member.name}: '${member.type}'`; - const delimiter = ( i != members.length - 1 ) ? ',\n' : '\n'; + const delimiter = ( i != members.length - 1 ) ? ',\n' : ''; structString += delimiter; } @@ -925,8 +924,6 @@ ${ this.tab }}`; } - this.userDefinedStructTypes = ast.userDefinedStructTypes; - for ( const statement of ast.body ) { code += this.emitExtraLine( statement, ast.body ); diff --git a/examples/jsm/transpiler/TranspilerUtils.js b/examples/jsm/transpiler/TranspilerUtils.js index 1774460838c918..880ce3e17085d8 100644 --- a/examples/jsm/transpiler/TranspilerUtils.js +++ b/examples/jsm/transpiler/TranspilerUtils.js @@ -1,6 +1,6 @@ export function isExpression( st ) { - return st.isFunctionDeclaration !== true && st.isFor !== true && st.isWhile !== true && st.isConditional !== true && st.isSwitch !== true; + return st.isFunctionDeclaration !== true && st.isFor !== true && st.isWhile !== true && st.isConditional !== true && st.isSwitch !== true && st.isStructDefinition !== true; } From b5edfcc7902d995a74450c6015043acc4e56522f Mon Sep 17 00:00:00 2001 From: sunag Date: Thu, 20 Nov 2025 20:17:46 -0300 Subject: [PATCH 6/9] cleanup --- examples/jsm/transpiler/TSLEncoder.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 2c688ff3f082d6..9f67d4f92f5b28 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -728,8 +728,11 @@ ${ this.tab }} )`; structString += `${this.tab}\t${member.name}: '${member.type}'`; - const delimiter = ( i != members.length - 1 ) ? ',\n' : ''; - structString += delimiter; + if ( i != members.length - 1 ) { + + structString += ',\n'; + + } } From f7a0046ece2dffc501a9ec589f717c7ad7d28f77 Mon Sep 17 00:00:00 2001 From: sunag Date: Thu, 20 Nov 2025 23:47:50 -0300 Subject: [PATCH 7/9] fix getProgram --- examples/jsm/transpiler/AST.js | 2 +- examples/jsm/transpiler/TSLEncoder.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index 393a91c1c31747..2ee61ffbd95359 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -56,7 +56,7 @@ export class ASTNode { } - return current; + return current && current.isProgram === true ? current : null; } diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 9f67d4f92f5b28..54fd43623f4b35 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -673,7 +673,9 @@ ${ this.tab }} )`; } else { - if ( node.getProgram().structTypes.has( type ) ) { + const program = node.getProgram(); + + if ( program && program.structTypes.has( type ) ) { varStr += ` = ${ type }()`; From d791fbda1139a90e971ad3519df5e8c0956b0442 Mon Sep 17 00:00:00 2001 From: sunag Date: Thu, 20 Nov 2025 23:50:12 -0300 Subject: [PATCH 8/9] fix AST node parents --- examples/jsm/transpiler/ShaderToyDecoder.js | 2 ++ examples/jsm/transpiler/TSLEncoder.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/jsm/transpiler/ShaderToyDecoder.js b/examples/jsm/transpiler/ShaderToyDecoder.js index f4fe871432e18c..ad0a04e70b0271 100644 --- a/examples/jsm/transpiler/ShaderToyDecoder.js +++ b/examples/jsm/transpiler/ShaderToyDecoder.js @@ -38,6 +38,8 @@ class ShaderToyDecoder extends GLSLDecoder { node.body.unshift( new VariableDeclaration( 'vec4', 'fragColor' ) ); node.body.push( new Return( fragColor ) ); + node.initialize(); + } return node; diff --git a/examples/jsm/transpiler/TSLEncoder.js b/examples/jsm/transpiler/TSLEncoder.js index 54fd43623f4b35..1039e9131036c5 100644 --- a/examples/jsm/transpiler/TSLEncoder.js +++ b/examples/jsm/transpiler/TSLEncoder.js @@ -675,7 +675,7 @@ ${ this.tab }} )`; const program = node.getProgram(); - if ( program && program.structTypes.has( type ) ) { + if ( program.structTypes.has( type ) ) { varStr += ` = ${ type }()`; From b4adb4911ebf1123750ea3fc935b4da4a84f772e Mon Sep 17 00:00:00 2001 From: sunag Date: Fri, 21 Nov 2025 00:03:11 -0300 Subject: [PATCH 9/9] Update AST.js --- examples/jsm/transpiler/AST.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/jsm/transpiler/AST.js b/examples/jsm/transpiler/AST.js index 2ee61ffbd95359..ac89ff5899a62a 100644 --- a/examples/jsm/transpiler/AST.js +++ b/examples/jsm/transpiler/AST.js @@ -56,7 +56,7 @@ export class ASTNode { } - return current && current.isProgram === true ? current : null; + return current.isProgram === true ? current : null; }