Created
October 12, 2017 11:40
-
-
Save erukiti/a9527ab25fb828d2fe72a3dfda0b3cef to your computer and use it in GitHub Desktop.
最適化プラグイン
This file contains 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 characters
const {transform} = require('babel-core') | |
const babylon = require('babylon') | |
const WasCreated = Symbol('WasCreated') | |
const source = ` | |
let b = 0 | |
console.log(b) | |
b = b + 2 | |
console.log(b) | |
b += 3 | |
console.log(b) | |
` | |
const optimizePlugin = ({types: t}) => { | |
const valueToLiteral = value => { | |
let node | |
switch (typeof value) { | |
case 'string': { | |
node = t.stringLiteral(value) | |
node[WasCreated] = true | |
return node | |
} | |
case 'number': { | |
node = t.numericLiteral(value) | |
node[WasCreated] = true | |
return node | |
} | |
case 'boolean': { | |
node = t.booleanLiteral(value) | |
node[WasCreated] = true | |
return node | |
} | |
} | |
} | |
const evaluateVisitor = { | |
exit: (nodePath) => { | |
if (nodePath.node[WasCreated]) { | |
nodePath.node[WasCreated] = false | |
return | |
} | |
nodePath.scope.crawl() | |
const {confident, value} = nodePath.evaluate() | |
if (confident) { | |
nodePath.replaceWith(valueToLiteral(value)) | |
} | |
}, | |
ReferencedIdentifier: (nodePath) => { | |
nodePath.scope.crawl() | |
const {name} = nodePath.node | |
if (name in nodePath.scope.bindings) { | |
const binding = nodePath.scope.bindings[name] | |
const statement = nodePath.getStatementParent() | |
const violations = statement.getAllPrevSiblings().filter(p => { | |
return binding.constantViolations.filter(v => v.node.start === p.node.start).length > 0 | |
}) | |
if (violations.length === 0) { | |
const {confident, value} = binding.path.get('init').evaluate() | |
nodePath.replaceWith(valueToLiteral(value)) | |
return | |
} | |
// console.log('!', violations.getSource()) | |
} | |
}, | |
AssignmentExpression: { | |
exit: (nodePath) => { | |
nodePath.scope.crawl() | |
if (nodePath.get('left').isIdentifier()) { | |
const {name} = nodePath.node.left | |
if (name in nodePath.scope.bindings) { | |
const binding = nodePath.scope.bindings[name] | |
const statement = nodePath.getStatementParent() | |
const refs = statement.getAllPrevSiblings().filter(p => { | |
return binding.referencePaths.filter(r => r.node.start === p.node.start).length > 0 | |
}) | |
if (refs.length === 0) { | |
const {operator, right} = nodePath.node | |
if (operator === '=') { | |
binding.path.get('init').replaceWith(right) | |
} else { | |
const left = binding.path.node.init | |
const init = t.binaryExpression(operator.substr(0, 1), left, right) | |
binding.path.get('init').replaceWith(init) | |
} | |
nodePath.remove() | |
} | |
} | |
} | |
} | |
}, | |
} | |
return { | |
visitor: { | |
Program: (nodePath) => { | |
nodePath.traverse(evaluateVisitor) | |
}, | |
VariableDeclarator: (nodePath) => { | |
nodePath.scope.crawl() | |
if (nodePath.get('id').isIdentifier()) { | |
const {name} = nodePath.node.id | |
if (name in nodePath.scope.bindings) { | |
const binding = nodePath.scope.bindings[name] | |
nodePath.remove() | |
} | |
} | |
} | |
} | |
} | |
} | |
console.log(transform(source, {plugins: [optimizePlugin]}).code) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment