Code coverage report for sc/lang/compiler/rewriter/rewriter.js

Statements: 100% (66 / 66)      Branches: 100% (33 / 33)      Functions: 100% (16 / 16)      Lines: 100% (66 / 66)      Ignored: 1 statement, 1 branch     

All files » sc/lang/compiler/rewriter/ » rewriter.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 1281     1 1   1 1   1                   1 44 44     1 44 44 8   44     1 1133   1133 121 1012 361   651     1133     1 121 170       1 361   361 11 350 8 8 10 8 8         361   919 1   919       361 11     361     1 8 8 8   1 214   214 86 200     214 3 3 3       8 14 14     8     1 722     1 350       1 247       1    
(function(sc) {
  "use strict";
 
  require("../compiler");
  require("../node/node");
 
  var Syntax = sc.lang.compiler.Syntax;
  var Node = sc.lang.compiler.Node;
 
  var SegmentedMethod = {
    idle: true,
    sleep: true,
    wait: true,
    yield: true,
    alwaysYield: true,
    yieldAndReset: true,
    embedInStream: true,
  };
 
  function Rewriter() {
    this.functionStack = [];
    this.functionArray = [];
  }
 
  Rewriter.prototype.rewrite = function(ast) {
    ast = this.traverse(ast);
    this.functionArray.forEach(function(node) {
      node.body = this.segment(node.body);
    }, this);
    return ast;
  };
 
  Rewriter.prototype.traverse = function(node) {
    var result;
 
    if (Array.isArray(node)) {
      result = this.traverse$Array(node);
    } else if (node && typeof node === "object") {
      result = this.traverse$Object(node);
    } else {
      result = node;
    }
 
    return result;
  };
 
  Rewriter.prototype.traverse$Array = function(node) {
    return node.map(function(node) {
      return this.traverse(node);
    }, this);
  };
 
  Rewriter.prototype.traverse$Object = function(node) {
    var result = {};
 
    if (isFunctionExpression(node)) {
      this.functionStack.push(result);
    } else if (isSegmentedMethod(node)) {
      result.segmented = true;
      this.functionStack.forEach(function(node) {
        if (!node.segmented) {
          this.functionArray.push(node);
          node.segmented = true;
        }
      }, this);
    }
 
    Object.keys(node).forEach(function(key) {
      /* istanbul ignore next */
      Iif (key === "range" || key === "loc") {
        result[key] = node[key];
      } else {
        result[key] = this.traverse(node[key]);
      }
    }, this);
 
    if (isFunctionExpression(result)) {
      this.functionStack.pop();
    }
 
    return result;
  };
 
  Rewriter.prototype.segment = function(list) {
    var result = [];
    var id = 0;
    var i, imax;
 
    function traverse(parent, node, key) {
      var expr;
 
      if (node && typeof node === "object") {
        Object.keys(node).forEach(function(key) {
          traverse(node, node[key], key);
        });
      }
      if (isValueMethod(node)) {
        expr = Node.createValueMethodEvaluator(id, node);
        parent[key] = Node.createValueMethodResult(id++);
        result.push(expr);
      }
    }
 
    for (i = 0, imax = list.length; i < imax; ++i) {
      traverse(list, list[i], i);
      result.push(list[i]);
    }
 
    return result;
  };
 
  function isFunctionExpression(node) {
    return node && node.type === Syntax.FunctionExpression;
  }
 
  function isSegmentedMethod(node) {
    return node && node.type === Syntax.CallExpression &&
      (SegmentedMethod.hasOwnProperty(node.method.name) || isValueMethod(node));
  }
 
  function isValueMethod(node) {
    return node && node.type === Syntax.CallExpression &&
      node.method.name.substr(0, 5) === "value";
  }
 
  sc.lang.compiler.Rewriter = Rewriter;
})(sc);