コード例 #1
0
function fixSuperclass(def) {
    
    var ctorVarName = def.getCtorVarName();
    var target = def.returnStatements.length ? def.returnStatements[def.returnStatements.length - 1] : null;

    // console.log('def.superclass: ', ctorVarName, 'TARGET: ', target);

    if (ctorVarName && target) {
        var inheritStatement = {
            "type": "ExpressionStatement",
            "expression": {
                "type": "CallExpression",
                "callee": {
                    "type": "MemberExpression",
                    "computed": false,
                    "object": {
                        "type": "CallExpression",
                        "callee": {
                            "type": "Identifier",
                            "name": "require"
                        },
                        "arguments": [
                            {
                                "type": "Literal",
                                "value": "raptor-util",
                                "raw": "'raptor-util'"
                            }
                        ]
                    },
                    "property": {
                        "type": "Identifier",
                        "name": "inherit"
                    }
                },
                "arguments": [
                    {
                        "type": "Identifier",
                        "name": ctorVarName
                    }
                ]
            }
        };

        if (def.superclass.type === 'Literal') {
            inheritStatement.expression.arguments.push({
                    "type": "CallExpression",
                    "callee": {
                        "type": "Identifier",
                        "name": "require"
                    },
                    "arguments": [
                        def.superclass
                    ]
                });
        }
        else {
            inheritStatement.expression.arguments.push(def.superclass);
        }

        insertBefore(target.node, target.parent, [inheritStatement]);

        // Walk the tree again to fix all references to the superclass
        estraverse.replace(target.parent, {
            enter: function(node, parent) {
                
            },

            leave: function(node, parent) {
                var finalParts = [];
                var modified = false;

                if (node.type === 'ExpressionStatement' &&
                    node.expression.type === 'CallExpression') {

                    var callee = node.expression.callee;
                    
                    

                    if (callee.type === 'MemberExpression' &&
                        callee.object.type === 'MemberExpression') {
                        var idParts = idNodeToArray(callee);

                        // console.log("*****", idParts);
                        if (idParts && idParts.length) {
                            if (idParts[0] === ctorVarName) {
                                var i=0;

                                while (i<idParts.length) {
                                    var cur = idParts[i];
                                    var next = i+1<idParts.length ? idParts[i+1] : undefined;
                                    if (cur === 'superclass' && next) {
                                        if (next === 'constructor') {
                                            i++; // Skip past 'superclass'
                                            i++; // Skip past 'constructor'
                                            finalParts.push('$super');
                                            modified = true;
                                            continue;
                                        }
                                        else if (next !== 'call' && next !== 'apply') {
                                            i++; // Skip past 'superclass'
                                            i++; // Skip past 'constructor'
                                            finalParts.push('$super');
                                            finalParts.push('prototype');
                                            finalParts.push(next);
                                            modified = true;
                                            continue;
                                        }
                                    }
                                    else {
                                        finalParts.push(cur);
                                    }

                                    i++;
                                    continue;
                                    
                                }
                            }
                        }
                    }

                    if (modified) {
                        node.expression.callee = idArrayToNode(finalParts);
                    }
                    
                }
                
            }
        });
    }
}
コード例 #2
0
function transformAST(ast) {
    var defs = [];
    var defStack = [];
    var def;

    function checkNode(node, parent) {
        var curDef;

        if ((curDef = parseDefineNode(node))) {
            def = curDef;
            def.node = node;

            def.parent = parent;
            defs.push(def);
            defStack.push(def);
        }
        else if (def && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration') && node !== def.factoryFunctionNode) {
            def.curLevel++;
        }

        checkModuleLogger(def, node, parent);
        

        if (def) {
            if (node.type === 'FunctionDeclaration') {
                def.scope[node.id.name] = node;
            }
            else if (node.type === 'VariableDeclarator') {
                def.scope[node.id.name] = node.init;
            }
        }
    }

    ast = estraverse.replace(ast, {
        enter: function(node, parent) {
            checkNode(node, parent);
        },

        leave: function(node, parent) {
            if (def && def.node === node) {
                defStack.pop();
                def = defStack.length ? defStack[defStack.length-1] : null;
            }
            else if (def && node.type === 'ReturnStatement') {
                if (def.curLevel === 0) {
                    if (node.argument && node.argument.type === 'Identifier') {
                        def.exportsVarName = node.argument.name;
                    }

                    def.returnStatements.push({
                        node: node,
                        parent: parent
                    });


                }
            }
            else if (def && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration')) {
                def.curLevel--;
            }

            
        }
    });

    // Transform found define nodes
    defs.forEach(transformDef);

    // Fix top-level "use strict" (if found)
    fixUseStrict(ast);

    return ast;
}
コード例 #3
0
module.exports = function (code) {
    let ast = esprima.parse(code);
    let attrs = Object.create(null);
    let identifiers = [];
    estraverse.traverse(ast, {
        enter: node => {
            if (node.type == estraverse.Syntax.Identifier) {
                if (identifiers.indexOf(node.name) == -1) {
                    identifiers.push(node.name);
                }
            }
            if (node.type !== estraverse.Syntax.MemberExpression || node.computed) {
                return;
            }
            let name = node.property.name;
            let existing = attrs[name];
            if (!existing) {
                attrs[name] = [];
            }
            attrs[name].push(node);
        }
    });

    // filter out the attributes that are beneficial for compression
    let vars = [];
    Object.keys(attrs).forEach(key => {
        let occurrences = attrs[key];
        let count = occurrences.length;
        // We only get smaller code if length * (count - 1) > (2*count + 5) :
        // .attr -> [x]  // -c*(l-2) = 2c-lc
        // (function (,x) {}(,"attr")  // +5+l
        // 2c-lc + 5+l < 0 <=> l(c-1) > 2c+5
        if (key.length * (count - 1) > (2 * count + 5)) {
            let varName = util.getFreeLetter(identifiers);
            occurrences.forEach(node => {
                node.computed = true;
                node.property.name = varName;
            });
            identifiers.push(varName);
            vars.push({
                name: varName,
                value: `'${key}'`
            });
        }
    });

    // move first variable statement to attributes (this only works with string values ATM)
    let target;
    let varDecl = [];
    estraverse.traverse(ast, {
        enter: node => {
            if (target) {
                return;
            }
            if (node.type === estraverse.Syntax.VariableDeclarator) {
                let value;
                if (node.init) {
                    value = node.init.name || node.init.raw;
                }
                varDecl.push({name: node.id.name, value: value});
            }
        },
        leave: node => {
            if (node.type === estraverse.Syntax.VariableDeclaration) {
                target = node;
            }
        }
    });
    estraverse.replace(ast, {
        enter: node => {
            if (node === target) {
                return estraverse.VisitorOption.Remove;
            }
        }
    });

    vars = vars.concat(varDecl);
    vars.sort((a, b) => {
        if (typeof a.value == 'undefined') {
            return typeof b.value == 'undefined' ? 0 : 1;
        }
        if (typeof b.value == 'undefined') {
            return -1;
        }
        return a.value === b.value ? 0 : a.value < b.value ? -1 : 1;
    });
    let f = escodegen.generate(ast, {
        format: {
            compact: true,
            quotes: 'double',
            semicolons: false
        }
    });
    let names = vars.map(v => v.name);
    let strings = vars.map(x => x.value).filter(x => x);
    return `(function (${names.join(', ')}) {${f}})(${strings.join(', ')});`;
};
コード例 #4
0
ファイル: static.js プロジェクト: LSnyd/SoverS
function buildFunction(type, functionName, gen, scope) {
    var code = gen.toString(functionName)
        .replace(/((?!\.)types\[\d+])(\.values)/g, "$1"); // enums: use types[N] instead of reflected types[N].values

    var ast = espree.parse(code);
    /* eslint-disable no-extra-parens */
    estraverse.replace(ast, {
        enter: function(node, parent) {
            // rename vars
            if (
                node.type === "Identifier" && renameVars[node.name]
                && (
                    (parent.type === "MemberExpression" && parent.object === node)
                 || (parent.type === "BinaryExpression" && parent.right === node)
                )
            )
                return {
                    "type": "Identifier",
                    "name": renameVars[node.name]
                };
            // replace this.ctor with the actual ctor
            if (
                node.type === "MemberExpression"
             && node.object.type === "ThisExpression"
             && node.property.type === "Identifier" && node.property.name === "ctor"
            )
                return {
                    "type": "Identifier",
                    "name": "$root" + type.fullName
                };
            // replace types[N] with the field's actual type
            if (
                node.type === "MemberExpression"
             && node.object.type === "Identifier" && node.object.name === "types"
             && node.property.type === "Literal"
            )
                return {
                    "type": "Identifier",
                    "name": "$root" + type.fieldsArray[node.property.value].resolvedType.fullName
                };
            return undefined;
        }
    });
    /* eslint-enable no-extra-parens */
    code = escodegen.generate(ast, {
        format: {
            newline: "\n",
            quotes: "double"
        }
    });

    if (config.beautify)
        code = beautifyCode(code);

    code = code.replace(/ {4}/g, "\t");

    var hasScope = scope && Object.keys(scope).length,
        isCtor = functionName === type.name;

    if (hasScope) // remove unused scope vars
        Object.keys(scope).forEach(function(key) {
            if (!new RegExp("\\b(" + key + ")\\b", "g").test(code))
                delete scope[key];
        });

    var lines = code.split(/\n/g);
    if (isCtor) // constructor
        push(lines[0]);
    else if (hasScope) // enclose in an iife
        push(escapeName(type.name) + "." + escapeName(functionName) + " = (function(" + Object.keys(scope).map(escapeName).join(", ") + ") { return " + lines[0]);
    else
        push(escapeName(type.name) + "." + escapeName(functionName) + " = " + lines[0]);
    lines.slice(1, lines.length - 1).forEach(function(line) {
        var prev = indent;
        var i = 0;
        while (line.charAt(i++) === "\t")
            ++indent;
        push(line.trim());
        indent = prev;
    });
    if (isCtor)
        push("}");
    else if (hasScope)
        push("};})(" + Object.keys(scope).map(function(key) { return scope[key]; }).join(", ") + ");");
    else
        push("};");
}
コード例 #5
0
ファイル: transform.js プロジェクト: darkoverlordofdata/dish
function code(packge, moduleName, ast) {

    const esprima = require('esprima')
    const escodegen = require('escodegen')
    const estraverse = require('estraverse')
    const factory = require('./asmfactory')
    const meta = require('../dish.json')

    /** get the phase I scanned meta data */
    const symtbl = meta[packge][moduleName].symtbl
    const fields = meta[packge][moduleName].data

    const mem = {   /** memory parameters */
        byte:   {size: 0, width: 1, heap: 'HEAPU8'},
        char:   {size: 1, width: 2, heap: 'HEAPI16'},
        bool:   {size: 2, width: 4, heap: 'HEAPI32'},
        int:    {size: 2, width: 4, heap: 'HEAPI32'},
        uint:   {size: 2, width: 4, heap: 'HEAPU32'},
        object: {size: 2, width: 4, heap: 'HEAPI32'},
        float:  {size: 2, width: 4, heap: 'HEAPF32'},
        double: {size: 3, width: 8, heap: 'HEAPF64'}
    }

    /**
     * Transform Code
     */
    const body = ast.body
    const lines = []

    /**
     * Do the MemberExpression thunks
     * 
     * 0 - ExpressionStatement  'use asm'
     * 1 - VariableDeclaration  - imports
     * i - FunctionDeclaration  - functions
     * n - ReturnStatement      - exports
     */
    for (let each in body) {
        if (body[each].type === 'FunctionDeclaration') {
            const func = body[each]

            for (let k = func.params.length; k<func.body.body.length; k++) {
                estraverse.replace(func.body.body[k], {
                    enter: function(node, parent) {

                        if (node.type === 'CallExpression' 
                            && node.callee.type === 'MemberExpression' &&  !node.callee.computed) {
                            /**
                             *  self.hasComponent(...) 
                             *      => 
                             *  Klass_hasComponent(...)
                             */

                            const object = symtbl[func.id.name][node.callee.object.name]
                            const name = object.type === moduleName
                                        ? node.callee.property.name
                                        : object.type+'_'+node.callee.property.name
                            node.arguments.unshift({ type: 'Identifier', name: object.name })

                            return factory.ObjectMethod(name, node.arguments)
                            
                        }

                        if (node.type === 'MemberExpression' && !node.computed
                            && parent.type !== 'MemberExpression') {
                            /**
                             *  self.x 
                             *      => 
                             *  HEAP[self+x>>size]
                             */
                            const object = symtbl[func.id.name][node.object.name]
                            const member = getField(node.property.name, meta[packge][object.type].data)
                            if (member) {
                                const heap = mem[member.type].heap
                                const size = mem[member.type].size
                                const offset = member.offset
                                
                                return factory.ObjectMember(node.object.name, offset, heap, size)
                            }                        
                        }

                        if (node.type === 'MemberExpression' && node.computed) {
                            if (node.object.type === 'MemberExpression' ) {
                                /**
                                 *  self.components[index] 
                                 *      => 
                                 *  HEAP[self+components+(index<<size)>>size]
                                 */
                                const object = symtbl[func.id.name][node.object.object.name]
                                const member = getField(node.object.property.name, meta[packge][object.type].data)
                                if (member) {
                                    const heap = mem[member.type].heap
                                    const size = mem[member.type].size
                                    const offset = member.offset
                                    return factory.ObjectArray(node.object.object.name, node.object.property.name, offset, heap, size)
                                }                        
                                
                            } else {
                                /**
                                 *  indices[index] 
                                 *      => 
                                 *  HEAP[indices+(index<<size)>>size]
                                 */
                                const object = symtbl[func.id.name][node.object.name]
                                const index = symtbl[func.id.name][node.property.name]
                                const heap = mem[object.type].heap
                                const size = mem[object.type].size
                                return factory.LocalArray(object.name, index.name, heap, size)
                            }

                        }
                    }
                })
            }

            /**
             * Ensure the RHS is coerced
             */
            for (let k = func.params.length; k<func.body.body.length; k++) {
                estraverse.replace(func.body.body[k], {
                    enter: function(node, parent) {
                        // if (node.type === 'AssignmentExpression') {
                            //BinaryExpression
                            //ReturnStatement
                            console.log(JSON.stringify(node, null, 2))
                            console.log('-------------------------------------')
                            // right hand side should be coerced
                        // }

                    }
                })
            }
            
        }
    }
    

    //const out = str.substr(0, startPos)+escodegen.generate(ast)
    const out = escodegen.generate(ast)
    return out

    function getField(name, fields) {
        for (let f in fields) {
            if (fields[f].name === name) {
                return fields[f]
            }
        }
    }
}
コード例 #6
0
function main(fileName) {
  var code = require('fs').readFileSync(fileName).toString();
  var ast = esprima.parse(code);
  var strings = {};
  var scopeDepth = 0; // initial: global

  // pass 1: extract all strings
  estraverse.traverse(ast, {
    enter: function(node) {
	  if (shouldSwitchScope(node)) {
	    scopeDepth++;
	  }
	  
      if (scopeDepth == 0 &&
		node.type === esprima.Syntax.VariableDeclarator &&
        node.init &&
        node.init.type === esprima.Syntax.ArrayExpression &&
		node.init.elements.every(function(e) {return e.type === esprima.Syntax.Literal})) {
        strings[node.id.name] = node.init.elements.map(function(e) {
          return e.value;
        });
        this.skip();
      }
    },
	leave: function(node) {
      if (shouldSwitchScope(node)) {
		scopeDepth--;
	  }
	}
  });

  // pass 2: restore code
  ast = estraverse.replace(ast, {
    enter: function(node) {
    },
	leave: function(node) {
	  // restore strings
	  if (node.type === esprima.Syntax.MemberExpression &&
        node.computed &&
        strings.hasOwnProperty(node.object.name) &&
        node.property.type === esprima.Syntax.Literal
      ) {
        var val = strings[node.object.name][node.property.value];
        return {
          type: esprima.Syntax.Literal,
          value: val,
          raw: val
        }
      }
	  
	  if (node.type === esprima.Syntax.MemberExpression &&
        node.property.type === esprima.Syntax.Literal &&
        typeof node.property.value === 'string'
      ) {
        return {
          type: esprima.Syntax.MemberExpression,
          computed: false,
          object: node.object,
          property: {
            type: esprima.Syntax.Identifier,
            name: node.property.value
          }
        }
      }
	}
  });

  console.log(escodegen.generate(ast));
}
コード例 #7
0
ファイル: compiler.js プロジェクト: indutny/bemhtml.js
Compiler.prototype.translate = function translate(ast) {
  if (this.options.ibem !== false) {
    // Lazily parse i-bem
    if (!ibemAst) {
      ibemAst = esprima.parse('function ibem() {' + bemhtml.ibem + '\n}');
      ibemAst = JSON.stringify(ibemAst.body[0].body.body);
    }

    var ibem = JSON.parse(ibemAst);

    // Add i-bem block to the AST
    assert.equal(ast.type, 'Program');
    ast = {
      type: 'Program',
      body: ibem.concat(ast.body)
    };
  }

  // Ok, I admit it. Translation process is a bit f****d.
  var self = this;
  var allowed = {
    Program: true,
    ExpressionStatement: true,
    CallExpression: true,
    MemberExpression: true
  };
  ast = estraverse.replace(ast, {
    enter: function(ast, parent, notify) {
      // Do not get too deep
      if (!allowed[ast.type]) {
        this.skip();
      }
    },
    leave: function(ast) {
      // 1. mark all match calls
      ast = self.markMatches(ast);

      // 2. replace all custom matches with match() calls
      ast = self.replaceCustom(ast);

      // 3. Merge match(cond).match(cond) into match(cond, cond) and
      //    match(cond)(match(cond)) into match()(match(cond, cond)
      ast = self.mergeMatches(ast);

      return ast;
    }
  });

  // 4. Flatten every statement and replace local/apply/applyNext/applyCtx
  for (var i = 0; i < ast.body.length; i++) {
    var stmt = ast.body[i];
    if (stmt.type !== 'ExpressionStatement' ||
        !stmt.expression.bemMarked) {
      continue;
    }

    var exprs = this.flatten(stmt.expression);
    ast.body.splice.apply(ast.body, [ i, 1 ].concat(exprs.map(function(expr) {
      return {
        type: 'ExpressionStatement',
        expression: expr
      }
    })));
    i += exprs.length - 1;
  }

  return xjst.translate(ast, this.options);
};