Skip to content

Instantly share code, notes, and snippets.

@mzgoddard
Last active November 5, 2017 17:55

Revisions

  1. mzgoddard revised this gist Nov 5, 2017. 1 changed file with 286 additions and 58 deletions.
    344 changes: 286 additions & 58 deletions babel-boxart-plugin-rudimentary.js
    Original 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 } = babel;
    const { types: t, traverse } = 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);
    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]));
    // }
    // },
    FunctionExpression(path) {},
    BinaryExpression(path) {
    // }
    },
    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("left").isNumberLiteral() &&
    path.get("right").isNumberLiteral() &&
    path.node.operator === "*"
    path.get("callee").isIdentifier() &&
    state[path.node.callee.name]
    ) {
    path.replaceWith(t.numberLiteral(path.node.left.value * path.node.right.value));
    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) => {
    });
    }
    },
    Identifier(path) {
    if (values[path.node.name]) {
    path.replaceWith(values[path.node.name]);
    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));
    }
    });
    }
    console.log(path.parentPath);
    }
    }
    };

    if (path.parentPath.isVariableDeclarator()) {
    path.node.name = "a";
    // values[path.node.name] = t.numberLiteral(2);
    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));
    }
    }
    // 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];
    });
    },
    };

    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: []};
    }
    },
    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);
    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();
    },
    }
    };
    }
  2. mzgoddard created this gist Oct 30, 2017.
    78 changes: 78 additions & 0 deletions babel-boxart-plugin-rudimentary.js
    Original 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);
    }
    }
    }
    }
    };
    }