export class WGSLReflection { constructor(wgslSource) { this.src = wgslSource; this.structs = {}; this.bindings = []; this.parseStructs(); this.parseBindings(); } // // ------------------------------------------------------------ // STRUCT PARSING // ------------------------------------------------------------ // parseStructs() { const structRegex = /struct\s+(\w+)\s*\{([^}]+)\}/g; let match; while ((match = structRegex.exec(this.src))) { const structName = match[1]; const body = match[2].trim(); const fields = this.parseStructFields(body); const size = fields.reduce((sum, f) => sum + f.size, 0); this.structs[structName] = { name: structName, fields, size }; } } parseStructFields(body) { const lines = body.split("\n"); const fields = []; for (let line of lines) { line = line.trim(); if (!line) continue; const m = line.match(/(\w+)\s*:\s*([^;]+);/); if (!m) continue; const fieldName = m[1]; const wgslType = m[2].trim(); const size = this.computeTypeSize(wgslType); fields.push({ fieldName, wgslType, size }); } return fields; } // // ------------------------------------------------------------ // BINDING PARSING // ------------------------------------------------------------ // parseBindings() { const varRegex = /@group\((\d+)\)\s*@binding\((\d+)\)\s*var<([^>]+)>\s+(\w+)\s*:\s*([^;]+);/g; let match; while ((match = varRegex.exec(this.src))) { const group = parseInt(match[1]); const binding = parseInt(match[2]); const type = match[3].trim(); const varName = match[4].trim(); const varType = match[5].trim(); const size = this.computeTypeSize(varType); this.bindings.push({ group, binding, type, varName, varType, size }); } } // // ------------------------------------------------------------ // TYPE SIZE COMPUTATION (Simplified) // ------------------------------------------------------------ // computeTypeSize(wgslType) { // scalar if (wgslType === "f32" || wgslType === "u32" || wgslType === "i32") { return 4; } // array const arrMatch = wgslType.match(/array<(\w+),\s*(\d+)>/); if (arrMatch) { const elementType = arrMatch[1]; const count = parseInt(arrMatch[2]); return this.computeTypeSize(elementType) * count; } // array runtime-sized → minimal const runtimeArr = wgslType.match(/array<(\w+)>/); if (runtimeArr) { return 4; } // struct if (this.structs[wgslType]) { return this.structs[wgslType].size; } return 4; } // // ------------------------------------------------------------ // SUMMARY OUTPUT // ------------------------------------------------------------ // reflect() { return { structs: this.structs, bindings: this.bindings }; } }