nodejs.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. "use strict";
  2. var Class = require("rtl.js").Class;
  3. var Code = require("js/Code.js");
  4. var ContextHierarchy = require("js/ContextHierarchy.js");
  5. var oc = require("oc.js");
  6. var makeRTL = require("rtl_code.js").makeRTL;
  7. var fs = require("fs");
  8. var path = require("path");
  9. var ModuleGenerator = Class.extend({
  10. init: function Nodejs$ModuleGenerator(name, imports, importDir){
  11. this.__name = name;
  12. this.__imports = imports;
  13. this.__importDir = importDir;
  14. },
  15. prolog: function(){
  16. var result = "";
  17. var modules = this.__imports;
  18. for(var name in modules){
  19. var alias = modules[name];
  20. var importName = this.__importDir ? this.__importDir + "/" + name
  21. : name;
  22. result += "var " + alias + " = " + (name == "this"
  23. ? "GLOBAL"
  24. : "require(\"" + importName + ".js\")") + ";\n";
  25. }
  26. return result;
  27. },
  28. epilog: function(exports){
  29. var result = "";
  30. for(var access in exports){
  31. var e = exports[access];
  32. var code = Code.genExport(e);
  33. if (code){
  34. var id = Code.exportId(e);
  35. result += "exports." + id + " = " + code + ";\n";
  36. }
  37. }
  38. return result;
  39. }
  40. });
  41. var RtlCodeUsingWatcher = Class.extend({
  42. init: function(){this.__used = false;},
  43. using: function(){this.__used = true;},
  44. used: function(){return this.__used;},
  45. reset: function(){this.__used = false;}
  46. });
  47. function writeCompiledModule(name, code, outDir){
  48. var filePath = path.join(outDir, name + ".js");
  49. fs.writeFileSync(filePath, code);
  50. }
  51. function compile(sources, language, handleErrors, includeDirs, outDir, importDir){
  52. var rtlCodeWatcher = new RtlCodeUsingWatcher();
  53. var rtl = new makeRTL(language.rtl, rtlCodeWatcher.using.bind(rtlCodeWatcher));
  54. var moduleCode = function(name, imports){
  55. return new ModuleGenerator(name, imports, importDir);};
  56. var compiledFilesStack = [];
  57. oc.compileModules(
  58. sources,
  59. function(name){
  60. var fileName = name;
  61. if (!path.extname(fileName).length)
  62. fileName += ".ob";
  63. compiledFilesStack.push(fileName);
  64. var readPath = fileName;
  65. var i = 0;
  66. while (!fs.existsSync(readPath) && i < includeDirs.length){
  67. readPath = path.join(includeDirs[i], fileName);
  68. ++i;
  69. }
  70. if (!fs.existsSync(readPath))
  71. throw new Error("cannot find file: '" + fileName + "' in " + includeDirs);
  72. return fs.readFileSync(readPath, "utf8");
  73. },
  74. language.grammar,
  75. function(moduleResolver){return new ContextHierarchy.Root(
  76. { codeGenerator: language.codeGenerator.make(),
  77. moduleGenerator: moduleCode,
  78. rtl: rtl,
  79. types: language.types,
  80. stdSymbols: language.stdSymbols,
  81. moduleResolver: moduleResolver
  82. });},
  83. function(e){handleErrors("File \"" + compiledFilesStack[compiledFilesStack.length - 1] + "\", " + e);},
  84. function(name, code){
  85. if (rtlCodeWatcher.used()){
  86. code = "var " + rtl.name() + " = require(\"" + rtl.module() + "\");\n" + code;
  87. rtlCodeWatcher.reset();
  88. }
  89. writeCompiledModule(name, code, outDir);
  90. compiledFilesStack.pop();
  91. });
  92. }
  93. exports.compile = compile;