From 813e3a322bb75d471bb78663b24f561aa48eaad9 Mon Sep 17 00:00:00 2001 From: axion014 Date: Wed, 12 Jun 2019 09:08:10 +0900 Subject: [PATCH 1/4] recognize commutative * --- index.js | 30 +++++++++++++++++++++++++ tap-snapshots/test-basic.js-TAP.test.js | 7 ++++-- test/commutative-operators.glsl | 4 ++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 9711418..daf9051 100644 --- a/index.js +++ b/index.js @@ -15,6 +15,7 @@ function minifier(safe_words, mutate_storages) { var _ = {} , seen_names = {} + , variable_type = new Map() , counter for(var i = 0, len = safe_words.length; i < len; ++i) @@ -51,6 +52,12 @@ function minifier(safe_words, mutate_storages) { } } + if(is_variable(node)) { + var scope = variable_type.get(node.scope) || {} + scope[node.data] = node.parent.parent.token.data + variable_type.set(node.scope, scope) + } + // 1.0 => 1. // 0.1 => .1 // 0.0 => .0 if(node.type === 'literal') { if(/0\.\d/.test(node.data)) node.data = node.data.replace(/^0\./, '.') @@ -60,6 +67,20 @@ function minifier(safe_words, mutate_storages) { this.emit('data', node) } + function get_type(node) { + if (node.type === 'ident') return variable_type.get(node.scope)[node.data] || 'unidentified' + if (node.type === 'literal') { + if (node.data === 'true' || node.data === 'false') return 'bool' + if (node.data.includes('.')) return 'float' + return 'int' + } + if (node.type === 'call') { + if (/^int|float|bool|[ib]?vec[234]|mat[234]$/.test(node.children[0].data)) return node.children[0].data + return 'unidentified' + } + return 'unidentified' + } + function should_mutate(node) { var base = ( is_variable(node) || @@ -72,12 +93,21 @@ function minifier(safe_words, mutate_storages) { } function is_unnecessary_group(node) { + function is_commutative_multiply(node) { + if(node.data !== '*') return false + var type_a = get_type(node.children[0]) + , type_b = get_type(node.children[1]) + if(/^unidentified|mat[234]$/.test(type_a) && /^unidentified|[ib]?vec[234]|mat[234]$/.test(type_b)) return false + if(/^[ib]?vec[234]$/.test(type_a) && /^unidentified|mat[234]$/.test(type_b)) return false + return true + } if(node.type !== 'group') return false if(node.children[0].lbp > node.parent.lbp) return true if(node.children[0].lbp === node.parent.lbp) { for(var i = 0; i < commutative_operators.length; i++) { if(node.parent.data === commutative_operators[i] && node.children[0].data === commutative_operators[i]) return true } + if(is_commutative_multiply(node.parent) && is_commutative_multiply(node.children[0])) 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 3272e44..2117a4d 100644 --- a/tap-snapshots/test-basic.js-TAP.test.js +++ b/tap-snapshots/test-basic.js-TAP.test.js @@ -740,8 +740,11 @@ exports[`test/basic.js TAP grouping removal test > output 1`] = ` float a = 2e10 + .2e2 + 1.e3 * (0xFaBc09 + 3); float b = 2e10 + (.2e2 - 1.e3 / (0xFaBc09 + 3)); -bool c = 1. && true && true; -bool d = 0. || false || true; +float c = 1 * 2 * 3; +mat3 d = mat3(1, 2, 3, 4, 5, 6, 7, 8, 9); +mat3 e = 2 * (vec3(1, 2, 3) * d); +bool f = 1. && true && true; +bool g = 0. || false || true; ` exports[`test/basic.js TAP vec shorthand > output 1`] = ` diff --git a/test/commutative-operators.glsl b/test/commutative-operators.glsl index e48b55a..0868fe0 100644 --- a/test/commutative-operators.glsl +++ b/test/commutative-operators.glsl @@ -1,5 +1,9 @@ float x = 2e10 + (.2e2 + (1.e3 * (0xFaBc09 + 3))); float y = 2e10 + (.2e2 - (1.e3 / (0xFaBc09 + 3))); +float z = 1 * (2 * 3); + +mat3 m = mat3(1, 2, 3, 4, 5, 6, 7, 8, 9); +mat3 n = 2 * (vec3(1, 2, 3) * m); bool a = 1. && (true && true); From dabe6239b5df8b035fb0b641b8ae4c5afdc2e0fe Mon Sep 17 00:00:00 2001 From: axion014 Date: Wed, 12 Jun 2019 09:37:40 +0900 Subject: [PATCH 2/4] evaluate return type of expressions --- index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/index.js b/index.js index daf9051..fa5745c 100644 --- a/index.js +++ b/index.js @@ -78,6 +78,11 @@ function minifier(safe_words, mutate_storages) { if (/^int|float|bool|[ib]?vec[234]|mat[234]$/.test(node.children[0].data)) return node.children[0].data return 'unidentified' } + if (node.type === 'binary') { + if (node.data === '==' || node.data === '&&' || node.data === '||' || node.data === '^^') return 'bool' + if (node.data === '+' || node.data === '-' || node.data === '/') return get_type(node.children[0]) + } + if (node.type === 'unary' || node.type === 'group' || node.type === 'suffix') return get_type(node.children[0]) return 'unidentified' } From 187258e364d5f02b4c23a84f37ffdb69704819cf Mon Sep 17 00:00:00 2001 From: axion014 Date: Wed, 12 Jun 2019 09:58:19 +0900 Subject: [PATCH 3/4] evaluate return type of function calls --- index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index fa5745c..9274ea5 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ function minifier(safe_words, mutate_storages) { var _ = {} , seen_names = {} , variable_type = new Map() + , function_type = {} , counter for(var i = 0, len = safe_words.length; i < len; ++i) @@ -58,6 +59,8 @@ function minifier(safe_words, mutate_storages) { variable_type.set(node.scope, scope) } + if(is_function(node)) function_type[node.data] = node.parent.parent.token.data + // 1.0 => 1. // 0.1 => .1 // 0.0 => .0 if(node.type === 'literal') { if(/0\.\d/.test(node.data)) node.data = node.data.replace(/^0\./, '.') @@ -76,7 +79,7 @@ function minifier(safe_words, mutate_storages) { } if (node.type === 'call') { if (/^int|float|bool|[ib]?vec[234]|mat[234]$/.test(node.children[0].data)) return node.children[0].data - return 'unidentified' + return function_type[node.children[0].data] || 'unidentified' } if (node.type === 'binary') { if (node.data === '==' || node.data === '&&' || node.data === '||' || node.data === '^^') return 'bool' From 908bceb7b60396e6cdf49405d4b8b86ab59f869a Mon Sep 17 00:00:00 2001 From: axion014 Date: Wed, 12 Jun 2019 10:06:15 +0900 Subject: [PATCH 4/4] add test for new code --- tap-snapshots/test-basic.js-TAP.test.js | 9 +++++++-- test/commutative-operators.glsl | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tap-snapshots/test-basic.js-TAP.test.js b/tap-snapshots/test-basic.js-TAP.test.js index 2117a4d..f4942f0 100644 --- a/tap-snapshots/test-basic.js-TAP.test.js +++ b/tap-snapshots/test-basic.js-TAP.test.js @@ -743,8 +743,13 @@ float b = 2e10 + (.2e2 - 1.e3 / (0xFaBc09 + 3)); float c = 1 * 2 * 3; mat3 d = mat3(1, 2, 3, 4, 5, 6, 7, 8, 9); mat3 e = 2 * (vec3(1, 2, 3) * d); -bool f = 1. && true && true; -bool g = 0. || false || true; +vec2 f() { + return vec2(1); +} +vec2 g = (2 + 3) * vec2(2) * f(); +vec2 h = (2 + 3) * (d * vec2(2)); +bool i = 1. && true && true; +bool j = 0. || false || true; ` exports[`test/basic.js TAP vec shorthand > output 1`] = ` diff --git a/test/commutative-operators.glsl b/test/commutative-operators.glsl index 0868fe0..c88f04e 100644 --- a/test/commutative-operators.glsl +++ b/test/commutative-operators.glsl @@ -5,6 +5,13 @@ float z = 1 * (2 * 3); mat3 m = mat3(1, 2, 3, 4, 5, 6, 7, 8, 9); mat3 n = 2 * (vec3(1, 2, 3) * m); +vec2 f() { + return vec2(1, 1); +} + +vec2 v = (2 + 3) * (vec2(2, 2) * f()); +vec2 w = (2 + 3) * (m * vec2(2, 2)); + bool a = 1. && (true && true); bool b = 0. || (false || true);