diff --git a/index.js b/index.js index f3dcc49..af49ca8 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,10 @@ function minifier(safe_words, mutate_storages) { return through(mutate) function mutate(node) { + // vec2(1.0, 1.0) => vec2(1.0) + if(node.parent && is_redundant_vector_literal(node.parent) && node.parent.children.indexOf(node) > 1) return + if(is_redundant_vector_literal(node)) node.children = node.children.slice(0, 2) + if(should_mutate(node)) { var t = node.parent.parent.children[1] if(mutate_storages || (t.type === 'placeholder' || t.token.data === 'const')) { @@ -51,4 +55,14 @@ function minifier(safe_words, mutate_storages) { return base && !safe_words.hasOwnProperty(node.token.data) } + + function is_redundant_vector_literal(node) { + if(node.type === 'call' && /^[ib]?vec[234]$/.test(node.children[0].data) && + (node.children[1].type === 'literal' || node.children[1].type === 'ident')) { + var first = node.children[1].data + for(var i = 2; i < node.children.length; i++) if(node.children[i].data !== first) return false + return true + } + return false + } } diff --git a/tap-snapshots/test-basic.js-TAP.test.js b/tap-snapshots/test-basic.js-TAP.test.js index 052251b..709c5bc 100644 --- a/tap-snapshots/test-basic.js-TAP.test.js +++ b/tap-snapshots/test-basic.js-TAP.test.js @@ -143,7 +143,7 @@ void N() { i[0] = i[1] = i[2] = i[3] = s; i[4] = X * s; i[5] = W * s; - k[0] = vec3(0, 0, 0); + k[0] = vec3(0); k[1] = S * (1. + X / W); k[2] = T * (1. + W / X); j[0][0] = normalize(S - V); @@ -197,7 +197,7 @@ void main(void) { float bb = cos(Z); mat3 bc = mat3(vec3(bb, 0, ba), vec3(0, 1, 0), vec3(-ba, 0, bb)); vec3 bd = vec3(0, 1, 0); - vec3 be = vec3(0, 0, 0); + vec3 be = vec3(0); float bf = .0; float bg = .5 * c / 2.01; vec3 bh = bc * vec3(cos(bg), sin(bg), .0) * 2.; @@ -383,7 +383,7 @@ void M() { h[0] = h[1] = h[2] = h[3] = r; h[4] = W * r; h[5] = V * r; - j[0] = vec3(0, 0, 0); + j[0] = vec3(0); j[1] = R * (1. + W / V); j[2] = S * (1. + V / W); i[0][0] = normalize(R - U); @@ -437,7 +437,7 @@ void main(void) { float ba = cos(Y); mat3 bb = mat3(vec3(ba, 0, Z), vec3(0, 1, 0), vec3(-Z, 0, ba)); vec3 bc = vec3(0, 1, 0); - vec3 bd = vec3(0, 0, 0); + vec3 bd = vec3(0); float be = .0; float bf = .5 * PI / 2.01; vec3 bg = bb * vec3(cos(bf), sin(bf), .0) * 2.; @@ -623,7 +623,7 @@ void R() { m[0] = m[1] = m[2] = m[3] = w; m[4] = bb * w; m[5] = ba * w; - o[0] = vec3(0, 0, 0); + o[0] = vec3(0); o[1] = W * (1. + bb / ba); o[2] = X * (1. + ba / bb); n[0][0] = normalize(W - Z); @@ -677,7 +677,7 @@ void main(void) { float bf = cos(bd); mat3 bg = mat3(vec3(bf, 0, be), vec3(0, 1, 0), vec3(-be, 0, bf)); vec3 bh = vec3(0, 1, 0); - vec3 bi = vec3(0, 0, 0); + vec3 bi = vec3(0); float bj = .0; float bk = .5 * g / 2.01; vec3 bl = bg * vec3(cos(bk), sin(bk), .0) * 2.; @@ -735,3 +735,26 @@ float e = 1.; float f = .1; float g = .01; ` + +exports[`test/basic.js TAP vec shorthand > output 1`] = ` + +vec2 vec2Long = vec2(.0, 1.); +vec2 vec2Short = vec2(.0); +bvec2 bvec2Long = bvec2(.0, 1.); +bvec2 bvec2Short = bvec2(.0); +ivec2 ivec2Long = ivec2(.0, 1.); +ivec2 ivec2Short = ivec2(.0); +vec3 vec3Long = vec3(.0, 1., 1.); +vec3 vec3Short = vec3(.0); +bvec3 bvec3Long = bvec3(.0, 1., 1., 1.); +bvec3 bvec3Short = bvec3(.0); +ivec3 ivec3Long = ivec3(.0, 1., 1., 1.); +ivec3 ivec3Short = ivec3(.0); +vec4 vec4Long = vec4(.0, 1., 1., 1.); +vec4 vec4Short = vec4(.0); +bvec4 bvec4Long = bvec4(.0, 1., 1., 1.); +bvec4 bvec4Short = bvec4(.0); +ivec4 ivec4Long = ivec4(.0, 1., 1., 1.); +ivec4 ivec4Short = ivec4(.0); +ivec4 a = ivec4(vec2(.0, 1.), vec2(.0, 1.)); +` diff --git a/test/basic.js b/test/basic.js index 24b3652..4888efc 100644 --- a/test/basic.js +++ b/test/basic.js @@ -10,6 +10,7 @@ const through = require("through"); const zeroGLSL = path.resolve(__dirname, "./zero-decimals.glsl"); const workingGLSL = path.resolve(__dirname, "./working.glsl"); +const vecGLSL = path.resolve(__dirname, "./vec-shorthand.glsl"); tap.test("basic", t => { let output = ""; @@ -71,7 +72,6 @@ tap.test("basic storage mutation", t => { .pipe(endStream); }); - tap.test("decimals starting or ending with 0", t => { let output = ""; @@ -89,3 +89,51 @@ tap.test("decimals starting or ending with 0", t => { .pipe(deparser()) .pipe(endStream); }); + +tap.test("vec shorthand", t => { + const types = ["", "b", "i"] + .map(prefix => [2,3,4].map(size => `${prefix}vec${size}`)) + .reduce((a, b) => a.concat(b)); + + const variableNames = types + .map(type => ["Short", "Long"].map(suffix => `${type}${suffix}`)) + .reduce((a, b) => a.concat(b)); + + const safewords = [ + "main", + ...variableNames, + ]; + + let output = ""; + + const endStream = through((data) => { + output += data; + }, () => { + t.matchSnapshot(output, "output"); + + t.ok( + variableNames + .filter(name => name.endsWith("Long")) + .every(name => output.includes(`${name} = ${name.replace("Long", "")}(.0, 1.`)), + "does not retain differing scalars" + ); + + t.ok( + variableNames + .filter(name => name.endsWith("Short")) + .every(name => output.includes(`${name} = ${name.replace("Short", "")}(.0)`)), + "does not shorten identical scalars" + ); + + t.ok(output.includes("ivec4(vec2(.0, 1.), vec2(.0, 1.))"), "does not preserve vectors in initalizer"); + + t.end(); + }); + + fs.createReadStream(vecGLSL) + .pipe(tokenizer()) + .pipe(parser()) + .pipe(minify(safewords)) + .pipe(deparser()) + .pipe(endStream); +}); diff --git a/test/vec-shorthand.glsl b/test/vec-shorthand.glsl new file mode 100644 index 0000000..b6d50f9 --- /dev/null +++ b/test/vec-shorthand.glsl @@ -0,0 +1,28 @@ +vec2 vec2Long = vec2(0.0, 1.0); +vec2 vec2Short = vec2(0.0, 0.0); + +bvec2 bvec2Long = bvec2(0.0, 1.0); +bvec2 bvec2Short = bvec2(0.0, 0.0); + +ivec2 ivec2Long = ivec2(0.0, 1.0); +ivec2 ivec2Short = ivec2(0.0, 0.0); + +vec3 vec3Long = vec3(0.0, 1.0, 1.0); +vec3 vec3Short = vec3(0.0, 0.0, 0.0); + +bvec3 bvec3Long = bvec3(0.0, 1.0, 1.0, 1.0); +bvec3 bvec3Short = bvec3(0.0, 0.0, 0.0); + +ivec3 ivec3Long = ivec3(0.0, 1.0, 1.0, 1.0); +ivec3 ivec3Short = ivec3(0.0, 0.0, 0.0); + +vec4 vec4Long = vec4(0.0, 1.0, 1.0, 1.0); +vec4 vec4Short = vec4(0.0, 0.0, 0.0, 0.0); + +bvec4 bvec4Long = bvec4(0.0, 1.0, 1.0, 1.0); +bvec4 bvec4Short = bvec4(0.0, 0.0, 0.0, 0.0); + +ivec4 ivec4Long = ivec4(0.0, 1.0, 1.0, 1.0); +ivec4 ivec4Short = ivec4(0.0, 0.0, 0.0, 0.0); + +ivec4 ivec4Mix = ivec4(vec2(0.0, 1.0), vec2(0.0, 1.0));