【问题标题】:code refactoring a java script compiler重构 javascript 编译器的代码
【发布时间】:2016-07-02 13:08:31
【问题描述】:

我试图了解一个 JavaScript 包编译器并重新设计了基本结构。 每次编译一个字符串时,它都会被添加到SrcTable 数组中。并扔在输出端。 但是,要获得输出,SrcTable 必须声明为全局的。 but the example from which i am building this code has that variable declared as local。 我想了解:- 1.为什么我不能在这里将变量声明为本地变量? 2. 我需要更改什么才能使其在本地工作?

srcTable 位于 preprocessors.compiler 变量中。

function resolveRequest(request) {
  var match = request.match(/^\s*import\s+(.*)$/),
    imports = {};

  if (match) {
    match[1].replace(/\s*([\w.\-$]+)(?:\s+as\s+([\w.\-$]+))?,?/g, function(_, from, as) {
      imports = {
        from: from,
        as: as || from
      };
    });
  }
  return imports;
}

var preprocessors = {
  import: "var importExpr = /^(\\s*)(import\\s+[^=+*\"'\\r\\n;\\/]+|from\\s+[^=+\"'\\r\\n;\\/ ]+\\s+import\\s+[^=+\"'\\r\\n;\\/]+)(;|\\/|$)/gm;" +
    "function replace(raw, p1, p2, p3) {" +
    "  return p1 + 'jsio(\"' + p2 + '\")' + p3;" +
    "};" +
    "exports = function(src) {" +
    "  return src.replace(importExpr, replace);" +
    "};",
  compiler: "srcTable = [];" + // this array needs to be local
    "        exports = function (src) {" +
    "          var jsioNormal = " + /^(.*)jsio\s*\(\s*(['"].+?['"])\s*(,\s*\{[^}]+\})?\)/gm + "\n;" +
    "          var match = jsioNormal.exec(src);\n" +
    "          if(match) {" +
    "            var request = eval(match[2]);\n" +
    "            jsio(request, ['import', 'compiler']);\n" +
    "          } \n" +
    "          srcTable.push(src);"+
    "          return '';\n" +
    "        };" +
    "        exports.compile = function(request) {" +
    "          jsio(request, ['import', 'compiler']);" +
    "        };" + 
    "        exports.generateSrc = function (callback) {"+
    "          callback(srcTable);"+
    "        };"
};

function _require(previousCtx, request, p) {
  var p = p || ['import'];
  var request = resolveRequest(request);
  var src = eval(request.from);

  p.forEach(function(name, index) {
    var args = name == 'import' ? [] : null;
    var preprocessor = jsio('import preprocessors.' + name, args);

    src = preprocessor(src);
  });

  var code = "(function (__) { with (__) {" + src + "}});";
  var fn = eval(code);
  var context = makeContext();
  fn(context);
  previousCtx[request.as] = context.exports;
  return context.exports;
}

function makeContext() {
  return {
    jsio: function(request, p) {
      return _require(this, request, p);
    },
    exports: {}
  };
}

var jsio = makeContext().jsio;

var example = {
  app: "import example.calculator as calculator;" +
    "   calculator.add(2, 3);",

  calculator: "import example.print as print;" +
    "          exports = {" +
    "            add: function (a, b) {" +
    "              print(a+b);" +
    "            }" +
    "          }",

  print: "exports = function(res) {" +
    "       console.log(res);" +
    "     }"
};

var compiler = jsio('import preprocessors.compiler;');
compiler.compile('import example.app;');
compiler.generateSrc(function(src) {
  console.log(src);
});

【问题讨论】:

    标签: javascript compiler-construction global local


    【解决方案1】:

    由于代码是使用 java-script with 上下文编译的,因此,评估代码的函数需要被缓存,否则每次编译相同的代码都会重新创建实例。 所以解决方案是

    function resolveRequest(request) {
      var match = request.match(/^\s*import\s+(.*)$/),
        imports = {};
    
      if (match) {
        match[1].replace(/\s*([\w.\-$]+)(?:\s+as\s+([\w.\-$]+))?,?/g, function(_, from, as) {
          imports = {
            from: from,
            as: as || from
          };
        });
      }
      return imports;
    }
    
    var preprocessors = {
      import: "var importExpr = /^(\\s*)(import\\s+[^=+*\"'\\r\\n;\\/]+|from\\s+[^=+\"'\\r\\n;\\/ ]+\\s+import\\s+[^=+\"'\\r\\n;\\/]+)(;|\\/|$)/gm;" +
        "function replace(raw, p1, p2, p3) {" +
        "  return p1 + 'jsio(\"' + p2 + '\")' + p3;" +
        "};" +
        "exports = function(src) {" +
        "  return src.replace(importExpr, replace);" +
        "};",
      compiler: "var srcTable = [];\n" +
        "        exports = function (src) {\n" +
        "          var jsioNormal = " + /^(.*)jsio\s*\(\s*(['"].+?['"])\s*(,\s*\{[^}]+\})?\)/gm + "\n;" +
        "          var match = jsioNormal.exec(src);\n" +
        "          if(match) {\n" +
        "            var request = eval(match[2]);\n" +
        "            jsio(request, ['import', 'compiler']);\n" +
        "          } \n" +
        "          srcTable.push(src);\n" +
        "          return '';\n" +
        "        };\n" +
        "        exports.compile = function(request) {\n" +
        "          jsio(request, ['import', 'compiler']);\n" +
        "        };\n" +
        "        exports.generateSrc = function (callback) {\n" +
        "          callback(srcTable);\n" +
        "        };\n"
    };
    
    var _cache_context = [];
    
    function _require(previousCtx, request, p) {
      var p = p || ['import'];
      var request = resolveRequest(request);
      var src = loadModule(request).src;
    
      p.forEach(function(name, index) {
        var args = name == 'import' ? [] : null;
        var preprocessor = jsio('import preprocessors.' + name, args);
        src = preprocessor(src);
      });
    
      if (src) {
        if (!_cache_context[request.from]) {
          var code = "(function (__) { with (__) {\n" + src + "\n}});";
          var fn = eval(code);
          var context = makeContext();
          fn(context);
          _cache_context[request.from] = context.exports;
        }
        previousCtx[request.as] = _cache_context[request.from];
        return previousCtx[request.as];
      }
    }
    
    function loadModule(request){
     var src = eval(request.from);
    
     return {
       src: src,
       path: request.from
     } 
    }
    
    function makeContext() {
      return {
        jsio: function(request, p) {
          return _require(this, request, p);
        },
        exports: {}
      };
    }
    
    var jsio = makeContext().jsio;
    
    var example = {
      app: "import example.calculator as calculator;" +
        "   calculator.add(2, 3);",
    
      calculator: "import example.print as print;" +
        "          exports = {" +
        "            add: function (a, b) {" +
        "              print(a+b);" +
        "            }" +
        "          }",
    
      print: "exports = function(res) {" +
        "       console.log(res);" +
        "     }"
    };
    
    var compiler = jsio('import preprocessors.compiler;');
    compiler.compile('import example.app;');
    compiler.generateSrc(function(src) {
      console.log(src);
    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-10
      • 1970-01-01
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多