Last active
November 5, 2017 17:55
Revisions
-
mzgoddard revised this gist
Nov 5, 2017 . 1 changed file with 286 additions and 58 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,78 +1,306 @@ // function gen() { // return (function(fn) { // const f = function(t, state, begin, end) { // var b = {b: 1}; // var c = {f2: function(t) {return t;}}; // state.left = c.f2(b.b, state, begin, end) * 2; // return state; // }; // return f; // })((function(fn) { // const f = function(t) {return fn(t * 2) * 2;}; // return f; // })((function(fn) { // const f = function(t) {return fn(t * 2) * 2;}; // return f; // })((function(fn) { // const f = function(t) {return fn(t * 2) * 2;}; // return f; // })((function(c) { // const f = function(t) {return t * c;}; // return f; // })(3))))); // } export default function(babel) { const { types: t, traverse } = babel; let values = {}; const memberLookup = (path, state) => { let stack = []; let node = path.node; while (t.isMemberExpression(node)) { if (node.computed) {return;} if (!t.isIdentifier(node.property)) {return;} stack.unshift(node.property.name); node = node.object; } if (!t.isIdentifier(node)) {return;} let value = state[node.name]; while (t.isObjectExpression(value) && stack.length > 0) { const name = stack.shift(); value = value.properties.find(prop => prop.key.name === name); if (value) { value = value.value; } } if (t.isLiteral(value) || t.isIdentifier(value) || t.isFunctionExpression(value)) { path.replaceWith(t.cloneDeep(value)); } }; const inlineFunctions = { FunctionExpression(path, state) {}, Identifier(path, state) { // if ( // !path.parentPath.isVariableDeclarator() || // path.parent.id !== path.node // ) { // if (t.isLiteral(state[path.node.name]) || t.isFunction(state[path.node.name])) { // path.replaceWith(t.cloneDeep(state[path.node.name])); // } // } }, VariableDeclarator: { enter(path, state) { path.scope.rename(path.node.id.name); }, exit(path, state) { if (path.get("init").isIdentifier() && state[path.node.id.name]) { path.get('init').replaceWith(t.cloneDeep(state[path.node.id.name])); } if (path.get("init").isFunctionExpression()) { state[path.node.id.name] = path.node.init; } if (path.get("init").isNumericLiteral()) { state[path.node.id.name] = path.node.init; } if (path.get("init").isObjectExpression()) { state[path.node.id.name] = path.node.init; } } }, CallExpression: { enter(path, state) { if (path.get("callee").isMemberExpression()) { memberLookup(path.get('callee'), state); // path.get("callee").replaceWith(t.cloneDeep(state[path.node.callee.name])); } if ( path.get("callee").isIdentifier() && state[path.node.callee.name] ) { path.get("callee").replaceWith(t.cloneDeep(state[path.node.callee.name])); } if (path.get("callee").isFunctionExpression()) { state = Object.assign({}, state, { __parentstate: state }); const args = path.node.arguments; const params = path.node.callee.params; params.forEach((p, i) => { }); } }, exit(path, state) { if (path.get("callee").isFunctionExpression()) { const args = path.node.arguments; const params = path.node.callee.params; params.forEach((p, i) => { path.get("callee").scope.rename(p.name); path .getStatementParent() .insertBefore( t.variableDeclaration( "const", [t.variableDeclarator(t.identifier(p.name), args[i])] ) ); if ( path.get(`arguments.${i}`).isIdentifier() && t.isFunctionExpression(state[args[i].name]) ) { state[p.name] = state[args[i].name]; } if (path.get(`arguments.${i}`).isLiteral()) { state[p.name] = args[i]; } }); } if (path.get("callee").isFunctionExpression()) { path.get("callee.body").node.body.forEach(expr => { if (t.isReturnStatement(expr)) { path.replaceWith(t.cloneDeep(expr.argument)); } else { path.getStatementParent().insertBefore(t.cloneDeep(expr)); } }); } } } }; const lookupAndOps = { VariableDeclarator: { exit(path, state) { if ( path.get('init').isLiteral() || path.get('init').isObjectExpression() ) { state[path.node.id.name] = path.node.init; } }, }, MemberExpression(path, state) { let stack = []; let node = path.node; while (t.isMemberExpression(node)) { if (node.computed) {return;} if (!t.isIdentifier(node.property)) {return;} stack.unshift(node.property.name); node = node.object; } // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${String(stack)}`))); if (!t.isIdentifier(node)) {return;} let value = state[node.name]; // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${JSON.stringify(node.name)}`))); // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${JSON.stringify(value)}`))); while (t.isObjectExpression(value) && stack.length > 0) { const name = stack.shift(); // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${name}`))); value = value.properties.find(prop => prop.key.name === name); if (value) { value = value.value; } } // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${stack.length} ${JSON.stringify(value)}`))); if (t.isLiteral(value)) { path.replaceWith(t.cloneDeep(value)); } }, Identifier(path, state) { if ( path.parent.id !== path.node ) { if (state[path.node.name]) { path.replaceWith(t.cloneDeep(state[path.node.name])); } } }, BinaryExpression: { exit(path, state) { // const e = path.evaluate(); // if (e.confident) { // } if ( path.get('left').isLiteral() && path.get('right').isLiteral() && path.node.operator === '*' ) { const e = path.evaluate(); if (e.confident && typeof e.value === 'number') { path.replaceWith(t.numericLiteral(e.value)); } } if ( path.get('left').isBinaryExpression() && path.node.left.operator === '*' && path.node.operator === '*' && path.get('left.right').isLiteral() && path.get('right').isLiteral() ) { path.replaceWith( t.binaryExpression( '*', path.node.left.left, t.binaryExpression('*', path.node.left.right, path.node.right) ) ); const e = path.get('right').evaluate(); if (e.confident && typeof e.value === 'number') { path.get('right').replaceWith(t.numericLiteral(e.value)); } } }, }, }; const refCount = { Identifier(path, state) { if (path.getStatementParent().parentPath.isProgram()) { return; } if (path.parent.id === path.node) { if (!(state[path.node.name] || {}).node) { // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(path.node.name))); state[path.node.name] = {node: path.node, refs: [], refsFrom: []}; } } if ( path.getStatementParent().isVariableDeclaration() && path.findParent(t.isVariableDeclarator).node.id.name !== path.node.name ) { const declId = path.findParent(t.isVariableDeclarator).node.id.name; const id = path.node.name; if ((state[id] || {}).node) { // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(String([declId, id])))); if (!(state[declId] || {}).node) { state[declId] = {node: path.parent.id, refs: [], refsFrom: []}; } state[declId].refs.push(id); if (!(state[id] || {}).node) { state[id] = {node: path.node, refs: [], refsFrom: []}; } state[id].refsFrom.push(declId); } } if (path.getStatementParent().isReturnStatement()) { const id = path.node.name; if (!(state[id] || {}).node) { state[id] = {node: path.node, refs: [], refsFrom: []}; } state[id].refsFrom.push('__return__'); } }, }; const deadCode = { Identifier(path, state) { if ( path.parent.id === path.node ) { // path.getStatementParent().insertBefore(t.expressionStatement(t.stringLiteral(`${path.node.name}: ${String((state[path.node.name] || {refsFrom: []}).refsFrom.length)}`))); } if ( path.parent.id === path.node && state[path.node.name] && state[path.node.name].refsFrom.length === 0 ) { if (!path.getStatementParent().parentPath.isProgram()) { path.getStatementParent().remove(); } } }, }; return { visitor: { Program(path) { path.traverse(inlineFunctions, {}); path.traverse(lookupAndOps, {}); let refs = {}; path.traverse(refCount, refs); let lastRefs = refs; let removed = Infinity; while (removed > 0) { removed = 0; refs = {}; path.traverse(deadCode, lastRefs); path.traverse(refCount, refs); if (Object.keys(refs).length < Object.keys(lastRefs).length) { removed = 1; } lastRefs = refs; } path.skip(); }, } }; } -
mzgoddard created this gist
Oct 30, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,78 @@ export default function(babel) { const { types: t } = babel; let values = {}; return { name: "ast-transform", // not required visitor: { Program() {}, VariableDeclarator: { enter(path) { path.scope.rename(path.node.id.name); }, exit(path) { // values[path.node.id.name] = path.node.init; // values[path.node.id.name] = t.numberLiteral(1); } }, // "VariableDeclarator|Identifier": { // enter(path) { // // path.name = 'a'; // }, // exit(path) { // // path.node.name = 'a'; // // values[path.node.name] = t.numberLiteral(1); // } // }, FunctionExpression(path) {}, BinaryExpression(path) { if ( path.get("left").isNumberLiteral() && path.get("right").isNumberLiteral() && path.node.operator === "*" ) { path.replaceWith(t.numberLiteral(path.node.left.value * path.node.right.value)); } }, Identifier(path) { if (values[path.node.name]) { path.replaceWith(values[path.node.name]); } console.log(path.parentPath); if (path.parentPath.isVariableDeclarator()) { path.node.name = "a"; // values[path.node.name] = t.numberLiteral(2); } // path.node.name = path.node.name.split('').reverse().join(''); }, CallExpression: { enter(path) { if (path.get("callee").isFunctionExpression()) { values = Object.assign({}, values, { __parentValues: values }); const args = path.node.arguments; const params = path.node.callee.params; params.forEach((p, i) => { path.scope.rename(p.name); values[p.name] = args[i]; }); } }, exit(path) { if (path.get("callee").isFunctionExpression()) { //values = values.__parentValues; path.get("callee.body").node.body.forEach(expr => { if (t.isReturnStatement(expr)) { path.replaceWith(expr.argument); } else { path.parentPath.insertBefore(expr); } }); // path.replaceWithMultiple(path.get('callee.body').node.body); } } } } }; }